1
0

upload old common

This commit is contained in:
Sky Johnson 2025-08-31 20:59:51 -05:00
parent 361330460e
commit 115cc364f4
78 changed files with 26345 additions and 0 deletions

328
old/CRC16.cpp Normal file
View File

@ -0,0 +1,328 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
unsigned long IntArray[]={
0x00000000,
0x77073096,
0xEE0E612C,
0x990951BA,
0x076DC419,
0x706AF48F,
0xE963A535,
0x9E6495A3,
0x0EDB8832,
0x79DCB8A4,
0xE0D5E91E,
0x97D2D988,
0x09B64C2B,
0x7EB17CBD,
0xE7B82D07,
0x90BF1D91,
0x1DB71064,
0x6AB020F2,
0xF3B97148,
0x84BE41DE,
0x1ADAD47D,
0x6DDDE4EB,
0xF4D4B551,
0x83D385C7,
0x136C9856,
0x646BA8C0,
0xFD62F97A,
0x8A65C9EC,
0x14015C4F,
0x63066CD9,
0xFA0F3D63,
0x8D080DF5,
0x3B6E20C8,
0x4C69105E,
0xD56041E4,
0xA2677172,
0x3C03E4D1,
0x4B04D447,
0xD20D85FD,
0xA50AB56B,
0x35B5A8FA,
0x42B2986C,
0xDBBBC9D6,
0xACBCF940,
0x32D86CE3,
0x45DF5C75,
0xDCD60DCF,
0xABD13D59,
0x26D930AC,
0x51DE003A,
0xC8D75180,
0xBFD06116,
0x21B4F4B5,
0x56B3C423,
0xCFBA9599,
0xB8BDA50F,
0x2802B89E,
0x5F058808,
0xC60CD9B2,
0xB10BE924,
0x2F6F7C87,
0x58684C11,
0xC1611DAB,
0xB6662D3D,
0x76DC4190,
0x01DB7106,
0x98D220BC,
0xEFD5102A,
0x71B18589,
0x06B6B51F,
0x9FBFE4A5,
0xE8B8D433,
0x7807C9A2,
0x0F00F934,
0x9609A88E,
0xE10E9818,
0x7F6A0DBB,
0x086D3D2D,
0x91646C97,
0xE6635C01,
0x6B6B51F4,
0x1C6C6162,
0x856530D8,
0xF262004E,
0x6C0695ED,
0x1B01A57B,
0x8208F4C1,
0xF50FC457,
0x65B0D9C6,
0x12B7E950,
0x8BBEB8EA,
0xFCB9887C,
0x62DD1DDF,
0x15DA2D49,
0x8CD37CF3,
0xFBD44C65,
0x4DB26158,
0x3AB551CE,
0xA3BC0074,
0xD4BB30E2,
0x4ADFA541,
0x3DD895D7,
0xA4D1C46D,
0xD3D6F4FB,
0x4369E96A,
0x346ED9FC,
0xAD678846,
0xDA60B8D0,
0x44042D73,
0x33031DE5,
0xAA0A4C5F,
0xDD0D7CC9,
0x5005713C,
0x270241AA,
0xBE0B1010,
0xC90C2086,
0x5768B525,
0x206F85B3,
0xB966D409,
0xCE61E49F,
0x5EDEF90E,
0x29D9C998,
0xB0D09822,
0xC7D7A8B4,
0x59B33D17,
0x2EB40D81,
0xB7BD5C3B,
0xC0BA6CAD,
0xEDB88320,
0x9ABFB3B6,
0x03B6E20C,
0x74B1D29A,
0xEAD54739,
0x9DD277AF,
0x04DB2615,
0x73DC1683,
0xE3630B12,
0x94643B84,
0x0D6D6A3E,
0x7A6A5AA8,
0xE40ECF0B,
0x9309FF9D,
0x0A00AE27,
0x7D079EB1,
0xF00F9344,
0x8708A3D2,
0x1E01F268,
0x6906C2FE,
0xF762575D,
0x806567CB,
0x196C3671,
0x6E6B06E7,
0xFED41B76,
0x89D32BE0,
0x10DA7A5A,
0x67DD4ACC,
0xF9B9DF6F,
0x8EBEEFF9,
0x17B7BE43,
0x60B08ED5,
0xD6D6A3E8,
0xA1D1937E,
0x38D8C2C4,
0x4FDFF252,
0xD1BB67F1,
0xA6BC5767,
0x3FB506DD,
0x48B2364B,
0xD80D2BDA,
0xAF0A1B4C,
0x36034AF6,
0x41047A60,
0xDF60EFC3,
0xA867DF55,
0x316E8EEF,
0x4669BE79,
0xCB61B38C,
0xBC66831A,
0x256FD2A0,
0x5268E236,
0xCC0C7795,
0xBB0B4703,
0x220216B9,
0x5505262F,
0xC5BA3BBE,
0xB2BD0B28,
0x2BB45A92,
0x5CB36A04,
0xC2D7FFA7,
0xB5D0CF31,
0x2CD99E8B,
0x5BDEAE1D,
0x9B64C2B0,
0xEC63F226,
0x756AA39C,
0x026D930A,
0x9C0906A9,
0xEB0E363F,
0x72076785,
0x05005713,
0x95BF4A82,
0xE2B87A14,
0x7BB12BAE,
0x0CB61B38,
0x92D28E9B,
0xE5D5BE0D,
0x7CDCEFB7,
0x0BDBDF21,
0x86D3D2D4,
0xF1D4E242,
0x68DDB3F8,
0x1FDA836E,
0x81BE16CD,
0xF6B9265B,
0x6FB077E1,
0x18B74777,
0x88085AE6,
0xFF0F6A70,
0x66063BCA,
0x11010B5C,
0x8F659EFF,
0xF862AE69,
0x616BFFD3,
0x166CCF45,
0xA00AE278,
0xD70DD2EE,
0x4E048354,
0x3903B3C2,
0xA7672661,
0xD06016F7,
0x4969474D,
0x3E6E77DB,
0xAED16A4A,
0xD9D65ADC,
0x40DF0B66,
0x37D83BF0,
0xA9BCAE53,
0xDEBB9EC5,
0x47B2CF7F,
0x30B5FFE9,
0xBDBDF21C,
0xCABAC28A,
0x53B39330,
0x24B4A3A6,
0xBAD03605,
0xCDD70693,
0x54DE5729,
0x23D967BF,
0xB3667A2E,
0xC4614AB8,
0x5D681B02,
0x2A6F2B94,
0xB40BBE37,
0xC30C8EA1,
0x5A05DF1B,
0x2D02EF8D,
};
unsigned long CRC16(const unsigned char *buf, int size, int key)
{
unsigned long ecx = key; //mov ecx, [esp+arg_8]
unsigned long eax = ecx; //mov eax, ecx
unsigned long edi;
eax = ~ eax; //not eax
eax&=0xFF; //and eax, 0FFh
eax=IntArray[eax]; //mov eax, dword_0_10115D38[eax*4] IntArray
eax ^= 0x00FFFFFF; //xor eax, 0FFFFFFh
int edx = ecx; //mov edx, ecx
edx = edx >> 8; //sar edx, 8
edx = edx ^ eax; //xor edx, eax
eax = eax >> 8; //sar eax, 8
edx &= 0xFF; //and edx, 0FFh
eax &= 0x00FFFFFF; //and eax, 0FFFFFFh
eax ^= IntArray[edx]; //xor eax, dword_0_10115D38[edx*4]
edx = ecx; //mov edx, ecx
edx = edx >> 0x10; //sar edx, 10h
edx ^= eax; //xor edx, eax
eax = eax >> 8; //sar eax, 8
edx &= 0xFF; //and edx, 0FFh
int esi = IntArray[edx]; //mov esi, dword_0_10115D38[edx*4]
edx = size; //mov edx, [esp+4+arg_4]
eax &= 0x00FFFFFF; //and eax, 0FFFFFFh
eax ^= esi; //xor eax, esi
ecx = ecx >> 0x18; //sar ecx, 18h
ecx ^= eax; //xor ecx, eax
ecx &= 0xFF; //and ecx, 0FFh
esi = IntArray[ecx]; //mov esi, dword_0_10115D38[ecx*4]
ecx = (int)*buf; //mov ecx, [esp+4+arg_0]
eax = eax >> 8; //sar eax, 8
eax &= 0x00FFFFFF; //and eax, 0FFFFFFh
eax ^= esi; //xor eax, esi
for(int x = 0; x < size; x++)
{ //eax is the crc, ecx is the current part of the buffer
int edx = 0; //xor edx, edx
edx = buf[x] & 0x00FF; //mov dl, [ecx]
edx ^= eax; //xor edx, eax
eax = eax >> 8; //sar eax, 8
edx &= 0xFF; //and edx, 0FFh
edi = IntArray[edx]; //mov edi, dword_0_10115D38[edx*4]
eax &= 0x00FFFFFF; //and eax, 0FFFFFFh
eax ^= edi; //xor eax, edi
}
return ~eax;
}

25
old/CRC16.h Normal file
View File

@ -0,0 +1,25 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CRC16_H
#define _CRC16_H
unsigned long CRC16(const unsigned char *buf, int size, int key);
#endif

32
old/Common_Defines.h Normal file
View File

@ -0,0 +1,32 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#define BASEDIR "./"
#ifndef DB_INI_FILE
#ifdef LOGIN
#define DB_INI_FILE BASEDIR "login_db.ini"
#else
#define DB_INI_FILE BASEDIR "world_db.ini"
#endif
#endif
#ifndef MAIN_CONFIG_FILE
#define MAIN_CONFIG_FILE BASEDIR "server_config.json"
#endif

133
old/Condition.cpp Normal file
View File

@ -0,0 +1,133 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "debug.h"
#include "Condition.h"
#ifdef WIN32
#else
#include <pthread.h>
#include <sys/time.h>
#include <errno.h>
#endif
#ifdef WIN32
/*
Windows does not support condition variables by default.
So we use a simple hack of sleeping in wait() and doing
nothing anywhere else.
some possible places to look for ways to do this:
http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
http://sources.redhat.com/pthreads-win32/
http://sources.redhat.com/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_signal.c?rev=1.7&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32
*/
#define CONDITION_HACK_GRANULARITY 4
Condition::Condition()
{
}
void Condition::Signal()
{
}
void Condition::SignalAll()
{
}
void Condition::Wait()
{
Sleep(CONDITION_HACK_GRANULARITY);
}
Condition::~Condition()
{
}
#else //!WIN32
Condition::Condition()
{
pthread_cond_init(&cond,NULL);
pthread_mutex_init(&mutex,NULL);
}
void Condition::Signal()
{
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void Condition::SignalAll()
{
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
void Condition::Wait()
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
pthread_mutex_unlock(&mutex);
}
/*
I commented this specifically because I think it might be very
difficult to write a windows counterpart to it, so I would like
to discourage its use until we can confirm that it can be reasonably
implemented on windows.
bool Condition::TimedWait(unsigned long usec)
{
struct timeval now;
struct timespec timeout;
int retcode=0;
pthread_mutex_lock(&mutex);
gettimeofday(&now,NULL);
now.tv_usec+=usec;
timeout.tv_sec = now.tv_sec + (now.tv_usec/1000000);
timeout.tv_nsec = (now.tv_usec%1000000) *1000;
//cout << "now=" << now.tv_sec << "."<<now.tv_usec << endl;
//cout << "timeout=" << timeout.tv_sec << "."<<timeout.tv_nsec << endl;
retcode=pthread_cond_timedwait(&cond,&mutex,&timeout);
pthread_mutex_unlock(&mutex);
return retcode!=ETIMEDOUT;
}
*/
Condition::~Condition()
{
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&cond);
pthread_cond_destroy(&cond);
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
}
#endif

48
old/Condition.h Normal file
View File

@ -0,0 +1,48 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CONDITION_H
#define __CONDITION_H
#ifndef WIN32
#include <pthread.h>
#endif
//Sombody, someday needs to figure out how to implement a condition
//system on windows...
class Condition {
private:
#ifndef WIN32
pthread_cond_t cond;
pthread_mutex_t mutex;
#endif
public:
Condition();
void Signal();
void SignalAll();
void Wait();
// bool TimedWait(unsigned long usec);
~Condition();
};
#endif

304
old/ConfigReader.cpp Normal file
View File

@ -0,0 +1,304 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ConfigReader.h"
#include "Log.h"
ConfigReader::~ConfigReader(){
MStructs.lock();
DestroyStructs();
MStructs.unlock();
}
PacketStruct* ConfigReader::getStructByVersion(const char* name, int16 version){
PacketStruct* packet = 0;
PacketStruct* newpacket = 0;
MStructs.lock();
vector<PacketStruct*>* struct_versions = structs[string(name)];
if(struct_versions){
vector<PacketStruct*>::iterator iter;
for(iter = struct_versions->begin(); iter != struct_versions->end(); iter++){
packet = *iter;
if(packet && packet->GetVersion() == version){
newpacket = new PacketStruct(packet, version);
break;
}
}
}
MStructs.unlock();
if(!newpacket)
LogWrite(PACKET__ERROR, 0, "Packet", "Could not find struct named '%s' with version: %i", name, version);
return newpacket;
}
void ConfigReader::ReloadStructs(){
MStructs.lock();
DestroyStructs();
for(int32 i=0;i<load_files.size();i++)
processXML_Elements(load_files[i].c_str());
MStructs.unlock();
}
void ConfigReader::DestroyStructs(){
map<string, vector<PacketStruct*>*>::iterator struct_iterator;
for(struct_iterator=structs.begin();struct_iterator!=structs.end();struct_iterator++) {
vector<PacketStruct*>* versions = struct_iterator->second;
vector<PacketStruct*>::iterator version_iter;
if(versions){
for(version_iter = versions->begin(); version_iter != versions->end(); version_iter++){
safe_delete(*version_iter);
}
}
safe_delete(versions);
}
structs.clear();
}
PacketStruct* ConfigReader::getStruct(const char* name, int16 version){
PacketStruct* latest_version = 0;
PacketStruct* new_latest_version = 0;
MStructs.lock();
vector<PacketStruct*>* struct_versions = structs[string(name)];
if(struct_versions){
vector<PacketStruct*>::iterator iter;
for(iter = struct_versions->begin(); iter != struct_versions->end(); iter++){
if((*iter)->GetVersion() <= version && (!latest_version || (*iter)->GetVersion() > latest_version->GetVersion()))
latest_version = *iter;
}
if (latest_version) {
// TODO: Need to revisit this, if we have a packet struct with a version of 1, but no opcodes, we still go to the else if statement
// which results in sending corrupt data to client
if (latest_version->GetOpcode() != OP_Unknown && (latest_version->GetOpcodeValue(version) == 0xFFFF || latest_version->GetOpcodeValue(version)==0xCDCD)) {
LogWrite(PACKET__ERROR, 0, "Packet", "Could not find valid opcode for Packet Struct '%s' and client version %d", latest_version->GetName(), version);
}
else if(strlen(latest_version->GetOpcodeType()) == 0 || latest_version->GetOpcode() != OP_Unknown)
new_latest_version = new PacketStruct(latest_version, version);
}
}
MStructs.unlock();
if(!new_latest_version && !latest_version)
LogWrite(PACKET__ERROR, 0, "Packet", "Could not find struct named '%s' with version: %i", name, version);
return new_latest_version;
}
int16 ConfigReader::GetStructVersion(const char* name, int16 version){
MStructs.lock();
vector<PacketStruct*>* struct_versions = structs[string(name)];
int16 ret = 0;
if(struct_versions){
vector<PacketStruct*>::iterator iter;
PacketStruct* latest_version = 0;
for(iter = struct_versions->begin(); iter != struct_versions->end(); iter++){
if(!latest_version || ( (*iter)->GetVersion() > latest_version->GetVersion() && (*iter)->GetVersion() <= version) )
latest_version = *iter;
}
if(latest_version)
ret = latest_version->GetVersion();
}
MStructs.unlock();
return ret;
}
void ConfigReader::addStruct(const char* name, int16 version, PacketStruct* new_struct){
string strname(name);
vector<PacketStruct*>* struct_versions = structs[strname];
if(struct_versions)
struct_versions->push_back(new_struct);
else{
struct_versions = new vector<PacketStruct*>;
struct_versions->push_back(new_struct);
structs[strname] = struct_versions;
}
}
bool ConfigReader::LoadFile(const char* name){
load_files.push_back(name);
return processXML_Elements(name);
}
bool ConfigReader::processXML_Elements(const char* fileName){
XMLNode xMainNode=XMLNode::openFileHelper(fileName,"EQ2Emulator");
if(xMainNode.isEmpty())
return false;
for(int i=0;i<xMainNode.nChildNode("Struct");i++){
const char* struct_name = xMainNode.getChildNode("Struct", i).getAttribute("Name");
const char* str_version = xMainNode.getChildNode("Struct", i).getAttribute("ClientVersion");
const char* opcode_name = xMainNode.getChildNode("Struct", i).getAttribute("OpcodeName");
const char* opcode_type = xMainNode.getChildNode("Struct", i).getAttribute("OpcodeType");
if(!struct_name || !str_version)
{
LogWrite(MISC__WARNING, 0, "Misc", "Ignoring invalid struct, all structs must include at least a Name and ClientVersion!");
continue;
}
int16 version = 1;
try
{
version = atoi(str_version);
}
catch(...)
{
LogWrite(MISC__WARNING, 0, "Misc", "Ignoring invalid version for struct named '%s': '%s'", struct_name, str_version);
continue;
}
PacketStruct* new_struct = new PacketStruct();
new_struct->SetName(struct_name);
if(opcode_type)
new_struct->SetOpcodeType(opcode_type);
if(opcode_name){
if(!new_struct->SetOpcode(opcode_name)){
safe_delete(new_struct);
continue;
}
}
new_struct->SetVersion(version);
loadDataStruct(new_struct, xMainNode.getChildNode("Struct", i));
addStruct(struct_name, version, new_struct);
}
return true;
}
void ConfigReader::loadDataStruct(PacketStruct* packet, XMLNode parentNode, bool array_packet){
for(int x=0;x<parentNode.nChildNode();x++){
const char* name = parentNode.getChildNode("Data", x).getAttribute("ElementName");
const char* type = parentNode.getChildNode("Data", x).getAttribute("Type");
const char* size = parentNode.getChildNode("Data", x).getAttribute("Size");
const char* type2 = parentNode.getChildNode("Data", x).getAttribute("Type2");
const char* array_size = parentNode.getChildNode("Data", x).getAttribute("ArraySizeVariable");
const char* max_array = parentNode.getChildNode("Data", x).getAttribute("MaxArraySize");
const char* substruct = parentNode.getChildNode("Data", x).getAttribute("Substruct");
const char* default_value = parentNode.getChildNode("Data", x).getAttribute("DefaultByteValue");
const char* oversized = parentNode.getChildNode("Data", x).getAttribute("OversizedValue");
const char* oversized_byte = parentNode.getChildNode("Data", x).getAttribute("OversizedByte");
const char* if_variable = parentNode.getChildNode("Data", x).getAttribute("IfVariableSet");
const char* if_not_variable = parentNode.getChildNode("Data", x).getAttribute("IfVariableNotSet");
const char* if_equals_variable = parentNode.getChildNode("Data", x).getAttribute("IfVariableEquals");
const char* if_not_equals_variable = parentNode.getChildNode("Data", x).getAttribute("IfVariableNotEquals");
const char* optional = parentNode.getChildNode("Data", x).getAttribute("Optional");
const char* if_flag_not_set_variable = parentNode.getChildNode("Data", x).getAttribute("IfFlagNotSet");
const char* if_flag_set_variable = parentNode.getChildNode("Data", x).getAttribute("IfFlagSet");
//const char* type2criteria = parentNode.getChildNode("Data", x).getAttribute("Type2Criteria"); // JA: LE added to PacketAnalyzer for Items parsing - 12.2012
//const char* criteria = parentNode.getChildNode("Data", x).getAttribute("Criteria"); // JA: LE added to PacketAnalyzer for Items parsing - 12.2012
int8 max_array_size = 0;
try{
if(max_array)
max_array_size = atoi(max_array);
}
catch(...){}
int16 num_size = 1;
try{
if(size)
num_size = atoi(size);
}
catch(...){}
int8 byte_val = 0;
try{
if(default_value)
byte_val = atoi(default_value);
}
catch(...){}
if(substruct && name){
PacketStruct* substruct_packet = getStruct(substruct, packet->GetVersion());
if(substruct_packet){
vector<DataStruct*>::iterator itr;
vector<DataStruct*>* structs = substruct_packet->getStructs();
DataStruct* ds = 0;
int i = 0;
char tmp[12] = {0};
for(i=0;i<num_size;i++){
snprintf(tmp, sizeof(tmp)-1, "%i", i);
for(itr=structs->begin();itr!=structs->end();itr++) {
ds = *itr;
string new_name;
if(array_packet)
new_name = string(name).append("_").append(ds->GetStringName());
else
new_name = string(name).append("_").append(ds->GetStringName()).append("_").append(tmp);
DataStruct* ds2 = new DataStruct(new_name.c_str(), ds->GetType(),ds->GetLength(), ds->GetType2());
if(!array_packet && strlen(ds->GetArraySizeVariable()) > 1)
ds2->SetArraySizeVariable(string(name).append("_").append(ds->GetArraySizeVariable()).append("_").append(tmp).c_str());
ds2->SetOversized(ds->GetOversized());
ds2->SetOversizedByte(ds->GetOversizedByte());
ds2->SetDefaultValue(ds->GetDefaultValue());
ds2->SetMaxArraySize(ds->GetMaxArraySize());
ds2->SetIfSetVariable(ds->GetIfSetVariable() ? ds->GetIfSetVariable() : if_variable);
ds2->SetIfNotSetVariable(ds->GetIfSetVariable() ? ds->GetIfNotSetVariable() : if_not_variable);
ds2->SetIfNotEqualsVariable(ds->GetIfNotEqualsVariable());
ds2->SetIfFlagNotSetVariable(ds->GetIfFlagNotSetVariable());
ds2->SetIfFlagSetVariable(ds->GetIfFlagSetVariable());
ds2->SetIsOptional(ds->IsOptional());
ds2->AddIfSetVariable(if_variable); //add this if the modifier is on the piece that is including the substruct
ds2->AddIfNotSetVariable(if_not_variable); //add this if the modifier is on the piece that is including the substruct
packet->add(ds2);
}
}
if(!array_packet){
i--;
substruct_packet->renameSubstructArray(name, i);
//ds2->SetArraySizeVariable((char*)string(name).append("_").append(ds->GetArraySizeVariable()).append("_").append(tmp).c_str());
packet->addPacketArrays(substruct_packet);
}
safe_delete(substruct_packet);
}
continue;
}
else if(type && strncasecmp(type,"Array", 5)==0 && array_size){
PacketStruct* new_packet = new PacketStruct;
new_packet->SetName(name);
new_packet->IsSubPacket(true);
new_packet->SetVersion(packet->GetVersion());
loadDataStruct(new_packet, parentNode.getChildNode("Data", x), true);
packet->add(new_packet);
}
if(!name || !type)
{
LogWrite(MISC__WARNING, 0, "Misc", "Ignoring invalid Data Element, all elements must include at least an ElementName and Type!");
LogWrite(MISC__WARNING, 0, "Misc", "\tStruct: '%s', version: %i", parentNode.getAttribute("Name"), parentNode.getAttribute("ClientVersion"));
continue;
}
DataStruct* ds = new DataStruct(name, type, num_size, type2);
int8 oversized_value = 0;
int8 oversized_byte_value = 255;
if(oversized){
try{
oversized_value = atoi(oversized);
}
catch(...){}
}
if(oversized_byte){
try{
oversized_byte_value = atoi(oversized_byte);
}
catch(...){}
}
ds->SetOversizedByte(oversized_byte_value);
ds->SetOversized(oversized_value);
ds->SetMaxArraySize(max_array_size);
if(array_size)
ds->SetArraySizeVariable(array_size);
ds->SetDefaultValue(byte_val);
ds->SetIfSetVariable(if_variable);
ds->SetIfNotSetVariable(if_not_variable);
ds->SetIfEqualsVariable(if_equals_variable);
ds->SetIfNotEqualsVariable(if_not_equals_variable);
ds->SetIfFlagNotSetVariable(if_flag_not_set_variable);
ds->SetIfFlagSetVariable(if_flag_set_variable);
if (optional && strlen(optional) > 0 && (strcmp("true", optional) == 0 || strcmp("TRUE", optional) == 0 || strcmp("True", optional) == 0))
ds->SetIsOptional(true);
packet->add(ds);
}
}

52
old/ConfigReader.h Normal file
View File

@ -0,0 +1,52 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CONFIG_READER__
#define __CONFIG_READER__
#include <stdio.h>
#include "PacketStruct.h"
#include <map>
#include <string>
#include <vector>
#include "xmlParser.h"
#include "Mutex.h"
using namespace std;
class ConfigReader{
public:
~ConfigReader();
void addStruct(const char* name, int16 version, PacketStruct* new_struct);
PacketStruct* getStruct(const char* name, int16 version);
PacketStruct* getStructByVersion(const char* name, int16 version);
void loadDataStruct(PacketStruct* packet, XMLNode parentNode, bool array_packet = false);
bool processXML_Elements(const char* fileName);
int16 GetStructVersion(const char* name, int16 version);
void DestroyStructs();
void ReloadStructs();
bool LoadFile(const char* name);
private:
Mutex MStructs;
vector<string> load_files;
map<string, vector<PacketStruct*>*> structs;
//vector<PacketStruct*> structs;
};
#endif

47
old/Crypto.cpp Normal file
View File

@ -0,0 +1,47 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Crypto.h"
#include <iostream>
#include "../common/packet_dump.h"
using namespace std;
void test();
int64 Crypto::RSADecrypt(uchar* text, int16 size){
int64 ret = 0;
uchar* buffer = new uchar[8];
for(int i=7;i>=0;i--)
buffer[7-i] = text[i];
memcpy(&ret, buffer, 8);
safe_delete_array(buffer);
return ret;
}
void Crypto::RC4Decrypt(uchar* text, int32 size){
MCrypto.lock();
client->Cypher(text, size);
MCrypto.unlock();
}
void Crypto::RC4Encrypt(uchar* text, int32 size){
MCrypto.lock();
server->Cypher(text, size);
MCrypto.unlock();
}

66
old/Crypto.h Normal file
View File

@ -0,0 +1,66 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CRYPTO_H
#define _CRYPTO_H
#include <string>
#include <mutex>
#include "RC4.h"
#include "../common/types.h"
using namespace std;
class Crypto {
public:
~Crypto(){ safe_delete(client); safe_delete(server); }
Crypto() { rc4_key = 0; encrypted = false; client = 0; server = 0; };
static int64 RSADecrypt(uchar* text, int16 size);
void RC4Encrypt(uchar* text, int32 size);
void RC4Decrypt(uchar* text, int32 size);
int64 getRC4Key() { return rc4_key; }
void setRC4Key(int64 key) {
rc4_key = key;
if(key > 0){
encrypted = true;
client = new RC4(~key);
server = new RC4(key);
uchar temp[20];
client->Cypher(temp, 20);
server->Cypher(temp, 20);
}
else{
encrypted = false;
safe_delete(client);
safe_delete(server);
}
}
bool isEncrypted(){ return encrypted; }
void setEncrypted(bool in_val){ encrypted = in_val; }
private:
RC4* server;
RC4* client;
bool encrypted;
int64 rc4_key;
mutex MCrypto;
};
#endif

207
old/DataBuffer.h Normal file
View File

@ -0,0 +1,207 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __EQ2_DATABUFFER_
#define __EQ2_DATABUFFER_
#include <string>
#include "../common/types.h"
#include "../common/EQPacket.h"
#include "../common/EQ2_Common_Structs.h"
#ifdef WORLD
#include "../WorldServer/SpawnLists.h"
#endif
using namespace std;
class DataBuffer{
public:
bool changed;
uchar* getData(){ return (uchar*)buffer.c_str(); }
int32 getDataSize(){ return buffer.length(); }
string* getDataString(){ return &buffer; }
void CreateEQ2Color(EQ2_Color& color){
CreateEQ2Color(&color);
}
uchar* GetLoadBuffer(){
return load_buffer;
}
int32 GetLoadPos(){
return load_pos;
}
int32 GetLoadLen(){
return load_len;
}
void SetLoadPos(int32 new_pos){
load_pos = new_pos;
}
void CreateEQ2Color(EQ2_Color* color){
int8 rgb[3];
float* tmp = 0;
for(int i=0;i<3;i++){
tmp = (float*)(load_buffer + load_pos);
rgb[i] = (int8)((*tmp)*255);
load_pos += sizeof(float);
}
color->red = rgb[0];
color->green = rgb[1];
color->blue = rgb[2];
}
template<class Type> void MakeEQ2_Int8(Type& output){
MakeEQ2_Int8(&output);
}
template<class Type> void MakeEQ2_Int8(Type* output){
float* tmp = (float*)(load_buffer + load_pos);
if(*tmp < 0)
*tmp *= -1;
sint8 result = (sint8)((*tmp)*100);
memcpy(output, &result, sizeof(sint8));
load_pos += sizeof(float);
}
void InitializeGetData(){
get_buffer = (uchar*)buffer.c_str();
get_len = buffer.length();
get_pos = 0;
}
void InitializeLoadData(uchar* input, int32 size){
buffer = string((char*)input, size);
load_buffer = (uchar*)buffer.c_str();
load_len = size;
load_pos = 0;
}
template<class String> void LoadDataString(String& output){
LoadDataString(&output);
}
template<class String> void LoadDataString(String* output){
if((sizeof(output->size) + load_pos) <= load_len){
memcpy(&output->size, load_buffer + load_pos, sizeof(output->size));
load_pos += sizeof(output->size);
}
if((output->size + load_pos) <= load_len){
output->data = string((char*)(load_buffer + load_pos), output->size);
load_pos += output->size;
}
}
template<class Type> void LoadData(Type& output){
LoadData(&output);
}
template<class Type> void LoadData(Type* output, int32 array_size){
if(array_size<=1){
LoadData(output);
}
else{
for(int32 i=0;i<array_size;i++)
LoadData(&output[i]);
}
}
template<class Type> void LoadData(Type* output){
if((sizeof(Type) + load_pos) <= load_len){
memcpy(output, load_buffer + load_pos, sizeof(Type));
load_pos += sizeof(Type);
}
}
template<class Type> void LoadData(Type& output, int32 array_size){
LoadData(&output, array_size);
}
void LoadSkip(int8 bytes){
load_pos += bytes;
}
template<class Type> void LoadSkip(Type& skip){
LoadSkip(&skip);
}
template<class Type> void LoadSkip(Type* skip){
load_pos += sizeof(Type);
}
template<class Type> void GetData(Type* output){
if((sizeof(Type) + get_pos) <= get_len){
*output = (Type*)get_buffer;
get_pos += sizeof(output);
}
}
void AddZeros(int16 num){
int8* data = new int8[num];
memset(data, 0, num);
AddData(*data);
safe_delete_array(data);
}
template<class Type> void StructAddData(Type input, int16 size, string* datastring){
if(datastring)
datastring->append((char*)&input, size);
else
buffer.append((char*)&input, size);
}
template<class Type> void StructAddData(Type input, int32 array_size, int16 size, string* datastring){
if(array_size>0){
for(int32 i=0;i<array_size;i++)
StructAddData(input[i], size, datastring);
}
else
StructAddData(input, size, datastring);
}
template<class Type> void AddData(Type input, string* datastring = 0){
if(!datastring)
datastring = &buffer;
datastring->append((char*)&input, sizeof(input));
}
template<class Type> void AddData(Type input, int32 array_size, string* datastring = 0){
if(array_size>0){
for(int32 i=0;i<array_size;i++)
AddData(input[i], datastring);
}
else
AddData(input, datastring);
}
template<class String> void AddDataString(String* input, string* datastring = 0){
AddDataString(*input, datastring);
}
template<class String> void AddDataString(String input, string* datastring = 0){
input.size = input.data.length();
if(!datastring)
datastring = &buffer;
datastring->append((char*)&input.size, sizeof(input.size));
datastring->append(input.data);
}
void AddCharArray(char* array, string* datastring = 0){
if(!datastring)
datastring = &buffer;
datastring->append(array);
}
void AddCharArray(char* array, int16 size, string* datastring = 0){
if(!datastring)
datastring = &buffer;
datastring->append(array, size);
}
void AddData(string data, string* datastring = 0){
if(!datastring)
datastring = &buffer;
datastring->append(data);
}
void Clear() { buffer.clear(); }
private:
string buffer;
uchar* get_buffer;
uchar* load_buffer;
int32 get_len;
int32 get_pos;
int32 load_len;
int32 load_pos;
};
#endif

422
old/DatabaseNew.cpp Normal file
View File

@ -0,0 +1,422 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "Log.h"
#include "DatabaseNew.h"
#include <errmsg.h>
//increase this if large queries are being run frequently to make less calls to malloc()
#define QUERY_INITIAL_SIZE 512
#if defined WORLD
#define DB_INI "world_db.ini"
#elif defined LOGIN
#define DB_INI "login_db.ini"
#elif defined PARSER
#define DB_INI "parser_db.ini"
#endif
DatabaseNew::DatabaseNew() {
mysql_init(&mysql);
int timeout = 10;
mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
MMysql.SetName("DatabaseNew::mysql");
}
DatabaseNew::~DatabaseNew() {
mysql_close(&mysql);
#if MYSQL_VERSION_ID >= 50003
mysql_library_end();
#else
mysql_server_end();
#endif
}
bool DatabaseNew::Connect() {
char line[256], *key, *val;
char host[256], user[64], password[64], database[64], port[64];
bool found_section = false;
FILE *f;
if ((f = fopen(DB_INI, "r")) == NULL) {
LogWrite(DATABASE__ERROR, 0, "Database", "Unable to read %s\n", DB_INI);
return false;
}
memset(host, 0, sizeof(host));
memset(user, 0, sizeof(user));
memset(password, 0, sizeof(password));
memset(database, 0, sizeof(database));
memset(port, 0, sizeof(port));
while (fgets(line, sizeof(line), f) != NULL) {
if (line[0] == '#' || line[0] == '\n' || line[0] == '\r')
continue;
if (!found_section) {
if (strncasecmp(line, "[Database]", 10) == 0)
found_section = true;
}
else {
if ((key = strtok(line, "=")) != NULL) {
if ((val = strtok(NULL, "\r\n")) != NULL) {
if (strncasecmp(line, "host", 4) == 0)
strncpy(host, val, sizeof(host) - 1);
else if (strncasecmp(line, "user", 4) == 0)
strncpy(user, val, sizeof(user) - 1);
else if (strncasecmp(line, "password", 8) == 0)
strncpy(password, val, sizeof(password) - 1);
else if (strncasecmp(line, "database", 8) == 0)
strncpy(database, val, sizeof(database) - 1);
else if (strncasecmp(line, "port", 4) == 0)
strncpy(port, val, sizeof(port) - 1);
}
}
}
}
fclose(f);
if (host[0] == '\0') {
LogWrite(DATABASE__ERROR, 0, "Database", "Unknown 'host' in '%s'\n", DB_INI);
return false;
}
if (user[0] == '\0') {
LogWrite(DATABASE__ERROR, 0, "Database", "Unknown 'user' in '%s'\n", DB_INI);
return false;
}
if (password[0] == '\0') {
LogWrite(DATABASE__ERROR, 0, "Database", "Unknown 'password' in '%s'\n", DB_INI);
return false;
}
if (database[0] == '\0') {
LogWrite(DATABASE__ERROR, 0, "Database", "Unknown 'database' in '%s'\n", DB_INI);
return false;
}
unsigned int portnum = atoul(port);
return Connect(host, user, password, database, portnum);
}
bool DatabaseNew::Connect(const char *host, const char *user, const char *password, const char *database, unsigned int port) {
if (mysql_real_connect(&mysql, host, user, password, database, port, NULL, 0) == NULL) {
LogWrite(DATABASE__ERROR, 0, "Database", "Unable to connect to MySQL server at %s:%u: %s\n", host, port, mysql_error(&mysql));
return false;
}
return true;
}
bool DatabaseNew::Query(const char *query, ...) {
char *buf;
size_t size = QUERY_INITIAL_SIZE;
int num_chars;
va_list args;
bool ret = true;
MMysql.writelock(__FUNCTION__, __LINE__);
while (true) {
if ((buf = (char *)malloc(size)) == NULL) {
LogWrite(DATABASE__ERROR, 0, "Database", "Out of memory trying to allocate database query of %u bytes\n", size);
MMysql.releasewritelock(__FUNCTION__, __LINE__);
return false;
}
va_start(args, query);
num_chars = vsnprintf(buf, size, query, args);
va_end(args);
if (num_chars > -1 && (size_t)num_chars < size)
break;
if (num_chars > -1)
size = num_chars + 1;
else
size *= 2;
free(buf);
}
if (mysql_real_query(&mysql, buf, num_chars) != 0) {
if (mysql_errno(&mysql) == CR_SERVER_LOST || mysql_errno(&mysql) == CR_SERVER_GONE_ERROR) {
LogWrite(DATABASE__ERROR, 0, "Database", "Lost connection, attempting to recover and retry query...");
Connect();
// retry attempt of previous query (1 try and we give up)
if (mysql_real_query(&mysql, buf, num_chars) != 0) {
ret = false;
}
}
else if (!IsIgnoredErrno(mysql_errno(&mysql))) {
LogWrite(DATABASE__ERROR, 0, "Database", "Error %i running MySQL query: %s\n%s\n", mysql_errno(&mysql), mysql_error(&mysql), buf);
ret = false;
}
}
free(buf);
MMysql.releasewritelock(__FUNCTION__, __LINE__);
return ret;
}
bool DatabaseNew::Select(DatabaseResult *result, const char *query, ...) {
char *buf;
size_t size = QUERY_INITIAL_SIZE;
int num_chars;
va_list args;
MYSQL_RES *res;
bool ret = true;
MMysql.writelock(__FUNCTION__, __LINE__);
while (true) {
if ((buf = (char *)malloc(size)) == NULL) {
LogWrite(DATABASE__ERROR, 0, "Database", "Out of memory trying to allocate database query of %u bytes\n", size);
MMysql.releasewritelock(__FUNCTION__, __LINE__);
return false;
}
va_start(args, query);
num_chars = vsnprintf(buf, size, query, args);
va_end(args);
if (num_chars > -1 && (size_t)num_chars < size)
break;
if (num_chars > -1)
size = num_chars + 1;
else
size *= 2;
free(buf);
}
if (mysql_real_query(&mysql, buf, (unsigned long)num_chars) != 0) {
if (mysql_errno(&mysql) == CR_SERVER_LOST || mysql_errno(&mysql) == CR_SERVER_GONE_ERROR) {
LogWrite(DATABASE__ERROR, 0, "Database", "Lost connection, attempting to recover and retry query...");
mysql_close(&mysql);
Connect();
// retry attempt of previous query (1 try and we give up)
if (mysql_real_query(&mysql, buf, (unsigned long)num_chars) != 0) {
ret = false;
}
}
else if (!IsIgnoredErrno(mysql_errno(&mysql))) {
LogWrite(DATABASE__ERROR, 0, "Database", "Error %i running MySQL query: %s\n%s\n", mysql_errno(&mysql), mysql_error(&mysql), buf);
ret = false;
}
}
if (ret && !IsIgnoredErrno(mysql_errno(&mysql))) {
res = mysql_store_result(&mysql);
if (res != NULL)
{
// Grab number of rows and number of fields from the query
uint8 num_rows = mysql_affected_rows(&mysql);
uint8 num_fields = mysql_field_count(&mysql);
ret = result->StoreResult(res, num_fields, num_rows);
}
else {
LogWrite(DATABASE__ERROR, 0, "Database", "Error storing MySql query result (%d): %s\n%s", mysql_errno(&mysql), mysql_error(&mysql), buf);
ret = false;
}
}
free(buf);
MMysql.releasewritelock(__FUNCTION__, __LINE__);
return ret;
}
int32 DatabaseNew::LastInsertID()
{
return (int32)mysql_insert_id(&mysql);
}
long DatabaseNew::AffectedRows()
{
return mysql_affected_rows(&mysql);
}
char * DatabaseNew::Escape(const char *str, size_t len) {
char *buf = (char *)malloc(len * 2 + 1);
if (buf == NULL) {
LogWrite(DATABASE__ERROR, 0, "Database", "Out of memory trying to allocate %u bytes in %s:%u\n", len * 2 + 1, __FUNCTION__, __LINE__);
return NULL;
}
mysql_real_escape_string(&mysql, buf, str, len);
return buf;
}
char * DatabaseNew::Escape(const char *str) {
return Escape(str, strlen(str));
}
string DatabaseNew::EscapeStr(const char *str, size_t len) {
char *buf = (char *)malloc(len * 2 + 1);
string ret;
if (buf == NULL) {
LogWrite(DATABASE__ERROR, 0, "Database", "Out of memory trying to allocate %u bytes in %s:%u\n", len * 2 + 1, __FUNCTION__, __LINE__);
return NULL;
}
mysql_real_escape_string(&mysql, buf, str, len);
ret.append(buf);
free(buf);
return ret;
}
string DatabaseNew::EscapeStr(const char *str) {
return EscapeStr(str, strlen(str));
}
string DatabaseNew::EscapeStr(string str) {
return EscapeStr(str.c_str(), str.length());
}
bool DatabaseNew::QueriesFromFile(const char * file) {
bool success = true;
long size;
char *buf;
int ret;
MYSQL_RES *res;
FILE *f;
f = fopen(file, "rb");
if (f == NULL) {
LogWrite(DATABASE__ERROR, 0, "Database", "Unable to open '%s' for reading: %s", file, strerror(errno));
return false;
}
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
buf = (char *)malloc(size + 1);
if (buf == NULL) {
fclose(f);
LogWrite(DATABASE__ERROR, 0, "Database", "Out of memory trying to allocate %u bytes in %s:%u\n", size + 1, __FUNCTION__, __LINE__);
return false;
}
if (fread(buf, sizeof(*buf), size, f) != (size_t)size) {
LogWrite(DATABASE__ERROR, 0, "Database", "Failed to read from '%s': %s", file, strerror(errno));
fclose(f);
free(buf);
return false;
}
buf[size] = '\0';
fclose(f);
mysql_set_server_option(&mysql, MYSQL_OPTION_MULTI_STATEMENTS_ON);
ret = mysql_real_query(&mysql, buf, size);
free(buf);
if (ret != 0) {
LogWrite(DATABASE__ERROR, 0, "Database", "Error running MySQL queries from file '%s' (%d): %s", file, mysql_errno(&mysql), mysql_error(&mysql));
success = false;
}
else {
//all results must be processed
do {
res = mysql_store_result(&mysql);
if (res != NULL)
mysql_free_result(res);
ret = mysql_next_result(&mysql);
if (ret > 0) {
LogWrite(DATABASE__ERROR, 0, "Database", "Error running MySQL queries from file '%s' (%d): %s", file, mysql_errno(&mysql), mysql_error(&mysql));
success = false;
}
} while (ret == 0);
}
mysql_set_server_option(&mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF);
return success;
}
void DatabaseNew::SetIgnoredErrno(unsigned int db_errno) {
vector<unsigned int>::iterator itr;
for (itr = ignored_errnos.begin(); itr != ignored_errnos.end(); itr++) {
if ((*itr) == db_errno)
return;
}
ignored_errnos.push_back(db_errno);
}
void DatabaseNew::RemoveIgnoredErrno(unsigned int db_errno) {
vector<unsigned int>::iterator itr;
for (itr = ignored_errnos.begin(); itr != ignored_errnos.end(); itr++) {
if ((*itr) == db_errno) {
ignored_errnos.erase(itr);
break;
}
}
}
bool DatabaseNew::IsIgnoredErrno(unsigned int db_errno) {
vector<unsigned int>::iterator itr;
for (itr = ignored_errnos.begin(); itr != ignored_errnos.end(); itr++) {
if ((*itr) == db_errno)
return true;
}
return false;
}
// Sends the MySQL server a keepalive
void DatabaseNew::PingNewDB() {
MMysql.writelock(__FUNCTION__, __LINE__);
mysql_ping(&mysql);
int32* errnum = new int32;
*errnum = mysql_errno(&mysql);
switch (*errnum)
{
case CR_COMMANDS_OUT_OF_SYNC:
case CR_SERVER_GONE_ERROR:
case CR_UNKNOWN_ERROR:
{
LogWrite(DATABASE__ERROR, 0, "Database", "[Database] We lost connection to the database., errno: %i", errno);
break;
}
}
safe_delete(errnum);
MMysql.releasewritelock(__FUNCTION__, __LINE__);
}

48
old/DatabaseNew.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef COMMON_DATABASE_H_
#define COMMON_DATABASE_H_
#include <string>
#include "DatabaseResult.h"
using namespace std;
class DatabaseNew {
public:
DatabaseNew();
virtual ~DatabaseNew();
unsigned int GetError() {return mysql_errno(&mysql);}
const char * GetErrorMsg() {return mysql_error(&mysql);}
bool Connect();
bool Connect(const char *host, const char *user, const char *password, const char *database, unsigned int port = 3306);
bool Query(const char *query, ...);
bool Select(DatabaseResult *result, const char *query, ...);
int32 LastInsertID();
long AffectedRows();
//these two must free() the return char* after it's used in a query
char * Escape(const char *str, size_t len);
char * Escape(const char *str);
//does not need free()
string EscapeStr(const char *str, size_t len);
string EscapeStr(const char *str);
string EscapeStr(string str);
bool QueriesFromFile(const char *file);
void SetIgnoredErrno(unsigned int db_errno);
void RemoveIgnoredErrno(unsigned int db_errno);
bool IsIgnoredErrno(unsigned int db_errno);
void PingNewDB();
private:
MYSQL mysql;
Mutex MMysql;
vector<unsigned int> ignored_errnos;
};
#endif

234
old/DatabaseResult.cpp Normal file
View File

@ -0,0 +1,234 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <string.h>
#include "Log.h"
#include "DatabaseResult.h"
//enforced by MySQL...couldn't find a #define in their headers though
#define FIELD_NAME_MAX 64
//return this instead of NULL for certain functions to prevent crashes from coding errors
static const char *empty_str = "";
DatabaseResult::DatabaseResult(): field_map(), result(0), num_fields(0), row(0) {
}
DatabaseResult::~DatabaseResult() {
unsigned int i;
if (result != NULL)
mysql_free_result(result);
if (field_map.size()) {
field_map.clear();
}
}
bool DatabaseResult::StoreResult(MYSQL_RES* res, uint8 field_count, uint8 row_count) {
//clear any previously stored result
if (result != NULL)
mysql_free_result(result);
//clear any field names from a previous result
if (field_map.size()) {
field_map.clear();
}
result = res;
num_rows = row_count;
num_fields = field_count;
// No rows or fields then we don't care
if (!num_rows || !num_fields) {
mysql_free_result(res);
result = NULL;
return false;
}
const MYSQL_FIELD* fields = mysql_fetch_fields(result);
for (uint8 i = 0; i < num_fields; ++i) {
field_map.emplace(std::make_pair(std::string_view(fields[i].name), i));
}
return true;
}
const char * DatabaseResult::GetFieldValue(unsigned int index) {
if (index >= num_fields) {
LogWrite(DATABASE__ERROR, 0, "Database Result", "Attempt to access field at index %u but there %s only %u field%s", index, num_fields == 1 ? "is" : "are", num_fields, num_fields == 1 ? "" : "s");
return NULL;
}
return row[index];
}
const char * DatabaseResult::GetFieldValueStr(const char *field_name) {
const auto& map_iterator = field_map.find(std::string_view(field_name));
if (map_iterator != field_map.end()) {
return row[map_iterator->second];
}
LogWrite(DATABASE__ERROR, 0, "Database Result", "Unknown field name '%s'", field_name);
return NULL;
}
bool DatabaseResult::Next() {
return (result != NULL && (row = mysql_fetch_row(result)) != NULL);
}
bool DatabaseResult::IsNull(unsigned int index) {
const char *value = GetFieldValue(index);
return value == NULL;
}
bool DatabaseResult::IsNullStr(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
return value == NULL;
}
int8 DatabaseResult::GetInt8(unsigned int index) {
const char *value = GetFieldValue(index);
return value == NULL ? 0 : atoi(value);
}
int8 DatabaseResult::GetInt8Str(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
return value == NULL ? 0 : atoi(value);
}
sint8 DatabaseResult::GetSInt8(unsigned int index) {
const char *value = GetFieldValue(index);
return value == NULL ? 0 : atoi(value);
}
sint8 DatabaseResult::GetSInt8Str(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
return value == NULL ? 0 : atoi(value);
}
int16 DatabaseResult::GetInt16(unsigned int index) {
const char *value = GetFieldValue(index);
return value == NULL ? 0 : atoi(value);
}
int16 DatabaseResult::GetInt16Str(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
return value == NULL ? 0 : atoi(value);
}
sint16 DatabaseResult::GetSInt16(unsigned int index) {
const char *value = GetFieldValue(index);
return value == NULL ? 0 : atoi(value);
}
sint16 DatabaseResult::GetSInt16Str(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
return value == NULL ? 0 : atoi(value);
}
int32 DatabaseResult::GetInt32(unsigned int index) {
const char *value = GetFieldValue(index);
return value == NULL ? 0U : strtoul(value, NULL, 10);
}
int32 DatabaseResult::GetInt32Str(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
return value == NULL ? 0U : strtoul(value, NULL, 10);
}
sint32 DatabaseResult::GetSInt32(unsigned int index) {
const char *value = GetFieldValue(index);
return value == NULL ? 0 : atoi(value);
}
sint32 DatabaseResult::GetSInt32Str(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
return value == NULL ? 0 : atoi(value);
}
uint64 DatabaseResult::GetInt64(unsigned int index) {
const char *value = GetFieldValue(index);
#ifdef _WIN32
return value == NULL ? 0UL : _strtoui64(value, NULL, 10);
#else
return value == NULL ? 0UL : strtoull(value, NULL, 10);
#endif
}
uint64 DatabaseResult::GetInt64Str(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
#ifdef _WIN32
return value == NULL ? 0UL : _strtoui64(value, NULL, 10);
#else
return value == NULL ? 0UL : strtoull(value, NULL, 10);
#endif
}
sint64 DatabaseResult::GetSInt64(unsigned int index) {
const char *value = GetFieldValue(index);
#ifdef _WIN32
return value == NULL ? 0L : _strtoi64(value, NULL, 10);
#else
return value == NULL ? 0L : strtoll(value, NULL, 10);
#endif
}
sint64 DatabaseResult::GetSInt64Str(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
#ifdef _WIN32
return value == NULL ? 0L : _strtoi64(value, NULL, 10);
#else
return value == NULL ? 0L : strtoll(value, NULL, 10);
#endif
}
float DatabaseResult::GetFloat(unsigned int index) {
const char *value = GetFieldValue(index);
return value == NULL ? 0.0F : atof(value);
}
float DatabaseResult::GetFloatStr(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
return value == NULL ? 0.0F : atof(value);
}
char DatabaseResult::GetChar(unsigned int index) {
const char *value = GetFieldValue(index);
return value == NULL ? '\0' : value[0];
}
char DatabaseResult::GetCharStr(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
return value == NULL ? '\0' : value[0];
}
const char * DatabaseResult::GetString(unsigned int index) {
const char *value = GetFieldValue(index);
return value == NULL ? empty_str : value;
}
const char * DatabaseResult::GetStringStr(const char *field_name) {
const char *value = GetFieldValueStr(field_name);
return value == NULL ? empty_str : value;
}

57
old/DatabaseResult.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef COMMON_DATABASERESULT_H_
#define COMMON_DATABASERESULT_H_
#include "types.h"
#ifdef _WIN32
#include <WinSock2.h> //#include <my_global.h> when we/if we go to winsock2 :/
#endif
#include <mysql.h>
#include <map>
class DatabaseResult {
public:
DatabaseResult();
virtual ~DatabaseResult();
bool StoreResult(MYSQL_RES* result, uint8 field_count, uint8 row_count);
bool Next();
bool IsNull(unsigned int index);
bool IsNullStr(const char *field_name);
int8 GetInt8(unsigned int index);
int8 GetInt8Str(const char *field_name);
sint8 GetSInt8(unsigned int index);
sint8 GetSInt8Str(const char *field_name);
int16 GetInt16(unsigned int index);
int16 GetInt16Str(const char *field_name);
sint16 GetSInt16(unsigned int index);
sint16 GetSInt16Str(const char *field_name);
int32 GetInt32(unsigned int index);
int32 GetInt32Str(const char *field_name);
sint32 GetSInt32(unsigned int index);
sint32 GetSInt32Str(const char *field_name);
int64 GetInt64(unsigned int index);
int64 GetInt64Str(const char *field_name);
sint64 GetSInt64(unsigned int index);
sint64 GetSInt64Str(const char *field_name);
float GetFloat(unsigned int index);
float GetFloatStr(const char *field_name);
char GetChar(unsigned int index);
char GetCharStr(const char *field_name);
const char * GetString(unsigned int index);
const char * GetStringStr(const char *field_name);
const unsigned int GetNumRows() { return num_rows; }
const char * GetFieldValue(unsigned int index);
const char * GetFieldValueStr(const char *field_name);
private:
MYSQL_RES *result;
MYSQL_ROW row;
unsigned int num_rows;
unsigned int num_fields;
std::map<std::string_view,uint8> field_map;
};
#endif

361
old/EQ2_Common_Structs.h Normal file
View File

@ -0,0 +1,361 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _EQ2COMMON_STRUCTS_
#define _EQ2COMMON_STRUCTS_
#define SPAWN_PACKET_SIZE 895
#define EQUIPMENT_L_WEAPON_INDEX 0 //chars left hand weapon
#define EQUIPMENT_R_WEAPON_INDEX 1 //chars right hand weapon
#define EQUIPMENT_HELMET 2
#pragma pack(1)
struct KeyGen_Struct{
int32 size;
};
struct KeyGen_End_Struct{
int32 exponent_len;
int8 exponent;
};
struct LoginByNumRequest_Struct{
int32 account_id;
int32 access_code;
int16 version;
int32 unknown2[5];
};
struct LS_LoginResponse{
int8 reply_code; // 0 granted, 1 denied
int16 unknown01;
int8 unknown02;
sint32 unknown03; // -1 denied, 0 granted
sint32 unknown04;
sint32 unknown05;
sint32 unknown06;
int8 unknown07;
int8 unknown08;
int8 unknown09;
int8 unknown10;
sint32 unknown11;
int32 accountid;
int16 unknown12;
};
#pragma pack()
enum EQ2_EquipmentSlot {
slot_primary=0,
slot_secondary=1,
slot_head=2,
slot_chest=3,
slot_shoulders=4,
slot_forearms=5,
slot_hands=6,
slot_legs=7,
slot_feet=8,
slot_left_ring=9,
slot_right_ring=10,
slot_ears=11,
slot_neck=12,
slot_left_wrist=13,
slot_right_wrist=14,
slot_ranged=15,
slot_ammo=16,
slot_waist=17,
slot_activate1=18,
slot_activate2=19,
slot_textures=20,
slot_hair=21,
slot_beard=22,
slot_naked_chest=23,
slot_naked_legs=24
};
struct EQ2_EquipmentItem{
int16 type;
EQ2_Color color;
EQ2_Color highlight;
};
struct EQ2_Equipment{
int16 equip_id[25];
EQ2_Color color[25];
EQ2_Color highlight[25];
};
#pragma pack(1)
struct CharFeatures{
int16 hair_type;
int16 hair_face_type;
int16 wing_type;
int16 chest_type;
int16 legs_type;
sint8 eye_type[3];
sint8 ear_type[3];
sint8 eye_brow_type[3];
sint8 cheek_type[3];
sint8 lip_type[3];
sint8 chin_type[3];
sint8 nose_type[3];
sint8 body_size;
sint8 body_age;
sint8 soga_eye_type[3];
sint8 soga_ear_type[3];
sint8 soga_eye_brow_type[3];
sint8 soga_cheek_type[3];
int16 soga_chest_type;
int16 soga_legs_type;
sint8 soga_lip_type[3];
sint8 soga_chin_type[3];
sint8 soga_nose_type[3];
sint8 soga_body_size;
sint8 soga_body_age;
int16 soga_hair_type;
int16 soga_hair_face_type;
int16 combat_voice;
int16 emote_voice;
int16 mount_model_type;
EQ2_Color mount_saddle_color;
EQ2_Color mount_color;
EQ2_Color skin_color;
EQ2_Color eye_color;
EQ2_Color hair_type_color;
EQ2_Color hair_type_highlight_color;
EQ2_Color hair_face_color;
EQ2_Color hair_face_highlight_color;
EQ2_Color hair_highlight_color;
EQ2_Color wing_color1;
EQ2_Color wing_color2;
EQ2_Color shirt_color;
EQ2_Color pants_color;
EQ2_Color hair_color1;
EQ2_Color hair_color2;
EQ2_Color soga_skin_color;
EQ2_Color soga_eye_color;
EQ2_Color soga_hair_color1;
EQ2_Color soga_hair_color2;
EQ2_Color soga_hair_type_color;
EQ2_Color soga_hair_type_highlight_color;
EQ2_Color soga_hair_face_color;
EQ2_Color soga_hair_face_highlight_color;
EQ2_Color soga_hair_highlight_color;
EQ2_Color model_color;
EQ2_Color soga_model_color;
};
struct PositionData{
int32 grid_id;
int32 bad_grid_id;
sint8 Speed1;
sint8 Speed2;
sint16 Dir1;
sint16 Dir2;
sint16 Pitch1;
sint16 Pitch2;
sint16 Roll;
float X;
float Y;
float Z;
float X2;
float Y2;
float Z2;
float X3;
float Y3;
float Z3;
float SpawnOrigX;
float SpawnOrigY;
float SpawnOrigZ;
float SpawnOrigHeading;
float SpawnOrigPitch;
float SpawnOrigRoll;
float SpeedX;
float SpeedY;
float SpeedZ;
float SideSpeed;
float VertSpeed;
float ClientHeading1;
float ClientHeading2;
float ClientPitch;
int16 collision_radius;
int16 state;
};
struct AppearanceData {
PositionData pos;
int16 model_type;
int16 soga_model_type;
int16 activity_status;
int16 visual_state;
int16 action_state;
int16 mood_state;
int16 emote_state;
int8 attackable;
int8 icon;
int8 hide_hood;
int8 show_level;
int8 locked_no_loot;
int8 quest_flag;
int8 heroic_flag;
int8 show_command_icon;
int8 display_hand_icon;
int8 player_flag;
int8 targetable;
int8 display_name;
char sub_title[255]; //Guild
int32 display_hp;//0 = 100 percent
int32 power_left; //bar not shown if >=100
int8 adventure_class;
int8 tradeskill_class;
int8 level;
int8 tradeskill_level;
int8 min_level;
int8 max_level;
int8 difficulty;
int16 visible; // 02 = normal, 15 = shadow
char name[128]; //size around here somewhere
char last_name[64];
char prefix_title[128];
char suffix_title[128];
int8 race;
int8 gender;
int32 randomize;
int8 lua_race_id;
};
struct Player_Update{
/*0000*/ int32 activity;
/*0004*/ float unknown2; // 1
/*0008*/ float direction1;
/*0012*/ float unknown3[8];
/*0044*/ float speed;
/*0048*/ float side_speed;
/*0052*/ float vert_speed;
/*0056*/ float orig_x;
/*0060*/ float orig_y;
/*0064*/ float orig_z;
/*0068*/ float orig_x2;
/*0072*/ float orig_y2;
/*0076*/ float orig_z2;
/*0080*/ float unknown5[3];
/*0092*/ int32 unknown6;
/*0096*/ float unknown7[3];
/*0108*/ int32 unknown8;
/*0112*/ int32 grid_location;
/*0116*/ float x;
/*0120*/ float y;
/*0124*/ float z;
/*0128*/ float direction2;
/*0132*/ float pitch;
/*0136*/ float unknown10;
/*0140*/ float speed_x;
/*0144*/ float speed_y;
/*0148*/ float speed_z;
};
struct Player_Update283 {
/*0000*/ int32 activity;
/*0004*/ int32 movement_mode; // 1
/*0008*/ float direction1;
/*0012*/ float desiredpitch;
/*0016*/ float desired_heading_speed;
/*0020*/ float desired_pitch_speed;
/*0024*/ float collision_radius;
/*0028*/ float collision_scale;
/*0032*/ float temp_scale;
/*0036*/ float speed_modifier;
/*0040*/ float swim_speed_modifier;
/*0044*/ float speed;
/*0048*/ float side_speed;
/*0052*/ float vert_speed;
/*0056*/ float orig_x;
/*0060*/ float orig_y;
/*0064*/ float orig_z;
/*0068*/ float orig_x2;
/*0072*/ float orig_y2;
/*0076*/ float orig_z2;
/*0080*/ int32 face_actor_id;
/*0084*/ int32 face_actor_range;
/*0088*/ int32 grid_location;
/*0092*/ float x;
/*0096*/ float y;
/*0100*/ float z;
/*0104*/ float direction2;
/*0108*/ float pitch;
/*0112*/ float roll;
/*0116*/ float speed_x;
/*0120*/ float speed_y;
/*0124*/ float speed_z;
};//0128
struct Player_Update1096{
/*0000*/ int32 activity;
/*0004*/ float unknown2; // 1
/*0008*/ float direction1;
/*0012*/ float unknown3[8];
/*0044*/ float unk_speed;
/*0048*/ float speed;
/*0052*/ float side_speed;
/*0056*/ float vert_speed;
/*0060*/ float orig_x;
/*0064*/ float orig_y;
/*0068*/ float orig_z;
/*0072*/ float orig_x2;
/*0076*/ float orig_y2;
/*0080*/ float orig_z2;
/*0092*/ float unknown5[3];
/*0096*/ int32 unknown6;
/*0108*/ float unknown7[3];
/*0112*/ int32 unknown8;
/*0116*/ int32 grid_location;
/*0120*/ float x;
/*0124*/ float y;
/*0128*/ float z;
/*0132*/ float direction2;
/*0136*/ float pitch;
/*0140*/ float unknown10;
/*0144*/ float speed_x;
/*0148*/ float speed_y;
/*0152*/ float speed_z;
};
struct Player_Update1144{
/*0000*/ int32 activity;
/*0004*/ float unknown2; // 1
/*0008*/ float direction1;
/*0012*/ float unknown3[12];
/*0044*/ float unk_speed;
/*0048*/ float speed;
/*0052*/ float side_speed;
/*0056*/ float vert_speed;
/*0060*/ float orig_x;
/*0064*/ float orig_y;
/*0068*/ float orig_z;
/*0072*/ float orig_x2;
/*0076*/ float orig_y2;
/*0080*/ float orig_z2;
/*0092*/ float unknown5[3];
/*0096*/ int32 unknown6;
/*0108*/ float unknown7[3];
/*0112*/ int32 unknown8;
/*0116*/ int32 grid_location;
/*0120*/ float x;
/*0124*/ float y;
/*0128*/ float z;
/*0132*/ float direction2;
/*0136*/ float pitch;
/*0140*/ float unknown10;
/*0144*/ float speed_x;
/*0148*/ float speed_y;
/*0152*/ float speed_z;
};
#pragma pack()
#endif

131
old/EQEMuError.cpp Normal file
View File

@ -0,0 +1,131 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef WIN32
#include <WinSock2.h>
#include <windows.h>
#endif
#include "EQEMuError.h"
#include "linked_list.h"
#include "Mutex.h"
#include "MiscFunctions.h"
#include <stdio.h>
#include <string.h>
#ifdef WIN32
#include <conio.h>
#endif
void CatchSignal(int sig_num);
const char* EQEMuErrorText[EQEMuError_MaxErrorID] = { "ErrorID# 0, No Error",
"MySQL Error #1405 or #2001 means your mysql server rejected the username and password you presented it.",
"MySQL Error #2003 means you were unable to connect to the mysql server.",
"MySQL Error #2005 means you there are too many connections on the mysql server. The server is overloaded.",
"MySQL Error #2007 means you the server is out of memory. The server is overloaded.",
};
LinkedList<char*>* EQEMuErrorList;
Mutex* MEQEMuErrorList;
AutoDelete< LinkedList<char*> > ADEQEMuErrorList(&EQEMuErrorList);
AutoDelete<Mutex> ADMEQEMuErrorList(&MEQEMuErrorList);
const char* GetErrorText(int32 iError) {
if (iError >= EQEMuError_MaxErrorID)
return "ErrorID# out of range";
else
return EQEMuErrorText[iError];
}
void AddEQEMuError(eEQEMuError iError, bool iExitNow) {
if (!iError)
return;
if (!EQEMuErrorList) {
EQEMuErrorList = new LinkedList<char*>;
MEQEMuErrorList = new Mutex;
}
LockMutex lock(MEQEMuErrorList);
LinkedListIterator<char*> iterator(*EQEMuErrorList);
iterator.Reset();
while (iterator.MoreElements()) {
if (iterator.GetData()[0] == 1) {
if (*((eEQEMuError*) &(iterator.GetData()[1])) == iError)
return;
}
iterator.Advance();
}
char* tmp = new char[6];
tmp[0] = 1;
tmp[5] = 0;
*((int32*) &tmp[1]) = iError;
EQEMuErrorList->Append(tmp);
if (iExitNow)
CatchSignal(2);
}
void AddEQEMuError(char* iError, bool iExitNow) {
if (!iError)
return;
if (!EQEMuErrorList) {
EQEMuErrorList = new LinkedList<char*>;
MEQEMuErrorList = new Mutex;
}
LockMutex lock(MEQEMuErrorList);
char* tmp = strcpy(new char[strlen(iError) + 1], iError);
EQEMuErrorList->Append(tmp);
if (iExitNow)
CatchSignal(2);
}
int32 CheckEQEMuError() {
if (!EQEMuErrorList)
return 0;
int32 ret = 0;
char* tmp = 0;
bool HeaderPrinted = false;
LockMutex lock(MEQEMuErrorList);
while ((tmp = EQEMuErrorList->Pop() )) {
if (!HeaderPrinted) {
fprintf(stdout, "===============================\nRuntime errors:\n\n");
HeaderPrinted = true;
}
if (tmp[0] == 1) {
fprintf(stdout, "%s\n", GetErrorText(*((int32*) &tmp[1])));
}
else {
fprintf(stdout, "%s\n\n", tmp);
}
safe_delete(tmp);
ret++;
}
return ret;
}
void CheckEQEMuErrorAndPause() {
if (CheckEQEMuError()) {
fprintf(stdout, "Hit any key to exit\n");
getchar();
}
}

39
old/EQEMuError.h Normal file
View File

@ -0,0 +1,39 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EQEMuError_H
#define EQEMuError_H
#include "../common/types.h"
enum eEQEMuError { EQEMuError_NoError,
EQEMuError_Mysql_1405,
EQEMuError_Mysql_2003,
EQEMuError_Mysql_2005,
EQEMuError_Mysql_2007,
EQEMuError_MaxErrorID };
void AddEQEMuError(eEQEMuError iError, bool iExitNow = false);
void AddEQEMuError(char* iError, bool iExitNow = false);
int32 CheckEQEMuError();
void CheckEQEMuErrorAndPause();
#endif

661
old/EQPacket.cpp Normal file
View File

@ -0,0 +1,661 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "debug.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>
#include "EQPacket.h"
#include "misc.h"
#include "op_codes.h"
#include "CRC16.h"
#include "opcodemgr.h"
#include "packet_dump.h"
#include <map>
#include "Log.h"
#include <time.h>
using namespace std;
extern map<int16,OpcodeManager*>EQOpcodeManager;
uint8 EQApplicationPacket::default_opcode_size=2;
EQPacket::EQPacket(const uint16 op, const unsigned char *buf, uint32 len)
{
this->opcode=op;
this->pBuffer=NULL;
this->size=0;
version = 0;
setTimeInfo(0,0);
if (len>0) {
this->size=len;
pBuffer= new unsigned char[this->size];
if (buf) {
memcpy(this->pBuffer,buf,this->size);
} else {
memset(this->pBuffer,0,this->size);
}
}
}
const char* EQ2Packet::GetOpcodeName() {
int16 OpcodeVersion = GetOpcodeVersion(version);
if (EQOpcodeManager.count(OpcodeVersion) > 0)
return EQOpcodeManager[OpcodeVersion]->EmuToName(login_op);
else
return NULL;
}
int8 EQ2Packet::PreparePacket(int16 MaxLen) {
int16 OpcodeVersion = GetOpcodeVersion(version);
// stops a crash for incorrect version
if (EQOpcodeManager.count(OpcodeVersion) == 0)
{
LogWrite(PACKET__ERROR, 0, "Packet", "Version %i is not listed in the opcodes table.", version);
return -1;
}
packet_prepared = true;
int16 login_opcode = EQOpcodeManager[OpcodeVersion]->EmuToEQ(login_op);
if (login_opcode == 0xcdcd)
{
LogWrite(PACKET__ERROR, 0, "Packet", "Version %i is not listed in the opcodes table for opcode %s", version, EQOpcodeManager[OpcodeVersion]->EmuToName(login_op));
return -1;
}
int16 orig_opcode = login_opcode;
int8 offset = 0;
//one of the int16s is for the seq, other is for the EQ2 opcode and compressed flag (OP_Packet is the header, not the opcode)
int32 new_size = size + sizeof(int16) + sizeof(int8);
bool oversized = false;
if (login_opcode != 2) {
new_size += sizeof(int8); //for opcode
if (login_opcode >= 255) {
new_size += sizeof(int16);
oversized = true;
}
else
login_opcode = ntohs(login_opcode);
}
uchar* new_buffer = new uchar[new_size];
memset(new_buffer, 0, new_size);
uchar* ptr = new_buffer + sizeof(int16); // sequence is first
if (login_opcode != 2) {
if (oversized) {
ptr += sizeof(int8); //compressed flag
int8 addon = 0xff;
memcpy(ptr, &addon, sizeof(int8));
ptr += sizeof(int8);
}
memcpy(ptr, &login_opcode, sizeof(int16));
ptr += sizeof(int16);
}
else {
memcpy(ptr, &login_opcode, sizeof(int8));
ptr += sizeof(int8);
}
memcpy(ptr, pBuffer, size);
safe_delete_array(pBuffer);
pBuffer = new_buffer;
offset = new_size - size - 1;
size = new_size;
return offset;
}
uint32 EQProtocolPacket::serialize(unsigned char *dest, int8 offset) const
{
if (opcode>0xff) {
*(uint16 *)dest=opcode;
} else {
*(dest)=0;
*(dest+1)=opcode;
}
memcpy(dest+2,pBuffer+offset,size-offset);
return size+2;
}
uint32 EQApplicationPacket::serialize(unsigned char *dest) const
{
uint8 OpCodeBytes = app_opcode_size;
if (app_opcode_size==1)
*(unsigned char *)dest=opcode;
else
{
// Application opcodes with a low order byte of 0x00 require an extra 0x00 byte inserting prior to the opcode.
if ((opcode & 0x00ff) == 0)
{
*(uint8*)dest = 0;
*(uint16*)(dest + 1) = opcode;
++OpCodeBytes;
}
else
*(uint16*)dest = opcode;
}
memcpy(dest+app_opcode_size,pBuffer,size);
return size+ OpCodeBytes;
}
EQPacket::~EQPacket()
{
safe_delete_array(pBuffer);
pBuffer=NULL;
}
void EQPacket::DumpRawHeader(uint16 seq, FILE* to) const
{
/*if (timestamp.tv_sec) {
char temp[20];
tm t;
const time_t sec = timestamp.tv_sec;
localtime_s(&t, &sec);
strftime(temp, 20, "%F %T", &t);
fprintf(to, "%s.%06lu ", temp, timestamp.tv_usec);
}*/
DumpRawHeaderNoTime(seq, to);
}
const char* EQPacket::GetOpcodeName(){
int16 OpcodeVersion = GetOpcodeVersion(version);
if(EQOpcodeManager.count(OpcodeVersion) > 0)
return EQOpcodeManager[OpcodeVersion]->EQToName(opcode);
else
return NULL;
}
void EQPacket::DumpRawHeaderNoTime(uint16 seq, FILE *to) const
{
if (src_ip) {
string sIP,dIP;;
sIP=long2ip(src_ip);
dIP=long2ip(dst_ip);
fprintf(to, "[%s:%d->%s:%d] ",sIP.c_str(),src_port,dIP.c_str(),dst_port);
}
if (seq != 0xffff)
fprintf(to, "[Seq=%u] ",seq);
string name;
int16 OpcodeVersion = GetOpcodeVersion(version);
if(EQOpcodeManager.count(OpcodeVersion) > 0)
name = EQOpcodeManager[OpcodeVersion]->EQToName(opcode);
fprintf(to, "[OpCode 0x%04x (%s) Size=%u]\n",opcode,name.c_str(),size);
}
void EQPacket::DumpRaw(FILE *to) const
{
DumpRawHeader();
if (pBuffer && size)
dump_message_column(pBuffer, size, " ", to);
fprintf(to, "\n");
}
EQProtocolPacket::EQProtocolPacket(const unsigned char *buf, uint32 len, int in_opcode)
{
uint32 offset = 0;
if(in_opcode>=0) {
opcode = in_opcode;
}
else {
// Ensure there are at least 2 bytes for the opcode
if (len < 2 || buf == nullptr) {
// Not enough data to read opcode; set defaults or handle error appropriately
opcode = 0; // or set to a designated invalid opcode
offset = len; // no payload available
} else {
offset = 2;
opcode = ntohs(*(const uint16 *)buf);
}
}
// Check that there is payload data after the header
if (len > offset) {
size = len - offset;
pBuffer = new unsigned char[size];
if(buf)
memcpy(pBuffer, buf + offset, size);
else
memset(pBuffer, 0, size);
} else {
pBuffer = nullptr;
size = 0;
}
version = 0;
eq2_compressed = false;
packet_prepared = false;
packet_encrypted = false;
sent_time = 0;
attempt_count = 0;
sequence = 0;
}
bool EQ2Packet::AppCombine(EQ2Packet* rhs){
bool result = false;
uchar* tmpbuffer = 0;
bool over_sized_packet = false;
int32 new_size = 0;
//bool whee = false;
// DumpPacket(this);
// DumpPacket(rhs);
/*if(rhs->size >= 255){
DumpPacket(this);
DumpPacket(rhs);
whee = true;
}*/
if (opcode==OP_AppCombined && ((size + rhs->size + 3) < 255)){
int16 tmp_size = rhs->size - 2;
if(tmp_size >= 255){
new_size = size+tmp_size+3;
over_sized_packet = true;
}
else
new_size = size+tmp_size+1;
tmpbuffer = new uchar[new_size];
uchar* ptr = tmpbuffer;
memcpy(ptr, pBuffer, size);
ptr += size;
if(over_sized_packet){
memset(ptr, 255, sizeof(int8));
ptr += sizeof(int8);
tmp_size = htons(tmp_size);
memcpy(ptr, &tmp_size, sizeof(int16));
ptr += sizeof(int16);
}
else{
memcpy(ptr, &tmp_size, sizeof(int8));
ptr += sizeof(int8);
}
memcpy(ptr, rhs->pBuffer+2, rhs->size-2);
delete[] pBuffer;
size = new_size;
pBuffer=tmpbuffer;
safe_delete(rhs);
result=true;
}
else if (rhs->size > 2 && size > 2 && (size + rhs->size + 6) < 255) {
int32 tmp_size = size - 2;
int32 tmp_size2 = rhs->size - 2;
opcode=OP_AppCombined;
bool over_sized_packet2 = false;
new_size = size;
if(tmp_size >= 255){
new_size += 5;
over_sized_packet = true;
}
else
new_size += 3;
if(tmp_size2 >= 255){
new_size += tmp_size2+3;
over_sized_packet2 = true;
}
else
new_size += tmp_size2+1;
tmpbuffer = new uchar[new_size];
tmpbuffer[2]=0;
tmpbuffer[3]=0x19;
uchar* ptr = tmpbuffer+4;
if(over_sized_packet){
memset(ptr, 255, sizeof(int8));
ptr += sizeof(int8);
tmp_size = htons(tmp_size);
memcpy(ptr, &tmp_size, sizeof(int16));
ptr += sizeof(int16);
}
else{
memcpy(ptr, &tmp_size, sizeof(int8));
ptr += sizeof(int8);
}
memcpy(ptr, pBuffer+2, size-2);
ptr += (size-2);
if(over_sized_packet2){
memset(ptr, 255, sizeof(int8));
ptr += sizeof(int8);
tmp_size2 = htons(tmp_size2);
memcpy(ptr, &tmp_size2, sizeof(int16));
ptr += sizeof(int16);
}
else{
memcpy(ptr, &tmp_size2, sizeof(int8));
ptr += sizeof(int8);
}
memcpy(ptr, rhs->pBuffer+2, rhs->size-2);
size = new_size;
delete[] pBuffer;
pBuffer=tmpbuffer;
safe_delete(rhs);
result=true;
}
/*if(whee){
DumpPacket(this);
cout << "fsdfsdf";
}*/
//DumpPacket(this);
return result;
}
bool EQProtocolPacket::combine(const EQProtocolPacket *rhs)
{
bool result=false;
//if(dont_combine)
// return false;
//if (opcode==OP_Combined && size+rhs->size+5<256) {
if (opcode == OP_Combined && size + rhs->size + 5 < 256) {
auto tmpbuffer = new unsigned char[size + rhs->size + 3];
memcpy(tmpbuffer, pBuffer, size);
uint32 offset = size;
tmpbuffer[offset++] = rhs->Size();
offset += rhs->serialize(tmpbuffer + offset);
size = offset;
delete[] pBuffer;
pBuffer = tmpbuffer;
result = true;
}
else if (size + rhs->size + 7 < 256) {
auto tmpbuffer = new unsigned char[size + rhs->size + 6];
uint32 offset = 0;
tmpbuffer[offset++] = Size();
offset += serialize(tmpbuffer + offset);
tmpbuffer[offset++] = rhs->Size();
offset += rhs->serialize(tmpbuffer + offset);
size = offset;
delete[] pBuffer;
pBuffer = tmpbuffer;
opcode = OP_Combined;
result = true;
}
return result;
}
EQApplicationPacket::EQApplicationPacket(const unsigned char *buf, uint32 len, uint8 opcode_size)
{
uint32 offset=0;
app_opcode_size=(opcode_size==0) ? EQApplicationPacket::default_opcode_size : opcode_size;
if (app_opcode_size==1) {
opcode=*(const unsigned char *)buf;
offset++;
} else {
opcode=*(const uint16 *)buf;
offset+=2;
}
if ((len-offset)>0) {
pBuffer=new unsigned char[len-offset];
memcpy(pBuffer,buf+offset,len-offset);
size=len-offset;
} else {
pBuffer=NULL;
size=0;
}
emu_opcode = OP_Unknown;
}
bool EQApplicationPacket::combine(const EQApplicationPacket *rhs)
{
cout << "CALLED AP COMBINE!!!!\n";
return false;
}
void EQApplicationPacket::SetOpcode(EmuOpcode emu_op) {
if(emu_op == OP_Unknown) {
opcode = 0;
emu_opcode = OP_Unknown;
return;
}
opcode = EQOpcodeManager[GetOpcodeVersion(version)]->EmuToEQ(emu_op);
if(opcode == OP_Unknown) {
LogWrite(PACKET__DEBUG, 0, "Packet", "Unable to convert Emu opcode %s (%d) into an EQ opcode.", OpcodeNames[emu_op], emu_op);
}
//save the emu opcode we just set.
emu_opcode = emu_op;
}
const EmuOpcode EQApplicationPacket::GetOpcodeConst() const {
if(emu_opcode != OP_Unknown) {
return(emu_opcode);
}
if(opcode == 10000) {
return(OP_Unknown);
}
EmuOpcode emu_op;
emu_op = EQOpcodeManager[GetOpcodeVersion(version)]->EQToEmu(opcode);
if(emu_op == OP_Unknown) {
LogWrite(PACKET__DEBUG, 1, "Packet", "Unable to convert EQ opcode 0x%.4X (%i) to an emu opcode (%s)", opcode, opcode, __FUNCTION__);
}
return(emu_op);
}
EQApplicationPacket *EQProtocolPacket::MakeApplicationPacket(uint8 opcode_size) const {
EQApplicationPacket *res = new EQApplicationPacket;
res->app_opcode_size=(opcode_size==0) ? EQApplicationPacket::default_opcode_size : opcode_size;
if (res->app_opcode_size==1) {
res->pBuffer= new unsigned char[size+1];
memcpy(res->pBuffer+1,pBuffer,size);
*(res->pBuffer)=htons(opcode)&0xff;
res->opcode=opcode&0xff;
res->size=size+1;
} else {
res->pBuffer= new unsigned char[size];
memcpy(res->pBuffer,pBuffer,size);
res->opcode=opcode;
res->size=size;
}
res->copyInfo(this);
return(res);
}
bool EQProtocolPacket::ValidateCRC(const unsigned char *buffer, int length, uint32 Key)
{
bool valid=false;
// OP_SessionRequest, OP_SessionResponse, OP_OutOfSession are not CRC'd
if (buffer[0]==0x00 && (buffer[1]==OP_SessionRequest || buffer[1]==OP_SessionResponse || buffer[1]==OP_OutOfSession)) {
valid=true;
} else if(buffer[2] == 0x00 && buffer[3] == 0x19){
valid = true;
}
else {
uint16 comp_crc=CRC16(buffer,length-2,Key);
uint16 packet_crc=ntohs(*(const uint16 *)(buffer+length-2));
#ifdef EQN_DEBUG
if (packet_crc && comp_crc != packet_crc) {
cout << "CRC mismatch: comp=" << hex << comp_crc << ", packet=" << packet_crc << dec << endl;
}
#endif
valid = (!packet_crc || comp_crc == packet_crc);
}
return valid;
}
uint32 EQProtocolPacket::Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize)
{
uint32 newlen=0;
uint32 flag_offset=0;
newbuf[0]=buffer[0];
if (buffer[0]==0x00) {
flag_offset=2;
newbuf[1]=buffer[1];
} else
flag_offset=1;
if (length>2 && buffer[flag_offset]==0x5a) {
LogWrite(PACKET__DEBUG, 0, "Packet", "In Decompress 1");
newlen=Inflate(const_cast<unsigned char *>(buffer+flag_offset+1),length-(flag_offset+1)-2,newbuf+flag_offset,newbufsize-flag_offset)+2;
// something went bad with zlib
if (newlen == -1)
{
LogWrite(PACKET__ERROR, 0, "Packet", "Debug Bad Inflate!");
DumpPacket(buffer, length);
memcpy(newbuf, buffer, length);
return length;
}
newbuf[newlen++]=buffer[length-2];
newbuf[newlen++]=buffer[length-1];
} else if (length>2 && buffer[flag_offset]==0xa5) {
LogWrite(PACKET__DEBUG, 0, "Packet", "In Decompress 2");
memcpy(newbuf+flag_offset,buffer+flag_offset+1,length-(flag_offset+1));
newlen=length-1;
} else {
memcpy(newbuf,buffer,length);
newlen=length;
}
return newlen;
}
uint32 EQProtocolPacket::Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize) {
uint32 flag_offset=1,newlength;
//dump_message_column(buffer,length,"Before: ");
newbuf[0]=buffer[0];
if (buffer[0]==0) {
flag_offset=2;
newbuf[1]=buffer[1];
}
if (length>30) {
newlength=Deflate(const_cast<unsigned char *>(buffer+flag_offset),length-flag_offset,newbuf+flag_offset+1,newbufsize);
*(newbuf+flag_offset)=0x5a;
newlength+=flag_offset+1;
} else {
memmove(newbuf+flag_offset+1,buffer+flag_offset,length-flag_offset);
*(newbuf+flag_offset)=0xa5;
newlength=length+1;
}
//dump_message_column(newbuf,length,"After: ");
return newlength;
}
void EQProtocolPacket::ChatDecode(unsigned char *buffer, int size, int DecodeKey)
{
if (buffer[1]!=0x01 && buffer[0]!=0x02 && buffer[0]!=0x1d) {
int Key=DecodeKey;
unsigned char *test=(unsigned char *)malloc(size);
buffer+=2;
size-=2;
int i;
for (i = 0 ; i+4 <= size ; i+=4)
{
int pt = (*(int*)&buffer[i])^(Key);
Key = (*(int*)&buffer[i]);
*(int*)&test[i]=pt;
}
unsigned char KC=Key&0xFF;
for ( ; i < size ; i++)
{
test[i]=buffer[i]^KC;
}
memcpy(buffer,test,size);
free(test);
}
}
void EQProtocolPacket::ChatEncode(unsigned char *buffer, int size, int EncodeKey)
{
if (buffer[1]!=0x01 && buffer[0]!=0x02 && buffer[0]!=0x1d) {
int Key=EncodeKey;
char *test=(char*)malloc(size);
int i;
buffer+=2;
size-=2;
for ( i = 0 ; i+4 <= size ; i+=4)
{
int pt = (*(int*)&buffer[i])^(Key);
Key = pt;
*(int*)&test[i]=pt;
}
unsigned char KC=Key&0xFF;
for ( ; i < size ; i++)
{
test[i]=buffer[i]^KC;
}
memcpy(buffer,test,size);
free(test);
}
}
bool EQProtocolPacket::IsProtocolPacket(const unsigned char* in_buff, uint32_t len, bool bTrimCRC) {
bool ret = false;
uint16_t opcode = ntohs(*(uint16_t*)in_buff);
uint32_t offset = 2;
switch (opcode) {
case OP_SessionRequest:
case OP_SessionDisconnect:
case OP_KeepAlive:
case OP_SessionStatResponse:
case OP_Packet:
case OP_Combined:
case OP_Fragment:
case OP_Ack:
case OP_OutOfOrderAck:
case OP_OutOfSession:
{
ret = true;
break;
}
}
return ret;
}
void DumpPacketHex(const EQApplicationPacket* app)
{
DumpPacketHex(app->pBuffer, app->size);
}
void DumpPacketAscii(const EQApplicationPacket* app)
{
DumpPacketAscii(app->pBuffer, app->size);
}
void DumpPacket(const EQProtocolPacket* app) {
DumpPacketHex(app->pBuffer, app->size);
}
void DumpPacket(const EQApplicationPacket* app, bool iShowInfo) {
if (iShowInfo) {
cout << "Dumping Applayer: 0x" << hex << setfill('0') << setw(4) << app->GetOpcode() << dec;
cout << " size:" << app->size << endl;
}
DumpPacketHex(app->pBuffer, app->size);
// DumpPacketAscii(app->pBuffer, app->size);
}
void DumpPacketBin(const EQApplicationPacket* app) {
DumpPacketBin(app->pBuffer, app->size);
}

209
old/EQPacket.h Normal file
View File

@ -0,0 +1,209 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _EQPACKET_H
#define _EQPACKET_H
#include "types.h"
#include <stdio.h>
#include <string.h>
#ifdef WIN32
#include <time.h>
#include <WinSock2.h>
#else
#include <sys/time.h>
#include <netinet/in.h>
#endif
#include "emu_opcodes.h"
#include "op_codes.h"
#include "packet_dump.h"
class OpcodeManager;
class EQStream;
class EQPacket {
friend class EQStream;
public:
unsigned char *pBuffer;
uint32 size;
uint32 src_ip,dst_ip;
uint16 src_port,dst_port;
uint32 priority;
timeval timestamp;
int16 version;
~EQPacket();
void DumpRawHeader(uint16 seq=0xffff, FILE *to = stdout) const;
void DumpRawHeaderNoTime(uint16 seq=0xffff, FILE *to = stdout) const;
void DumpRaw(FILE *to = stdout) const;
const char* GetOpcodeName();
void setVersion(int16 new_version){ version = new_version; }
void setSrcInfo(uint32 sip, uint16 sport) { src_ip=sip; src_port=sport; }
void setDstInfo(uint32 dip, uint16 dport) { dst_ip=dip; dst_port=dport; }
void setTimeInfo(uint32 ts_sec, uint32 ts_usec) { timestamp.tv_sec=ts_sec; timestamp.tv_usec=ts_usec; }
void copyInfo(const EQPacket *p) { src_ip=p->src_ip; src_port=p->src_port; dst_ip=p->dst_ip; dst_port=p->dst_port; timestamp.tv_sec=p->timestamp.tv_sec; timestamp.tv_usec=p->timestamp.tv_usec; }
uint32 Size() const { return size+2; }
//no reason to have this method in zone or world
uint16 GetRawOpcode() const { return(opcode); }
inline bool operator<(const EQPacket &rhs) {
return (timestamp.tv_sec < rhs.timestamp.tv_sec || (timestamp.tv_sec==rhs.timestamp.tv_sec && timestamp.tv_usec < rhs.timestamp.tv_usec));
}
void SetProtocolOpcode(int16 new_opcode){
opcode = new_opcode;
}
protected:
uint16 opcode;
EQPacket(const uint16 op, const unsigned char *buf, const uint32 len);
EQPacket(const EQPacket &p) { version = 0; }
EQPacket() { opcode=0; pBuffer=NULL; size=0; version = 0; setTimeInfo(0, 0); }
};
class EQApplicationPacket;
class EQProtocolPacket : public EQPacket {
public:
EQProtocolPacket(uint16 op, const unsigned char *buf, uint32 len) : EQPacket(op,buf,len) {
eq2_compressed = false;
packet_prepared = false;
packet_encrypted = false;
sequence = 0;
sent_time = 0;
attempt_count = 0;
acked = false;
}
EQProtocolPacket(const unsigned char *buf, uint32 len, int in_opcode = -1);
bool combine(const EQProtocolPacket *rhs);
uint32 serialize (unsigned char *dest, int8 offset = 0) const;
static bool ValidateCRC(const unsigned char *buffer, int length, uint32 Key);
static uint32 Decompress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
static uint32 Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
static void ChatDecode(unsigned char *buffer, int size, int DecodeKey);
static void ChatEncode(unsigned char *buffer, int size, int EncodeKey);
static bool IsProtocolPacket(const unsigned char* in_buff, uint32_t len, bool bTrimCRC);
EQProtocolPacket *Copy() {
EQProtocolPacket* new_packet = new EQProtocolPacket(opcode,pBuffer,size);
new_packet->eq2_compressed = this->eq2_compressed;
new_packet->packet_prepared = this->packet_prepared;
new_packet->packet_encrypted = this->packet_encrypted;
return new_packet;
}
EQApplicationPacket *MakeApplicationPacket(uint8 opcode_size=0) const;
bool eq2_compressed;
bool packet_prepared;
bool packet_encrypted;
bool acked;
int32 sent_time;
int8 attempt_count;
int32 sequence;
private:
EQProtocolPacket(const EQProtocolPacket &p) { }
//bool dont_combine;
};
class EQ2Packet : public EQProtocolPacket {
public:
EQ2Packet(const EmuOpcode in_login_op, const unsigned char *buf, uint32 len) : EQProtocolPacket(OP_Packet,buf,len){
login_op = in_login_op;
eq2_compressed = false;
packet_prepared = false;
packet_encrypted = false;
}
bool AppCombine(EQ2Packet* rhs);
EQ2Packet* Copy() {
EQ2Packet* new_packet = new EQ2Packet(login_op,pBuffer,size);
new_packet->eq2_compressed = this->eq2_compressed;
new_packet->packet_prepared = this->packet_prepared;
new_packet->packet_encrypted = this->packet_encrypted;
return new_packet;
}
int8 PreparePacket(int16 MaxLen);
const char* GetOpcodeName();
EmuOpcode login_op;
};
class EQApplicationPacket : public EQPacket {
friend class EQProtocolPacket;
friend class EQStream;
public:
EQApplicationPacket() : EQPacket(0,NULL,0) { emu_opcode = OP_Unknown; app_opcode_size=default_opcode_size; }
EQApplicationPacket(const EmuOpcode op) : EQPacket(0,NULL,0) { SetOpcode(op); app_opcode_size=default_opcode_size; }
EQApplicationPacket(const EmuOpcode op, const uint32 len) : EQPacket(0,NULL,len) { SetOpcode(op); app_opcode_size=default_opcode_size; }
EQApplicationPacket(const EmuOpcode op, const unsigned char *buf, const uint32 len) : EQPacket(0,buf,len) { SetOpcode(op); app_opcode_size=default_opcode_size; }
bool combine(const EQApplicationPacket *rhs);
uint32 serialize (unsigned char *dest) const;
uint32 Size() const { return size+app_opcode_size; }
EQApplicationPacket *Copy() const {
EQApplicationPacket *it = new EQApplicationPacket;
try {
it->pBuffer= new unsigned char[size];
memcpy(it->pBuffer,pBuffer,size);
it->size=size;
it->opcode = opcode;
it->emu_opcode = emu_opcode;
it->version = version;
return(it);
}
catch( bad_alloc &ba )
{
cout << ba.what() << endl;
if( NULL != it )
delete it;
}
return NULL;
}
void SetOpcodeSize(uint8 s) { app_opcode_size=s; }
void SetOpcode(EmuOpcode op);
const EmuOpcode GetOpcodeConst() const;
inline const EmuOpcode GetOpcode() const { return(GetOpcodeConst()); }
//caching version of get
inline const EmuOpcode GetOpcode() { EmuOpcode r = GetOpcodeConst(); emu_opcode = r; return(r); }
static uint8 default_opcode_size;
protected:
//this is just a cache so we dont look it up several times on Get()
EmuOpcode emu_opcode;
private:
//this constructor should only be used by EQProtocolPacket, as it
//assumes the first two bytes of buf are the opcode.
EQApplicationPacket(const unsigned char *buf, uint32 len, uint8 opcode_size=0);
EQApplicationPacket(const EQApplicationPacket &p) { emu_opcode = OP_Unknown; app_opcode_size=default_opcode_size; }
uint8 app_opcode_size;
};
void DumpPacketHex(const EQApplicationPacket* app);
void DumpPacket(const EQProtocolPacket* app);
void DumpPacketAscii(const EQApplicationPacket* app);
void DumpPacket(const EQApplicationPacket* app, bool iShowInfo = false);
void DumpPacketBin(const EQApplicationPacket* app);
#endif

1921
old/EQStream.cpp Normal file

File diff suppressed because it is too large Load Diff

375
old/EQStream.h Normal file
View File

@ -0,0 +1,375 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _EQPROTOCOL_H
#define _EQPROTOCOL_H
#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <map>
#include <set>
#ifndef WIN32
#include <netinet/in.h>
#endif
#include "EQPacket.h"
#include "Mutex.h"
#include "opcodemgr.h"
#include "misc.h"
#include "Condition.h"
#include "Crypto.h"
#include "zlib.h"
#include "timer.h"
#ifdef WRITE_PACKETS
#include <stdarg.h>
#endif
using namespace std;
typedef enum {
ESTABLISHED,
WAIT_CLOSE,
CLOSING,
DISCONNECTING,
CLOSED
} EQStreamState;
#define FLAG_COMPRESSED 0x01
#define FLAG_ENCODED 0x04
#define RATEBASE 1048576 // 1 MB
#define DECAYBASE 78642 // RATEBASE/10
#ifndef RETRANSMIT_TIMEOUT_MULT
#define RETRANSMIT_TIMEOUT_MULT 3.0
#endif
#ifndef RETRANSMIT_TIMEOUT_MAX
#define RETRANSMIT_TIMEOUT_MAX 5000
#endif
#ifndef AVERAGE_DELTA_MAX
#define AVERAGE_DELTA_MAX 2500
#endif
#pragma pack(1)
struct SessionRequest {
uint32 UnknownA;
uint32 Session;
uint32 MaxLength;
};
struct SessionResponse {
uint32 Session;
uint32 Key;
uint8 UnknownA;
uint8 Format;
uint8 UnknownB;
uint32 MaxLength;
uint32 UnknownD;
};
//Deltas are in ms, representing round trip times
struct ClientSessionStats {
/*000*/ uint16 RequestID;
/*002*/ uint32 last_local_delta;
/*006*/ uint32 average_delta;
/*010*/ uint32 low_delta;
/*014*/ uint32 high_delta;
/*018*/ uint32 last_remote_delta;
/*022*/ uint64 packets_sent;
/*030*/ uint64 packets_recieved;
/*038*/
};
struct ServerSessionStats {
uint16 RequestID;
uint32 current_time;
uint32 unknown1;
uint32 received_packets;
uint32 unknown2;
uint32 sent_packets;
uint32 unknown3;
uint32 sent_packets2;
uint32 unknown4;
uint32 received_packets2;
};
#pragma pack()
class OpcodeManager;
extern OpcodeManager *EQNetworkOpcodeManager;
class EQStreamFactory;
typedef enum {
UnknownStream=0,
LoginStream,
WorldStream,
ZoneStream,
ChatOrMailStream,
ChatStream,
MailStream,
EQ2Stream,
} EQStreamType;
class EQStream {
protected:
typedef enum {
SeqPast,
SeqInOrder,
SeqFuture
} SeqOrder;
uint32 received_packets;
uint32 sent_packets;
uint32 remote_ip;
uint16 remote_port;
uint8 buffer[8192];
unsigned char *oversize_buffer;
uint32 oversize_offset,oversize_length;
unsigned char *rogue_buffer;
uint32 roguebuf_offset,roguebuf_size;
uint8 app_opcode_size;
EQStreamType StreamType;
bool compressed,encoded;
unsigned char write_buffer[2048];
uint32 retransmittimer;
uint32 retransmittimeout;
//uint32 buffer_len;
uint16 sessionAttempts;
uint16 reconnectAttempt;
bool streamactive;
uint32 Session, Key;
uint16 NextInSeq;
uint16 NextOutSeq;
uint16 SequencedBase; //the sequence number of SequencedQueue[0]
uint32 MaxLen;
uint16 MaxSends;
int8 timeout_delays;
uint8 active_users; //how many things are actively using this
Mutex MInUse;
#ifdef WRITE_PACKETS
FILE* write_packets = NULL;
char GetChar(uchar in);
void WriteToFile(char* pFormat, ...);
void WritePackets(const char* opcodeName, uchar* data, int32 size, bool outgoing);
void WritePackets(EQ2Packet* app, bool outgoing);
Mutex MWritePackets;
#endif
EQStreamState State;
Mutex MState;
uint32 LastPacket;
Mutex MVarlock;
EQApplicationPacket* CombinedAppPacket;
Mutex MCombinedAppPacket;
long LastSeqSent;
Mutex MLastSeqSent;
void SetLastSeqSent(uint32);
// Ack sequence tracking.
long MaxAckReceived,NextAckToSend,LastAckSent;
long GetMaxAckReceived();
long GetNextAckToSend();
long GetLastAckSent();
void SetMaxAckReceived(uint32 seq);
void SetNextAckToSend(uint32);
void SetLastAckSent(uint32);
Mutex MAcks;
// Packets waiting to be sent
queue<EQProtocolPacket*> NonSequencedQueue;
deque<EQProtocolPacket*> SequencedQueue;
map<uint16, EQProtocolPacket *> OutOfOrderpackets;
Mutex MOutboundQueue;
// Packes waiting to be processed
deque<EQApplicationPacket *> InboundQueue;
Mutex MInboundQueue;
static uint16 MaxWindowSize;
sint32 BytesWritten;
Mutex MRate;
sint32 RateThreshold;
sint32 DecayRate;
uint32 AverageDelta;
EQStreamFactory *Factory;
public:
Mutex MCombineQueueLock;
bool CheckCombineQueue();
deque<EQ2Packet*> combine_queue;
Timer* combine_timer;
Crypto* crypto;
int8 EQ2_Compress(EQ2Packet* app, int8 offset = 3);
z_stream stream;
uchar* stream_buffer;
int32 stream_buffer_size;
bool eq2_compressed;
int8 compressed_offset;
int16 client_version;
int16 GetClientVersion(){ return client_version; }
void SetClientVersion(int16 version){ client_version = version; }
void ResetSessionAttempts() { reconnectAttempt = 0; }
bool HasSessionAttempts() { return reconnectAttempt>0; }
EQStream() { init(); remote_ip = 0; remote_port = 0; State = CLOSED; StreamType = UnknownStream; compressed = true;
encoded = false; app_opcode_size = 2;}
EQStream(sockaddr_in addr);
virtual ~EQStream() {
MOutboundQueue.lock();
SetState(CLOSED);
MOutboundQueue.unlock();
RemoveData();
safe_delete(crypto);
safe_delete(combine_timer);
safe_delete(resend_que_timer);
safe_delete_array(oversize_buffer);
safe_delete_array(rogue_buffer);
deque<EQ2Packet*>::iterator cmb;
MCombineQueueLock.lock();
for (cmb = combine_queue.begin(); cmb != combine_queue.end(); cmb++){
safe_delete(*cmb);
}
MCombineQueueLock.unlock();
deflateEnd(&stream);
map<int16, EQProtocolPacket*>::iterator oop;
for (oop = OutOfOrderpackets.begin(); oop != OutOfOrderpackets.end(); oop++){
safe_delete(oop->second);
}
#ifdef WRITE_PACKETS
if (write_packets)
fclose(write_packets);
#endif
}
inline void SetFactory(EQStreamFactory *f) { Factory=f; }
void init(bool resetSession = true);
void SetMaxLen(uint32 length) { MaxLen=length; }
int8 getTimeoutDelays(){ return timeout_delays; }
void addTimeoutDelay(){ timeout_delays++; }
void EQ2QueuePacket(EQ2Packet* app, bool attempted_combine = false);
void PreparePacket(EQ2Packet* app, int8 offset = 0);
void UnPreparePacket(EQ2Packet* app);
void EncryptPacket(EQ2Packet* app, int8 compress_offset, int8 offset);
void FlushCombinedPacket();
void SendPacket(EQApplicationPacket *p);
void QueuePacket(EQProtocolPacket *p);
void SendPacket(EQProtocolPacket *p);
vector<EQProtocolPacket *> convert(EQApplicationPacket *p);
void NonSequencedPush(EQProtocolPacket *p);
void SequencedPush(EQProtocolPacket *p);
Mutex MResendQue;
Mutex MCompressData;
deque<EQProtocolPacket*>resend_que;
void CheckResend(int eq_fd);
void AckPackets(uint16 seq);
void Write(int eq_fd);
void SetActive(bool val) { streamactive = val; }
void WritePacket(int fd,EQProtocolPacket *p);
void EncryptPacket(uchar* data, int16 size);
uint32 GetKey() { return Key; }
void SetKey(uint32 k) { Key=k; }
void SetSession(uint32 s) { Session=s; }
void SetLastPacketTime(uint32 t) {LastPacket=t;}
void Process(const unsigned char *data, const uint32 length);
void ProcessPacket(EQProtocolPacket *p, EQProtocolPacket* lastp=NULL);
bool ProcessEmbeddedPacket(uchar* pBuffer, uint16 length, int8 opcode = OP_Packet);
bool HandleEmbeddedPacket(EQProtocolPacket *p, int16 offset = 2, int16 length = 0);
EQProtocolPacket * ProcessEncryptedPacket(EQProtocolPacket *p);
EQProtocolPacket * ProcessEncryptedData(uchar* data, int32 size, int16 opcode);
virtual void DispatchPacket(EQApplicationPacket *p) { p->DumpRaw(); }
void SendSessionResponse();
void SendSessionRequest();
void SendDisconnect(bool setstate = true);
void SendAck(uint16 seq);
void SendOutOfOrderAck(uint16 seq);
bool CheckTimeout(uint32 now, uint32 timeout=30) { return (LastPacket && (now-LastPacket) > timeout); }
bool Stale(uint32 now, uint32 timeout=30) { return (LastPacket && (now-LastPacket) > timeout); }
void InboundQueuePush(EQApplicationPacket *p);
EQApplicationPacket *PopPacket(); // InboundQueuePop
void InboundQueueClear();
void OutboundQueueClear();
bool HasOutgoingData();
void SendKeyRequest();
int16 processRSAKey(EQProtocolPacket *p, uint16 subpacket_length = 0);
void RemoveData() { InboundQueueClear(); OutboundQueueClear(); if (CombinedAppPacket) delete CombinedAppPacket; }
//
inline bool IsInUse() { bool flag; MInUse.lock(); flag=(active_users>0); MInUse.unlock(); return flag; }
inline void PutInUse() { MInUse.lock(); active_users++; MInUse.unlock(); }
inline void ReleaseFromUse() { MInUse.lock(); if(active_users > 0) active_users--; MInUse.unlock(); }
static SeqOrder CompareSequence(uint16 expected_seq, uint16 seq);
inline EQStreamState GetState() { return State; }
inline void SetState(EQStreamState state) { MState.lock(); State = state; MState.unlock(); }
inline uint32 GetRemoteIP() { return remote_ip; }
inline uint32 GetrIP() { return remote_ip; }
inline uint16 GetRemotePort() { return remote_port; }
inline uint16 GetrPort() { return remote_port; }
static EQProtocolPacket *Read(int eq_fd, sockaddr_in *from);
void Close() { SendDisconnect(); }
bool CheckActive() { return (GetState()==ESTABLISHED); }
bool CheckClosed() { return GetState()==CLOSED; }
void SetOpcodeSize(uint8 s) { app_opcode_size = s; }
void SetStreamType(EQStreamType t);
inline const EQStreamType GetStreamType() const { return StreamType; }
void ProcessQueue();
EQProtocolPacket* RemoveQueue(uint16 seq);
void Decay();
void AdjustRates(uint32 average_delta);
Timer* resend_que_timer;
};
#endif

444
old/EQStreamFactory.cpp Normal file
View File

@ -0,0 +1,444 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "EQStreamFactory.h"
#include "Log.h"
#ifdef WIN32
#include <WinSock2.h>
#include <windows.h>
#include <process.h>
#include <io.h>
#include <stdio.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#endif
#include <fcntl.h>
#include <fstream>
#include <iostream>
#include "op_codes.h"
#include "EQStream.h"
#include "packet_dump.h"
#ifdef WORLD
#include "../WorldServer/client.h"
#endif
using namespace std;
#ifdef WORLD
extern ClientList client_list;
#endif
ThreadReturnType EQStreamFactoryReaderLoop(void *eqfs)
{
if(eqfs){
EQStreamFactory *fs=(EQStreamFactory *)eqfs;
fs->ReaderLoop();
}
THREAD_RETURN(NULL);
}
ThreadReturnType EQStreamFactoryWriterLoop(void *eqfs)
{
if(eqfs){
EQStreamFactory *fs=(EQStreamFactory *)eqfs;
fs->WriterLoop();
}
THREAD_RETURN(NULL);
}
ThreadReturnType EQStreamFactoryCombinePacketLoop(void *eqfs)
{
if(eqfs){
EQStreamFactory *fs=(EQStreamFactory *)eqfs;
fs->CombinePacketLoop();
}
THREAD_RETURN(NULL);
}
EQStreamFactory::EQStreamFactory(EQStreamType type, int port)
{
StreamType=type;
Port=port;
listen_ip_address = 0;
}
void EQStreamFactory::Close()
{
CheckTimeout(true);
Stop();
if (sock != -1) {
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
sock = -1;
}
}
bool EQStreamFactory::Open()
{
struct sockaddr_in address;
#ifndef WIN32
pthread_t t1, t2, t3;
#endif
/* Setup internet address information.
This is used with the bind() call */
memset((char *) &address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(Port);
#if defined(LOGIN) || defined(MINILOGIN)
if(listen_ip_address)
address.sin_addr.s_addr = inet_addr(listen_ip_address);
else
address.sin_addr.s_addr = htonl(INADDR_ANY);
#else
address.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
/* Setting up UDP port for new clients */
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
return false;
}
if (::bind(sock, (struct sockaddr *) &address, sizeof(address)) < 0) {
//close(sock);
sock=-1;
return false;
}
#ifdef WIN32
unsigned long nonblock = 1;
ioctlsocket(sock, FIONBIO, &nonblock);
#else
fcntl(sock, F_SETFL, O_NONBLOCK);
#endif
//moved these because on windows the output was delayed and causing the console window to look bad
#ifdef LOGIN
LogWrite(LOGIN__DEBUG, 0, "Login", "Starting factory Reader");
LogWrite(LOGIN__DEBUG, 0, "Login", "Starting factory Writer");
#elif WORLD
LogWrite(WORLD__DEBUG, 0, "World", "Starting factory Reader");
LogWrite(WORLD__DEBUG, 0, "World", "Starting factory Writer");
#endif
#ifdef WIN32
_beginthread(EQStreamFactoryReaderLoop,0, this);
_beginthread(EQStreamFactoryWriterLoop,0, this);
_beginthread(EQStreamFactoryCombinePacketLoop,0, this);
#else
pthread_create(&t1,NULL,EQStreamFactoryReaderLoop,this);
pthread_create(&t2,NULL,EQStreamFactoryWriterLoop,this);
pthread_create(&t3,NULL,EQStreamFactoryCombinePacketLoop,this);
pthread_detach(t1);
pthread_detach(t2);
pthread_detach(t3);
#endif
return true;
}
EQStream *EQStreamFactory::Pop()
{
if (!NewStreams.size())
return NULL;
EQStream *s=NULL;
//cout << "Pop():Locking MNewStreams" << endl;
MNewStreams.lock();
if (NewStreams.size()) {
s=NewStreams.front();
NewStreams.pop();
s->PutInUse();
}
MNewStreams.unlock();
//cout << "Pop(): Unlocking MNewStreams" << endl;
return s;
}
void EQStreamFactory::Push(EQStream *s)
{
//cout << "Push():Locking MNewStreams" << endl;
MNewStreams.lock();
NewStreams.push(s);
MNewStreams.unlock();
//cout << "Push(): Unlocking MNewStreams" << endl;
}
void EQStreamFactory::ReaderLoop()
{
fd_set readset;
map<string,EQStream *>::iterator stream_itr;
int num;
int length;
unsigned char buffer[2048];
sockaddr_in from;
int socklen=sizeof(sockaddr_in);
timeval sleep_time;
ReaderRunning=true;
while(sock!=-1) {
MReaderRunning.lock();
if (!ReaderRunning)
break;
MReaderRunning.unlock();
FD_ZERO(&readset);
FD_SET(sock,&readset);
sleep_time.tv_sec=30;
sleep_time.tv_usec=0;
if ((num=select(sock+1,&readset,NULL,NULL,&sleep_time))<0) {
// What do we wanna do?
} else if (num==0)
continue;
if (FD_ISSET(sock,&readset)) {
#ifdef WIN32
if ((length=recvfrom(sock,(char*)buffer,sizeof(buffer),0,(struct sockaddr*)&from,(int *)&socklen))<2)
#else
if ((length=recvfrom(sock,buffer,2048,0,(struct sockaddr *)&from,(socklen_t *)&socklen))<2)
#endif
{
// What do we wanna do?
} else {
char temp[25];
sprintf(temp,"%u.%d",ntohl(from.sin_addr.s_addr),ntohs(from.sin_port));
MStreams.lock();
if ((stream_itr=Streams.find(temp))==Streams.end() || buffer[1]==OP_SessionRequest) {
MStreams.unlock();
if (buffer[1]==OP_SessionRequest) {
if(stream_itr != Streams.end() && stream_itr->second)
stream_itr->second->SetState(CLOSED);
EQStream *s=new EQStream(from);
s->SetFactory(this);
s->SetStreamType(StreamType);
Streams[temp]=s;
WriterWork.Signal();
Push(s);
s->Process(buffer,length);
s->SetLastPacketTime(Timer::GetCurrentTime2());
}
} else {
EQStream *curstream = stream_itr->second;
//dont bother processing incoming packets for closed connections
if(curstream->CheckClosed())
curstream = NULL;
else
curstream->PutInUse();
MStreams.unlock();
if(curstream) {
curstream->Process(buffer,length);
curstream->SetLastPacketTime(Timer::GetCurrentTime2());
curstream->ReleaseFromUse();
}
}
}
}
}
}
void EQStreamFactory::CheckTimeout(bool remove_all)
{
//lock streams the entire time were checking timeouts, it should be fast.
MStreams.lock();
unsigned long now=Timer::GetCurrentTime2();
map<string,EQStream *>::iterator stream_itr;
for(stream_itr=Streams.begin();stream_itr!=Streams.end();) {
EQStream *s = stream_itr->second;
EQStreamState state = s->GetState();
if (state==CLOSING && !s->HasOutgoingData()) {
stream_itr->second->SetState(CLOSED);
state = CLOSED;
} else if (s->CheckTimeout(now, STREAM_TIMEOUT)) {
const char* stateString;
switch (state){
case ESTABLISHED:
stateString = "Established";
break;
case CLOSING:
stateString = "Closing";
break;
case CLOSED:
stateString = "Closed";
break;
case WAIT_CLOSE:
stateString = "Wait-Close";
break;
default:
stateString = "Unknown";
break;
}
LogWrite(WORLD__DEBUG, 0, "World", "Timeout up!, state=%s (%u)", stateString, state);
if (state==ESTABLISHED) {
s->Close();
}
else if (state == WAIT_CLOSE) {
s->SetState(CLOSING);
state = CLOSING;
}
else if (state == CLOSING) {
//if we time out in the closing state, just give up
s->SetState(CLOSED);
state = CLOSED;
}
}
//not part of the else so we check it right away on state change
if (remove_all || state==CLOSED) {
if (!remove_all && s->getTimeoutDelays()<2) {
s->addTimeoutDelay();
//give it a little time for everybody to finish with it
} else {
//everybody is done, we can delete it now
#ifdef LOGIN
LogWrite(LOGIN__DEBUG, 0, "Login", "Removing connection...");
#else
LogWrite(WORLD__DEBUG, 0, "World", "Removing connection...");
#endif
map<string,EQStream *>::iterator temp=stream_itr;
stream_itr++;
//let whoever has the stream outside delete it
#ifdef WORLD
client_list.RemoveConnection(temp->second);
#endif
EQStream* stream = temp->second;
Streams.erase(temp);
delete stream;
continue;
}
}
stream_itr++;
}
MStreams.unlock();
}
void EQStreamFactory::CombinePacketLoop(){
deque<EQStream*> combine_que;
CombinePacketRunning = true;
bool packets_waiting = false;
while(sock!=-1) {
if (!CombinePacketRunning)
break;
MStreams.lock();
map<string,EQStream *>::iterator stream_itr;
for(stream_itr=Streams.begin();stream_itr!=Streams.end();stream_itr++) {
if(!stream_itr->second){
continue;
}
if(stream_itr->second->combine_timer && stream_itr->second->combine_timer->Check())
combine_que.push_back(stream_itr->second);
}
EQStream* stream = 0;
packets_waiting = false;
while(combine_que.size()){
stream = combine_que.front();
if(stream->CheckActive()){
if(!stream->CheckCombineQueue())
packets_waiting = true;
}
combine_que.pop_front();
}
MStreams.unlock();
if(!packets_waiting)
Sleep(25);
Sleep(1);
}
}
void EQStreamFactory::WriterLoop()
{
map<string,EQStream *>::iterator stream_itr;
vector<EQStream *> wants_write;
vector<EQStream *>::iterator cur,end;
deque<EQStream*> resend_que;
bool decay=false;
uint32 stream_count;
Timer DecayTimer(20);
WriterRunning=true;
DecayTimer.Enable();
while(sock!=-1) {
Timer::SetCurrentTime();
//if (!havework) {
//WriterWork.Wait();
//}
MWriterRunning.lock();
if (!WriterRunning)
break;
MWriterRunning.unlock();
wants_write.clear();
decay=DecayTimer.Check();
//copy streams into a seperate list so we dont have to keep
//MStreams locked while we are writting
MStreams.lock();
for(stream_itr=Streams.begin();stream_itr!=Streams.end();stream_itr++) {
// If it's time to decay the bytes sent, then let's do it before we try to write
if(!stream_itr->second){
Streams.erase(stream_itr);
break;
}
if (decay)
stream_itr->second->Decay();
if (stream_itr->second->HasOutgoingData()) {
stream_itr->second->PutInUse();
wants_write.push_back(stream_itr->second);
}
if(stream_itr->second->resend_que_timer->Check())
resend_que.push_back(stream_itr->second);
}
MStreams.unlock();
//do the actual writes
cur = wants_write.begin();
end = wants_write.end();
for(; cur != end; cur++) {
(*cur)->Write(sock);
(*cur)->ReleaseFromUse();
}
while(resend_que.size()){
resend_que.front()->CheckResend(sock);
resend_que.pop_front();
}
Sleep(10);
MStreams.lock();
stream_count=Streams.size();
MStreams.unlock();
if (!stream_count) {
//cout << "No streams, waiting on condition" << endl;
WriterWork.Wait();
//cout << "Awake from condition, must have a stream now" << endl;
}
}
}

86
old/EQStreamFactory.h Normal file
View File

@ -0,0 +1,86 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _EQSTREAMFACTORY_H
#define _EQSTREAMFACTORY_H
#include <queue>
#include <map>
#include "../common/EQStream.h"
#include "../common/Condition.h"
#include "../common/opcodemgr.h"
#include "../common/timer.h"
#define STREAM_TIMEOUT 45000 //in ms
class EQStreamFactory {
private:
int sock;
int Port;
bool ReaderRunning;
Mutex MReaderRunning;
bool WriterRunning;
Mutex MWriterRunning;
bool CombinePacketRunning;
Mutex MCombinePacketRunning;
Condition WriterWork;
EQStreamType StreamType;
queue<EQStream *> NewStreams;
Mutex MNewStreams;
map<string,EQStream *> Streams;
Mutex MStreams;
Timer *DecayTimer;
public:
char* listen_ip_address;
void CheckTimeout(bool remove_all = false);
EQStreamFactory(EQStreamType type) { ReaderRunning=false; WriterRunning=false; StreamType=type; }
EQStreamFactory(EQStreamType type, int port);
~EQStreamFactory(){
safe_delete_array(listen_ip_address);
}
EQStream *Pop();
void Push(EQStream *s);
bool loadPublicKey();
bool Open();
bool Open(unsigned long port) { Port=port; return Open(); }
void Close();
void ReaderLoop();
void WriterLoop();
void CombinePacketLoop();
void Stop() { StopReader(); StopWriter(); StopCombinePacket(); }
void StopReader() { MReaderRunning.lock(); ReaderRunning=false; MReaderRunning.unlock(); }
void StopWriter() { MWriterRunning.lock(); WriterRunning=false; MWriterRunning.unlock(); WriterWork.Signal(); }
void StopCombinePacket() { MCombinePacketRunning.lock(); CombinePacketRunning=false; MCombinePacketRunning.unlock(); }
void SignalWriter() { WriterWork.Signal(); }
};
#endif

58
old/GlobalHeaders.h Normal file
View File

@ -0,0 +1,58 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
//Character Creation Replies, put in globals so name filter can return proper responses
#define UNKNOWNERROR_REPLY 0
#define CREATESUCCESS_REPLY 1
#define NOSERVERSAVAIL_REPLY 2
#define CREATEPENDING_REPLY 3
#define MAXCHARSALLOWED_REPLY 4
#define INVALIDRACE_REPLY 5
#define INVALIDCITY_REPLY 6
#define INVALIDCLASS_REPLY 7
#define INVALIDGENDER_REPLY 8
#define INVALIDFIRST_LVL_REPLY 9
#define BADNAMELENGTH_REPLY 10
#define NAMEINVALID_REPLY 11
#define NAMEFILTER_REPLY 12 // name_filter reply (bad word or blocked words)
#define NAMETAKEN_REPLY 13
#define OVERLOADEDSERVER_REPLY 14
#define UNKNOWNERROR_REPLY2 15
#define INVALIDFEATURES1_REPLY 16
#define INVALIDFEATURES2_REPLY 17
#define INVALIDRACE_APPEARANCE_REPLY 18
#define PLAY_ERROR_PROBLEM 0
#define PLAY_ERROR_ZONE_DOWN 4
#define PLAY_ERROR_CHAR_NOT_LOADED 5
#define PLAY_ERROR_CHAR_NOT_FOUND 6
#define PLAY_ERROR_ACCOUNT_IN_USE 7
#define PLAY_ERROR_SERVER_TIMEOUT 8
#define PLAY_ERROR_SERVER_SHUTDOWN 9
#define PLAY_ERROR_LOADING_ERROR 10
#define PLAY_ERROR_EXCHANGE_SERVER 11
#define PLAY_ERROR_REGION_SERVER 12
#define PLAY_ERROR_CLASS_INVALID 13
#define PLAY_ERROR_TOO_MANY_CHARACTERS 14
#define PLAY_ERROR_EOF_EXP_NOT_FOUND 15
#define PLAY_ERROR_UNKNOWN_RESPONSE 16
#define PLAY_ERROR_UNKNOWN 17
#define PLAY_ERROR_ACCOUNT_BANNED 18
#define PLAY_ERROR_PROHIBITED 19

97
old/JsonParser.cpp Normal file
View File

@ -0,0 +1,97 @@
#include "JsonParser.h"
JsonParser::JsonParser(const std::string &filename) {
is_loaded = false;
try {
boost::property_tree::read_json(filename, pt);
parseTree(pt, "");
is_loaded = true;
} catch (const boost::property_tree::json_parser_error &e) {
std::cerr << "Error reading JSON file: " << e.what() << std::endl;
}
}
bool JsonParser::convertStringToUnsignedChar(const std::string& str, unsigned char& result) {
unsigned long ul;
try {
ul = std::stoul(str);
} catch (const std::invalid_argument&) {
return false; // Not a valid number
} catch (const std::out_of_range&) {
return false; // Number is too large for unsigned long
}
if (ul > std::numeric_limits<unsigned char>::max()) {
return false; // Number is too large for unsigned short
}
result = static_cast<unsigned char>(ul);
return true;
}
bool JsonParser::convertStringToUnsignedShort(const std::string& str, unsigned short& result) {
unsigned long ul;
try {
ul = std::stoul(str);
} catch (const std::invalid_argument&) {
return false; // Not a valid number
} catch (const std::out_of_range&) {
return false; // Number is too large for unsigned long
}
if (ul > std::numeric_limits<unsigned short>::max()) {
return false; // Number is too large for unsigned short
}
result = static_cast<unsigned short>(ul);
return true;
}
bool JsonParser::convertStringToUnsignedInt(const std::string& str, unsigned int& result) {
unsigned long ul;
try {
ul = std::stoul(str);
} catch (const std::invalid_argument&) {
return false; // Not a valid number
} catch (const std::out_of_range&) {
return false; // Number is too large for unsigned long
}
if (ul > std::numeric_limits<unsigned int>::max()) {
return false; // Number is too large for unsigned short
}
result = static_cast<unsigned int>(ul);
return true;
}
bool JsonParser::convertStringToUnsignedLong(const std::string& str, unsigned long& result) {
unsigned long ul;
try {
ul = std::stoul(str);
} catch (const std::invalid_argument&) {
return false; // Not a valid number
} catch (const std::out_of_range&) {
return false; // Number is too large for unsigned long
}
if (ul > std::numeric_limits<unsigned long>::max()) {
return false; // Number is too large for unsigned short
}
result = ul;
return true;
}
void JsonParser::parseTree(const boost::property_tree::ptree &tree, const std::string &path) {
for (const auto &node : tree) {
std::string currentPath = path.empty() ? node.first : path + "." + node.first;
if (node.second.empty()) {
std::string name = currentPath;
boost::algorithm::to_lower(name);
values[name] = node.second.get_value<std::string>();
} else {
parseTree(node.second, currentPath);
}
}
}

33
old/JsonParser.h Normal file
View File

@ -0,0 +1,33 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
#include <string>
#include <map>
class JsonParser {
public:
JsonParser(const std::string &filename);
std::string getValue(const std::string &path) const {
auto it = values.find(path);
if (it != values.end()) {
return it->second;
}
return "";
}
static bool convertStringToUnsignedChar(const std::string& str, unsigned char& result);
static bool convertStringToUnsignedShort(const std::string& str, unsigned short& result);
static bool convertStringToUnsignedInt(const std::string& str, unsigned int& result);
static bool convertStringToUnsignedLong(const std::string& str, unsigned long& result);
bool IsLoaded() { return is_loaded; }
private:
boost::property_tree::ptree pt;
std::map<std::string, std::string> values;
void parseTree(const boost::property_tree::ptree &tree, const std::string &path);
bool is_loaded;
};

615
old/Log.cpp Normal file
View File

@ -0,0 +1,615 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Log.h"
#include "xmlParser.h"
#include "types.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include "../WorldServer/World.h"
#include "../WorldServer/client.h"
#include "../WorldServer/zoneserver.h"
extern ZoneList zone_list;
#ifdef _WIN32
#include <process.h>
#ifndef snprintf
#define snprintf sprintf_s
#endif
#include <WinSock2.h>
#include <Windows.h>
#else
#endif
#define LOG_CATEGORY(category) #category,
const char *log_category_names[NUMBER_OF_LOG_CATEGORIES] = {
#include "LogTypes.h"
};
#define LOG_TYPE(category, type, level, color, enabled, logfile, console, client, str) { level, color, enabled, logfile, console, client, LOG_ ##category, #category "__" #type, ( strlen(str)>0 ) ? str : #category "__" #type },
static LogTypeStatus real_log_type_info[NUMBER_OF_LOG_TYPES+1] =
{
#include "LogTypes.h"
{ 0, 0, false, false, false, false, NUMBER_OF_LOG_CATEGORIES, "BAD TYPE", "Bad Name" } /* dummy trailing record */
};
LogTypeStatus *log_type_info = real_log_type_info;
//make these rules?
#define LOG_CYCLE 100 //milliseconds between each batch of log writes
#define LOGS_PER_CYCLE 50 //amount of logs to write per cycle
#define LOG_DIR "logs"
#if defined LOGIN
#define EXE_NAME "login"
#elif defined WORLD
#define EXE_NAME "world"
#elif defined PARSER
#define EXE_NAME "parser"
#elif defined PATCHER
#define EXE_NAME "patcher"
#else
#define EXE_NAME "whatprogyourunning"
#endif
#define DATE_MAX 8
#define LOG_NAME_MAX 32
struct logq_t {
LogType log_type;
char date[DATE_MAX + 1];
char name[LOG_NAME_MAX + 1];
char *text;
struct logq_t *next;
struct logq_t *prev;
};
//doubly linked list of logs
static logq_t head;
static logq_t tail;
static int num_logqs = 0;
static Mutex mlogqs;
//loop until....
static bool looping = false;
//because our code has LogWrite's before main(), make sure any of those do the
//call to LogStart if it hasn't been called already...
static bool start_called = false;
static void SetConsoleColor(int color) {
#ifdef _WIN32
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
if (handle == NULL || handle == INVALID_HANDLE_VALUE)
return;
#endif
switch (color) {
case FOREGROUND_WHITE:
case FOREGROUND_WHITE_BOLD:
case FOREGROUND_RED:
case FOREGROUND_RED_BOLD:
case FOREGROUND_GREEN:
case FOREGROUND_GREEN_BOLD:
case FOREGROUND_BLUE:
case FOREGROUND_BLUE_BOLD:
case FOREGROUND_YELLOW:
case FOREGROUND_YELLOW_BOLD:
case FOREGROUND_CYAN:
case FOREGROUND_CYAN_BOLD:
case FOREGROUND_MAGENTA:
case FOREGROUND_MAGENTA_BOLD:
#ifdef _WIN32
SetConsoleTextAttribute(handle, color);
#else
printf("\033[%i;%i;40m", color > 100 ? 1 : 0, color > 100 ? color - 100 : color);
#endif
break;
default:
#ifdef _WIN32
SetConsoleTextAttribute(handle, FOREGROUND_WHITE_BOLD);
#else
printf("\033[0;37;40m");
#endif
break;
}
}
static FILE * OpenLogFile() {
char file[FILENAME_MAX + 1];
struct stat st;
struct tm *tm;
time_t now;
FILE *f;
now = time(NULL);
tm = localtime(&now);
//make sure the logs directory exists
if (stat(LOG_DIR, &st) != 0) {
#ifdef _WIN32
if (!CreateDirectory(LOG_DIR, NULL)) {
fprintf(stderr, "Unable to create directory '%s'\n", LOG_DIR);
return stderr;
}
#else
if (mkdir(LOG_DIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
fprintf(stderr, "Unable to create direcotry '%s': %s\n", LOG_DIR, strerror(errno));
return stderr;
}
#endif
}
#ifdef NO_PIDLOG
snprintf(file, FILENAME_MAX, LOG_DIR"/%04i-%02i-%02i_eq2" EXE_NAME ".log", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
#else
snprintf(file, FILENAME_MAX, LOG_DIR"/%04i-%02i-%02i_eq2" EXE_NAME "_%04i.log", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, getpid());
#endif
if ((f = fopen(file, "a")) == NULL) {
fprintf(stderr, "Could not open '%s' for writing: %s\n", file, strerror(errno));
return stderr;
}
return f;
}
static void WriteQueuedLogs(int count) {
logq_t pending_head, pending_tail, *logq, *tmp;
int i = 0;
FILE *f;
pending_head.next = &pending_tail;
pending_tail.prev = &pending_head;
//loop through our queued logs and store at most `count` logs into a temporary list
//since io functions are expensive, we'll write from a temporary list so we don't hold the
//write lock of the main list for a long period of time
mlogqs.writelock();
logq = head.next;
while (head.next != &tail) {
//first remove the log from the master list
logq = head.next;
logq->next->prev = &head;
head.next = logq->next;
//now insert it into the temporary list
tmp = pending_tail.prev;
tmp->next = logq;
logq->prev = tmp;
logq->next = &pending_tail;
pending_tail.prev = logq;
--num_logqs;
logq = logq->next;
//if we have a limit, check it
if (count > 0 && ++i == count)
break;
}
//if we have no logs to write, we're done
if ((logq = pending_head.next) == &pending_tail)
{
mlogqs.releasewritelock();
return;
}
while (logq != &pending_tail) {
if (log_type_info[logq->log_type].console) {
SetConsoleColor(FOREGROUND_WHITE_BOLD);
printf("%s ", logq->date);
SetConsoleColor(log_type_info[logq->log_type].color);
printf("%s ", log_type_info[logq->log_type].display_name);
SetConsoleColor(FOREGROUND_WHITE_BOLD);
printf("%-10s: ", logq->name);
SetConsoleColor(log_type_info[logq->log_type].color);
printf("%s\n", logq->text);
SetConsoleColor(-1);
fflush(stdout);
}
if (log_type_info[logq->log_type].logfile) {
f = OpenLogFile();
if (f != stderr || (f == stderr && !log_type_info[logq->log_type].console)) {
fprintf(f, "%s %s %s: %s\n", logq->date, log_type_info[logq->log_type].display_name, logq->name, logq->text);
fflush(f);
if (f != stderr)
fclose(f);
}
}
#if defined WORLD
if (log_type_info[logq->log_type].client) {
// eventually output logging to the client who "subscribed" to the logger
// in-game, they type:
// /logsys add WORLD__DEBUG 5
// to watch world debug loggers of level 5 or less
}
#endif
tmp = logq;
logq = logq->next;
free(tmp->text);
free(tmp);
}
mlogqs.releasewritelock();
}
ThreadReturnType LogLoop(void *args) {
while (looping) {
WriteQueuedLogs(LOGS_PER_CYCLE);
Sleep(LOG_CYCLE);
}
THREAD_RETURN(NULL);
}
void LogStart() {
if (start_called)
return;
//initialize the doubly linked list
head.prev = NULL;
head.next = &tail;
tail.prev = &head;
tail.next = NULL;
mlogqs.SetName("logqueue");
looping = true;
#ifdef _WIN32
_beginthread(LogLoop, 0, NULL);
#else
pthread_t thread;
pthread_create(&thread, NULL, LogLoop, NULL);
pthread_detach(thread);
#endif
start_called = true;
}
void LogStop() {
looping = false;
WriteQueuedLogs(-1);
start_called = false;
}
static void LogQueueAdd(LogType log_type, char *text, int len, const char *cat_text = NULL) {
logq_t *logq;
struct tm *tm;
time_t now;
if ((logq = (logq_t *)calloc(1, sizeof(logq_t))) == NULL) {
free(text);
fprintf(stderr, "%s: %u: Unable to allocate %zu bytes\n", __FUNCTION__, __LINE__, sizeof(logq_t));
return;
}
if ((logq->text = (char *)calloc(len + 1, sizeof(char))) == NULL) {
free(text);
free(logq);
fprintf(stderr, "%s: %u: Unable to allocate %i bytes\n", __FUNCTION__, __LINE__, len + 1);
return;
}
now = time(NULL);
tm = localtime(&now);
logq->log_type = log_type;
snprintf(logq->date, DATE_MAX + 1, "%02i:%02i:%02i", tm->tm_hour, tm->tm_min, tm->tm_sec);
strncpy(logq->name, cat_text == NULL || cat_text[0] == '\0' ? log_type_info[log_type].name : cat_text, LOG_NAME_MAX);
strncpy(logq->text, text, len);
free(text);
if (!start_called)
LogStart();
//insert at the end
mlogqs.writelock();
tail.prev->next = logq;
logq->prev = tail.prev;
logq->next = &tail;
tail.prev = logq;
++num_logqs;
mlogqs.releasewritelock();
}
int8 GetLoggerLevel(LogType type)
{
return log_type_info[type].level;
}
// JA: horrific hack for Parser, since queued logging keeps crashing between parses.
#ifndef PARSER
void LogWrite(LogType type, int8 log_level, const char *cat_text, const char *fmt, ...) {
int count, size = 64;
char *buf;
va_list ap;
// if there is no formatting, or the logger is DISABLED
// or the log_level param exceeds the minimum allowed value, abort logwrite
if (!log_type_info[type].enabled || (log_level > 0 && log_type_info[type].level < log_level))
return;
while (true) {
if ((buf = (char *)malloc(size)) == NULL) {
fprintf(stderr, "%s: %i: Unable to allocate %i bytes\n", __FUNCTION__, __LINE__, size);
return;
}
va_start(ap, fmt);
count = vsnprintf(buf, size, fmt, ap);
va_end(ap);
if (count > -1 && count < size)
break;
free(buf);
if (count > 1)
size = count + 1;
else
size *= 2;
}
LogQueueAdd(type, buf, count, cat_text);
}
#else
void LogWrite(LogType type, int8 log_level, const char *cat_text, const char *format, ...)
{
// if there is no formatting, or the logger is DISABLED
// or the log_level param exceeds the minimum allowed value, abort logwrite
if ( !format || !log_type_info[type].enabled || (log_level > 0 && log_type_info[type].level < log_level) )
return;
time_t clock;
struct tm *tm;
char buffer[LOG_BUFFER_SIZE], date[32];
va_list args;
FILE *f;
size_t cat_text_len = 0;
memset(buffer, 0, sizeof(buffer));
memset(date, 0, sizeof(date));
va_start(args, format);
vsnprintf(buffer, sizeof(buffer) - 1, format, args);
va_end(args);
time(&clock);
tm = localtime(&clock);
snprintf(date, sizeof(date)-1, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);
// DateString(date, sizeof(date));
cat_text_len = strlen(cat_text);
//if( strlen(cat_text) == 0 ) // cat_text was blank
// cat_text = (char*)log_type_info[type].name;
/* write to the log file? */
if (log_type_info[type].logfile)
{
char exename[200] = "";
#ifdef LOGIN
snprintf(exename, sizeof(exename), "login");
#endif
#ifdef WORLD
snprintf(exename, sizeof(exename), "world");
#endif
#ifdef PARSER
snprintf(exename, sizeof(exename), "parser");
#endif
#ifdef PATCHER
snprintf(exename, sizeof(exename), "patcher");
#endif
char filename[200], log_header[200] = "";
#ifndef NO_PIDLOG
snprintf(filename, sizeof(filename)-1, "logs/%04d-%02d-%02d_eq2%s_%04i.log", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, exename, getpid());
#else
snprintf(filename, sizeof(filename)-1, "logs/%04d-%02d-%02d_eq2%s.log", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, exename);
#endif
f=fopen(filename, "r");
if( !f )
snprintf(log_header, sizeof(log_header), "===[ New log '%s' started ]===\n\n", filename);
else
fclose (f);
f = fopen(filename, "a");
if (f) {
if( strlen(log_header) > 0 )
fprintf(f, "%s\n", log_header);
fprintf(f, "%s %s %s: %s\n", date, log_type_info[type].display_name, cat_text, buffer);
fclose(f);
}
}
/* write to the console? */
if (log_type_info[type].console)
{
#ifdef _WIN32
ColorizeLog(log_type_info[type].color, date, log_type_info[type].display_name, cat_text_len == 0 ? log_type_info[type].name : cat_text, (string)buffer);
#else
printf("%s %s %s: %s\n", date, log_type_info[type].display_name, cat_text_len == 0 ? log_type_info[type].name : cat_text, buffer);
#endif
}
}
void
ColorizeLog(int color, char *date, const char *display_name, const char *category, string buffer)
{
#ifdef _WIN32
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
if (console == INVALID_HANDLE_VALUE) {
printf("%s %s %s: %s\n", date, display_name, category, buffer);
return;
}
printf("%s ", date);
SetConsoleTextAttribute(console, color);
printf("%s ", display_name);
SetConsoleTextAttribute(console, FOREGROUND_WHITE_BOLD);
printf("%s: ", category);
SetConsoleTextAttribute(console, color);
printf("%s\n", buffer.c_str());
SetConsoleTextAttribute(console, FOREGROUND_WHITE);
#endif
}
#endif
LogTypeStatus *
GetLogTypeStatus(const char *category, const char *type) {
char combined[256];
int i;
memset(combined, 0, sizeof(combined));
snprintf(combined, sizeof(combined) - 1, "%s__%s", category, type);
for (i = 0; i < NUMBER_OF_LOG_TYPES; i++) {
if (strcasecmp(log_type_info[i].name, combined) == 0)
return &log_type_info[i];
}
return &log_type_info[NUMBER_OF_LOG_TYPES];
}
void
ProcessLogConfig(XMLNode node) {
int i;
const char *category, *type, *level, *color, *enabled, *logs;
LogTypeStatus *lfs;
XMLNode child;
category = node.getAttribute("Category");
if (!category) {
LogWrite(MISC__WARNING, 0, "Misc", "Error parsing log config. Config missing a Category");
return;
}
for (i = 0; i < node.nChildNode("ConfigType"); i++) {
child = node.getChildNode("ConfigType", i);
type = child.getAttribute("Type");
if (!type) {
LogWrite(MISC__WARNING, 0, "Misc", "Error parsing log config. Config missing a Type");
continue;
}
lfs = GetLogTypeStatus(category, type);
level = child.getAttribute("Level");
enabled = child.getAttribute("Enabled");
color = child.getAttribute("Color");
logs = child.getAttribute("Logs");
if (!logs) {
LogWrite(MISC__WARNING, 0, "Misc", "Error parsing log config. Config missing 'Logs' attribute to specify which log(s) to write to");
continue;
}
if (!IsNumber(logs)) {
LogWrite(MISC__WARNING, 0, "Misc", "Error parsing log config. Attribute 'Logs' must be a number. See LogTypes.h for the valid types.");
continue;
}
if (enabled) {
if (!strcasecmp("true", enabled) || !strcasecmp("on", enabled))
lfs->enabled = true;
else if (!strcasecmp("false", enabled) || !strcasecmp("off", enabled))
lfs->enabled = false;
else
LogWrite(MISC__WARNING, 0, "Misc", "Error parsing log config. Log setting 'Enabled' has invalid value '%s'. 'true'/'on' or 'false'/'off' are valid values", enabled);
}
if (IsNumber(level))
lfs->level = atoi(level);
else
lfs->level = 0;
if (color) {
if (IsNumber(color))
lfs->color = atoi(color);
else if (!strcasecmp("White", color))
lfs->color = FOREGROUND_WHITE;
else if (!strcasecmp("Green", color))
lfs->color = FOREGROUND_GREEN;
else if (!strcasecmp("Yellow", color))
lfs->color = FOREGROUND_YELLOW;
else if (!strcasecmp("Red", color))
lfs->color = FOREGROUND_RED;
else if (!strcasecmp("Blue", color))
lfs->color = FOREGROUND_BLUE;
else if (!strcasecmp("Cyan", color))
lfs->color = FOREGROUND_CYAN;
else if (!strcasecmp("Magenta", color))
lfs->color = FOREGROUND_MAGENTA;
else if (!strcasecmp("WhiteBold", color))
lfs->color = FOREGROUND_WHITE_BOLD;
else if (!strcasecmp("GreenBold", color))
lfs->color = FOREGROUND_GREEN_BOLD;
else if (!strcasecmp("YellowBold", color))
lfs->color = FOREGROUND_YELLOW_BOLD;
else if (!strcasecmp("RedBold", color))
lfs->color = FOREGROUND_RED_BOLD;
else if (!strcasecmp("BlueBold", color))
lfs->color = FOREGROUND_BLUE_BOLD;
else if (!strcasecmp("CyanBold", color))
lfs->color = FOREGROUND_CYAN_BOLD;
else if (!strcasecmp("MagentaBold", color))
lfs->color = FOREGROUND_MAGENTA_BOLD;
else
LogWrite(MISC__WARNING, 0, "Misc", "Error parsing log config. Log setting 'Color' has invalid value '%s'", color);
}
// JA: something was wrong here, lfs->logfile or console always was true, even if bit was off. Will ask Scatman about it someday.
lfs->logfile = (atoi(logs) & LOG_LOGFILE);
lfs->console = (atoi(logs) & LOG_CONSOLE);
lfs->client = (atoi(logs) & LOG_CLIENT);
}
}
bool
LogParseConfigs() {
XMLNode main_node;
int i;
main_node = XMLNode::openFileHelper("log_config.xml", "EQ2EmuLogConfigs");
if (main_node.isEmpty()) {
LogWrite(MISC__WARNING, 0, "Misc", "Unable to parse the file 'log_config.xml' or it does not exist. Default values will be used");
return false;
}
for (i = 0; i < main_node.nChildNode("LogConfig"); i++)
ProcessLogConfig(main_node.getChildNode("LogConfig", i));
return true;
}

69
old/Log.h Normal file
View File

@ -0,0 +1,69 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOG_H_
#define LOG_H_
#include <string.h>
#include "../WorldServer/client.h"
#define LOG_BUFFER_SIZE 4096
#define LOG_CATEGORY(category) LOG_ ##category ,
enum LogCategory
{
#include "LogTypes.h"
NUMBER_OF_LOG_CATEGORIES
};
#define LOG_TYPE(category, type, level, color, enabled, logfile, console, client, str) category##__##type ,
enum LogType
{
#include "LogTypes.h"
NUMBER_OF_LOG_TYPES
};
extern const char* log_category_names[NUMBER_OF_LOG_CATEGORIES];
struct LogTypeStatus
{
int8 level;
int color;
bool enabled;
bool logfile;
bool console;
bool client;
LogCategory category;
const char *name;
const char *display_name;
};
extern LogTypeStatus* log_type_info;
void LogStart();
void LogStop();
int8 GetLoggerLevel(LogType type);
void LogWrite(LogType type, int8 log_level, const char *cat_text, const char *fmt, ...);
#ifdef PARSER
void ColorizeLog(int color, char *date, const char *display_name, const char *category, string buffer);
#endif
bool LogParseConfigs();
#endif

528
old/LogTypes.h Normal file
View File

@ -0,0 +1,528 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOG_CATEGORY
#define LOG_CATEGORY(name)
#endif
#ifndef LOG_TYPE
#define LOG_TYPE(category, type, level, color, enabled, logfile, console, client, str)
#endif
#ifndef ENABLED
#define ENABLED true
#endif
#ifndef DISABLED
#define DISABLED false
#endif
#ifdef _WIN32
#define FOREGROUND_WHITE (FOREGROUND_RED |FOREGROUND_GREEN | FOREGROUND_BLUE)
#define FOREGROUND_WHITE_BOLD (FOREGROUND_RED |FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY)
#define FOREGROUND_RED_BOLD (FOREGROUND_RED | FOREGROUND_INTENSITY)
#define FOREGROUND_GREEN_BOLD (FOREGROUND_GREEN | FOREGROUND_INTENSITY)
#define FOREGROUND_BLUE_BOLD (FOREGROUND_BLUE | FOREGROUND_INTENSITY)
#define FOREGROUND_YELLOW (FOREGROUND_RED | FOREGROUND_GREEN)
#define FOREGROUND_YELLOW_BOLD (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY)
#define FOREGROUND_CYAN (FOREGROUND_GREEN | FOREGROUND_BLUE)
#define FOREGROUND_CYAN_BOLD (FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY)
#define FOREGROUND_MAGENTA (FOREGROUND_RED | FOREGROUND_BLUE)
#define FOREGROUND_MAGENTA_BOLD (FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY)
#else
#define FOREGROUND_WHITE 37
#define FOREGROUND_WHITE_BOLD 137
#define FOREGROUND_RED 31
#define FOREGROUND_RED_BOLD 131
#define FOREGROUND_GREEN 32
#define FOREGROUND_GREEN_BOLD 132
#define FOREGROUND_BLUE 34
#define FOREGROUND_BLUE_BOLD 134
#define FOREGROUND_YELLOW 33
#define FOREGROUND_YELLOW_BOLD 133
#define FOREGROUND_CYAN 36
#define FOREGROUND_CYAN_BOLD 136
#define FOREGROUND_MAGENTA 35
#define FOREGROUND_MAGENTA_BOLD 135
#endif
#define LOG_LOGFILE 1
#define LOG_CONSOLE 2
#define LOG_CLIENT 4 /* not yet using */
/*
Legend for str output (optional):
I : Information messages
W : Warning messages
E : Error messages
D : Debug messages
P : DumpPacket/PrintPacket messages - should NEVER go to Client channel!!!
T : Low-level debug tracing messages - should NEVER go to Client channel!!!
Note: If str = null, output #catagory__#type to logs
*/
/*** SYSTEM Loggers ******************************************************************************/
// Logging specific to general events within the World code
LOG_CATEGORY(WORLD)
LOG_TYPE(WORLD, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I") // Information messages (minimum output)
LOG_TYPE(WORLD, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W") // Warning messages
LOG_TYPE(WORLD, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E") // Error messages (should always be enabled)
LOG_TYPE(WORLD, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D") // Debug messages (enabled during alpha dev)
LOG_TYPE(WORLD, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P") // DumpPacket/PrintPacket messages
LOG_TYPE(WORLD, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T") // Low-level debug tracing messages
// LoginServer and MiniLogin events
LOG_CATEGORY(LOGIN)
LOG_TYPE(LOGIN, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(LOGIN, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(LOGIN, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(LOGIN, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(LOGIN, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(LOGIN, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// PatchServer (DB auto-patcher) events
LOG_CATEGORY(PATCHER)
LOG_TYPE(PATCHER, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(PATCHER, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(PATCHER, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(PATCHER, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(PATCHER, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(PATCHER, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// PacketParser events
LOG_CATEGORY(PARSER)
LOG_TYPE(PARSER, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(PARSER, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(PARSER, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(PARSER, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(PARSER, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(PARSER, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// World/Login/Patcher/Parser Initialization loggers
LOG_CATEGORY(INIT)
LOG_TYPE(INIT, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(INIT, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(INIT, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(INIT, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(INIT, LOGIN_INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(INIT, LOGIN_WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(INIT, LOGIN_ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(INIT, LOGIN_DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(INIT, PATCHER_INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(INIT, PATCHER_WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(INIT, PATCHER_ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(INIT, PATCHER_DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
// General DB logging
LOG_CATEGORY(DATABASE)
LOG_TYPE(DATABASE, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(DATABASE, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(DATABASE, QUERY, 0, FOREGROUND_CYAN, DISABLED, DISABLED, DISABLED, DISABLED, "Q")
LOG_TYPE(DATABASE, RESULT, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "R")
LOG_TYPE(DATABASE, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(DATABASE, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
// Logging Mutex code
LOG_CATEGORY(MUTEX)
LOG_TYPE(MUTEX, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(MUTEX, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(MUTEX, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(MUTEX, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(MUTEX, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(MUTEX, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// anything else... including a special DEV type "TODO"
LOG_CATEGORY(MISC)
LOG_TYPE(MISC, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(MISC, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(MISC, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(MISC, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(MISC, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(MISC, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
LOG_TYPE(MISC, TODO, 0, FOREGROUND_YELLOW_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "M")
/*** NETWORK Loggers *****************************************************************************/
// Client Communications Logging
LOG_CATEGORY(CCLIENT)
LOG_TYPE(CCLIENT, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(CCLIENT, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(CCLIENT, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(CCLIENT, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(CCLIENT, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(CCLIENT, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Logging Net code
LOG_CATEGORY(NET)
LOG_TYPE(NET, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(NET, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(NET, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(NET, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(NET, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(NET, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Logging opcodes as they are encountered
LOG_CATEGORY(OPCODE)
LOG_TYPE(OPCODE, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(OPCODE, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(OPCODE, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(OPCODE, DEBUG, 0, FOREGROUND_MAGENTA_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(OPCODE, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(OPCODE, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Special category for dumping out excessive DumpPacket or Opcode debugging entries - All DISABLED by default!
LOG_CATEGORY(PACKET)
LOG_TYPE(PACKET, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(PACKET, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(PACKET, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(PACKET, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(PACKET, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(PACKET, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
/*** PLAYER Loggers ******************************************************************************/
// Events related to character progress
LOG_CATEGORY(PLAYER)
LOG_TYPE(PLAYER, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(PLAYER, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(PLAYER, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(PLAYER, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(PLAYER, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(PLAYER, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
/*** SUBSYSTEM Loggers ***************************************************************************/
// Achievements Logging
LOG_CATEGORY(ACHIEVEMENT)
LOG_TYPE(ACHIEVEMENT, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(ACHIEVEMENT, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(ACHIEVEMENT, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(ACHIEVEMENT, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(ACHIEVEMENT, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(ACHIEVEMENT, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Chat Logging
LOG_CATEGORY(CHAT)
LOG_TYPE(CHAT, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(CHAT, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(CHAT, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(CHAT, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(CHAT, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(CHAT, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Collection generated events
LOG_CATEGORY(COLLECTION)
LOG_TYPE(COLLECTION, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(COLLECTION, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(COLLECTION, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(COLLECTION, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(COLLECTION, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(COLLECTION, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Events related to combat,aggro, hate, melee, damages, etc.
LOG_CATEGORY(COMBAT)
LOG_TYPE(COMBAT, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(COMBAT, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(COMBAT, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(COMBAT, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(COMBAT, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(COMBAT, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Events related to commands (slash commands, UI commands, etc)
LOG_CATEGORY(COMMAND)
LOG_TYPE(COMMAND, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(COMMAND, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(COMMAND, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(COMMAND, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(COMMAND, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(COMMAND, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Faction-related events, adjustments, querying, etc.
LOG_CATEGORY(FACTION)
LOG_TYPE(FACTION, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(FACTION, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(FACTION, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(FACTION, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(FACTION, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(FACTION, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Guild events, members, logging, permissions, recruiting, etc.
LOG_CATEGORY(GUILD)
LOG_TYPE(GUILD, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(GUILD, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(GUILD, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(GUILD, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(GUILD, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(GUILD, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Group events, members, permissions, etc.
LOG_CATEGORY(GROUP)
LOG_TYPE(GROUP, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(GROUP, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(GROUP, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(GROUP, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(GROUP, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(GROUP, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Item events, stats, appearances, loading/reloading, etc.
LOG_CATEGORY(ITEM)
LOG_TYPE(ITEM, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(ITEM, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(ITEM, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(ITEM, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(ITEM, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(ITEM, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Loot events, loot lists, rules, smart loot
LOG_CATEGORY(LOOT)
LOG_TYPE(LOOT, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(LOOT, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(LOOT, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(LOOT, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(LOOT, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(LOOT, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Events that occur within the LUA subsystem
LOG_CATEGORY(LUA)
LOG_TYPE(LUA, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(LUA, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(LUA, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(LUA, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(LUA, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(LUA, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Merchant events, buy/sell/broker, faction merchants, etc.
LOG_CATEGORY(MERCHANT)
LOG_TYPE(MERCHANT, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(MERCHANT, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(MERCHANT, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(MERCHANT, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(MERCHANT, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(MERCHANT, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// NPC events, stats, appearances, movement, gear, abilities, etc.
LOG_CATEGORY(NPC)
LOG_TYPE(NPC, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(NPC, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(NPC, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(NPC, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(NPC, COMBAT, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(NPC, SPELLS, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(NPC, AI, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(NPC, DAMAGE, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(NPC, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(NPC, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// What is that NPC thinking?! ...etc.
LOG_CATEGORY(NPC_AI)
LOG_TYPE(NPC_AI, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(NPC_AI, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(NPC_AI, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(NPC_AI, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(NPC_AI, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(NPC_AI, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// PET events, stats, appearances, movement, gear, abilities, etc.
LOG_CATEGORY(PET)
LOG_TYPE(PET, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(PET, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(PET, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(PET, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(PET, COMBAT, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(PET, SPELLS, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(PET, AI, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(PET, DAMAGE, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(PET, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(PET, TRACE, 0, FOREGROUND_GREEN, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Quest generated events
LOG_CATEGORY(QUEST)
LOG_TYPE(QUEST, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(QUEST, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(QUEST, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(QUEST, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(QUEST, REWARD, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(QUEST, STEP, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(QUEST, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(QUEST, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Events relating to Recipes in the world
LOG_CATEGORY(RECIPE)
LOG_TYPE(RECIPE, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(RECIPE, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(RECIPE, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(RECIPE, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(RECIPE, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(RECIPE, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Events relating to Rules in the world
LOG_CATEGORY(RULESYS)
LOG_TYPE(RULESYS, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(RULESYS, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(RULESYS, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(RULESYS, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(RULESYS, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(RULESYS, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// The Skill system, books, scribing, stats, usage
LOG_CATEGORY(SKILL)
LOG_TYPE(SKILL, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(SKILL, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(SKILL, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(SKILL, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(SKILL, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(SKILL, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// The Spell system, books, scribing, stats, usage
LOG_CATEGORY(SPELL)
LOG_TYPE(SPELL, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(SPELL, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(SPELL, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(SPELL, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(SPELL, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(SPELL, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// The Crafting system, recipies, reactions, progress, etc.
LOG_CATEGORY(TRADESKILL)
LOG_TYPE(TRADESKILL, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(TRADESKILL, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(TRADESKILL, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(TRADESKILL, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(TRADESKILL, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(TRADESKILL, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// The Transportation system, teleporters, mounts, etc.
LOG_CATEGORY(TRANSPORT)
LOG_TYPE(TRANSPORT, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(TRANSPORT, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(TRANSPORT, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(TRANSPORT, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(TRANSPORT, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(TRANSPORT, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
/*** SPAWN Loggers *******************************************************************************/
// General Spawn events, location, placement, grouping
LOG_CATEGORY(SPAWN)
LOG_TYPE(SPAWN, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(SPAWN, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(SPAWN, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(SPAWN, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(SPAWN, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(SPAWN, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Events relating to interactable objects in the world
LOG_CATEGORY(OBJECT)
LOG_TYPE(OBJECT, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(OBJECT, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(OBJECT, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(OBJECT, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(OBJECT, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(OBJECT, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Events relating to Signs in the world
LOG_CATEGORY(SIGN)
LOG_TYPE(SIGN, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(SIGN, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(SIGN, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(SIGN, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(SIGN, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(SIGN, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Events relating to Widgets in the world
LOG_CATEGORY(WIDGET)
LOG_TYPE(WIDGET, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(WIDGET, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(WIDGET, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(WIDGET, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(WIDGET, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(WIDGET, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Events relating to Groundspawns in the world
LOG_CATEGORY(GROUNDSPAWN)
LOG_TYPE(GROUNDSPAWN, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(GROUNDSPAWN, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(GROUNDSPAWN, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(GROUNDSPAWN, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(GROUNDSPAWN, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(GROUNDSPAWN, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
/*** ZONE Loggers ********************************************************************************/
// Zone-related events, status, messaging, access
LOG_CATEGORY(ZONE)
LOG_TYPE(ZONE, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(ZONE, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(ZONE, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(ZONE, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(ZONE, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(ZONE, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Instance loading/reloading, etc.
LOG_CATEGORY(INSTANCE)
LOG_TYPE(INSTANCE, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(INSTANCE, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(INSTANCE, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(INSTANCE, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(INSTANCE, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(INSTANCE, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
/*** MAP Loggers ********************************************************************************/
// Map-related events, status, messaging, access
LOG_CATEGORY(MAP)
LOG_TYPE(MAP, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(MAP, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(MAP, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(MAP, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(MAP, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(MAP, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
/*** Region Map Loggers ********************************************************************************/
// RegionMap-related events, status, messaging, access
LOG_CATEGORY(REGION)
LOG_TYPE(REGION, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(REGION, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(REGION, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(REGION, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(REGION, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(REGION, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
// Logging Peering code
LOG_CATEGORY(PEERING)
LOG_TYPE(PEERING, INFO, 0, FOREGROUND_WHITE_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "I")
LOG_TYPE(PEERING, WARNING, 0, FOREGROUND_YELLOW_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "W")
LOG_TYPE(PEERING, ERROR, 0, FOREGROUND_RED_BOLD, ENABLED, ENABLED, ENABLED, DISABLED, "E")
LOG_TYPE(PEERING, DEBUG, 0, FOREGROUND_GREEN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "D")
LOG_TYPE(PEERING, PACKET, 0, FOREGROUND_CYAN_BOLD, DISABLED, DISABLED, DISABLED, DISABLED, "P")
LOG_TYPE(PEERING, TRACE, 0, FOREGROUND_YELLOW, DISABLED, DISABLED, DISABLED, DISABLED, "T")
#undef LOG_TYPE
#undef LOG_CATEGORY
#undef ENABLED
#undef DISABLED

973
old/MiscFunctions.cpp Normal file
View File

@ -0,0 +1,973 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../common/debug.h"
#include "../common/Log.h"
#include "MiscFunctions.h"
#include <string.h>
#include <time.h>
#include <math.h>
#include <chrono>
#include <random>
#ifndef WIN32
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#include <iostream>
#include <iomanip>
#ifdef WIN32
#include <io.h>
#endif
#include "../common/timer.h"
#include "../common/seperator.h"
#include "../common/packet_dump.h"
#include <algorithm>
using namespace std;
#ifndef PATCHER
extern map<int16, int16> EQOpcodeVersions;
#endif
#ifdef WIN32
#include <WinSock2.h>
#include <windows.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/time.h>
#ifdef FREEBSD //Timothy Whitman - January 7, 2003
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <sys/stat.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#endif
void CoutTimestamp(bool ms) {
time_t rawtime;
struct tm* gmt_t;
time(&rawtime);
gmt_t = gmtime(&rawtime);
struct timeval read_time;
gettimeofday(&read_time,0);
cout << (gmt_t->tm_year + 1900) << "/" << setw(2) << setfill('0') << (gmt_t->tm_mon + 1) << "/" << setw(2) << setfill('0') << gmt_t->tm_mday << " " << setw(2) << setfill('0') << gmt_t->tm_hour << ":" << setw(2) << setfill('0') << gmt_t->tm_min << ":" << setw(2) << setfill('0') << gmt_t->tm_sec;
if (ms)
cout << "." << setw(3) << setfill('0') << (read_time.tv_usec / 1000);
cout << " GMT";
}
string loadInt32String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_32BitString* eq_string){
buffer += *pos;
int32 size = *(int32*)buffer;
if((size + *pos + sizeof(int16)) > buffer_size){
cout << "Error in loadInt32String: Corrupt packet.\n";
return string("");
}
buffer += sizeof(int32);
string ret((char*)buffer, 0, size);
if(eq_string){
eq_string->size = size;
eq_string->data = ret;
}
*pos += (size + sizeof(int32));
return ret;
}
string loadInt16String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_16BitString* eq_string){
buffer += *pos;
int16 size = *(int16*)buffer;
if((size + *pos + sizeof(int16))> buffer_size){
cout << "Error in loadInt16String: Corrupt packet.\n";
return string("");
}
buffer += sizeof(int16);
string ret((char*)buffer, 0, size);
if(eq_string){
eq_string->size = size;
eq_string->data = ret;
}
*pos += (size + sizeof(int16));
return ret;
}
string loadInt8String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_8BitString* eq_string){
buffer += *pos;
int8 size = *(int8*)buffer;
if((size + *pos + sizeof(int16)) > buffer_size){
cout << "Error in loadInt8String: Corrupt packet.\n";
return string("");
}
buffer += sizeof(int8);
string ret((char*)buffer, 0, size);
if(eq_string){
eq_string->size = size;
eq_string->data = ret;
}
*pos += (size + sizeof(int8));
return ret;
}
sint16 storeInt32String(uchar* buffer, int16 buffer_size, string in_str){
sint16 string_size = in_str.length();
if((string_size + sizeof(int32)) > buffer_size)
return -1;
memcpy(buffer, &string_size, sizeof(int32));
buffer += sizeof(int32);
memcpy(buffer, in_str.c_str(), string_size);
buffer += string_size;
return (buffer_size - (string_size + sizeof(int32)));
}
sint16 storeInt16String(uchar* buffer, int16 buffer_size, string in_str){
sint16 string_size = in_str.length();
if((string_size + sizeof(int16)) > buffer_size)
return -1;
memcpy(buffer, &string_size, sizeof(int16));
buffer += sizeof(int16);
memcpy(buffer, in_str.c_str(), string_size);
buffer += string_size;
return (buffer_size - (string_size + sizeof(int16)));
}
sint16 storeInt8String(uchar* buffer, int16 buffer_size, string in_str){
sint16 string_size = in_str.length();
if((string_size + sizeof(int8)) > buffer_size)
return -1;
memcpy(buffer, &string_size, sizeof(int8));
buffer += sizeof(int8);
memcpy(buffer, in_str.c_str(), string_size);
buffer += string_size;
return (buffer_size - (string_size + sizeof(int8)));
}
sint32 filesize(FILE* fp) {
#ifdef WIN32
return _filelength(_fileno(fp));
#else
struct stat file_stat;
fstat(fileno(fp), &file_stat);
return (sint32) file_stat.st_size;
#endif
}
int32 ResolveIP(const char* hostname, char* errbuf) {
#ifdef WIN32
static InitWinsock ws;
#endif
if (errbuf)
errbuf[0] = 0;
if (hostname == 0) {
if (errbuf)
snprintf(errbuf, ERRBUF_SIZE, "ResolveIP(): hostname == 0");
return 0;
}
struct sockaddr_in server_sin;
#ifdef WIN32
PHOSTENT phostent = NULL;
#else
struct hostent *phostent = NULL;
#endif
server_sin.sin_family = AF_INET;
if ((phostent = gethostbyname(hostname)) == NULL) {
#ifdef WIN32
if (errbuf)
snprintf(errbuf, ERRBUF_SIZE, "Unable to get the host name. Error: %i", WSAGetLastError());
#else
if (errbuf)
snprintf(errbuf, ERRBUF_SIZE, "Unable to get the host name. Error: %s", strerror(errno));
#endif
return 0;
}
#ifdef WIN32
memcpy ((char FAR *)&(server_sin.sin_addr), phostent->h_addr, phostent->h_length);
#else
memcpy ((char*)&(server_sin.sin_addr), phostent->h_addr, phostent->h_length);
#endif
return server_sin.sin_addr.s_addr;
}
#ifdef WIN32
InitWinsock::InitWinsock() {
WORD version = MAKEWORD (1,1);
WSADATA wsadata;
WSAStartup (version, &wsadata);
}
InitWinsock::~InitWinsock() {
WSACleanup();
}
#endif
#ifndef WIN32
const char * itoa(int value) {
static char temp[_ITOA_BUFLEN];
memset(temp, 0, _ITOA_BUFLEN);
snprintf(temp, _ITOA_BUFLEN,"%d", value);
return temp;
}
char * itoa(int value, char *result, int base) {
char *ptr1, *ptr2;
char c;
int tmp_value;
//need a valid base
if (base < 2 || base > 36) {
*result = '\0';
return result;
}
ptr1 = ptr2 = result;
do {
tmp_value = value;
value /= base;
*ptr1++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
}
while (value > 0);
//apply a negative sign if need be
if (tmp_value < 0)
*ptr1++ = '-';
*ptr1-- = '\0';
while (ptr2 < ptr1) {
c = *ptr1;
*ptr1-- = *ptr2;
*ptr2++ = c;
}
return result;
}
#endif
/*
* solar: generate a random integer in the range low-high
* this should be used instead of the rand()%limit method
*/
int MakeRandomInt(int low, int high)
{
return (int)MakeRandomFloat((double)low, (double)high + 0.999);
}
int32 hextoi(char* num) {
int len = strlen(num);
if (len < 3)
return 0;
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
return 0;
int32 ret = 0;
int mul = 1;
for (int i=len-1; i>=2; i--) {
if (num[i] >= 'A' && num[i] <= 'F')
ret += ((num[i] - 'A') + 10) * mul;
else if (num[i] >= 'a' && num[i] <= 'f')
ret += ((num[i] - 'a') + 10) * mul;
else if (num[i] >= '0' && num[i] <= '9')
ret += (num[i] - '0') * mul;
else
return 0;
mul *= 16;
}
return ret;
}
int64 hextoi64(char* num) {
int len = strlen(num);
if (len < 3)
return 0;
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
return 0;
int64 ret = 0;
int mul = 1;
for (int i=len-1; i>=2; i--) {
if (num[i] >= 'A' && num[i] <= 'F')
ret += ((num[i] - 'A') + 10) * mul;
else if (num[i] >= 'a' && num[i] <= 'f')
ret += ((num[i] - 'a') + 10) * mul;
else if (num[i] >= '0' && num[i] <= '9')
ret += (num[i] - '0') * mul;
else
return 0;
mul *= 16;
}
return ret;
}
float MakeRandomFloat(float low, float high) {
// Handle edge case where range is zero or inverted
float diff = high - low;
if(!diff) return low;
if (low == high) return low;
if (low > high) std::swap(low, high);
// Use a thread-local random generator for thread safety
thread_local std::mt19937 generator(std::random_device{}()); // Seed once per thread
std::uniform_real_distribution<float> distribution(low, high);
return distribution(generator);
}
int32 GenerateEQ2Color(float* r, float* g, float* b){
int8 rgb[4] = {0};
rgb[0] = (int8)((*r)*255);
rgb[1] = (int8)((*b)*255);
rgb[2] = (int8)((*g)*255);
int32 color = 0;
memcpy(&color, rgb, sizeof(int32));
return color;
}
int32 GenerateEQ2Color(float* rgb[3]){
return GenerateEQ2Color(rgb[0], rgb[1], rgb[2]);
}
int8 MakeInt8(float* input){
float input2 = *input;
if(input2 < 0)
input2 *= -1;
return (int8)(input2*255);
}
vector<string>* SplitString(string str, char delim){
vector<string>* results = new vector<string>;
int32 pos;
while((pos = str.find_first_of(delim))!= str.npos){
if(pos > 0){
results->push_back(str.substr(0,pos));
}
if(str.length() > pos)
str = str.substr(pos+1);
else
break;
}
if(str.length() > 0)
results->push_back(str);
return results;
}
bool Unpack(uchar* data, uchar* dst, int16 dstLen, int16 version, bool reverse){
int32 srcLen = 0;
memcpy(&srcLen, data, sizeof(int32));
return Unpack(srcLen, data + 4, dst, dstLen, version, reverse);
}
bool Unpack(int32 srcLen, uchar* data, uchar* dst, int16 dstLen, int16 version, bool reverse) {
// int32 srcLen = 0;
// memcpy(&srcLen, data, sizeof(int32));
// data+=4;
if(reverse)
Reverse(data, srcLen);
int16 pos = 0;
int16 real_pos = 0;
while(srcLen && pos < dstLen) {
if(srcLen >= 0 && !srcLen--)
return false;
int8 code = data[real_pos++];
if(code >= 128) {
for(int8 index=0; index<7; index++) {
if(code & 1) {
if(pos >= dstLen)
return false;
if(srcLen >= 0 && !srcLen--)
return false;
dst[pos++] = data[real_pos++];
} else {
if(pos < dstLen) dst[pos++] = 0;
}
code >>= 1;
}
} else {
if(pos + code > dstLen)
return false;
memset(dst+pos, 0, code);
pos+=code;
}
}
return srcLen <= 0;
}
int32 Pack(uchar* data, uchar* src, int16 srcLen, int16 dstLen, int16 version, bool reverse) {
int16 real_pos = 4;
int32 pos = 0;
int32 code = 0;
int codePos = 0;
int codeLen = 0;
int8 zeroLen = 0;
memset(data,0,dstLen);
if (version > 1 && version <= 374)
reverse = false;
while(pos < srcLen) {
if(src[pos] || codeLen) {
if(!codeLen) {
/*if(zeroLen > 5) {
data[real_pos++] = zeroLen;
zeroLen = 0;
}
else if(zeroLen >= 1 && zeroLen<=5){
for(;zeroLen>0;zeroLen--)
codeLen++;
}*/
if (zeroLen) {
data[real_pos++] = zeroLen;
zeroLen = 0;
}
codePos = real_pos;
code = 0;
data[real_pos++] = 0;
}
if(src[pos]) {
data[real_pos++] = src[pos];
code |= 0x80;
}
code >>= 1;
codeLen++;
if(codeLen == 7) {
data[codePos] = int8(0x80 | code);
codeLen = 0;
}
} else {
if(zeroLen == 0x7F) {
data[real_pos++] = zeroLen;
zeroLen = 0;
}
zeroLen++;
}
pos++;
}
if(codeLen) {
code >>= (7 - codeLen);
data[codePos] = int8(0x80 | code);
} else if(zeroLen) {
data[real_pos++] = zeroLen;
}
if(reverse)
Reverse(data + 4, real_pos - 4);
int32 dataLen = real_pos - 4;
memcpy(&data[0], &dataLen, sizeof(int32));
return dataLen + 4;
}
void Reverse(uchar* input, int32 srcLen){
int16 real_pos = 0;
int16 orig_pos = 0;
int8 reverse_count = 0;
while(srcLen > 0 && srcLen < 0xFFFFFFFF){ // XXX it was >=0 before. but i think it was a bug
int8 code = input[real_pos++];
srcLen--;
if(code >= 128) {
for(int8 index=0; index<7; index++) {
if(code & 1) {
if(srcLen >= 0 && !srcLen--)
return;
real_pos++;
reverse_count++;
}
code >>= 1;
}
}
if(reverse_count > 0){
int8 tmp_data[8] = {0};
for(int8 i=0;i<reverse_count;i++){
tmp_data[i] = input[orig_pos + reverse_count-i];
}
memcpy(input + orig_pos + 1, tmp_data, reverse_count);
reverse_count = 0;
}
orig_pos = real_pos;
}
}
void MovementDecode(uchar* dst, uchar* newval, uchar* orig, int16 len){
int16 pos = len;
while(pos--)
dst[pos] = newval[pos] ^ orig[pos];
}
void Decode(uchar* dst, uchar* src, int16 len) {
int16 pos = len;
while(pos--)
dst[pos] ^= src[pos];
memcpy(src, dst, len);
}
void Encode(uchar* dst, uchar* src, int16 len) {
uchar* data = new uchar[len];
int16 pos = len;
while(pos--)
data[pos] = int8(src[pos] ^ dst[pos]);
memcpy(src, dst, len);
memcpy(dst, data, len);
safe_delete_array(data);
}
float TransformToFloat(sint16 data, int8 bits) {
return (float)(data / (float)(1 << bits));
}
sint16 TransformFromFloat(float data, int8 bits) {
return (sint16)(data * (1 << bits));
}
void SetColor(EQ2_Color* color, long data){
memcpy(color, &data, sizeof(EQ2_Color));
}
string ToUpper(string input){
string ret = input;
transform(input.begin(), input.end(), ret.begin(), ::toupper);
return ret;
}
string ToLower(string input){
string ret = input;
transform(input.begin(), input.end(), ret.begin(), ::tolower);
return ret;
}
int32 ParseIntValue(string input){
int32 ret = 0xFFFFFFFF;
try{
if(input.length() > 0){
ret = atoul(input.c_str());
}
}
catch(...){}
return ret;
}
int64 ParseLongLongValue(string input){
int64 ret = 0xFFFFFFFFFFFFFFFF;
try{
if(input.length() > 0){
#ifdef WIN32
ret = _strtoui64(input.c_str(), NULL, 10);
#else
ret = strtoull(input.c_str(), 0, 10);
#endif
}
}
catch(...){}
return ret;
}
map<string, string> TranslateBrokerRequest(string request){
map<string, string> ret;
string key;
string value;
int32 start_pos = 0;
int32 end_pos = 0;
int32 pos = request.find("=");
bool str_val = false;
while(pos < 0xFFFFFFFF){
str_val = false;
key = request.substr(start_pos, pos-start_pos);
if(request.find("|", pos) == pos+1){
pos++;
end_pos = request.find("|", pos+1);
str_val = true;
}
else
end_pos = request.find(" ", pos);
if(end_pos < 0xFFFFFFFF){
value = request.substr(pos+1, end_pos-pos-1);
start_pos = end_pos+1;
if(str_val){
start_pos++;
ret[key] = ToLower(value);
}
else
ret[key] = value;
pos = request.find("=", start_pos);
}
else{
value = request.substr(pos+1);
if(str_val){
start_pos++;
ret[key] = ToLower(value);
}
else
ret[key] = value;
break;
}
}
return ret;
}
int8 CheckOverLoadSize(int32 val){
int8 ret = 1;
if(val >= 0xFFFF) //int32
ret = sizeof(int16) + sizeof(int32);
else if(val >= 0xFF)
ret = sizeof(int8) + sizeof(int16);
return ret;
}
int8 DoOverLoad(int32 val, uchar* data){
int8 ret = 1;
if(val >= 0xFFFF){ //int32
memset(data, 0xFF, sizeof(int16));
memcpy(data + sizeof(int16), &val, sizeof(int32));
ret = sizeof(int16) + sizeof(int32);
}
else if(val >= 0xFF){ //int16
memset(data, 0xFF, sizeof(int8));
memcpy(data + sizeof(int8), &val, sizeof(int16));
ret = sizeof(int8) + sizeof(int16);
}
else
memcpy(data, &val, sizeof(int8));
return ret;
}
/* Treats contiguous spaces as one space. */
int32 CountWordsInString(const char* text) {
int32 words = 0;
if (text && strlen(text) > 0) {
bool on_word = false;
for (int32 i = 0; i < strlen(text); i++) {
char letter = text[i];
if (on_word && !((letter >= 48 && letter <= 57) || (letter >= 65 && letter <= 90) || (letter >= 97 && letter <= 122)))
on_word = false;
else if (!on_word && ((letter >= 48 && letter <= 57) || (letter >= 65 && letter <= 90) || (letter >= 97 && letter <= 122))){
on_word = true;
words++;
}
}
}
return words;
}
bool IsNumber(const char *num) {
size_t len, i;
if (!num)
return false;
len = strlen(num);
if (len == 0)
return false;
for (i = 0; i < len; i++) {
if (!isdigit(num[i]))
return false;
}
return true;
}
void PrintSep(Seperator *sep, const char *name) {
int32 i = 0;
LogWrite(MISC__DEBUG, 0, "Misc", "Printing sep %s", name ? name : "No Name");
if (!sep)
LogWrite(MISC__DEBUG, 0, "Misc", "\tSep is null");
else {
while (sep->arg[i] && strlen(sep->arg[i]) > 0) {
LogWrite(MISC__DEBUG, 0, "Misc", "\t%i => %s", i, sep->arg[i]);
i++;
}
}
}
#define INI_IGNORE(c) (c == '\n' || c == '\r' || c == '#')
static bool INIGoToSection(FILE *f, const char *section) {
size_t size = strlen(section) + 3;
char line[256], *buf, *tmp;
bool found = false;
if ((buf = (char *)malloc(size)) == NULL) {
fprintf(stderr, "%s: %u: Unable to allocate %zu bytes\n", __FUNCTION__, __LINE__, size);
return false;
}
sprintf(buf, "[%s]", section);
while (fgets(line, sizeof(line), f) != NULL) {
if (INI_IGNORE(line[0]))
continue;
if (line[0] == '[') {
if ((tmp = strstr(line, "\n")) != NULL)
*tmp = '\0';
if ((tmp = strstr(line, "\r")) != NULL)
*tmp = '\0';
if (strcasecmp(buf, line) == 0) {
found = true;
break;
}
}
}
free(buf);
return found;
}
static char * INIFindValue(FILE *f, const char *section, const char *property) {
char line[256], *key, *val;
if (section != NULL && !INIGoToSection(f, section))
return NULL;
while (fgets(line, sizeof(line), f) != NULL) {
if (INI_IGNORE(line[0]))
continue;
if (section != NULL && line[0] == '[')
return NULL;
if ((key = strtok(line, "=")) == NULL)
continue;
if (strcasecmp(key, property) == 0) {
val = strtok(NULL, "\n\r");
if (val == NULL)
return NULL;
return strdup(val);
}
}
return NULL;
}
bool INIReadInt(FILE *f, const char *section, const char *property, int *out) {
char *value;
rewind(f);
if ((value = INIFindValue(f, section, property)) == NULL)
return false;
if (!IsNumber(value)) {
free(value);
return false;
}
*out = atoi(value);
free(value);
return true;
}
bool INIReadBool(FILE *f, const char *section, const char *property, bool *out) {
char *value;
rewind(f);
if ((value = INIFindValue(f, section, property)) == NULL)
return false;
*out = (strcasecmp(value, "1") == 0 || strcasecmp(value, "true") == 0 || strcasecmp(value, "on") == 0 || strcasecmp(value, "yes") == 0);
free(value);
return true;
}
string GetDeviceName(string device) {
if (device == "chemistry_table")
device = "Chemistry Table";
else if (device == "work_desk")
device = "Engraved Desk";
else if (device == "forge")
device = "Forge";
else if (device == "stove and keg")
device = "Stove & Keg";
else if (device == "sewing_table")
device = "Sewing Table & Mannequin";
else if (device == "woodworking_table")
device = "Woodworking Table";
else if (device == "work_bench")
device = "Work Bench";
else if (device == "crafting_intro_anvil")
device = "Mender's Anvil";
return device;
}
int32 GetDeviceID(string device) {
if (device == "Chemistry Table")
return 3;
else if (device == "Engraved Desk")
return 4;
else if (device == "Forge")
return 2;
else if (device == "Stove & Keg")
return 7;
else if (device == "Sewing Table & Mannequin")
return 1;
else if (device == "Woodworking Table")
return 6;
else if (device == "Work Bench")
return 5;
else if (device == "Mender's Anvil")
return 0xFFFFFFFF;
return 0;
}
int16 GetItemPacketType(int32 version) {
int16 item_version;
if (version >= 64707)
item_version = 0x5CFE;
else if (version >= 63119)
item_version = 0x56FE;
else if (version >= 60024)
item_version = 0x51FE;
else if (version >= 57107)
item_version = 0x4CFE;
else if (version >= 57048)
item_version = 0x48FE;
else if (version >= 1199)
item_version = 0x44FE;
else if (version >= 1195)
item_version = 0x40FE;
else if (version >= 1193)
item_version = 0x3FFE;
else if (version >= 1190)
item_version = 0x3EFE;
else if (version >= 1188)
item_version = 0x3DFE;
else if (version >= 1096)
item_version = 0x35FE;
else if (version >= 1027)
item_version = 0x31FE;
else if (version >= 1008)
item_version = 0x2CFE;
else if (version >= 927)
item_version = 0x23FE;
else if (version >= 893)
item_version = 0x22FE;
else if (version >= 860)
item_version = 0x20FE;
else if (version > 546)
item_version = 0x1CFE;
else
item_version = 0;
return item_version;
}
#ifndef PATCHER
int16 GetOpcodeVersion(int16 version) {
int16 ret = version;
int16 version1 = 0;
int16 version2 = 0;
map<int16, int16>::iterator itr;
for (itr = EQOpcodeVersions.begin(); itr != EQOpcodeVersions.end(); itr++) {
version1 = itr->first;
version2 = itr->second;
if (version >= version1 && version <= version2) {
ret = version1;
break;
}
}
return ret;
}
#endif
void SleepMS(int32 milliseconds) {
#if defined(_WIN32)
Sleep(milliseconds);
#else
usleep(milliseconds * 1000);
#endif
}
size_t
strlcpy(char *dst, const char *src, size_t size) {
char *d = dst;
const char *s = src;
size_t n = size;
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
if (n == 0) {
if (size != 0)
*d = '\0';
while (*s++)
;
}
return(s - src - 1);
}
float short_to_float(const ushort x) { // IEEE-754 16-bit floating-point format (without infinity): 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits
const uint32 e = (x & 0x7C00) >> 10; // exponent
const uint32 m = (x & 0x03FF) << 13; // mantissa
const uint32 v = as_uint((float)m) >> 23; // evil log2 bit hack to count leading zeros in denormalized format
return as_float((x & 0x8000) << 16 | (e != 0) * ((e + 112) << 23 | m) | ((e == 0) & (m != 0)) * ((v - 37) << 23 | ((m << (150 - v)) & 0x007FE000))); // sign : normalized : denormalized
}
uint32 float_to_int(const float x) { // IEEE-754 16-bit floating-point format (without infinity): 1-5-10, exp-15, +-131008.0, +-6.1035156E-5, +-5.9604645E-8, 3.311 digits
const uint32 b = as_uint(x) + 0x00001000; // round-to-nearest-even: add last bit after truncated mantissa
const uint32 e = (b & 0x7F800000) >> 23; // exponent
const uint32 m = b & 0x007FFFFF; // mantissa; in line below: 0x007FF000 = 0x00800000-0x00001000 = decimal indicator flag - initial rounding
return (b & 0x80000000) >> 16 | (e > 112)* ((((e - 112) << 10) & 0x7C00) | m >> 13) | ((e < 113) & (e > 101))* ((((0x007FF000 + m) >> (125 - e)) + 1) >> 1) | (e > 143) * 0x7FFF; // sign : normalized : denormalized : saturate
}
uint32 as_uint(const float x) {
return *(uint32*)&x;
}
float as_float(const uint32 x) {
return *(float*)&x;
}
// Function to get the current timestamp in milliseconds
int64 getCurrentTimestamp() {
auto now = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
return duration.count();
}
std::tuple<int64, int64, int64, int64> convertTimestampDuration(int64 total_milliseconds) {
std::chrono::milliseconds duration(total_milliseconds);
// Convert to days, hours, minutes, and seconds
auto hours = std::chrono::duration_cast<std::chrono::hours>(duration);
duration -= hours;
auto days = hours / 24;
hours -= days * 24;
auto minutes = std::chrono::duration_cast<std::chrono::minutes>(duration);
duration -= minutes;
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
// Return the result as a tuple
return std::make_tuple(days.count(), hours.count(), minutes.count(), seconds.count());
}

228
old/MiscFunctions.h Normal file
View File

@ -0,0 +1,228 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MISCFUNCTIONS_H
#define MISCFUNCTIONS_H
#include "types.h"
#include "seperator.h"
#include <stdio.h>
#include <ctype.h>
#include <vector>
#include <map>
#include <tuple>
#include <string>
#include <sstream>
#include <cstdint>
#ifndef ERRBUF_SIZE
#define ERRBUF_SIZE 1024
#endif
//int MakeAnyLenString(char** ret, const char* format, ...);
int32 hextoi(char* num);
int64 hextoi64(char* num);
sint32 filesize(FILE* fp);
int32 ResolveIP(const char* hostname, char* errbuf = 0);
void CoutTimestamp(bool ms = true);
//char* strn0cpy(char* dest, const char* source, int32 size);
// return value =true if entire string(source) fit, false if it was truncated
//bool strn0cpyt(char* dest, const char* source, int32 size);
string loadInt32String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_32BitString* eq_string = NULL);
string loadInt16String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_16BitString* eq_string = NULL);
string loadInt8String(uchar* buffer, int16 buffer_size, int16* pos, EQ2_8BitString* eq_string = NULL);
sint16 storeInt32String(uchar* buffer, int16 buffer_size, string in_str);
sint16 storeInt16String(uchar* buffer, int16 buffer_size, string in_str);
sint16 storeInt8String(uchar* buffer, int16 buffer_size, string in_str);
int MakeRandomInt(int low, int high);
float MakeRandomFloat(float low, float high);
float TransformToFloat(sint16 data, int8 bits);
sint16 TransformFromFloat(float data, int8 bits);
int32 GenerateEQ2Color(float r, float g, float b);
int32 GenerateEQ2Color(float* rgb[3]);
void SetColor(EQ2_Color* color, long data);
//void CreateEQ2Color(EQ2_Color* color, uchar* data, int16* size);
int8 MakeInt8(uchar* data, int16* size);
int8 MakeInt8(float* input);
bool Unpack(int32 srcLen, uchar* data, uchar* dst, int16 dstLen, int16 version = 0, bool reverse = true);
bool Unpack(uchar* data, uchar* dst, int16 dstLen, int16 version = 0, bool reverse = true);
int32 Pack(uchar* data, uchar* src, int16 srcLen, int16 dstLen, int16 version = 0, bool reverse = true);
void Reverse(uchar* input, int32 srcLen);
void Encode(uchar* dst, uchar* src, int16 len);
void Decode(uchar* dst, uchar* src, int16 len);
string ToUpper(string input);
string ToLower(string input);
int32 ParseIntValue(string input);
int64 ParseLongLongValue(string input);
map<string, string> TranslateBrokerRequest(string request);
void MovementDecode(uchar* dst, uchar* newval, uchar* orig, int16 len);
vector<string>* SplitString(string str, char delim);
int8 DoOverLoad(int32 val, uchar* data);
int8 CheckOverLoadSize(int32 val);
int32 CountWordsInString(const char* text);
bool IsNumber(const char *num);
void PrintSep(Seperator *sep, const char *name = 0);
string GetDeviceName(string device);
int32 GetDeviceID(string device);
///<summary>Gets the packet type for the given version</summary>
///<param name='version'>The client version</param>
int16 GetItemPacketType(int32 version);
///<summary>Gets the opcode version_range1 from the clients version</summary>
///<param name='version'>The client version</param>
int16 GetOpcodeVersion(int16 version);
void SleepMS(int32 milliseconds);
size_t strlcpy(char *dst, const char *src, size_t size);
float short_to_float(const ushort x);
uint32 float_to_int(const float x);
uint32 as_uint(const float x);
float as_float(const uint32 x);
int64 getCurrentTimestamp();
std::tuple<int64, int64, int64, int64> convertTimestampDuration(int64 total_milliseconds);
bool INIReadBool(FILE *f, const char *section, const char *property, bool *out);
bool INIReadInt(FILE *f, const char *section, const char *property, int *out);
static bool IsPrivateAddress(uint32_t ip)
{
uint8_t b1, b2;//, b3, b4;
b1 = (uint8_t)(ip >> 24);
b2 = (uint8_t)((ip >> 16) & 0x0ff);
//b3 = (uint8_t)((ip >> 8) & 0x0ff);
//b4 = (uint8_t)(ip & 0x0ff);
// 10.x.y.z
if (b1 == 10)
return true;
// 172.16.0.0 - 172.31.255.255
if ((b1 == 172) && (b2 >= 16) && (b2 <= 31))
return true;
// 192.168.0.0 - 192.168.255.255
if ((b1 == 192) && (b2 == 168))
return true;
return false;
}
static std::string FormatCoinReceiveMessage(int64 total_copper, const std::string& reason) {
// breakdown into denominations
int64 platinum = total_copper / 1'000'000;
int64 rem = total_copper % 1'000'000;
int64 gold = rem / 10'000;
rem %= 10'000;
int64 silver = rem / 100;
int64 copper = rem % 100;
std::ostringstream oss;
oss << "You received ";
bool first = true;
if (platinum > 0) {
oss << platinum << " platinum";
first = false;
}
if (gold > 0) {
if (!first) oss << ", ";
oss << gold << " gold";
first = false;
}
if (silver > 0) {
if (!first) oss << ", ";
oss << silver << " silver";
first = false;
}
// if nothing else or there's copper, show copper
if (copper > 0 || first) {
if (!first) oss << ", ";
oss << copper << " copper";
}
oss << " earned through " << reason;
return oss.str();
}
template<class Type> void AddData(Type input, string* datastring){
if(datastring)
datastring->append((char*)&input, sizeof(input));
}
template<class Type> void AddData(Type input, int32 array_size, string* datastring){
if(array_size>0){
for(int32 i=0;i<array_size;i++)
AddData(input[i], datastring);
}
else
AddData(input, datastring);
}
#ifndef WIN32
#define _ITOA_BUFLEN 25
const char * itoa(int value);
char * itoa(int value, char *result, int base);
#endif
class InitWinsock {
public:
InitWinsock();
~InitWinsock();
};
template<class T> class AutoDelete {
public:
AutoDelete(T** iVar, T* iSetTo = 0) {
init(iVar, iSetTo);
}
AutoDelete() {}
void init(T** iVar, T* iSetTo = 0)
{
pVar = iVar;
if (iSetTo)
*pVar = iSetTo;
}
~AutoDelete() {
safe_delete(*pVar);
}
private:
T** pVar;
};
class VersionRange {
public:
VersionRange(int32 in_min_version, int32 in_max_version)
{
min_version = in_min_version;
max_version = in_max_version;
}
int32 GetMinVersion() { return min_version; }
int32 GetMaxVersion() { return max_version; }
private:
int32 min_version;
int32 max_version;
};
#endif

361
old/Mutex.cpp Normal file
View File

@ -0,0 +1,361 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../common/Log.h"
#include "../common/debug.h"
#include "../common/Mutex.h"
Mutex::Mutex() {
readers = 0;
mlocked = false;
writing = false;
name = "";
#ifdef DEBUG
stack.clear();
#endif
//CSLock is a pointer so we can use a different attribute type on create
CSLock = new CriticalSection(MUTEX_ATTRIBUTE_RECURSIVE);
}
Mutex::~Mutex() {
safe_delete(CSLock);
#ifdef DEBUG
stack.clear();
#endif
}
void Mutex::SetName(string in_name) {
#ifdef DEBUG
name = in_name;
#endif
}
void Mutex::lock() {
#ifdef DEBUG
int i = 0;
#endif
if (name.length() > 0) {
while (mlocked) {
#ifdef DEBUG
if (i > MUTEX_TIMEOUT_MILLISECONDS) {
LogWrite(MUTEX__ERROR, 0, "Mutex", "Possible deadlock attempt by '%s'!", name.c_str());
return;
}
i++;
#endif
Sleep(1);
}
}
mlocked = true;
CSLock->lock();
}
bool Mutex::trylock() {
return CSLock->trylock();
}
void Mutex::unlock() {
CSLock->unlock();
mlocked = false;
}
void Mutex::readlock(const char* function, int32 line) {
#ifdef DEBUG
int32 i = 0;
#endif
while (true) {
//Loop until there isn't a writer, then we can read!
CSRead.lock();
if (!writing) {
readers++;
CSRead.unlock();
#ifdef DEBUG
CSStack.lock();
if (function)
stack[(string)function]++;
CSStack.unlock();
#endif
return;
}
CSRead.unlock();
#ifdef DEBUG
if (i > MUTEX_TIMEOUT_MILLISECONDS) {
LogWrite(MUTEX__ERROR, 0, "Mutex", "The mutex %s called from %s at line %u timed out waiting for a readlock!", name.c_str(), function ? function : "name_not_provided", line);
LogWrite(MUTEX__ERROR, 0, "Mutex", "The following functions had locks:");
map<string, int32>::iterator itr;
CSStack.lock();
for (itr = stack.begin(); itr != stack.end(); itr++) {
if (itr->second > 0 && itr->first.length() > 0)
LogWrite(MUTEX__ERROR, 0, "Mutex", "%s, number of locks = %u", itr->first.c_str(), itr->second);
}
CSStack.unlock();
i = 0;
continue;
}
i++;
#endif
Sleep(1);
}
}
void Mutex::releasereadlock(const char* function, int32 line) {
//Wait for the readcount lock
CSRead.lock();
//Lower the readcount by one, when readcount is 0 writers may start writing
readers--;
CSRead.unlock();
#ifdef DEBUG
CSStack.lock();
if (function) {
map<string, int32>::iterator itr = stack.find((string)function);
if (itr != stack.end()) {
if (--(itr->second) == 0) {
stack.erase(itr);
}
}
}
CSStack.unlock();
#endif
}
bool Mutex::tryreadlock(const char* function) {
//This returns true if able to instantly obtain a readlock, false if not
CSRead.lock();
if (!writing) {
readers++;
CSRead.unlock();
}
else {
CSRead.unlock();
return false;
}
#ifdef DEBUG
CSStack.lock();
if (function)
stack[(string)function]++;
CSStack.unlock();
#endif
return true;
}
void Mutex::writelock(const char* function, int32 line) {
//Wait until the writer lock becomes available, then we can be the only writer!
#ifdef DEBUG
int32 i = 0;
#endif
while (!CSWrite.trylock()) {
#ifdef DEBUG
if (i > MUTEX_TIMEOUT_MILLISECONDS) {
LogWrite(MUTEX__ERROR, 0, "Mutex", "The mutex %s called from %s at line %u timed out waiting on another writelock!", name.c_str(), function ? function : "name_not_provided", line);
LogWrite(MUTEX__ERROR, 0, "Mutex", "The following functions had locks:");
map<string, int32>::iterator itr;
CSStack.lock();
for (itr = stack.begin(); itr != stack.end(); itr++) {
if (itr->second > 0 && itr->first.length() > 0)
LogWrite(MUTEX__ERROR, 0, "Mutex", "%s, number of locks = %u", itr->first.c_str(), itr->second);
}
CSStack.unlock();
i = 0;
continue;
}
i++;
#endif
Sleep(1);
}
waitReaders(function, line);
#ifdef DEBUG
CSStack.lock();
if (function)
stack[(string)function]++;
CSStack.unlock();
#endif
}
void Mutex::releasewritelock(const char* function, int32 line) {
//Wait for the readcount lock
CSRead.lock();
//Readers are aloud again
writing = false;
CSRead.unlock();
//Allow other writers to write
CSWrite.unlock();
#ifdef DEBUG
CSStack.lock();
if (function) {
map<string, int32>::iterator itr = stack.find((string)function);
if (itr != stack.end()) {
if (--(itr->second) == 0) {
stack.erase(itr);
}
}
}
CSStack.unlock();
#endif
}
bool Mutex::trywritelock(const char* function) {
//This returns true if able to instantly obtain a writelock, false if not
if (CSWrite.trylock()) {
CSRead.lock();
if (readers == 0)
writing = true;
CSRead.unlock();
if (!writing) {
CSWrite.unlock();
return false;
}
}
else
return false;
#ifdef DEBUG
CSStack.lock();
if (function)
stack[(string)function]++;
CSStack.unlock();
#endif
return true;
}
void Mutex::waitReaders(const char* function, int32 line)
{
//Wait for all current readers to stop, then we can write!
#ifdef DEBUG
int32 i = 0;
#endif
while (true)
{
CSRead.lock();
if (readers == 0)
{
writing = true;
CSRead.unlock();
break;
}
CSRead.unlock();
#ifdef DEBUG
if (i > MUTEX_TIMEOUT_MILLISECONDS) {
LogWrite(MUTEX__ERROR, 0, "Mutex", "The mutex %s called from %s at line %u timed out while waiting on readers!", name.c_str(), function ? function : "name_not_provided", line);
LogWrite(MUTEX__ERROR, 0, "Mutex", "The following functions had locks:");
map<string, int32>::iterator itr;
CSStack.lock();
for (itr = stack.begin(); itr != stack.end(); itr++) {
if (itr->second > 0 && itr->first.length() > 0)
LogWrite(MUTEX__ERROR, 0, "Mutex", "%s, number of locks = %u", itr->first.c_str(), itr->second);
}
CSStack.unlock();
i = 0;
continue;
}
i++;
#endif
Sleep(1);
}
}
LockMutex::LockMutex(Mutex* in_mut, bool iLock) {
mut = in_mut;
locked = iLock;
if (locked) {
mut->lock();
}
}
LockMutex::~LockMutex() {
if (locked) {
mut->unlock();
}
}
void LockMutex::unlock() {
if (locked)
mut->unlock();
locked = false;
}
void LockMutex::lock() {
if (!locked)
mut->lock();
locked = true;
}
CriticalSection::CriticalSection(int attribute) {
#ifdef WIN32
InitializeCriticalSection(&CSMutex);
#else
pthread_mutexattr_init(&type_attribute);
switch (attribute)
{
case MUTEX_ATTRIBUTE_FAST:
pthread_mutexattr_settype(&type_attribute, PTHREAD_MUTEX_FAST_NP);
break;
case MUTEX_ATTRIBUTE_RECURSIVE:
pthread_mutexattr_settype(&type_attribute, PTHREAD_MUTEX_RECURSIVE_NP);
break;
case MUTEX_ATTRIBUTE_ERRORCHK:
pthread_mutexattr_settype(&type_attribute, PTHREAD_MUTEX_ERRORCHECK_NP);
break;
default:
LogWrite(MUTEX__DEBUG, 0, "Critical Section", "Invalid mutex attribute type! Using PTHREAD_MUTEX_FAST_NP");
pthread_mutexattr_settype(&type_attribute, PTHREAD_MUTEX_FAST_NP);
break;
}
pthread_mutex_init(&CSMutex, &type_attribute);
#endif
}
CriticalSection::~CriticalSection() {
#ifdef WIN32
DeleteCriticalSection(&CSMutex);
#else
pthread_mutex_destroy(&CSMutex);
pthread_mutexattr_destroy(&type_attribute);
#endif
}
void CriticalSection::lock() {
//Waits for a lock on this critical section
#ifdef WIN32
EnterCriticalSection(&CSMutex);
#else
pthread_mutex_lock(&CSMutex);
#endif
}
void CriticalSection::unlock() {
//Gets rid of one of the current thread's locks on this critical section
#ifdef WIN32
LeaveCriticalSection(&CSMutex);
#else
pthread_mutex_unlock(&CSMutex);
#endif
}
bool CriticalSection::trylock() {
//Returns true if able to instantly get a lock on this critical section, false if not
#ifdef WIN32
return TryEnterCriticalSection(&CSMutex);
#else
return (pthread_mutex_trylock(&CSMutex) == 0);
#endif
}

103
old/Mutex.h Normal file
View File

@ -0,0 +1,103 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MYMUTEX_H
#define MYMUTEX_H
#ifdef WIN32
#include <WinSock2.h>
#include <windows.h>
#else
#include <pthread.h>
#include "../common/unix.h"
#endif
#include "../common/types.h"
#include <string>
#include <map>
#define MUTEX_ATTRIBUTE_FAST 1
#define MUTEX_ATTRIBUTE_RECURSIVE 2
#define MUTEX_ATTRIBUTE_ERRORCHK 3
#define MUTEX_TIMEOUT_MILLISECONDS 10000
class CriticalSection {
public:
CriticalSection(int attribute = MUTEX_ATTRIBUTE_FAST);
~CriticalSection();
void lock();
void unlock();
bool trylock();
private:
#ifdef WIN32
CRITICAL_SECTION CSMutex;
#else
pthread_mutex_t CSMutex;
pthread_mutexattr_t type_attribute;
#endif
};
class Mutex {
public:
Mutex();
~Mutex();
void lock();
void unlock();
bool trylock();
void readlock(const char* function = 0, int32 line = 0);
void releasereadlock(const char* function = 0, int32 line = 0);
bool tryreadlock(const char* function = 0);
void writelock(const char* function = 0, int32 line = 0);
void releasewritelock(const char* function = 0, int32 line = 0);
bool trywritelock(const char* function = 0);
void waitReaders(const char* function = 0, int32 line = 0);
void SetName(string in_name);
private:
CriticalSection CSRead;
CriticalSection CSWrite;
CriticalSection* CSLock;
#ifdef DEBUG //Used for debugging only
CriticalSection CSStack;
map<string, int32> stack;
#endif
int readers;
bool writing;
volatile bool mlocked;
string name;
};
class LockMutex {
public:
LockMutex(Mutex* in_mut, bool iLock = true);
~LockMutex();
void unlock();
void lock();
private:
bool locked;
Mutex* mut;
};
#endif

2742
old/PacketStruct.cpp Normal file

File diff suppressed because it is too large Load Diff

513
old/PacketStruct.h Normal file
View File

@ -0,0 +1,513 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __EQ2_PACKETSTRUCT__
#define __EQ2_PACKETSTRUCT__
#include "types.h"
#include "DataBuffer.h"
#include "opcodemgr.h"
#include <vector>
#include <map>
#ifdef WORLD
class Item;
class Player;
#endif
extern map<int16, OpcodeManager*>EQOpcodeManager;
using namespace std;
#define DATA_STRUCT_NONE 0
#define DATA_STRUCT_INT8 1
#define DATA_STRUCT_INT16 2
#define DATA_STRUCT_INT32 3
#define DATA_STRUCT_INT64 4
#define DATA_STRUCT_FLOAT 5
#define DATA_STRUCT_DOUBLE 6
#define DATA_STRUCT_COLOR 7
#define DATA_STRUCT_SINT8 8
#define DATA_STRUCT_SINT16 9
#define DATA_STRUCT_SINT32 10
#define DATA_STRUCT_CHAR 11
#define DATA_STRUCT_EQ2_8BIT_STRING 12
#define DATA_STRUCT_EQ2_16BIT_STRING 13
#define DATA_STRUCT_EQ2_32BIT_STRING 14
#define DATA_STRUCT_EQUIPMENT 15
#define DATA_STRUCT_ARRAY 16
#define DATA_STRUCT_ITEM 17
#define DATA_STRUCT_SINT64 18
class DataStruct {
public:
DataStruct();
DataStruct(DataStruct* data_struct);
DataStruct(const char* new_name, int8 new_type, int32 new_length = 1, int8 new_type2 = DATA_STRUCT_NONE);
DataStruct(const char* new_name, const char* new_type, int32 new_length = 1, const char* new_type2 = 0);
DataStruct(const char* new_name, int32 new_length);
void SetType(const char* new_type, int8* output_type);
void SetType(int8 new_type);
void SetName(const char* new_name);
void SetLength(int32 new_length);
void SetArraySizeVariable(const char* new_name);
void SetDefaultValue(int8 new_val);
void SetMaxArraySize(int8 size);
void SetOversized(int8 val);
void SetOversizedByte(int8 val);
void SetAddToStruct(bool val);
void SetAddType(int8 new_type);
void SetPackedIndex(int8 new_index);
void SetPackedSizeVariable(const char* new_name);
void SetPacked(const char* value);
void SetItemSize(int32 val);
void SetIfSetVariable(const char* variable);
void SetIfNotSetVariable(const char* variable);
void SetIfEqualsVariable(const char* variable);
void SetIfNotEqualsVariable(const char* variable);
void SetIfFlagSetVariable(const char* variable);
void SetIfFlagNotSetVariable(const char* variable);
void SetIsSet(bool val);
void SetIsOptional(bool val);
int8 GetPackedIndex();
const char* GetPackedSizeVariable();
const char* GetArraySizeVariable();
int8 GetDefaultValue();
int8 GetOversized();
int8 GetOversizedByte();
int8 GetMaxArraySize();
int8 GetType();
int8 GetType2();
const char* GetName();
string GetStringName();
int32 GetLength();
bool AddToStruct();
int8 GetAddType();
int32 GetItemSize();
bool GetIfSet();
const char* GetIfSetVariable();
bool GetIfNotSet();
const char* GetIfNotSetVariable();
bool GetIfEquals();
const char* GetIfEqualsVariable();
bool GetIfNotEquals();
const char* GetIfNotEqualsVariable();
bool GetIfFlagSet();
const char* GetIfFlagSetVariable();
bool GetIfFlagNotSet();
const char* GetIfFlagNotSetVariable();
bool IsSet();
bool IsOptional();
int32 GetDataSizeInBytes();
string AppendVariable(string orig, const char* val);
void AddIfSetVariable(const char* val) {
if (val) {
if_set_variable = AppendVariable(if_set_variable, val);
is_set = true;
}
}
void AddIfNotSetVariable(const char* val) {
if (val) {
if_not_set_variable = AppendVariable(if_not_set_variable, val);
if_not_set = true;
}
}
private:
bool is_set;
bool if_not_set;
bool optional;
bool if_set;
bool if_not_equals;
bool if_equals;
bool if_flag_set;
bool if_flag_not_set;
string if_flag_not_set_variable;
string if_flag_set_variable;
string if_not_equals_variable;
string if_equals_variable;
string if_not_set_variable;
string if_set_variable;
int8 oversized;
int8 oversized_byte;
bool add;
int8 addType;
int8 maxArraySize;
string array_size_variable;
string name;
int8 type;
int8 default_value;
int8 type2;
int32 length;
int32 item_size;
};
class PacketStruct : public DataBuffer {
public:
PacketStruct();
PacketStruct(PacketStruct* packet, bool sub);
PacketStruct(PacketStruct* packet, int16 in_client_version);
~PacketStruct();
void add(DataStruct* data);
void reAddAll(int32 length);
void add(PacketStruct* packet_struct);
void addPacketArrays(PacketStruct* packet);
void deletePacketArrays(PacketStruct* packet);
void deleteDataStructs(vector<DataStruct*>* data_structs);
void setSmallStringByName(const char* name, const char* text, int32 index = 0);
void setMediumStringByName(const char* name, const char* text, int32 index = 0);
void setLargeStringByName(const char* name, const char* text, int32 index = 0);
void setSmallString(DataStruct* data_struct, const char* text, int32 index = 0);
void setMediumString(DataStruct* data_struct, const char* text, int32 index = 0);
void setLargeString(DataStruct* data_struct, const char* text, int32 index = 0);
void renameSubstructArray(const char* substruct, int32 index);
template<class Data> void setSubstructSubstructDataByName(const char* substruct_name1, const char* substruct_name2, const char* name, Data data, int32 substruct_index1 = 0, int32 substruct_index2 = 0, int32 index = 0) {
char tmp[15] = { 0 };
sprintf(tmp, "_%i_%i", substruct_index1, substruct_index2);
string name2 = string(substruct_name1).append("_").append(substruct_name2).append("_").append(name).append(tmp);
setData(findStruct(name2.c_str(), index), data, index);
}
template<class Data> void setSubstructDataByName(const char* substruct_name, const char* name, Data data, int32 substruct_index = 0, int32 index = 0) {
char tmp[10] = { 0 };
sprintf(tmp, "_%i", substruct_index);
string name2 = string(substruct_name).append("_").append(name).append(tmp);
setData(findStruct(name2.c_str(), index), data, index);
}
template<class Data> void setSubstructColorByName(const char* substruct_name, const char* name, Data data, int32 substruct_index = 0, int32 index = 0) {
char tmp[10] = { 0 };
sprintf(tmp, "_%i", substruct_index);
string name2 = string(substruct_name).append("_").append(name).append(tmp);
setColor(findStruct(name2.c_str(), index), data, index);
}
template<class Data> void setSubstructArrayDataByName(const char* substruct_name, const char* name, Data data, int32 index = 0, int32 substruct_index = 0) {
char tmp[10] = { 0 };
sprintf(tmp, "_%i", substruct_index);
string name2 = string(substruct_name).append("_").append(name).append(tmp);
setData(findStruct(name2.c_str(), substruct_index, index), data, index);
}
template<class Data> void setSubstructArrayColorByName(const char* substruct_name, const char* name, Data data, int32 substruct_index = 0, int32 index = 0) {
char tmp[10] = { 0 };
sprintf(tmp, "_%i", substruct_index);
string name2 = string(substruct_name).append("_").append(name).append(tmp);
setColor(findStruct(name2.c_str(), index, substruct_index), data, index);
}
template<class Data> void setDataByName(const char* name, Data data, int32 index = 0, bool use_second_type = false) {
setData(findStruct(name, index), data, index, use_second_type);
}
template<class Data> void setDataByName(const char* name, Data* data, int32 index = 0, bool use_second_type = false) {
setData(findStruct(name, index), data, index, use_second_type);
}
template<class Data> void setSubArrayDataByName(const char* name, Data data, int32 index1 = 0, int32 index2 = 0, int32 index3 = 0) {
char tmp[20] = { 0 };
sprintf(tmp, "%i_%i", index1, index2);
string name2 = string(name).append(tmp);
setData(findStruct(name2.c_str(), index2, index3), data, index3);
}
template<class Data> void setArrayDataByName(const char* name, Data data, int32 index1 = 0, int32 index2 = 0, bool use_second_type = false) {
char tmp[10] = { 0 };
sprintf(tmp, "_%i", index1);
string name2 = string(name).append(tmp);
setData(findStruct(name2.c_str(), index1, index2), data, index2, use_second_type);
}
void setArrayAddToPacketByName(const char* name, bool new_val, int32 index1 = 0, int32 index2 = 0) {
char tmp[10] = { 0 };
sprintf(tmp, "_%i", index1);
string name2 = string(name).append(tmp);
DataStruct* data = findStruct(name2.c_str(), index2);
if (data)
data->SetAddToStruct(new_val);
}
void setAddToPacketByName(const char* name, bool new_val, int32 index = 0) {
DataStruct* data = findStruct(name, index);
if (data)
data->SetAddToStruct(new_val);
}
void setAddTypePacketByName(const char* name, int8 new_val, int32 index = 0) {
DataStruct* data = findStruct(name, index);
if (data)
data->SetAddType(new_val);
}
const char* GetOpcodeType();
bool IsSubPacket();
void IsSubPacket(bool new_val);
int32 GetSubPacketSize();
void SetSubPacketSize(int32 new_size);
void SetOpcodeType(const char* opcodeType);
int32 GetArraySizeByName(const char* name, int32 index);
int32 GetArraySize(DataStruct* data_struct, int32 index);
int32 GetArraySize(const char* name, int32 index);
void LoadFromPacketStruct(PacketStruct* packet, char* substruct_name = 0);
bool GetVariableIsSet(const char* name);
bool GetVariableIsNotSet(const char* name);
int8 getType_int8_ByName(const char* name, int32 index = 0, bool force = false);
int16 getType_int16_ByName(const char* name, int32 index = 0, bool force = false);
int32 getType_int32_ByName(const char* name, int32 index = 0, bool force = false);
int64 getType_int64_ByName(const char* name, int32 index = 0, bool force = false);
sint8 getType_sint8_ByName(const char* name, int32 index = 0, bool force = false);
sint16 getType_sint16_ByName(const char* name, int32 index = 0, bool force = false);
sint32 getType_sint32_ByName(const char* name, int32 index = 0, bool force = false);
sint64 getType_sint64_ByName(const char* name, int32 index = 0, bool force = false);
float getType_float_ByName(const char* name, int32 index = 0, bool force = false);
double getType_double_ByName(const char* name, int32 index = 0, bool force = false);
char getType_char_ByName(const char* name, int32 index = 0, bool force = false);
EQ2_8BitString getType_EQ2_8BitString_ByName(const char* name, int32 index = 0, bool force = false);
EQ2_16BitString getType_EQ2_16BitString_ByName(const char* name, int32 index = 0, bool force = false);
EQ2_32BitString getType_EQ2_32BitString_ByName(const char* name, int32 index = 0, bool force = false);
EQ2_Color getType_EQ2_Color_ByName(const char* name, int32 index = 0, bool force = false);
EQ2_EquipmentItem getType_EQ2_EquipmentItem_ByName(const char* name, int32 index = 0, bool force = false);
int8 getType_int8(DataStruct* data_struct, int32 index = 0, bool force = false);
int16 getType_int16(DataStruct* data_struct, int32 index = 0, bool force = false);
int32 getType_int32(DataStruct* data_struct, int32 index = 0, bool force = false);
int64 getType_int64(DataStruct* data_struct, int32 index = 0, bool force = false);
sint8 getType_sint8(DataStruct* data_struct, int32 index = 0, bool force = false);
sint16 getType_sint16(DataStruct* data_struct, int32 index = 0, bool force = false);
sint32 getType_sint32(DataStruct* data_struct, int32 index = 0, bool force = false);
sint64 getType_sint64(DataStruct* data_struct, int32 index = 0, bool force = false);
float getType_float(DataStruct* data_struct, int32 index = 0, bool force = false);
double getType_double(DataStruct* data_struct, int32 index = 0, bool force = false);
char getType_char(DataStruct* data_struct, int32 index = 0, bool force = false);
EQ2_8BitString getType_EQ2_8BitString(DataStruct* data_struct, int32 index = 0, bool force = false);
EQ2_16BitString getType_EQ2_16BitString(DataStruct* data_struct, int32 index = 0, bool force = false);
EQ2_32BitString getType_EQ2_32BitString(DataStruct* data_struct, int32 index = 0, bool force = false);
EQ2_Color getType_EQ2_Color(DataStruct* data_struct, int32 index = 0, bool force = false);
EQ2_EquipmentItem getType_EQ2_EquipmentItem(DataStruct* data_struct, int32 index = 0, bool force = false);
void setDataType(DataStruct* data_struct, char data, int32 index);
void setDataType(DataStruct* data_struct, int8 data, int32 index);
void setDataType(DataStruct* data_struct, int16 data, int32 index);
void setDataType(DataStruct* data_struct, int32 data, int32 index);
void setDataType(DataStruct* data_struct, int64 data, int32 index);
void setDataType(DataStruct* data_struct, sint8 data, int32 index);
void setDataType(DataStruct* data_struct, sint16 data, int32 index);
void setDataType(DataStruct* data_struct, sint32 data, int32 index);
void setDataType(DataStruct* data_struct, sint64 data, int32 index);
void setDataType(DataStruct* data_struct, float data, int32 index);
void setDataType(DataStruct* data_struct, double data, int32 index);
void setData(DataStruct* data_struct, EQ2_8BitString* input_string, int32 index, bool use_second_type = false);
void setData(DataStruct* data_struct, EQ2_16BitString* input_string, int32 index, bool use_second_type = false);
void setData(DataStruct* data_struct, EQ2_32BitString* input_string, int32 index, bool use_second_type = false);
template<class Data> void setData(DataStruct* data_struct, Data* data, int32 index, bool use_second_type = false) {
if (!data_struct)
return;
data_struct->SetIsOptional(false);
int8 type_to_use = (use_second_type) ? data_struct->GetType2() : data_struct->GetType();
if (type_to_use >= DATA_STRUCT_EQ2_8BIT_STRING && type_to_use <= DATA_STRUCT_EQ2_32BIT_STRING) {
if (type_to_use == DATA_STRUCT_EQ2_8BIT_STRING) {
setSmallString(data_struct, data, index);
}
else if (type_to_use == DATA_STRUCT_EQ2_16BIT_STRING) {
setMediumString(data_struct, data, index);
}
else {
setLargeString(data_struct, data, index);
}
}
else {
if (data_struct && index == 0 && data_struct->GetLength() > 1) {
if (type_to_use == DATA_STRUCT_CHAR) {
for (int32 i = 0; data && i < data_struct->GetLength() && i < strlen(data); i++)
setData(data_struct, data[i], i);
}
else {
for (int32 i = 0; i < data_struct->GetLength(); i++)
setData(data_struct, data[i], i);
}
}
else
setData(data_struct, *data, index);
}
}
template<class Data> void setData(DataStruct* data_struct, Data data, int32 index, bool use_second_type = false) {
if (data_struct && index < data_struct->GetLength()) {
data_struct->SetIsOptional(false);
int8 type_to_use = (use_second_type) ? data_struct->GetType2() : data_struct->GetType();
if (use_second_type) {
// Need to figure out why type2 always seems to be 205
// since only items use type2 for now just hardcoded the value needed (BAD!!!)
//type_to_use = DATA_STRUCT_SINT16; // 9;
data_struct->SetType(type_to_use);
}
switch (type_to_use) {
case DATA_STRUCT_INT8:
setDataType(data_struct, (int8)data, index);
break;
case DATA_STRUCT_INT16:
setDataType(data_struct, (int16)data, index);
break;
case DATA_STRUCT_INT32:
setDataType(data_struct, (int32)data, index);
break;
case DATA_STRUCT_INT64:
setDataType(data_struct, (int64)data, index);
break;
case DATA_STRUCT_SINT8:
setDataType(data_struct, (sint8)data, index);
break;
case DATA_STRUCT_SINT16:
setDataType(data_struct, (sint16)data, index);
break;
case DATA_STRUCT_SINT32:
setDataType(data_struct, (sint32)data, index);
break;
case DATA_STRUCT_SINT64:
setDataType(data_struct, (sint64)data, index);
break;
case DATA_STRUCT_CHAR:
setDataType(data_struct, (char)data, index);
break;
case DATA_STRUCT_FLOAT:
setDataType(data_struct, (float)data, index);
break;
case DATA_STRUCT_DOUBLE:
setDataType(data_struct, (double)data, index);
break;
case DATA_STRUCT_COLOR:
setColor(data_struct, *((EQ2_Color*)&data), index);
break;
case DATA_STRUCT_EQUIPMENT:
setEquipmentByName(data_struct, *((EQ2_EquipmentItem*)&data), index);
break;
case DATA_STRUCT_ITEM:
break;
}
}
}
template<class Data> void setSubArrayLengthByName(const char* name, Data data, int32 index1 = 0, int32 index2 = 0) {
char tmp[10] = { 0 };
sprintf(tmp, "_%i", index1);
string name2 = string(name).append(tmp);
DataStruct* data_struct = findStruct(name2.c_str(), index2);
setData(data_struct, data, index2);
UpdateArrayByArrayLength(data_struct, index2, data);
}
template<class Data> void setArrayLengthByName(const char* name, Data data, int32 index = 0) {
DataStruct* data_struct = findStruct(name, index);
setData(data_struct, data, index);
UpdateArrayByArrayLength(data_struct, index, data);
}
template<class Data> void setSubstructArrayLengthByName(const char* substruct_name, const char* name, Data data, int32 substruct_index = 0, int32 index = 0) {
char tmp[10] = { 0 };
sprintf(tmp, "_%i", substruct_index);
string name2 = string(substruct_name).append("_").append(name).append(tmp);
DataStruct* data_struct = findStruct(name2.c_str(), index);
setData(data_struct, data, index);
UpdateArrayByArrayLength(data_struct, index, data);
}
void UpdateArrayByArrayLengthName(const char* name, int32 index, int32 size);
void UpdateArrayByArrayLength(DataStruct* data_struct, int32 index, int32 size);
bool StructLoadData(DataStruct* data_struct, void* data, int32 len, bool useType2 = false, bool create_color = false);
bool LoadPacketData(uchar* data, int32 data_len, bool create_color = false);
bool CheckFlagExists(const char* name);
void setColorByName(const char* name, EQ2_Color* data, int32 index = 0) {
if (data)
setColorByName(name, data->red, data->green, data->blue, index);
}
void setColorByName(const char* name, EQ2_Color data, int32 index = 0) {
setColorByName(name, data.red, data.green, data.blue, index);
}
void setColor(DataStruct* data_struct, EQ2_Color data, int32 index = 0) {
if (data_struct) {
EQ2_Color* ptr = (EQ2_Color*)struct_data[data_struct];
ptr[index] = data;
}
}
void setColorByName(const char* name, int8 red, int8 green, int8 blue, int32 index = 0) {
setColor(findStruct(name, index), red, green, blue, index);
}
void setColor(DataStruct* data, int8 red, int8 green, int8 blue, int32 index);
void setEquipmentByName(DataStruct* data_struct, EQ2_EquipmentItem data, int32 index = 0) {
if (data_struct) {
EQ2_EquipmentItem* ptr = (EQ2_EquipmentItem*)struct_data[data_struct];
ptr[index] = data;
}
}
#ifdef WORLD
void setItem(DataStruct* ds, Item* item, Player* player, int32 index, sint8 offset = 0, bool loot_item = false, bool make_empty_item_packet = false, bool inspect = false);
void setItemByName(const char* name, Item* item, Player* player, int32 index = 0, sint8 offset = 0, bool loot_item = false, bool make_empty_item_packet = false, bool inspect = false);
void setItemArrayDataByName(const char* name, Item* item, Player* player, int32 index1 = 0, int32 index2 = 0, sint8 offset = 0, bool loot_item = false, bool make_empty_item_packet = false, bool inspect = false);
#endif
void setEquipmentByName(const char* name, EQ2_EquipmentItem data, int32 index = 0) {
setEquipmentByName(findStruct(name, index), data, index);
}
void setEquipmentByName(const char* name, EQ2_EquipmentItem* data, int32 size) {
DataStruct* data_struct = findStruct(name, 0);
if (data_struct) {
for (int32 i = 0; i < size; i++)
setEquipmentByName(data_struct, data[i], i);
}
}
void setEquipmentByName(const char* name, int32 type, int8 c_red, int8 c_blue, int8 c_green, int8 h_red, int8 h_blue, int8 h_green, int32 index = 0) {
setEquipment(findStruct(name, index), type, c_red, c_blue, c_green, h_red, h_blue, h_green, index);
}
void setEquipment(DataStruct* data, int16 type, int8 c_red, int8 c_blue, int8 c_green, int8 h_red, int8 h_blue, int8 h_green, int32 index);
void remove(DataStruct* data);
vector<DataStruct*>* getStructs() { return &structs; }
DataStruct* findStruct(const char* name, int32 index);
DataStruct* findStruct(const char* name, int32 index1, int32 index2);
void remove(const char* name);
void remove(int32 position);
void serializePacket(bool clear = true);
void AddSerializedData(DataStruct* data, int32 index = 0, string* datastring = 0);
EQ2Packet* serialize();
EQ2Packet* serializeCountPacket(int16 version, int8 offset = 0, uchar* orig_packet = 0, uchar* xor_packet = 0);
string* serializeString();
int32 GetVersion() { return version; }
void SetVersion(int32 in_version) { version = in_version; }
bool SetOpcode(const char* new_opcode);
EmuOpcode GetOpcode() { return opcode; }
int16 GetOpcodeValue(int16 client_version);
const char* GetName() { return name.c_str(); }
void SetName(const char* in_name) { name = string(in_name); }
bool LoadedSuccessfully() { return loadedSuccessfully; }
bool IsStringValueType(string in_name, int32 index);
bool IsColorValueType(string in_name, int32 index);
int32 GetTotalPacketSize();
PacketStruct* GetPacketStructByName(const char* name);
void* GetStructPointer(DataStruct* data_struct, bool erase = false);
void PrintPacket();
string GetSQLQuery(const char* table_name);
vector<DataStruct*> GetDataStructs();
void AddPackedData();
void ResetData();
void AddFlag(const char* name);
private:
PacketStruct* parent;
int32 sub_packet_size;
string opcode_type;
bool sub_packet;
bool loadedSuccessfully;
string name;
EmuOpcode opcode;
int16 version;
int16 client_version;
vector<PacketStruct*> arrays;
vector<string> flags;
map<DataStruct*, void*> struct_data;
map<int8, string> packed_data;
map<string, DataStruct*> struct_map;
vector<DataStruct*> structs;
vector<DataStruct*> orig_structs;
vector<PacketStruct*> orig_packets;
};
#endif

93
old/RC4.cpp Normal file
View File

@ -0,0 +1,93 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "RC4.h"
#include <string.h>
static bool g_bInitStateInitialized = false;
static uchar g_byInitState[256];
RC4::RC4(int64 nKey)
{
if( !g_bInitStateInitialized )
{
for(int16 i = 0; i < 256; i++ )
g_byInitState[i] = i;
}
Init(nKey);
}
RC4::~RC4()
{
}
void RC4::Init(int64 nKey)
{
memcpy(m_state, g_byInitState, 256);
m_x = 0;
m_y = 0;
ulong dwKeyIndex = 0;
ulong dwStateIndex = 0;
uchar* pKey = (uchar*)&nKey;
for(int16 i = 0; i < 256; i++ )
{
ulong dwTemp = m_state[i];
dwStateIndex += pKey[dwKeyIndex] + dwTemp;
dwStateIndex &= 0xFF;
m_state[i] = m_state[dwStateIndex];
m_state[dwStateIndex] = (uchar)dwTemp;
dwKeyIndex++;
dwKeyIndex &= 7;
}
}
// A = m_state[X + 1]
// B = m_state[Y + A]
// C ^= m_state[(A + B)]
// X = 20
// Y = ?
// C = 0
// m_state[(A + B)] = Cypher Byte
void RC4::Cypher(uchar* pBuffer, int32 nLength)
{
int32 nOffset = 0;
uchar byKey1 = m_x;
uchar byKey2 = m_y;
if( nLength > 0 )
{
do
{
byKey1++;
uchar byKeyVal1 = m_state[byKey1];
byKey2 += byKeyVal1;
uchar byKeyVal2 = m_state[byKey2];
m_state[byKey1] = byKeyVal2;
m_state[byKey2] = byKeyVal1;
pBuffer[nOffset++] ^= m_state[(byKeyVal1 + byKeyVal2) & 0xFF];
} while( nOffset < nLength );
}
m_x = byKey1;
m_y = byKey2;
}

38
old/RC4.h Normal file
View File

@ -0,0 +1,38 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _EQ2_RC4_H
#define _EQ2_RC4_H
#include "../common/types.h"
class RC4
{
public:
RC4(int64 nKey);
~RC4();
void Init(int64 nKey);
void Cypher(uchar* pData, int32 nLen);
private:
uchar m_state[256];
uchar m_x;
uchar m_y;
};
#endif

1729
old/TCPConnection.cpp Normal file

File diff suppressed because it is too large Load Diff

277
old/TCPConnection.h Normal file
View File

@ -0,0 +1,277 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TCP_CONNECTION_H
#define TCP_CONNECTION_H
/*
Parent classes for interserver TCP Communication.
-Quagmire
*/
#ifdef WIN32
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#include <process.h>
#else
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#include "unix.h"
#endif
#include "types.h"
#include "Mutex.h"
#include "linked_list.h"
#include "queue.h"
#include "servertalk.h"
#include "timer.h"
#include "MiscFunctions.h"
class TCPServer;
#define TCPConnection_ErrorBufferSize 1024
#define MaxTCPReceiveBufferSize 524288
#define TCPS_Ready 0
#define TCPS_Connecting 1
#define TCPS_Connected 100
#define TCPS_Disconnecting 200
#define TCPS_Disconnected 201
#define TCPS_Closing 250
#define TCPS_Error 255
#ifndef DEF_eConnectionType
#define DEF_eConnectionType
enum eConnectionType {Incomming, Outgoing};
#endif
#ifdef WIN32
void TCPServerLoop(void* tmp);
void TCPConnectionLoop(void* tmp);
#else
void* TCPServerLoop(void* tmp);
void* TCPConnectionLoop(void* tmp);
#endif
enum eTCPMode { modeConsole, modeTransition, modePacket };
class TCPConnection {
public:
#pragma pack(1)
struct TCPNetPacket_Struct {
int32 size;
struct {
int8
compressed : 1,
destination : 1,
flag3 : 1,
flag4 : 1,
flag5 : 1,
flag6 : 1,
flag7 : 1,
flag8 : 1;
} flags;
int16 opcode;
uchar buffer[0];
};
#pragma pack()
static TCPNetPacket_Struct* MakePacket(ServerPacket* pack, int32 iDestination = 0);
TCPConnection(TCPServer* iServer, SOCKET iSock, int32 irIP, int16 irPort, bool iOldFormat = false);
TCPConnection(bool iOldFormat = false, TCPServer* iRelayServer = 0, eTCPMode iMode = modePacket); // for outgoing connections
TCPConnection(TCPServer* iServer, TCPConnection* iRelayLink, int32 iRemoteID, int32 irIP, int16 irPort); // for relay connections
virtual ~TCPConnection();
// Functions for outgoing connections
bool Connect(char* irAddress, int16 irPort, char* errbuf = 0);
bool Connect(int32 irIP, int16 irPort, char* errbuf = 0);
void AsyncConnect(char* irAddress, int16 irPort);
void AsyncConnect(int32 irIP, int16 irPort);
virtual void Disconnect(bool iSendRelayDisconnect = true);
virtual bool SendPacket(ServerPacket* pack, int32 iDestination = 0);
virtual bool SendPacket(TCPNetPacket_Struct* tnps);
bool Send(const uchar* data, sint32 size);
char* PopLine();
ServerPacket* PopPacket(); // OutQueuePop()
inline int32 GetrIP() { return rIP; }
inline int16 GetrPort() { return rPort; }
virtual int8 GetState();
eTCPMode GetMode() { return TCPMode; }
inline bool Connected() { return (GetState() == TCPS_Connected); }
inline bool ConnectReady() { return (bool) (GetState() == TCPS_Ready && ConnectionType == Outgoing); }
void Free(); // Inform TCPServer that this connection object is no longer referanced
inline int32 GetID() { return id; }
inline bool IsRelayServer() { return RelayServer; }
inline int32 GetRemoteID() { return RemoteID; }
inline TCPConnection* GetRelayLink() { return RelayLink; }
bool GetEcho();
void SetEcho(bool iValue);
protected:
friend class TCPServer;
virtual bool Process();
void SetState(int8 iState);
inline bool IsFree() { return pFree; }
bool CheckNetActive();
#ifdef WIN32
friend void TCPConnectionLoop(void* tmp);
#else
friend void* TCPConnectionLoop(void* tmp);
#endif
SOCKET sock;
bool RunLoop();
Mutex MLoopRunning;
Mutex MAsyncConnect;
bool GetAsyncConnect();
bool SetAsyncConnect(bool iValue);
char* charAsyncConnect;
#ifdef WIN32
friend class TCPConnection;
#endif
void OutQueuePush(ServerPacket* pack);
void RemoveRelay(TCPConnection* relay, bool iSendRelayDisconnect);
private:
void ProcessNetworkLayerPacket(ServerPacket* pack);
void SendNetErrorPacket(const char* reason = 0);
TCPServer* Server;
TCPConnection* RelayLink;
int32 RemoteID;
sint32 RelayCount;
bool pOldFormat;
bool SendData(char* errbuf = 0);
bool RecvData(char* errbuf = 0);
bool ProcessReceivedData(char* errbuf = 0);
bool ProcessReceivedDataAsPackets(char* errbuf = 0);
bool ProcessReceivedDataAsOldPackets(char* errbuf = 0);
void ClearBuffers();
bool pAsyncConnect;
eConnectionType ConnectionType;
eTCPMode TCPMode;
bool RelayServer;
Mutex MRunLoop;
bool pRunLoop;
SOCKET connection_socket;
int32 id;
int32 rIP;
int16 rPort; // host byte order
bool pFree;
Mutex MState;
int8 pState;
void LineOutQueuePush(char* line);
MyQueue<char> LineOutQueue;
MyQueue<ServerPacket> OutQueue;
Mutex MOutQueueLock;
Timer* keepalive_timer;
Timer* timeout_timer;
uchar* recvbuf;
sint32 recvbuf_size;
sint32 recvbuf_used;
sint32 recvbuf_echo;
bool pEcho;
Mutex MEcho;
void InModeQueuePush(TCPNetPacket_Struct* tnps);
MyQueue<TCPNetPacket_Struct> InModeQueue;
Mutex MSendQueue;
uchar* sendbuf;
sint32 sendbuf_size;
sint32 sendbuf_used;
bool ServerSendQueuePop(uchar** data, sint32* size);
void ServerSendQueuePushEnd(const uchar* data, sint32 size);
void ServerSendQueuePushEnd(uchar** data, sint32 size);
void ServerSendQueuePushFront(uchar* data, sint32 size);
};
class TCPServer {
public:
TCPServer(int16 iPort = 0, bool iOldFormat = false);
virtual ~TCPServer();
bool Open(int16 iPort = 0, char* errbuf = 0); // opens the port
void Close(); // closes the port
bool IsOpen();
inline int16 GetPort() { return pPort; }
TCPConnection* NewQueuePop();
void SendPacket(ServerPacket* pack);
void SendPacket(TCPConnection::TCPNetPacket_Struct** tnps);
protected:
#ifdef WIN32
friend void TCPServerLoop(void* tmp);
#else
friend void* TCPServerLoop(void* tmp);
#endif
void Process();
bool RunLoop();
Mutex MLoopRunning;
friend class TCPConnection;
inline int32 GetNextID() { return NextID++; }
void AddConnection(TCPConnection* con);
TCPConnection* GetConnection(int32 iID);
private:
void ListenNewConnections();
int32 NextID;
bool pOldFormat;
Mutex MRunLoop;
bool pRunLoop;
Mutex MSock;
SOCKET sock;
int16 pPort;
Mutex MNewQueue;
MyQueue<TCPConnection> NewQueue;
void CheckInQueue();
Mutex MInQueue;
TCPConnection::TCPNetPacket_Struct* InQueuePop();
MyQueue<TCPConnection::TCPNetPacket_Struct> InQueue;
LinkedList<TCPConnection*>* list;
};
#endif

364
old/Web/WebServer.cpp Normal file
View File

@ -0,0 +1,364 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2005 - 2026 EQ2EMulator Development Team (http://www.eq2emu.com formerly http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "WebServer.h"
#include <iostream>
#include <sstream>
#include <random>
#include <chrono>
#include <boost/beast/core/detail/base64.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <sstream>
#include <string>
#include <iostream>
#include "../version.h"
#ifdef WORLD
#include "../../WorldServer/WorldDatabase.h"
extern WorldDatabase database;
#endif
#ifdef LOGIN
#include "../../LoginServer/LoginDatabase.h"
extern LoginDatabase database;
#endif
#ifdef WIN32
#include <process.h>
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#include <conio.h>
#else
#include <pthread.h>
#include "../unix.h"
#endif
ThreadReturnType RunWebServer (void* tmp);
static std::string keypasswd = "";
void web_handle_version(const http::request<http::string_body>& req, http::response<http::string_body>& res) {
res.set(http::field::content_type, "application/json");
boost::property_tree::ptree pt;
// Add key-value pairs to the property tree
pt.put("eq2emu_process", std::string(EQ2EMU_MODULE));
pt.put("version", std::string(CURRENT_VERSION));
pt.put("compile_date", std::string(COMPILE_DATE));
pt.put("compile_time", std::string(COMPILE_TIME));
// Create an output string stream to hold the JSON string
std::ostringstream oss;
// Write the property tree to the output string stream as JSON
boost::property_tree::write_json(oss, pt);
// Get the JSON string from the output string stream
std::string json = oss.str();
res.body() = json;
res.prepare_payload();
}
void web_handle_root(const http::request<http::string_body>& req, http::response<http::string_body>& res) {
res.set(http::field::content_type, "text/html");
res.body() = "Hello!";
res.prepare_payload();
}
// this function is called to obtain password info about an encrypted key
std::string WebServer::my_password_callback(
std::size_t max_length, // the maximum length for a password
ssl::context::password_purpose purpose ) // for_reading or for_writing
{
return keypasswd;
}
//void handle_root(const http::request<http::string_body>& req, http::response<http::string_body>& res);
WebServer::WebServer(const std::string& address, unsigned short port, const std::string& cert_file, const std::string& key_file, const std::string& key_password, const std::string& hardcode_user, const std::string& hardcode_password)
: ioc_(1),
ssl_ctx_(ssl::context::tlsv13_server),
acceptor_(ioc_, {boost_net::ip::make_address(address), port}) {
keypasswd = key_password;
// Initialize SSL context
if(cert_file.size() < 1 || key_file.size() < 1) {
is_ssl = false;
}
else {
ssl_ctx_.set_password_callback(my_password_callback);
ssl_ctx_.use_certificate_chain_file(cert_file);
ssl_ctx_.use_private_key_file(key_file, ssl::context::file_format::pem);
is_ssl = true;
}
keypasswd = ""; // reset no longer needed
if(hardcode_user.size() > 0 && hardcode_password.size() > 0)
credentials_[hardcode_user] = hardcode_password;
register_route("/", web_handle_root);
register_route("/version", web_handle_version);
}
WebServer::~WebServer() {
ioc_.stop();
}
ThreadReturnType RunWebServer (void* tmp) {
if(tmp == nullptr) {
THREAD_RETURN(NULL);
}
WebServer* ws = (WebServer*)tmp;
ws->start();
THREAD_RETURN(NULL);
}
void WebServer::start() {
do_accept();
ioc_.run();
}
void WebServer::run() {
pthread_t thread;
pthread_create(&thread, NULL, RunWebServer, this);
pthread_detach(thread);
}
void WebServer::register_route(const std::string& uri, std::function<void(const http::request<http::string_body>&, http::response<http::string_body>&)> handler, bool auth_req) {
int32 status = database.NoAuthRoute((char*)uri.c_str()); // overrides the default hardcode settings via DB
if(status == 0) {
auth_req = false;
}
if(auth_req) {
routes_[uri] = handler;
}
else {
noauth_routes_[uri] = handler;
}
route_required_status_[uri] = status;
}
void WebServer::do_accept() {
acceptor_.async_accept(
[this](beast::error_code ec, tcp::socket socket) {
this->on_accept(ec, std::move(socket));
});
}
void WebServer::on_accept(beast::error_code ec, tcp::socket socket) {
if (!ec) {
if(is_ssl) {
std::thread(&WebServer::do_session_ssl, this, std::move(socket)).detach();
}
else {
std::thread(&WebServer::do_session, this, std::move(socket)).detach();
}
}
do_accept();
}
void WebServer::do_session(tcp::socket socket) {
try {
bool close = false;
beast::flat_buffer buffer;
while (!close) {
// 1) Read a complete request
http::request<http::string_body> req;
http::read(socket, buffer, req);
// 2) Invoke your handler, giving it a lambda that
// sets up version/keep_alive on the response
handle_request(std::move(req), [&](auto&& response) {
// mirror HTTP version
response.version(req.version());
// propagate the clients keep-alive choice
response.keep_alive(req.keep_alive());
// if the client asked us to close, mark for shutdown
if (! req.keep_alive())
close = true;
http::write(socket, response);
});
// 3) Discard anything left in the buffer so the next
// http::read starts fresh
buffer.consume(buffer.size());
}
beast::error_code ec;
socket.shutdown(tcp::socket::shutdown_send, ec);
}
catch (const std::exception& e) {
// irrelevant spam for now really
}
}
void WebServer::do_session_ssl(tcp::socket socket) {
try {
ssl::stream<tcp::socket> stream(std::move(socket), ssl_ctx_);
stream.handshake(ssl::stream_base::server);
bool close = false;
beast::flat_buffer buffer;
while (!close) {
http::request<http::string_body> req;
http::read(stream, buffer, req);
handle_request(std::move(req), [&](auto&& response) {
response.version(req.version());
response.keep_alive(req.keep_alive());
if (! req.keep_alive())
close = true;
http::write(stream, response);
});
buffer.consume(buffer.size());
}
beast::error_code ec;
stream.next_layer().shutdown(tcp::socket::shutdown_send, ec);
}
catch (const std::exception& e) {
// irrelevant spam for now really
}
}
template <class Body, class Allocator>
void WebServer::handle_request(http::request<Body, http::basic_fields<Allocator>>&& req, std::function<void(http::response<http::string_body>&&)> send) {
auto it = noauth_routes_.find(req.target().to_string());
if (it != noauth_routes_.end()) {
http::response<http::string_body> res{http::status::ok, req.version()};
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
it->second(req, res);
return send(std::move(res));
}
int32 user_status = 0;
std::string session_id = authenticate(req, &user_status);
if (session_id.size() < 1) {
http::response<http::string_body> res{http::status::unauthorized, req.version()};
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
res.set(http::field::www_authenticate, "Basic realm=\"example\"");
res.body() = "Unauthorized";
res.prepare_payload();
return send(std::move(res));
}
auto status_it = route_required_status_.find(req.target().to_string());
if (status_it != route_required_status_.end()) {
if(status_it->second > 0 && status_it->second != 0xFFFFFFFF && status_it->second > user_status) {
http::response<http::string_body> res{http::status::unauthorized, req.version()};
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
res.body() = "Unauthorized status";
res.prepare_payload();
return send(std::move(res));
}
}
it = routes_.find(req.target().to_string());
if (it != routes_.end()) {
http::response<http::string_body> res{http::status::ok, req.version()};
res.set(http::field::set_cookie, "session_id=" + session_id);
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
it->second(req, res);
return send(std::move(res));
}
/*
http::response<http::string_body> res{http::status::not_found, req.version()};
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
res.body() = "Not Found";
res.prepare_payload();
return send(std::move(res));
*/
return send(http::response<http::string_body>{http::status::bad_request, req.version()});
}
std::string WebServer::authenticate(const http::request<http::string_body>& req, int32* user_status) {
auto it = req.find(http::field::cookie);
if (it != req.end()) {
std::istringstream cookie_stream(it->value().to_string());
std::string session_id;
std::getline(cookie_stream, session_id, '=');
if (session_id == "session_id") {
std::string id;
std::getline(cookie_stream, id);
if (sessions_.find(id) != sessions_.end()) {
if(sessions_status_.find(id) != sessions_status_.end()) {
*user_status = sessions_status_[id];
}
return id;
}
}
}
it = req.find(http::field::authorization);
if (it != req.end()) {
std::string auth_header = it->value().to_string();
if (auth_header.substr(0, 6) == "Basic ") {
std::string encoded_credentials = auth_header.substr(6);
std::string decoded_credentials;
decoded_credentials.resize(boost::beast::detail::base64::decoded_size(encoded_credentials.size()));
auto result = boost::beast::detail::base64::decode(
&decoded_credentials[0],
encoded_credentials.data(),
encoded_credentials.size()
);
decoded_credentials.resize(result.first);
std::istringstream credentials_stream(decoded_credentials);
std::string username, password;
std::getline(credentials_stream, username, ':');
std::getline(credentials_stream, password);
int32 out_status = 0;
if ((credentials_.find(username) != credentials_.end() && credentials_[username] == password) || (database.AuthenticateWebUser((char*)username.c_str(),(char*)password.c_str(), &out_status) > 0)) {
std::string session_id = generate_session_id();
sessions_[session_id] = username;
sessions_status_[session_id] = out_status;
*user_status = out_status;
return session_id;
}
}
}
return std::string("");
}
std::string WebServer::generate_session_id() {
static std::mt19937 rng{std::random_device{}()};
static std::uniform_int_distribution<> dist(0, 15);
std::string session_id;
for (int i = 0; i < 32; ++i) {
session_id += "0123456789abcdef"[dist(rng)];
}
return session_id;
}
// Explicit template instantiation
template void WebServer::handle_request<http::string_body, std::allocator<char>>(
http::request<http::string_body, http::basic_fields<std::allocator<char>>>&&,
std::function<void(http::response<http::string_body>&&)>
);

56
old/Web/WebServer.h Normal file
View File

@ -0,0 +1,56 @@
#pragma once
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/strand.hpp>
#include <boost/config.hpp>
#include <string>
#include <thread>
#include <functional>
#include <unordered_map>
#include "../types.h"
namespace beast = boost::beast; // from <boost/beast.hpp>
namespace http = beast::http; // from <boost/beast/http.hpp>
namespace boost_net = boost::asio; // from <boost/asio.hpp>
namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp>
using tcp = boost_net::ip::tcp; // from <boost/asio/ip/tcp.hpp>
class WebServer {
public:
WebServer(const std::string& address, unsigned short port, const std::string& cert_file, const std::string& key_file, const std::string& key_password, const std::string& hardcode_user, const std::string& hardcode_password);
~WebServer();
void run();
void start();
void register_route(const std::string& uri, std::function<void(const http::request<http::string_body>&, http::response<http::string_body>&)> handler, bool auth_required = true);
private:
bool is_ssl;
static std::string my_password_callback(std::size_t max_length, ssl::context::password_purpose purpose);
void do_accept();
void on_accept(beast::error_code ec, tcp::socket socket);
void do_session_ssl(tcp::socket socket);
void do_session(tcp::socket socket);
template <class Body, class Allocator>
void handle_request(http::request<Body, http::basic_fields<Allocator>>&& req, std::function<void(http::response<http::string_body>&&)> send);
std::string authenticate(const http::request<http::string_body>& req, int32* user_status = 0);
std::string generate_session_id();
boost_net::io_context ioc_;
ssl::context ssl_ctx_;
tcp::acceptor acceptor_;
std::unordered_map<std::string, std::string> sessions_; // session_id -> username
std::unordered_map<std::string, int32> sessions_status_; // session_id -> status
std::unordered_map<std::string, std::string> credentials_; // username -> password
std::unordered_map<std::string, int32> route_required_status_; // route -> status
std::unordered_map<std::string, std::function<void(const http::request<http::string_body>&, http::response<http::string_body>&)>> routes_;
std::unordered_map<std::string, std::function<void(const http::request<http::string_body>&, http::response<http::string_body>&)>> noauth_routes_;
};

602
old/database.cpp Normal file
View File

@ -0,0 +1,602 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../common/debug.h"
#include <iostream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errmsg.h>
//#include <mysqld_error.h>
#include <limits.h>
#include <ctype.h>
#include <assert.h>
#include <map>
// Disgrace: for windows compile
#ifdef WIN32
#include <WinSock2.h>
#include <windows.h>
#define snprintf _snprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else
#include "unix.h"
#include <netinet/in.h>
#endif
#include "database.h"
#include "EQStream.h"
#include "packet_functions.h"
#include "emu_opcodes.h"
#ifdef WORLD
#include "../WorldServer/WorldDatabase.h"
#include "../WorldServer/Web/PeerManager.h"
extern WorldDatabase database;
extern PeerManager peer_manager;
#endif
#ifdef LOGIN
#include "../LoginServer/LoginDatabase.h"
extern LoginDatabase database;
#endif
#ifdef PARSER
#include "../PacketParser/ParserDatabase.h"
extern ParserDatabase database;
#endif
#ifdef PATCHER
#include "../PatchServer/PatcherDatabase.h"
extern PatcherDatabase database;
#endif
#include "../common/EQEMuError.h"
#include "../common/packet_dump.h"
#include "../common/Log.h"
#ifdef WORLD
ThreadReturnType DBAsyncQueries(void* str)
{
// allow some buffer for multiple queries to collect
Sleep(10);
DBStruct* data = (DBStruct*)str;
database.RunAsyncQueries(data->queryid);
delete data;
THREAD_RETURN(NULL);
}
#endif
Database::Database()
{
InitVars();
}
bool Database::Init(bool silentLoad) {
char host[200], user[200], passwd[200], database[200];
unsigned int port=0;
bool compression = false;
bool items[6] = {false, false, false, false, false, false};
const char* exampleIni[] = { "[Database]", "host = localhost", "user = root", "password = pass", "database = dbname", "### --- Assure each parameter is on a new line!" };
if(!ReadDBINI(host, user, passwd, database, &port, &compression, items)) {
//exit(1);
return false;
}
if (!items[0] || !items[1] || !items[2] || !items[3])
{
LogWrite(DATABASE__ERROR, 0, "DB", "Database file %s is incomplete.", DB_INI_FILE);
int i;
for (i = 0; i < 4; i++)
{
if ( !items[i] )
LogWrite(DATABASE__ERROR, 0, "DB", "Could not find parameter %s", exampleIni[i+1]); // offset by 1 because the [Database] entry
}
LogWrite(DATABASE__ERROR, 0, "DB", "Example File:");
int length = sizeof exampleIni / sizeof exampleIni[0];
for(i=0;i<length;i++)
LogWrite(DATABASE__ERROR, 0, "DB", "%s", exampleIni[i]);
//exit (1);
return false;
}
int32 errnum = 0;
char errbuf[MYSQL_ERRMSG_SIZE];
if (!Open(host, user, passwd, database,port, &errnum, errbuf))
{
LogWrite(DATABASE__ERROR, 0, "DB", "Failed to connect to database: Error: %s", errbuf);
HandleMysqlError(errnum);
//exit(1);
return false;
}
else
{
if (!silentLoad)
LogWrite(DATABASE__INFO, 0, "DB", "Using database '%s' at %s", database, host);
}
return true;
}
map<int16, int16> Database::GetVersions(){
map<int16, int16> opcodes;
Query query;
MYSQL_ROW row;
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "select distinct version_range1, version_range2 from opcodes");
while(result && (row = mysql_fetch_row(result))){
if(row[0] && row[1])
opcodes[atoi(row[0])] = atoi(row[1]);
}
return opcodes;
}
map<string, uint16> Database::GetOpcodes(int16 version){
map<string, uint16> opcodes;
Query query;
MYSQL_ROW row;
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "select name, opcode from opcodes where %i between version_range1 and version_range2 order by version_range1, id", version);
while(result && (row = mysql_fetch_row(result))){
opcodes[row[0]] = atoi(row[1]);
}
return opcodes;
}
int32 Database::AuthenticateWebUser(char* userName, char* passwd, int32* status){
if(status) {
*status = 0;
}
Query query;
MYSQL_ROW row;
int32 id = 0;
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "select id, status from web_users where username='%s' and passwd = sha2('%s', 512)", getSafeEscapeString(userName).c_str(), getSafeEscapeString(passwd).c_str());
if(result && (row = mysql_fetch_row(result))){
id = atoul(row[0]);
if(status) {
*status = atoul(row[1]);
}
}
return id;
}
int32 Database::NoAuthRoute(char* route){
Query query;
MYSQL_ROW row;
int32 status = 0xFFFFFFFF;
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "select status from web_routes where route='%s'", getSafeEscapeString(route).c_str());
if(result && (row = mysql_fetch_row(result))){
status = atoul(row[0]);
}
return status;
}
void Database::HandleMysqlError(int32 errnum) {
switch(errnum) {
case 0:
break;
case 1045: // Access Denied
case 2001: {
AddEQEMuError(EQEMuError_Mysql_1405, true);
break;
}
case 2003: { // Unable to connect
AddEQEMuError(EQEMuError_Mysql_2003, true);
break;
}
case 2005: { // Unable to connect
AddEQEMuError(EQEMuError_Mysql_2005, true);
break;
}
case 2007: { // Unable to connect
AddEQEMuError(EQEMuError_Mysql_2007, true);
break;
}
}
}
void Database::InitVars() {
}
Database::~Database()
{
#ifdef WORLD
DBQueryMutex.writelock(__FUNCTION__, __LINE__);
activeQuerySessions.clear();
DBQueryMutex.releasewritelock(__FUNCTION__, __LINE__);
DBAsyncMutex.writelock();
continueAsync = false;
map<int32, deque<Query*>>::iterator itr;
for (itr = asyncQueries.begin(); itr != asyncQueries.end(); itr++)
{
asyncQueriesMutex[itr->first]->writelock();
deque<Query*> queries = itr->second;
while (queries.size() > 0)
{
Query* cur = queries.front();
queries.pop_front();
safe_delete(cur);
}
asyncQueriesMutex[itr->first]->releasewritelock();
Mutex* mutex = asyncQueriesMutex[itr->first];
asyncQueriesMutex.erase(itr->first);
safe_delete(mutex);
}
asyncQueries.clear();
asyncQueriesMutex.clear();
DBAsyncMutex.releasewritelock();
PurgeDBInstances();
#endif
}
#ifdef WORLD
void Query::AddQueryAsync(int32 queryID, Database* db, QUERY_TYPE type, const char* format, ...) {
in_type = type;
va_list args;
va_start(args, format);
#ifdef WIN32
char* buffer;
int buf_len = _vscprintf(format, args) + 1;
buffer = new char[buf_len];
vsprintf(buffer, format, args);
#else
char* buffer;
int buf_len;
va_list argcopy;
va_copy(argcopy, args);
buf_len = vsnprintf(NULL, 0, format, argcopy) + 1;
va_end(argcopy);
buffer = new char[buf_len];
vsnprintf(buffer, buf_len, format, args);
#endif
va_end(args);
query = string(buffer);
Query* asyncQuery = new Query(this, queryID, query);
safe_delete_array(buffer);
db->AddAsyncQuery(asyncQuery);
}
void Query::RunQueryAsync(Database* db) {
db->RunQuery(query.c_str(), query.length(), errbuf, &result, affected_rows, last_insert_id, &errnum, retry);
}
#endif
MYSQL_RES* Query::RunQuery2(QUERY_TYPE type, const char* format, ...){
va_list args;
va_start( args, format );
#ifdef WIN32
char * buffer;
int buf_len = _vscprintf( format, args ) + 1;
buffer = new char[buf_len];
vsprintf( buffer, format, args );
#else
char* buffer;
int buf_len;
va_list argcopy;
va_copy(argcopy, args);
buf_len = vsnprintf(NULL, 0, format, argcopy) + 1;
va_end(argcopy);
buffer = new char[buf_len];
vsnprintf(buffer, buf_len, format, args);
#endif
va_end(args);
query = string(buffer);
safe_delete_array( buffer );
return RunQuery2(query.c_str(), type);
}
MYSQL_RES* Query::RunQuery2(string in_query, QUERY_TYPE type){
switch(type){
case Q_SELECT:
break;
case Q_DBMS:
case Q_REPLACE:
case Q_DELETE:
case Q_UPDATE:
safe_delete(affected_rows);
affected_rows = new int32;
break;
case Q_INSERT:
safe_delete(last_insert_id);
last_insert_id = new int32;
}
if(result){
if(!multiple_results)
multiple_results = new vector<MYSQL_RES*>();
multiple_results->push_back(result);
}
query = in_query;
#if defined WORLD && defined _DEBUG
if (type == Q_UPDATE || type == Q_INSERT || type == Q_DELETE || type == Q_REPLACE)
{
char* filteredTables[] = { " characters", " character_", " `character_", " statistics", " variables", " char_colors", " `guild", " bugs" };
bool match = false;
for (int i = 0; i < sizeof(filteredTables) / sizeof(filteredTables[0]); i++)
{
if (query.find(filteredTables[i]) != std::string::npos) {
match = true;
break;
}
}
try
{
if (!match)
{
FILE* pFile;
pFile = fopen("sql_updates.sql", "a+");
fwrite(query.c_str(), 1, query.length(), pFile);
fwrite(";", sizeof(char), 1, pFile);
fwrite("\n", sizeof(char), 1, pFile);
fclose(pFile);
}
}
catch (...) {}
}
#endif
database.RunQuery(query.c_str(), query.length(), errbuf, &result, affected_rows, last_insert_id, &errnum, retry);
return result;
}
#ifdef WORLD
void Database::RunAsyncQueries(int32 queryid)
{
Database* asyncdb = FindFreeInstance();
DBAsyncMutex.writelock();
map<int32, deque<Query*>>::iterator itr = asyncQueries.find(queryid);
if (itr == asyncQueries.end())
{
DBAsyncMutex.releasewritelock();
return;
}
asyncQueriesMutex[queryid]->writelock();
deque<Query*> queries;
while (itr->second.size())
{
Query* cur = itr->second.front();
queries.push_back(cur);
itr->second.pop_front();
}
itr->second.clear();
asyncQueries.erase(itr);
DBAsyncMutex.releasewritelock();
asyncQueriesMutex[queryid]->releasewritelock();
int32 count = 0;
while (queries.size() > 0)
{
Query* cur = queries.front();
cur->RunQueryAsync(asyncdb);
this->RemoveActiveQuery(cur);
queries.pop_front();
safe_delete(cur);
}
FreeDBInstance(asyncdb);
bool isActive = LocalIsActiveQuery(queryid);
if (isActive)
{
continueAsync = true;
DBStruct* tmp = new DBStruct;
tmp->queryid = queryid;
#ifdef WIN32
_beginthread(DBAsyncQueries, 0, (void*)tmp);
#else
pthread_t t1;
pthread_create(&t1, NULL, DBAsyncQueries, (void*)tmp);
pthread_detach(t1);
#endif
}
}
void Database::AddAsyncQuery(Query* query)
{
DBAsyncMutex.writelock();
map<int32, Mutex*>::iterator mutexItr = asyncQueriesMutex.find(query->GetQueryID());
if (mutexItr == asyncQueriesMutex.end())
{
Mutex* queryMutex = new Mutex();
queryMutex->SetName("AsyncQuery" + query->GetQueryID());
asyncQueriesMutex.insert(make_pair(query->GetQueryID(), queryMutex));
}
map<int32, deque<Query*>>::iterator itr = asyncQueries.find(query->GetQueryID());
asyncQueriesMutex[query->GetQueryID()]->writelock();
if ( itr != asyncQueries.end())
itr->second.push_back(query);
else
{
deque<Query*> queue;
queue.push_back(query);
asyncQueries.insert(make_pair(query->GetQueryID(), queue));
}
AddActiveQuery(query);
asyncQueriesMutex[query->GetQueryID()]->releasewritelock();
DBAsyncMutex.releasewritelock();
bool isActive = LocalIsActiveQuery(query->GetQueryID(), query);
if (!isActive)
{
continueAsync = true;
DBStruct* tmp = new DBStruct;
tmp->queryid = query->GetQueryID();
#ifdef WIN32
_beginthread(DBAsyncQueries, 0, (void*)tmp);
#else
pthread_t t1;
pthread_create(&t1, NULL, DBAsyncQueries, (void*)tmp);
pthread_detach(t1);
#endif
}
}
Database* Database::FindFreeInstance()
{
Database* db_inst = 0;
map<Database*, bool>::iterator itr;
DBInstanceMutex.writelock(__FUNCTION__, __LINE__);
for (itr = dbInstances.begin(); itr != dbInstances.end(); itr++) {
if (!itr->second)
{
db_inst = itr->first;
itr->second = true;
break;
}
}
if (!db_inst)
{
WorldDatabase* tmp = new WorldDatabase();
db_inst = (Database*)tmp;
tmp->Init();
tmp->ConnectNewDatabase();
dbInstances.insert(make_pair(db_inst, true));
}
DBInstanceMutex.releasewritelock(__FUNCTION__, __LINE__);
return db_inst;
}
void Database::PurgeDBInstances()
{
map<Database*, bool>::iterator itr;
DBInstanceMutex.writelock(__FUNCTION__, __LINE__);
for (itr = dbInstances.begin(); itr != dbInstances.end(); itr++) {
WorldDatabase* tmpInst = (WorldDatabase*)itr->first;
safe_delete(tmpInst);
}
dbInstances.clear();
DBInstanceMutex.releasewritelock(__FUNCTION__, __LINE__);
}
void Database::PingAsyncDatabase()
{
map<Database*, bool>::iterator itr;
DBInstanceMutex.readlock(__FUNCTION__, __LINE__);
for (itr = dbInstances.begin(); itr != dbInstances.end(); itr++) {
Database* tmpInst = itr->first;
tmpInst->ping();
}
DBInstanceMutex.releasereadlock(__FUNCTION__, __LINE__);
}
void Database::FreeDBInstance(Database* cur)
{
DBInstanceMutex.writelock(__FUNCTION__, __LINE__);
dbInstances[cur] = false;
DBInstanceMutex.releasewritelock(__FUNCTION__, __LINE__);
}
void Database::RemoveActiveQuery(Query* query)
{
DBQueryMutex.writelock(__FUNCTION__, __LINE__);
vector<Query*>::iterator itr;
for (itr = activeQuerySessions.begin(); itr != activeQuerySessions.end(); itr++)
{
Query* curQuery = *itr;
if (query == curQuery)
{
activeQuerySessions.erase(itr);
break;
}
}
DBQueryMutex.releasewritelock(__FUNCTION__, __LINE__);
bool isActive = LocalIsActiveQuery(query->GetQueryID());
if(!isActive) {
peer_manager.sendPeersActiveQuery(query->GetQueryID(), true);
}
}
void Database::AddActiveQuery(Query* query)
{
peer_manager.sendPeersActiveQuery(query->GetQueryID(), false);
DBQueryMutex.writelock(__FUNCTION__, __LINE__);
activeQuerySessions.push_back(query);
DBQueryMutex.releasewritelock(__FUNCTION__, __LINE__);
}
bool Database::IsActiveQuery(int32 id, Query* skip) {
if (LocalIsActiveQuery(id, skip))
return true;
{
auto now = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> lock(_peerMtx);
// remove any entries older than timeout
for (auto it = _peerActive.begin(); it != _peerActive.end(); ) {
if (now - it->second > kStaleTimeout)
it = _peerActive.erase(it);
else
++it;
}
// if this id is still in the map, it's active
if (_peerActive.find(id) != _peerActive.end())
return true;
}
return false;
}
bool Database::LocalIsActiveQuery(int32 id, Query* skip)
{
bool isActive = false;
DBQueryMutex.readlock(__FUNCTION__, __LINE__);
for (auto query : activeQuerySessions) {
if (query == skip) continue;
if (query->GetQueryID() == id) {
isActive = true;
break;
}
}
DBQueryMutex.releasereadlock(__FUNCTION__, __LINE__);
return isActive;
}
void Database::AddPeerActiveQuery(int32 charID) {
auto now = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> lock(_peerMtx);
_peerActive[charID] = now; // inserts or updates timestamp
}
void Database::RemovePeerActiveQuery(int32 charID) {
std::lock_guard<std::mutex> lock(_peerMtx);
_peerActive.erase(charID);
}
#endif

192
old/database.h Normal file
View File

@ -0,0 +1,192 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EQ2EMU_DATABASE_H
#define EQ2EMU_DATABASE_H
#ifdef WIN32
#include <WinSock2.h>
#include <windows.h>
#endif
#include <mysql.h>
#include "dbcore.h"
#include "types.h"
#include "linked_list.h"
#include "EQStream.h"
#include "MiscFunctions.h"
#include "Mutex.h"
#include <string>
#include <vector>
#include <map>
#include <mutex>
#include <unordered_map>
#include <chrono>
using namespace std;
class Query;
class Database : public DBcore
{
public:
Database();
~Database();
bool Init(bool silentLoad=false);
bool LoadVariables();
void HandleMysqlError(int32 errnum);
map<string, uint16> GetOpcodes(int16 version);
int32 AuthenticateWebUser(char* userName, char* passwd,int32* status = 0);
int32 NoAuthRoute(char* route);
map<int16, int16> GetVersions();
#ifdef WORLD
void AddAsyncQuery(Query* query);
void RunAsyncQueries(int32 queryid);
Database* FindFreeInstance();
void RemoveActiveQuery(Query* query);
void AddActiveQuery(Query* query);
bool IsActiveQuery(int32 id, Query* skip=0);
void PingAsyncDatabase();
void AddPeerActiveQuery(int32 charID);
void RemovePeerActiveQuery(int32 charID);
#endif
protected:
private:
void InitVars();
bool LocalIsActiveQuery(int32 id, Query* skip = nullptr);
#ifdef WORLD
void PurgeDBInstances();
void FreeDBInstance(Database* cur);
bool continueAsync;
map<int32, deque<Query*>> asyncQueries;
map<int32, Mutex*> asyncQueriesMutex;
map<Database*, bool> dbInstances;
vector<Query*> activeQuerySessions;
Mutex DBAsyncMutex;
Mutex DBInstanceMutex;
Mutex DBQueryMutex;
std::unordered_map<int32, std::chrono::steady_clock::time_point> _peerActive;
std::mutex _peerMtx;
static constexpr std::chrono::seconds kStaleTimeout{30};
#endif
};
typedef struct {
int32 queryid;
}DBStruct;
class Query{
public:
Query() {
result = 0;
affected_rows = 0;
last_insert_id = 0;
errnum = 0;
row = 0;
retry = true;
escaped_name = 0;
escaped_pass = 0;
escaped_data1 = 0;
multiple_results = 0;
memset(errbuf, 0, sizeof(errbuf));
queryID = 0;
}
Query(Query* queryPtr, int32 in_id, std::string in_query) {
result = 0;
affected_rows = 0;
last_insert_id = 0;
errnum = 0;
row = 0;
retry = true;
escaped_name = 0;
escaped_pass = 0;
escaped_data1 = 0;
multiple_results = 0;
memset(errbuf, 0, sizeof(errbuf));
query = std::move(in_query);
in_type = queryPtr->GetQueryType();
queryID = in_id;
}
~Query(){
if(result)
mysql_free_result(result);
result = 0;
safe_delete(affected_rows);
safe_delete(last_insert_id);
safe_delete_array(escaped_name);
safe_delete_array(escaped_pass);
safe_delete_array(escaped_data1);
if(multiple_results){
vector<MYSQL_RES*>::iterator itr;
for(itr = multiple_results->begin(); itr != multiple_results->end(); itr++){
mysql_free_result(*itr);
}
safe_delete(multiple_results);
}
}
int32 GetLastInsertedID() { return *last_insert_id; }
int32 GetAffectedRows() { return *affected_rows; }
MYSQL_RES* GetResult() { return result; }
MYSQL_RES* RunQuery2(string in_query, QUERY_TYPE type);
char* GetError() { return errbuf; }
int32 GetErrorNumber(){ return errnum; }
const char* GetQuery() { return query.c_str(); }
char* GetField(int8 field_num) {
if(!row && result)
*row = mysql_fetch_row(result);
if(row && result && field_num < mysql_num_fields(result))
return *row[field_num];
else
return NULL;
}
void NextRow(){
if(result)
*row = mysql_fetch_row(result);
}
void AddQueryAsync(int32 queryID, Database* db, QUERY_TYPE type, const char* format, ...);
void RunQueryAsync(Database* db);
MYSQL_RES* RunQuery2(QUERY_TYPE type, const char* format, ...);
QUERY_TYPE GetQueryType() {
return in_type;
}
int32 GetQueryID() { return queryID; }
char* escaped_name;
char* escaped_pass;
char* escaped_data1;
private:
string query;
char errbuf[MYSQL_ERRMSG_SIZE];
MYSQL_RES *result;
vector<MYSQL_RES*>* multiple_results;
int32* affected_rows;
int32* last_insert_id;
int32 errnum;
QUERY_TYPE in_type;
bool retry;
MYSQL_ROW* row;
MYSQL mysql;
int32 queryID;
};
#endif

368
old/dbcore.cpp Normal file
View File

@ -0,0 +1,368 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "debug.h"
#include <iostream>
using namespace std;
#include <errmsg.h>
//#include <mysqld_error.h>
#include <limits.h>
#include "dbcore.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "types.h"
#include "MiscFunctions.h"
#include "Log.h"
#ifdef WIN32
#define snprintf _snprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#include <process.h>
#else
#include "unix.h"
#include <pthread.h>
#endif
#ifdef _EQDEBUG
#define DEBUG_MYSQL_QUERIES 0
#else
#define DEBUG_MYSQL_QUERIES 0
#endif
DBcore::DBcore() {
mysql_init(&mysql);
pHost = 0;
pPort = 0;
pUser = 0;
pPassword = 0;
pDatabase = 0;
pCompress = false;
pSSL = false;
pStatus = Closed;
}
DBcore::~DBcore() {
pStatus = Closed;
mysql_close(&mysql);
#if MYSQL_VERSION_ID >= 50003
mysql_library_end();
#else
mysql_server_end();
#endif
safe_delete_array(pHost);
safe_delete_array(pUser);
safe_delete_array(pPassword);
safe_delete_array(pDatabase);
}
bool DBcore::ReadDBINI(char* host, char* user, char* passwd, char* database, unsigned int* port, bool* compress, bool* items) {
char line[256], * key, * val;
bool on_database_section = false;
FILE* f;
if ((f = fopen(DB_INI_FILE, "r")) == NULL) {
LogWrite(DATABASE__ERROR, 0, "DBCore", "Unable to open '%s' for reading", DB_INI_FILE);
return false;
}
//read each line
while (fgets(line, sizeof(line), f) != NULL) {
//remove any new line or carriage return
while ((key = strstr(line, "\n")) != NULL)
*key = '\0';
while ((key = strstr(line, "\r")) != NULL)
*key = '\0';
//ignore blank lines and commented lines
if (strlen(line) == 0 || line[0] == '#')
continue;
key = strtok(line, "=");
if (key == NULL)
continue;
//don't do anything until we find the [Database] section
if (!on_database_section && strncasecmp(key, "[Database]", 10) == 0)
on_database_section = true;
else {
val = strtok(NULL, "=");
if (val == NULL)
{
if (strcasecmp(key, "password") == 0) {
strcpy(passwd, "");
items[2] = true;
}
continue;
}
if (strcasecmp(key, "host") == 0) {
strcpy(host, val);
items[0] = true;
}
else if (strcasecmp(key, "user") == 0) {
strcpy(user, val);
items[1] = true;
}
else if (strcasecmp(key, "password") == 0) {
strcpy(passwd, val);
items[2] = true;
}
else if (strcasecmp(key, "database") == 0) {
strcpy(database, val);
items[3] = true;
}
else if (strcasecmp(key, "port") == 0 && port) {
*port = atoul(val);
items[4] = true;
}
else if (strcasecmp(key, "compression") == 0) {
if (strcasecmp(val, "on") == 0) {
if(compress) {
*compress = true;
items[5] = true;
LogWrite(DATABASE__INFO, 0, "DBCore", "DB Compression on.");
}
}
}
}
}
fclose(f);
if (!on_database_section) {
LogWrite(DATABASE__ERROR, 0, "DBCore", "[Database] section not found in '%s'", DB_INI_FILE);
return false;
}
return true;
}
// Sends the MySQL server a keepalive
void DBcore::ping() {
if (!MDatabase.trylock()) {
// well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
return;
}
mysql_ping(&mysql);
int32* errnum = new int32;
*errnum = mysql_errno(&mysql);
switch (*errnum)
{
case CR_COMMANDS_OUT_OF_SYNC:
case CR_SERVER_GONE_ERROR:
case CR_UNKNOWN_ERROR:
{
LogWrite(DATABASE__ERROR, 0, "DBCore", "[Database] We lost connection to the database., errno: %i", errno);
break;
}
}
safe_delete(errnum);
MDatabase.unlock();
}
bool DBcore::RunQuery(const char* query, int32 querylen, char* errbuf, MYSQL_RES** result, int32* affected_rows, int32* last_insert_id, int32* errnum, bool retry) {
if (errnum)
*errnum = 0;
if (errbuf)
errbuf[0] = 0;
bool ret = false;
LockMutex lock(&MDatabase);
if (pStatus != Connected)
Open();
LogWrite(DATABASE__QUERY, 0, "DBCore", query);
if (mysql_real_query(&mysql, query, querylen)) {
if (mysql_errno(&mysql) == CR_SERVER_GONE_ERROR)
pStatus = Error;
if (mysql_errno(&mysql) == CR_SERVER_LOST || mysql_errno(&mysql) == CR_SERVER_GONE_ERROR) {
if (retry) {
LogWrite(DATABASE__ERROR, 0, "DBCore", "Lost connection, attempting to recover...");
ret = RunQuery(query, querylen, errbuf, result, affected_rows, last_insert_id, errnum, false);
}
else {
pStatus = Error;
if (errnum)
*errnum = mysql_errno(&mysql);
if (errbuf)
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
LogWrite(DATABASE__ERROR, 0, "DBCore", "#%i: %s\nQuery:\n%s", mysql_errno(&mysql), mysql_error(&mysql), query);
ret = false;
}
}
else {
if (errnum)
*errnum = mysql_errno(&mysql);
if (errbuf)
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
LogWrite(DATABASE__ERROR, 0, "DBCore", "#%i: %s\nQuery:\n%s", mysql_errno(&mysql), mysql_error(&mysql), query);
ret = false;
}
}
else {
if (result && mysql_field_count(&mysql)) {
*result = mysql_store_result(&mysql);
}
else if (result)
*result = 0;
if (affected_rows)
*affected_rows = mysql_affected_rows(&mysql);
if (last_insert_id)
*last_insert_id = mysql_insert_id(&mysql);
if (result) {
if (*result) {
ret = true;
}
else {
if (errnum)
*errnum = UINT_MAX;
if (errbuf){
if((!affected_rows || (affected_rows && *affected_rows == 0)) && (!last_insert_id || (last_insert_id && *last_insert_id == 0)))
LogWrite(DATABASE__RESULT, 1, "DBCore", "No Result.");
}
ret = false;
}
}
else {
ret = true;
}
}
if (ret)
{
char tmp1[200] = {0};
char tmp2[200] = {0};
if (result && (*result))
snprintf(tmp1, sizeof(tmp1), ", %i rows returned", (int) mysql_num_rows(*result));
if (affected_rows)
snprintf(tmp2, sizeof(tmp2), ", %i rows affected", (*affected_rows));
LogWrite(DATABASE__DEBUG, 0, "DBCore", "Query Successful%s%s", tmp1, tmp2);
}
else
LogWrite(DATABASE__DEBUG, 0, "DBCore", "Query returned no results in %s!\n%s", __FUNCTION__, query);
return ret;
}
int32 DBcore::DoEscapeString(char* tobuf, const char* frombuf, int32 fromlen) {
LockMutex lock(&MDatabase);
return mysql_real_escape_string(&mysql, tobuf, frombuf, fromlen);
}
bool DBcore::Open(const char* iHost, const char* iUser, const char* iPassword, const char* iDatabase,int32 iPort, int32* errnum, char* errbuf, bool iCompress, bool iSSL) {
LockMutex lock(&MDatabase);
safe_delete_array(pHost);
safe_delete_array(pUser);
safe_delete_array(pPassword);
safe_delete_array(pDatabase);
pHost = new char[strlen(iHost) + 1];
strcpy(pHost, iHost);
pUser = new char[strlen(iUser) + 1];
strcpy(pUser, iUser);
pPassword = new char[strlen(iPassword) + 1];
strcpy(pPassword, iPassword);
pDatabase = new char[strlen(iDatabase) + 1];
strcpy(pDatabase, iDatabase);
pCompress = iCompress;
pPort = iPort;
pSSL = iSSL;
return Open(errnum, errbuf);
}
bool DBcore::Open(int32* errnum, char* errbuf) {
if (errbuf)
errbuf[0] = 0;
LockMutex lock(&MDatabase);
if (GetStatus() == Connected)
return true;
if (GetStatus() == Error)
mysql_close(&mysql);
if (!pHost)
return false;
/*
Quagmire - added CLIENT_FOUND_ROWS flag to the connect
otherwise DB update calls would say 0 rows affected when the value already equalled
what the function was tring to set it to, therefore the function would think it failed
*/
int32 flags = CLIENT_FOUND_ROWS;
if (pCompress)
flags |= CLIENT_COMPRESS;
if (pSSL)
flags |= CLIENT_SSL;
if (mysql_real_connect(&mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) {
pStatus = Connected;
return true;
}
else {
if (errnum)
*errnum = mysql_errno(&mysql);
if (errbuf)
snprintf(errbuf, MYSQL_ERRMSG_SIZE, "#%i: %s", mysql_errno(&mysql), mysql_error(&mysql));
pStatus = Error;
return false;
}
}
char* DBcore::getEscapeString(const char* from_string){
if(!from_string)
from_string ="";
int orig_size = strlen(from_string);
int escape_size = (orig_size * 2) + 1;
char* escaped = new char[escape_size];
memset(escaped, 0, escape_size);
DoEscapeString(escaped, from_string, orig_size);
return escaped;
}
string DBcore::getSafeEscapeString(const char* from_string){
if(!from_string)
from_string ="";
int orig_size = strlen(from_string);
int escape_size = (orig_size * 2) + 1;
char* escaped = new char[escape_size];
memset(escaped, 0, escape_size);
DoEscapeString(escaped, from_string, orig_size);
string ret = string(escaped);
safe_delete_array(escaped);
return ret;
}
string DBcore::getSafeEscapeString(string* from_string){
if(!from_string)
return "";
int orig_size = from_string->length();
int escape_size = (orig_size * 2) + 1;
char* escaped = new char[escape_size];
memset(escaped, 0, escape_size);
DoEscapeString(escaped, from_string->c_str(), orig_size);
string ret = string(escaped);
safe_delete_array(escaped);
return ret;
}

80
old/dbcore.h Normal file
View File

@ -0,0 +1,80 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DBCORE_H
#define DBCORE_H
#ifdef WIN32
#include <WinSock2.h>
#include <windows.h>
//#include <WinSock2.h>
#endif
#include <mysql.h>
#include "../common/types.h"
#include "../common/Mutex.h"
#include "../common/linked_list.h"
#include "../common/queue.h"
#include "../common/timer.h"
#include "../common/Condition.h"
#ifdef LOGIN
#define DB_INI_FILE "login_db.ini"
#endif
#ifdef WORLD
#define DB_INI_FILE "world_db.ini"
#endif
#ifdef PARSER
#define DB_INI_FILE "parser_db.ini"
#endif
#ifdef PATCHER
#define DB_INI_FILE "patcher_db.ini"
#endif
class DBcore{
public:
enum eStatus { Closed, Connected, Error };
DBcore();
~DBcore();
eStatus GetStatus() { return pStatus; }
bool RunQuery(const char* query, int32 querylen, char* errbuf = 0, MYSQL_RES** result = 0, int32* affected_rows = 0, int32* last_insert_id = 0, int32* errnum = 0, bool retry = true);
int32 DoEscapeString(char* tobuf, const char* frombuf, int32 fromlen);
void ping();
char* getEscapeString(const char* from_string);
string getSafeEscapeString(const char* from_string);
string getSafeEscapeString(string* from_string);
protected:
bool Open(const char* iHost, const char* iUser, const char* iPassword, const char* iDatabase, int32 iPort, int32* errnum = 0, char* errbuf = 0, bool iCompress = false, bool iSSL = false);
bool ReadDBINI(char *host, char *user, char *pass, char *db, unsigned int* port, bool* compress, bool *items);
private:
bool Open(int32* errnum = 0, char* errbuf = 0);
MYSQL mysql;
Mutex MDatabase;
eStatus pStatus;
char* pHost;
char* pUser;
char* pPassword;
char* pDatabase;
bool pCompress;
int32 pPort;
bool pSSL;
};
#endif

336
old/debug.cpp Normal file
View File

@ -0,0 +1,336 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
/*
JA: File rendered obsolete (2011-08-12)
#include "debug.h"
#include <iostream>
using namespace std;
#include <time.h>
#include <string.h>
#ifdef WIN32
#include <process.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>
#endif
#include "../common/MiscFunctions.h"
EQEMuLog* LogFile = new EQEMuLog;
AutoDelete<EQEMuLog> adlf(&LogFile);
static const char* FileNames[EQEMuLog::MaxLogID] = { "logs/eq2emu", "logs/eq2emu", "logs/eq2emu_error", "logs/eq2emu_debug", "logs/eq2emu_quest", "logs/eq2emu_commands" };
static const char* LogNames[EQEMuLog::MaxLogID] = { "Status", "Normal", "Error", "Debug", "Quest", "Command" };
EQEMuLog::EQEMuLog() {
for (int i=0; i<MaxLogID; i++) {
fp[i] = 0;
#if EQDEBUG >= 2
pLogStatus[i] = 1 | 2;
#else
pLogStatus[i] = 0;
#endif
logCallbackFmt[i] = NULL;
logCallbackBuf[i] = NULL;
}
#if EQDEBUG < 2
pLogStatus[Status] = 3;
pLogStatus[Error] = 3;
pLogStatus[Debug] = 3;
pLogStatus[Quest] = 2;
pLogStatus[Commands] = 2;
#endif
}
EQEMuLog::~EQEMuLog() {
for (int i=0; i<MaxLogID; i++) {
if (fp[i])
fclose(fp[i]);
}
}
bool EQEMuLog::open(LogIDs id) {
if (id >= MaxLogID) {
return false;
}
LockMutex lock(&MOpen);
if (pLogStatus[id] & 4) {
return false;
}
if (fp[id]) {
return true;
}
char exename[200] = "";
#if defined(WORLD)
snprintf(exename, sizeof(exename), "_world");
#elif defined(ZONE)
snprintf(exename, sizeof(exename), "_zone");
#endif
char filename[200];
#ifndef NO_PIDLOG
snprintf(filename, sizeof(filename), "%s%s_%04i.log", FileNames[id], exename, getpid());
#else
snprintf(filename, sizeof(filename), "%s%s.log", FileNames[id], exename);
#endif
fp[id] = fopen(filename, "a");
if (!fp[id]) {
cerr << "Failed to open log file: " << filename << endl;
pLogStatus[id] |= 4; // set file state to error
return false;
}
fputs("---------------------------------------------\n",fp[id]);
return true;
}
bool EQEMuLog::write(LogIDs id, const char *fmt, ...) {
char buffer[4096];
if (!this) {
return false;
}
if (id >= MaxLogID) {
return false;
}
bool dofile = false;
if (pLogStatus[id] & 1) {
dofile = open(id);
}
if (!(dofile || pLogStatus[id] & 2))
return false;
LockMutex lock(&MLog[id]);
time_t aclock;
struct tm *newtime;
time( &aclock ); //Get time in seconds
newtime = localtime( &aclock ); //Convert time to struct
if (dofile){
#ifndef NO_PIDLOG
fprintf(fp[id], "[%04d%02d%02d %02d:%02d:%02d] ", newtime->tm_year+1900, newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec);
#else
fprintf(fp[id], "%04i [%04d%02d%02d %02d:%02d:%02d] ", getpid(), newtime->tm_year+1900, newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec);
#endif
}
va_list argptr;
va_start(argptr, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, argptr);
va_end(argptr);
if (dofile)
fprintf(fp[id], "%s\n", buffer);
if(logCallbackFmt[id]) {
msgCallbackFmt p = logCallbackFmt[id];
p(id, fmt, argptr );
}
if (pLogStatus[id] & 2) {
if (pLogStatus[id] & 8) {
fprintf(stderr, "[%04d%02d%02d %02d:%02d:%02d] [%s] ", newtime->tm_year+1900, newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec, LogNames[id]);
fprintf(stderr, "%s\n", buffer);
}
else {
fprintf(stdout, "[%04d%02d%02d %02d:%02d:%02d] [%s] ", newtime->tm_year+1900, newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec, LogNames[id]);
fprintf(stdout, "%s\n", buffer);
}
}
if (dofile)
fprintf(fp[id], "\n");
if (pLogStatus[id] & 2) {
if (pLogStatus[id] & 8)
fprintf(stderr, "\n");
else
fprintf(stdout, "\n");
}
if(dofile)
fflush(fp[id]);
return true;
}
bool EQEMuLog::writebuf(LogIDs id, const char *buf, int8 size, int32 count) {
if (!this) {
return false;
}
if (id >= MaxLogID) {
return false;
}
bool dofile = false;
if (pLogStatus[id] & 1) {
dofile = open(id);
}
if (!(dofile || pLogStatus[id] & 2))
return false;
LockMutex lock(&MLog[id]);
time_t aclock;
struct tm *newtime;
time( &aclock ); // Get time in seconds
newtime = localtime( &aclock ); // Convert time to struct
if (dofile){
#ifndef NO_PIDLOG
fprintf(fp[id], "[%02d.%02d. - %02d:%02d:%02d] ", newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec);
#else
fprintf(fp[id], "%04i [%02d.%02d. - %02d:%02d:%02d] ", getpid(), newtime->tm_mon+1, newtime->tm_mday, newtime->tm_hour, newtime->tm_min, newtime->tm_sec);
#endif
}
if (dofile) {
fwrite(buf, size, count, fp[id]);
fprintf(fp[id], "\n");
}
if(logCallbackBuf[id]) {
msgCallbackBuf p = logCallbackBuf[id];
p(id, buf, size, count);
}
if (pLogStatus[id] & 2) {
if (pLogStatus[id] & 8) {
fprintf(stderr, "[%s] ", LogNames[id]);
fwrite(buf, size, count, stderr);
fprintf(stderr, "\n");
} else {
fprintf(stdout, "[%s] ", LogNames[id]);
fwrite(buf, size, count, stdout);
fprintf(stdout, "\n");
}
}
if(dofile)
fflush(fp[id]);
return true;
}
bool EQEMuLog::writeNTS(LogIDs id, bool dofile, const char *fmt, ...) {
char buffer[4096];
va_list argptr;
va_start(argptr, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, argptr);
va_end(argptr);
if (dofile)
fprintf(fp[id], "%s\n", buffer);
if (pLogStatus[id] & 2) {
if (pLogStatus[id] & 8)
fprintf(stderr, "%s\n", buffer);
else
fprintf(stdout, "%s\n", buffer);
}
return true;
};
bool EQEMuLog::Dump(LogIDs id, int8* data, int32 size, int32 cols, int32 skip) {
if (!this) {
#if EQDEBUG >= 10
cerr << "Error: Dump() from null pointer"<<endl;
#endif
return false;
}
if (size == 0)
return true;
if (!LogFile)
return false;
if (id >= MaxLogID)
return false;
bool dofile = false;
if (pLogStatus[id] & 1) {
dofile = open(id);
}
if (!(dofile || pLogStatus[id] & 2))
return false;
LockMutex lock(&MLog[id]);
write(id, "Dumping Packet: %i", size);
// Output as HEX
int j = 0; char* ascii = new char[cols+1]; memset(ascii, 0, cols+1);
int32 i;
for(i=skip; i<size; i++) {
if ((i-skip)%cols==0) {
if (i != skip)
writeNTS(id, dofile, " | %s\n", ascii);
writeNTS(id, dofile, "%4i: ", i-skip);
memset(ascii, 0, cols+1);
j = 0;
}
else if ((i-skip)%(cols/2) == 0) {
writeNTS(id, dofile, "- ");
}
writeNTS(id, dofile, "%02X ", (unsigned char)data[i]);
if (data[i] >= 32 && data[i] < 127)
ascii[j++] = data[i];
else
ascii[j++] = '.';
}
int32 k = ((i-skip)-1)%cols;
if (k < 8)
writeNTS(id, dofile, " ");
for (int32 h = k+1; h < cols; h++) {
writeNTS(id, dofile, " ");
}
writeNTS(id, dofile, " | %s\n", ascii);
if (dofile)
fflush(fp[id]);
safe_delete_array(ascii);
return true;
}
void EQEMuLog::SetCallback(LogIDs id, msgCallbackFmt proc) {
if (!this)
return;
if (id >= MaxLogID) {
return;
}
logCallbackFmt[id] = proc;
}
void EQEMuLog::SetCallback(LogIDs id, msgCallbackBuf proc) {
if (!this)
return;
if (id >= MaxLogID) {
return;
}
logCallbackBuf[id] = proc;
}
void EQEMuLog::SetAllCallbacks(msgCallbackFmt proc) {
if (!this)
return;
int r;
for(r = Status; r < MaxLogID; r++) {
SetCallback((LogIDs)r, proc);
}
}
void EQEMuLog::SetAllCallbacks(msgCallbackBuf proc) {
if (!this)
return;
int r;
for(r = Status; r < MaxLogID; r++) {
SetCallback((LogIDs)r, proc);
}
}
*/

143
old/debug.h Normal file
View File

@ -0,0 +1,143 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EQDEBUG_H
#define EQDEBUG_H
// Debug Levels
/*
1 = Normal
3 = Some extended debug info
5 = Light DETAIL info
7 = Heavy DETAIL info
9 = DumpPacket/PrintPacket
You should use even numbers too, to define any subset of the above basic template
*/
#ifndef EQDEBUG
#define EQDEBUG 1
#endif
#if defined(DEBUG) && defined(WIN32)
//#ifndef _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#if (_MSC_VER < 1300)
#include <new>
#include <memory>
#define _CRTDBG_MAP_ALLOC
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
#endif
//#endif
#endif
#ifndef ThrowError
void CatchSignal(int);
#if defined(CATCH_CRASH) || defined(_EQDEBUG)
#define ThrowError(errstr) { cout << "Fatal error: " << errstr << " (" << __FILE__ << ", line " << __LINE__ << ")" << endl; LogWrite(WORLD__ERROR, 0, "Debug", "Thrown Error: %s (%s:%i)", errstr, __FILE__, __LINE__); throw errstr; }
#else
#define ThrowError(errstr) { cout << "Fatal error: " << errstr << " (" << __FILE__ << ", line " << __LINE__ << ")" << endl; LogWrite(WORLD__ERROR, 0, "Debug", "Thrown Error: %s (%s:%i)", errstr, __FILE__, __LINE__); CatchSignal(0); }
#endif
#endif
#ifdef WIN32
// VS6 doesn't like the length of STL generated names: disabling
#pragma warning(disable:4786)
#endif
#ifndef WIN32
#define DebugBreak() if(0) {}
#endif
#ifdef WIN32
#include <WinSock2.h>
#include <windows.h>
#endif
#include "../common/Mutex.h"
#include <stdio.h>
#include <stdarg.h>
class EQEMuLog {
public:
EQEMuLog();
~EQEMuLog();
enum LogIDs {
Status = 0, //this must stay the first entry in this list
Normal,
Error,
Debug,
Quest,
Commands,
MaxLogID
};
//these are callbacks called for each
typedef void (* msgCallbackBuf)(LogIDs id, const char *buf, int8 size, int32 count);
typedef void (* msgCallbackFmt)(LogIDs id, const char *fmt, va_list ap);
void SetAllCallbacks(msgCallbackFmt proc);
void SetAllCallbacks(msgCallbackBuf proc);
void SetCallback(LogIDs id, msgCallbackFmt proc);
void SetCallback(LogIDs id, msgCallbackBuf proc);
bool writebuf(LogIDs id, const char *buf, int8 size, int32 count);
bool write(LogIDs id, const char *fmt, ...);
bool Dump(LogIDs id, int8* data, int32 size, int32 cols=16, int32 skip=0);
private:
bool open(LogIDs id);
bool writeNTS(LogIDs id, bool dofile, const char *fmt, ...); // no error checking, assumes is open, no locking, no timestamp, no newline
Mutex MOpen;
Mutex MLog[MaxLogID];
FILE* fp[MaxLogID];
/* LogStatus: bitwise variable
1 = output to file
2 = output to stdout
4 = fopen error, dont retry
8 = use stderr instead (2 must be set)
*/
int8 pLogStatus[MaxLogID];
msgCallbackFmt logCallbackFmt[MaxLogID];
msgCallbackBuf logCallbackBuf[MaxLogID];
};
//extern EQEMuLog* LogFile;
#ifdef _EQDEBUG
class PerformanceMonitor {
public:
PerformanceMonitor(sint64* ip) {
p = ip;
QueryPerformanceCounter(&tmp);
}
~PerformanceMonitor() {
LARGE_INTEGER tmp2;
QueryPerformanceCounter(&tmp2);
*p += tmp2.QuadPart - tmp.QuadPart;
}
LARGE_INTEGER tmp;
sint64* p;
};
#endif
#endif

39
old/emu_opcodes.cpp Normal file
View File

@ -0,0 +1,39 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "emu_opcodes.h"
const char *OpcodeNames[_maxEmuOpcode+1] = {
"OP_Unknown",
//a preprocessor hack so we dont have to maintain two lists
#define N(x) #x
#if !defined(LOGIN)
#include "emu_oplist.h"
#endif
#ifdef LOGIN
#include "login_oplist.h"
#endif
#undef N
""
};

56
old/emu_opcodes.h Normal file
View File

@ -0,0 +1,56 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EMU_OPCODES_H
#define EMU_OPCODES_H
//this is the highest opcode possibly used in the regular EQ protocol
#define MAX_EQ_OPCODE 0xFFFF
/*
the list of opcodes is in emu_oplist.h
we somewhat rely on the fact that we have more than 255 opcodes,
so we know the enum type for the opcode defines must be at least
16 bits, so we can use the protocol flags on them.
*/
typedef enum { //EQEmu internal opcodes list
OP_Unknown=0,
//a preprocessor hack so we dont have to maintain two lists
#define N(x) x
#if !defined(LOGIN)
#include "emu_oplist.h"
#endif
#ifdef LOGIN
#include "login_oplist.h"
#endif
#undef N
_maxEmuOpcode
} EmuOpcode;
extern const char *OpcodeNames[_maxEmuOpcode+1];
#endif

505
old/emu_oplist.h Normal file
View File

@ -0,0 +1,505 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
N(OP_LoginReplyMsg),
N(OP_LoginByNumRequestMsg),
N(OP_WSLoginRequestMsg),
N(OP_ESInitMsg),
N(OP_ESReadyForClientsMsg),
N(OP_CreateZoneInstanceMsg),
N(OP_ZoneInstanceCreateReplyMsg),
N(OP_ZoneInstanceDestroyedMsg),
N(OP_ExpectClientAsCharacterRequest),
N(OP_ExpectClientAsCharacterReplyMs),
N(OP_ZoneInfoMsg),
N(OP_CreateCharacterRequestMsg),
N(OP_DoneLoadingZoneResourcesMsg),
N(OP_DoneSendingInitialEntitiesMsg),
N(OP_DoneLoadingEntityResourcesMsg),
N(OP_DoneLoadingUIResourcesMsg),
N(OP_PredictionUpdateMsg),
N(OP_RemoteCmdMsg),
N(OP_SetRemoteCmdsMsg),
N(OP_GameWorldTimeMsg),
N(OP_MOTDMsg),
N(OP_ZoneMOTDMsg),
N(OP_GuildRecruitingMemberInfo),
N(OP_GuildRecruiting),
N(OP_GuildRecruitingDetails),
N(OP_GuildRecruitingImage),
N(OP_AvatarCreatedMsg),
N(OP_AvatarDestroyedMsg),
N(OP_RequestCampMsg),
N(OP_MapRequest),
N(OP_CampStartedMsg),
N(OP_CampAbortedMsg),
N(OP_WhoQueryRequestMsg),
N(OP_WhoQueryReplyMsg),
N(OP_MonitorReplyMsg),
N(OP_MonitorCharacterListMsg),
N(OP_MonitorCharacterListRequestMsg),
N(OP_ClientCmdMsg),
N(OP_Lottery),
N(OP_DispatchClientCmdMsg),
N(OP_DispatchESMsg),
N(OP_UpdateTargetMsg),
N(OP_UpdateOpportunityMsg),
N(OP_UpdateTargetLocMsg),
N(OP_UpdateCharacterSheetMsg),
N(OP_UpdateSpellBookMsg),
N(OP_UpdateInventoryMsg),
N(OP_UpdateRecipeBookMsg),
N(OP_RequestRecipeDetailsMsg),
N(OP_RecipeDetailsMsg),
N(OP_UpdateSkillBookMsg),
N(OP_UpdateSkillsMsg),
N(OP_ChangeZoneMsg),
N(OP_ClientTeleportRequestMsg),
N(OP_TeleportWithinZoneMsg),
N(OP_TeleportWithinZoneNoReloadMsg),
N(OP_MigrateClientToZoneRequestMsg),
N(OP_MigrateClientToZoneReplyMsg),
N(OP_ReadyToZoneMsg),
//N(OP_AddClientToGroupMsg),
//N(OP_AddGroupToGroupMsg),
N(OP_RemoveClientFromGroupMsg),
N(OP_RemoveGroupFromGroupMsg),
N(OP_MakeGroupLeaderMsg),
N(OP_GroupCreatedMsg),
N(OP_GroupDestroyedMsg),
N(OP_GroupMemberAddedMsg),
N(OP_GroupMemberRemovedMsg),
N(OP_GroupRemovedFromGroupMsg),
N(OP_GroupLeaderChangedMsg),
N(OP_GroupSettingsChangedMsg),
N(OP_SendLatestRequestMsg),
N(OP_ClearDataMsg),
N(OP_SetSocialMsg),
N(OP_ESStatusMsg),
N(OP_ESZoneInstanceStatusMsg),
N(OP_ZonesStatusRequestMsg),
N(OP_ZonesStatusMsg),
N(OP_ESWeatherRequestMsg),
N(OP_ESWeatherRequestEndMsg),
//N(OP_WSWeatherUpdateMsg),
N(OP_DialogSelectMsg),
N(OP_DialogCloseMsg),
N(OP_RemoveSpellEffectMsg),
N(OP_RemoveConcentrationMsg),
N(OP_QuestJournalOpenMsg),
N(OP_QuestJournalInspectMsg),
//N(OP_SkillSlotMapping),
N(OP_QuestJournalSetVisibleMsg),
N(OP_QuestJournalWaypointMsg),
N(OP_CreateGuildRequestMsg),
N(OP_CreateGuildReplyMsg),
N(OP_GuildsayMsg),
//N(OP_GuildKickMsg),
N(OP_GuildUpdateMsg),
N(OP_FellowshipExpMsg),
N(OP_ConsignmentCloseStoreMsg),
N(OP_ConsignItemRequestMsg),
N(OP_ConsignItemResponseMsg),
//N(OP_PurchaseConsignmentRequestMsg),
N(OP_PurchaseConsignmentLoreCheckRe),
N(OP_QuestReward),
//N(OP_PurchaseConsignmentResponseMsg),
//N(OP_ProcessScriptMsg),
//N(OP_ProcessWorkspaceMsg),
N(OP_HouseDeletedRemotelyMsg),
N(OP_UpdateHouseDataMsg),
N(OP_UpdateHouseAccessDataMsg),
N(OP_PlayerHouseBaseScreenMsg),
N(OP_PlayerHousePurchaseScreenMsg),
N(OP_PlayerHouseAccessUpdateMsg),
N(OP_PlayerHouseDisplayStatusMsg),
N(OP_PlayerHouseCloseUIMsg),
N(OP_BuyPlayerHouseMsg),
N(OP_BuyPlayerHouseTintMsg),
N(OP_CollectAllHouseItemsMsg),
N(OP_RelinquishHouseMsg),
N(OP_EnterHouseMsg),
N(OP_ExitHouseMsg),
N(OP_ExamineConsignmentRequestMsg),
N(OP_MoveableObjectPlacementCriteri),
N(OP_EnterMoveObjectModeMsg),
N(OP_PositionMoveableObject),
N(OP_CancelMoveObjectModeMsg),
N(OP_ShaderCustomizationMsg),
N(OP_ReplaceableSubMeshesMsg),
N(OP_ExamineConsignmentResponseMsg),
N(OP_HouseDefaultAccessSetMsg),
N(OP_HouseAccessSetMsg),
N(OP_HouseAccessRemoveMsg),
N(OP_PayHouseUpkeepMsg),
N(OP_TintWidgetsMsg),
N(OP_UISettingsResponseMsg),
N(OP_UIResetMsg),
N(OP_KeymapLoadMsg),
N(OP_KeymapNoneMsg),
N(OP_KeymapDataMsg),
N(OP_KeymapSaveMsg),
N(OP_DispatchSpellCmdMsg),
N(OP_HouseCustomizationScreenMsg),
N(OP_CustomizationPurchaseRequestMs),
N(OP_CustomizationSetRequestMsg),
N(OP_CustomizationReplyMsg),
N(OP_EntityVerbsRequestMsg),
N(OP_EntityVerbsReplyMsg),
N(OP_EntityVerbsVerbMsg),
N(OP_ChatRelationshipUpdateMsg),
N(OP_ChatCreateChannelMsg),
N(OP_ChatJoinChannelMsg),
N(OP_ChatWhoChannelMsg),
N(OP_ChatLeaveChannelMsg),
N(OP_ChatTellChannelMsg),
N(OP_ChatTellUserMsg),
N(OP_ChatToggleFriendMsg),
N(OP_ChatToggleIgnoreMsg),
N(OP_ChatSendFriendsMsg),
N(OP_ChatSendIgnoresMsg),
N(OP_ChatFiltersMsg),
N(OP_LootItemsRequestMsg),
N(OP_StoppedLootingMsg),
N(OP_SitMsg),
N(OP_StandMsg),
N(OP_SatMsg),
N(OP_StoodMsg),
//N(OP_QuickbarAddMsg),
N(OP_DefaultGroupOptionsRequestMsg),
N(OP_DefaultGroupOptionsMsg),
N(OP_GroupOptionsMsg),
N(OP_DisplayGroupOptionsScreenMsg),
N(OP_DisplayInnVisitScreenMsg),
N(OP_DumpSchedulerMsg),
//N(OP_LSRequestPlayerDescMsg),
N(OP_LSCheckAcctLockMsg),
N(OP_WSAcctLockStatusMsg),
N(OP_RequestHelpRepathMsg),
N(OP_UpdateMotdMsg),
N(OP_RequestTargetLocMsg),
N(OP_PerformPlayerKnockbackMsg),
N(OP_PerformCameraShakeMsg),
N(OP_PopulateSkillMapsMsg),
N(OP_CancelledFeignMsg),
N(OP_SignalMsg),
N(OP_SkillInfoRequest),
N(OP_SkillInfoResponse),
N(OP_ShowCreateFromRecipeUIMsg),
N(OP_CancelCreateFromRecipeMsg),
N(OP_BeginItemCreationMsg),
N(OP_StopItemCreationMsg),
N(OP_ShowItemCreationProcessUIMsg),
N(OP_UpdateItemCreationProcessUIMsg),
N(OP_DisplayTSEventReactionMsg),
N(OP_ShowRecipeBookMsg),
N(OP_KnowledgebaseRequestMsg),
N(OP_KnowledgebaseResponseMsg),
N(OP_CSTicketHeaderRequestMsg),
N(OP_CSTicketInfoMsg),
N(OP_CSTicketCommentRequestMsg),
N(OP_CSTicketCommentResponseMsg),
N(OP_CSTicketCreateMsg),
N(OP_CSTicketAddCommentMsg),
N(OP_CSTicketDeleteMsg),
N(OP_CSTicketChangeNotificationMsg),
N(OP_WorldDataUpdateMsg),
N(OP_WorldDataChangeMsg),
N(OP_KnownLanguagesMsg),
N(OP_LsRequestClientCrashLogMsg),
N(OP_LsClientBaselogReplyMsg),
N(OP_LsClientCrashlogReplyMsg),
N(OP_LsClientAlertlogReplyMsg),
N(OP_LsClientVerifylogReplyMsg),
N(OP_ClientTeleportToLocationMsg),
N(OP_UpdateClientPredFlagsMsg),
N(OP_ChangeServerControlFlagMsg),
N(OP_CSToolsRequestMsg),
N(OP_CSToolsResponseMsg),
N(OP_CreateBoatTransportsMsg),
N(OP_PositionBoatTransportMsg),
N(OP_MigrateBoatTransportMsg),
N(OP_MigrateBoatTransportReplyMsg),
N(OP_DisplayDebugNLLPointsMsg),
N(OP_ExamineInfoRequestMsg),
N(OP_QuickbarInitMsg),
N(OP_QuickbarUpdateMsg),
N(OP_MacroInitMsg),
N(OP_MacroUpdateMsg),
N(OP_QuestionnaireMsg),
N(OP_LevelChangedMsg),
N(OP_SpellGainedMsg),
N(OP_EncounterBrokenMsg),
N(OP_OnscreenMsgMsg),
N(OP_DisplayWarningMsg),
N(OP_ModifyGuildMsg),
N(OP_GuildEventMsg),
N(OP_GuildEventAddMsg),
N(OP_GuildEventActionMsg),
N(OP_GuildEventListMsg),
N(OP_RequestGuildEventDetailsMsg),
N(OP_GuildEventDetailsMsg),
N(OP_RequestGuildBankEventDetailsMs),
N(OP_GuildBankUpdateMsg),
N(OP_RewardPackMsg),
N(OP_RenameGuildMsg),
N(OP_ZoneToFriendRequestMsg),
N(OP_ZoneToFriendReplyMsg),
N(OP_WaypointRequestMsg),
N(OP_WaypointReplyMsg),
N(OP_WaypointSelectMsg),
N(OP_WaypointUpdateMsg),
N(OP_CharNameChangedMsg),
N(OP_ShowZoneTeleporterDestinations),
N(OP_SelectZoneTeleporterDestinatio),
N(OP_ReloadLocalizedTxtMsg),
N(OP_RequestGuildMembershipMsg),
N(OP_GuildMembershipResponseMsg),
N(OP_LeaveGuildNotifyMsg),
N(OP_JoinGuildNotifyMsg),
N(OP_RequestGuildInfoMsg),
N(OP_GuildBankEventListMsg),
N(OP_AvatarUpdateMsg),
N(OP_BioUpdateMsg),
N(OP_InspectPlayerMsg),
N(OP_WSServerLockMsg),
N(OP_WSServerHideMsg),
N(OP_LSServerLockMsg),
N(OP_CsCategoryRequestMsg),
N(OP_CsCategoryResponseMsg),
N(OP_KnowledgeWindowSlotMappingMsg),
N(OP_LFGUpdateMsg),
N(OP_AFKUpdateMsg),
N(OP_AnonUpdateMsg),
N(OP_UpdateActivePublicZonesMsg),
N(OP_UnknownNpcMsg),
N(OP_PromoFlagsDetailsMsg),
N(OP_ConsignViewCreateMsg),
N(OP_ConsignViewGetPageMsg),
N(OP_ConsignViewReleaseMsg),
N(OP_UpdateDebugRadiiMsg),
N(OP_ConsignRemoveItemsMsg),
//N(OP_SnoopMsg),
N(OP_ReportMsg),
N(OP_UpdateRaidMsg),
N(OP_ConsignViewSortMsg),
N(OP_TitleUpdateMsg),
N(OP_FlightPathsMsg),
N(OP_ClientFellMsg),
N(OP_ClientInDeathRegionMsg),
N(OP_CampClientMsg),
N(OP_GetAvatarAccessRequestForCSToo),
N(OP_CSToolAccessResponseMsg),
N(OP_DeleteGuildMsg),
N(OP_TrackingUpdateMsg),
N(OP_BeginTrackingMsg),
N(OP_StopTrackingMsg),
N(OP_AdvancementRequestMsg),
N(OP_MapFogDataInitMsg),
N(OP_MapFogDataUpdateMsg),
//N(OP_UpdateAvgFrameTimeMsg),
N(OP_CloseGroupInviteWindowMsg),
N(OP_UpdateGroupMemberDataMsg),
N(OP_WorldPingMsg),
N(OP_MoveLogUpdateMsg),
N(OP_OfferQuestMsg),
//N(OP_MailGetHeadersMsg),
N(OP_MailGetMessageMsg),
N(OP_MailSendMessageMsg),
N(OP_MailDeleteMessageMsg),
N(OP_MailGetHeadersReplyMsg),
N(OP_MailGetMessageReplyMsg),
N(OP_MailSendMessageReplyMsg),
N(OP_MailCommitSendMessageMsg),
N(OP_MailSendSystemMessageMsg),
N(OP_MailRemoveAttachFromMailMsg),
N(OP_WorldShutdownUpdateMsg),
N(OP_ClientIdleBeginMsg),
N(OP_ClientIdleEndMsg),
N(OP_DisplayMailScreenMsg),
N(OP_NotifyApprenticeStoppedMentori),
N(OP_CorruptedClientMsg),
N(OP_MailEventNotificationMsg),
N(OP_RestartZoneMsg),
N(OP_CharTransferStartRequestMsg),
N(OP_CharTransferStartReplyMsg),
N(OP_CharTransferRequestMsg),
N(OP_CharTransferReplyMsg),
N(OP_CharTransferRollbackRequestMsg),
N(OP_CharTransferCommitRequestMsg),
N(OP_CharTransferRollbackReplyMsg),
N(OP_CharTransferCommitReplyMsg),
N(OP_GetCharacterSerializedRequestM),
N(OP_GetCharacterSerializedReplyMsg),
N(OP_CreateCharFromCBBRequestMsg),
N(OP_CreateCharFromCBBReplyMsg),
N(OP_HousingDataChangedMsg),
N(OP_HousingRestoreMsg),
N(OP_AuctionItem),
N(OP_AuctionItemReply),
N(OP_AuctionCoin),
N(OP_AuctionCoinReply),
N(OP_AuctionCharacter),
N(OP_AuctionCharacterReply),
N(OP_AuctionCommitMsg),
N(OP_AuctionAbortMsg),
N(OP_CharTransferValidateRequestMsg),
N(OP_CharTransferValidateReplyMsg),
N(OP_CharacterLinkdeadMsg),
N(OP_RaceRestrictionMsg),
N(OP_SetInstanceDisplayNameMsg),
N(OP_EqHearChatCmd),
N(OP_EqDisplayTextCmd),
N(OP_EqCreateGhostCmd),
N(OP_EqCreateWidgetCmd),
N(OP_EqCreateSignWidgetCmd),
N(OP_EqDestroyGhostCmd),
N(OP_EqUpdateGhostCmd),
N(OP_EqSetControlGhostCmd),
N(OP_EqSetPOVGhostCmd),
N(OP_EqHearCombatCmd),
N(OP_EqHearSpellCastCmd),
N(OP_EqHearSpellInterruptCmd),
N(OP_EqHearSpellFizzleCmd),
N(OP_EqHearConsiderCmd),
N(OP_EqUpdateSubClassesCmd),
N(OP_EqCreateListBoxCmd),
N(OP_EqSetDebugPathPointsCmd),
N(OP_EqCannedEmoteCmd),
N(OP_EqStateCmd),
N(OP_EqPlaySoundCmd),
N(OP_EqPlaySound3DCmd),
N(OP_EqPlayVoiceCmd),
N(OP_EqHearDrowningCmd),
N(OP_EqHearDeathCmd),
N(OP_EqGroupMemberRemovedCmd),
N(OP_EqHearChainEffectCmd),
N(OP_EqReceiveOfferCmd),
N(OP_EqInspectPCResultsCmd),
N(OP_EqDrawablePathGraphCmd),
N(OP_EqDialogOpenCmd),
N(OP_EqDialogCloseCmd),
N(OP_EqCollectionUpdateCmd),
N(OP_EqCollectionFilterCmd),
N(OP_EqCollectionItemCmd),
N(OP_EqQuestJournalUpdateCmd),
N(OP_EqQuestJournalReplyCmd),
N(OP_EqQuestGroupCmd),
N(OP_EqUpdateMerchantCmd),
N(OP_EqUpdateStoreCmd),
N(OP_EqUpdatePlayerTradeCmd),
N(OP_EqHelpPathCmd),
N(OP_EqHelpPathClearCmd),
N(OP_EqUpdateBankCmd),
N(OP_EqExamineInfoCmd),
N(OP_EqCloseWindowCmd),
N(OP_EqUpdateLootCmd),
N(OP_EqJunctionListCmd),
N(OP_EqShowDeathWindowCmd),
N(OP_EqDisplaySpellFailCmd),
N(OP_EqSpellCastStartCmd),
N(OP_EqSpellCastEndCmd),
N(OP_EqResurrectedCmd),
N(OP_EqChoiceWinCmd),
N(OP_EqSetDefaultVerbCmd),
N(OP_EqInstructionWindowCmd),
N(OP_EqInstructionWindowCloseCmd),
N(OP_EqInstructionWindowGoalCmd),
N(OP_EqInstructionWindowTaskCmd),
N(OP_EqEnableGameEventCmd),
N(OP_EqShowWindowCmd),
N(OP_EqEnableWindowCmd),
N(OP_EqFlashWindowCmd),
N(OP_EqHearPlayFlavorCmd),
N(OP_EqUpdateSignWidgetCmd),
N(OP_EqDebugPVDCmd),
N(OP_EqShowBookCmd),
N(OP_EqQuestionnaireCmd),
N(OP_EqGetProbsCmd),
N(OP_EqHearHealCmd),
N(OP_EqChatChannelUpdateCmd),
N(OP_EqWhoChannelQueryReplyCmd),
N(OP_EqAvailWorldChannelsCmd),
N(OP_ArenaGameTypesMsg),
N(OP_EqUpdateTargetCmd),
N(OP_EqConsignmentItemsCmd),
N(OP_EqStartBrokerCmd),
N(OP_EqMapExplorationCmd),
N(OP_EqStoreLogCmd),
N(OP_EqSpellMoveToRangeAndRetryCmd),
N(OP_EqUpdatePlayerMailCmd),
N(OP_EqFactionUpdateCmd),
N(OP_UpdateTitleCmd),
N(OP_UpdatePositionMsg),
N(OP_AttackNotAllowed),
N(OP_AttackAllowed),
N(OP_CancelSpellCast),
N(OP_BadLanguageFilter),
N(OP_DressingRoom),
N(OP_TraitsList),
N(OP_PointOfInterest),
N(OP_AdventureList),
N(OP_CharacterAchievements),
N(OP_RecipeList),
N(OP_BagOptions),
N(OP_AchievementUpdateMsg),
N(OP_PetOptions),
N(OP_BrokerAddBag),
N(OP_CharacterPet),
N(OP_ClearForTakeOffMsg),
N(OP_CharacterCurrency),
N(OP_TradeskillList),
N(OP_RecipeBook),
N(OP_CharacterMerc),
N(OP_AfterInvSpellUpdate),
N(OP_CharacterCreatedDungeons),
N(OP_CharacterHousingList),
N(OP_HouseItemsList),
N(OP_CharacterMounts),
N(OP_LoadCalendarEvents),
N(OP_LoadWelcomeWindow),
N(OP_DungeonMakerItemRequest),
N(OP_SysClient),
N(OP_LFGGroupSearch),
N(OP_MarketPlacePrices),
N(OP_MarketFundsUpdate),
N(OP_MarketAddFundsRequest),
N(OP_ZoneBgInstanceList),
N(OP_UIEvent),
N(OP_Launchpad),
N(OP_EQHearThreatCmd),
N(OP_EqHearSpellNoLandCmd),
N(OP_Weakness),
N(OP_SavageBarInitMsg),
N(OP_PetOptionsResponse),
N(OP_CurrentPet),
N(OP_JournalQuestStoryline),
N(OP_DailyObjectives),
N(OP_RecipeListUnknown),
N(OP_EQHearDispellCmd),
N(OP_ClearForLandingMsg),
N(OP_LikeOption),
N(OP_HeritageMsg),
N(OP_OpenCharCust),
N(OP_PaperdollImage),
N(OP_ReadyForTakeOffMsg),
N(OP_EarlyLandingRequestMsg),
N(OP_SubmitCharCust),
N(OP_DietyAbilityWindow),
N(OP_EqTargetItemCmd),

445
old/linked_list.h Normal file
View File

@ -0,0 +1,445 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "types.h"
enum direction{FORWARD,BACKWARD};
template<class TYPE> class LinkedListIterator;
template<class TYPE>
class ListElement
{
private:
TYPE data;
ListElement<TYPE>* next;
ListElement<TYPE>* prev;
public:
ListElement ();
ListElement (const TYPE&);
ListElement (const ListElement<TYPE>&);
~ListElement ();
ListElement<TYPE>& operator= (const ListElement<TYPE>&);
ListElement<TYPE>* GetLast ()
{
ListElement<TYPE>* tmp = this;
while (tmp->GetNext()) {
tmp = tmp->GetNext();
}
return tmp;
}
ListElement<TYPE>* GetNext () const { return next ; }
ListElement<TYPE>* GetPrev () const { return prev ; }
inline TYPE& GetData () { return data ; }
inline const TYPE& GetData () const { return data ; }
void SetData ( const TYPE& d ) { data = d ; } // Quagmire - this may look like a mem leak, but dont change it, this behavior is expected where it's called
void SetLastNext ( ListElement<TYPE>* p )
{
GetLast()->SetNext(p);
}
void SetNext (ListElement<TYPE>* n) { next = n ; }
void SetPrev (ListElement<TYPE>* p) { prev = p ; }
void ReplaceData(const TYPE&);
};
template<class TYPE>
class LinkedList
{
private:
int32 count;
ListElement<TYPE>* first;
bool list_destructor_invoked;
public:
LinkedList();
~LinkedList();
bool dont_delete;
LinkedList<TYPE>& operator= (const LinkedList<TYPE>&);
void Append (const TYPE&);
void Insert (const TYPE&);
TYPE Pop();
TYPE PeekTop();
void Clear();
void LCount() { count--; }
void ResetCount() { count=0; }
int32 Count() { return count; }
friend class LinkedListIterator<TYPE>;
};
template<class TYPE>
class LinkedListIterator
{
private:
LinkedList<TYPE>& list;
ListElement<TYPE>* current_element;
direction dir;
public:
LinkedListIterator(LinkedList<TYPE>& l,direction d = FORWARD) : list(l), dir(d) {};
void Advance();
const TYPE& GetData();
bool IsFirst()
{
if (current_element->GetPrev() == 0)
return true;
else
return false;
}
bool IsLast()
{
if (current_element->GetNext() == 0)
return true;
else
return false;
}
bool MoreElements();
void MoveFirst();
void MoveLast();
void RemoveCurrent(bool DeleteData = true);
void Replace(const TYPE& new_data);
void Reset();
void SetDir(direction);
};
template<class TYPE>
void LinkedListIterator<TYPE>::Advance()
{
if (current_element == 0)
{
return;
}
if (dir == FORWARD)
{
current_element = current_element->GetNext();
}
else
{
current_element = current_element->GetPrev();
}
if (list.list_destructor_invoked)
{
while(current_element && current_element->GetData() == 0)
{
// if (current_element == 0)
// {
// return;
// }
if (dir == FORWARD)
{
current_element = current_element->GetNext();
}
else
{
current_element = current_element->GetPrev();
}
}
}
}
template<class TYPE>
bool LinkedListIterator<TYPE>::MoreElements()
{
if (current_element == 0)
return false;
return true;
}
template<class TYPE>
const TYPE& LinkedListIterator<TYPE>::GetData()
{
return current_element->GetData();
}
template<class TYPE>
void LinkedListIterator<TYPE>::MoveFirst()
{
ListElement<TYPE>* prev = current_element->GetPrev();
ListElement<TYPE>* next = current_element->GetNext();
if (prev == 0)
{
return;
}
// if (prev != 0)
// {
prev->SetNext(next);
// }
if (next != 0)
{
next->SetPrev(prev);
}
current_element->SetPrev(0);
current_element->SetNext(list.first);
list.first->SetPrev(current_element);
list.first = current_element;
}
template<class TYPE>
void LinkedListIterator<TYPE>::MoveLast()
{
ListElement<TYPE>* prev = current_element->GetPrev();
ListElement<TYPE>* next = current_element->GetNext();
if (next == 0)
{
return;
}
if (prev != 0)
{
prev->SetNext(next);
}
else
{
list.first = next;
}
// if (next != 0)
// {
next->SetPrev(prev);
// }
current_element->SetNext(0);
current_element->SetPrev(next->GetLast());
next->GetLast()->SetNext(current_element);
}
template<class TYPE>
void LinkedListIterator<TYPE>::RemoveCurrent(bool DeleteData)
{
ListElement<TYPE>* save;
if (list.first == current_element)
{
list.first = current_element->GetNext();
}
if (current_element->GetPrev() != 0)
{
current_element->GetPrev()->SetNext(current_element->GetNext());
}
if (current_element->GetNext() != 0)
{
current_element->GetNext()->SetPrev(current_element->GetPrev());
}
if (dir == FORWARD)
{
save = current_element->GetNext();
}
else
{
save = current_element->GetPrev();
}
current_element->SetNext(0);
current_element->SetPrev(0);
if (!DeleteData)
current_element->SetData(0);
safe_delete(current_element);
current_element = save;
list.LCount();
}
template<class TYPE>
void LinkedListIterator<TYPE>::Replace(const TYPE& new_data)
{
current_element->ReplaceData(new_data);
}
template<class TYPE>
void LinkedListIterator<TYPE>::Reset()
{
if (!(&list))
{
current_element=0;
return;
}
if (dir == FORWARD)
{
current_element = list.first;
}
else
{
if (list.first == 0)
{
current_element = 0;
}
else
{
current_element = list.first->GetLast();
}
}
if (list.list_destructor_invoked)
{
while(current_element && current_element->GetData() == 0)
{
// if (current_element == 0)
// {
// return;
// }
if (dir == FORWARD)
{
current_element = current_element->GetNext();
}
else
{
current_element = current_element->GetPrev();
}
}
}
}
template<class TYPE>
void LinkedListIterator<TYPE>::SetDir(direction d)
{
dir = d;
}
template<class TYPE>
ListElement<TYPE>::ListElement(const TYPE& d)
{
data = d;
next = 0;
prev = 0;
}
template<class TYPE>
ListElement<TYPE>::~ListElement()
{
// cout << "ListElement<TYPE>::~ListElement()" << endl;
if (data != 0)
safe_delete(data);
data = 0;
if (next != 0)
{
safe_delete(next);
next = 0;
}
}
template<class TYPE>
void ListElement<TYPE>::ReplaceData(const TYPE& new_data)
{
if (data != 0)
safe_delete(data);
data = new_data;
}
template<class TYPE>
LinkedList<TYPE>::LinkedList()
{
list_destructor_invoked = false;
first = 0;
count = 0;
dont_delete = false;
}
template<class TYPE>
LinkedList<TYPE>::~LinkedList()
{
list_destructor_invoked = true;
if(!dont_delete)
Clear();
}
template<class TYPE>
void LinkedList<TYPE>::Clear() {
while (first) {
ListElement<TYPE>* tmp = first;
first = tmp->GetNext();
tmp->SetNext(0);
safe_delete(tmp);
}
ResetCount();
}
template<class TYPE>
void LinkedList<TYPE>::Append(const TYPE& data)
{
ListElement<TYPE>* new_element = new ListElement<TYPE>(data);
if (first == 0)
{
first = new_element;
}
else
{
new_element->SetPrev(first->GetLast());
first->SetLastNext(new_element);
}
count++;
}
template<class TYPE>
void LinkedList<TYPE>::Insert(const TYPE& data)
{
ListElement<TYPE>* new_element = new ListElement<TYPE>(data);
new_element->SetNext(first);
if (first != 0)
{
first->SetPrev(new_element);
}
first = new_element;
count++;
}
template<class TYPE>
TYPE LinkedList<TYPE>::Pop() {
TYPE ret = 0;
if (first) {
ListElement<TYPE>* tmpdel = first;
first = tmpdel->GetNext();
if (first)
first->SetPrev(0);
ret = tmpdel->GetData();
tmpdel->SetData(0);
tmpdel->SetNext(0);
safe_delete(tmpdel);
count--;
}
return ret;
}
template<class TYPE>
TYPE LinkedList<TYPE>::PeekTop() {
if (first)
return first->GetData();
return 0;
}
#endif

61
old/login_oplist.h Normal file
View File

@ -0,0 +1,61 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(LOGIN) || defined(MINILOGIN)
N(OP_LoginRequestMsg),
N(OP_LoginByNumRequestMsg),
N(OP_WSLoginRequestMsg),
N(OP_ESLoginRequestMsg),
N(OP_LoginReplyMsg),
N(OP_WorldListMsg),
N(OP_WorldStatusChangeMsg),
N(OP_AllWSDescRequestMsg),
N(OP_WSStatusReplyMsg),
N(OP_AllCharactersDescRequestMsg),
N(OP_AllCharactersDescReplyMsg),
N(OP_CreateCharacterRequestMsg),
N(OP_ReskinCharacterRequestMsg),
N(OP_CreateCharacterReplyMsg),
N(OP_WSCreateCharacterRequestMsg),
N(OP_WSCreateCharacterReplyMsg),
N(OP_DeleteCharacterRequestMsg),
N(OP_DeleteCharacterReplyMsg),
N(OP_PlayCharacterRequestMsg),
N(OP_PlayCharacterReplyMsg),
N(OP_ServerPlayCharacterRequestMsg),
N(OP_ServerPlayCharacterReplyMsg),
N(OP_KeymapLoadMsg),
N(OP_KeymapNoneMsg),
N(OP_KeymapDataMsg),
N(OP_KeymapSaveMsg),
//N(OP_LSRequestPlayerDescMsg),
N(OP_LSCheckAcctLockMsg),
N(OP_WSAcctLockStatusMsg),
N(OP_LsRequestClientCrashLogMsg),
N(OP_LsClientBaselogReplyMsg),
N(OP_LsClientCrashlogReplyMsg),
N(OP_LsClientAlertlogReplyMsg),
N(OP_LsClientVerifylogReplyMsg),
N(OP_BadLanguageFilter),
N(OP_WSServerLockMsg),
N(OP_WSServerHideMsg),
N(OP_LSServerLockMsg),
N(OP_UpdateCharacterSheetMsg),
N(OP_UpdateInventoryMsg),
#endif

281
old/md5.cpp Normal file
View File

@ -0,0 +1,281 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h> /* for memcpy() */
#include "../common/md5.h"
#include "../common/MiscFunctions.h"
#include "../common/seperator.h"
MD5::MD5() {
memset(pMD5, 0, 16);
}
MD5::MD5(const uchar* buf, uint32 len) {
Generate(buf, len, pMD5);
}
MD5::MD5(const char* buf, uint32 len) {
Generate((const uchar*) buf, len, pMD5);
}
MD5::MD5(const int8 buf[16]) {
Set(buf);
}
MD5::MD5(const char* iMD5String) {
Set(iMD5String);
}
void MD5::Generate(const char* iString) {
Generate((const uchar*) iString, strlen(iString));
}
void MD5::Generate(const int8* buf, uint32 len) {
Generate(buf, len, pMD5);
}
bool MD5::Set(const int8 buf[16]) {
memcpy(pMD5, buf, 16);
return true;
}
bool MD5::Set(const char* iMD5String) {
char tmp[5] = { '0', 'x', 0, 0, 0 };
for (int i=0; i<16; i++) {
tmp[2] = iMD5String[i*2];
tmp[3] = iMD5String[(i*2) + 1];
if (!Seperator::IsHexNumber(tmp))
return false;
pMD5[i] = hextoi(tmp);
}
return true;
}
MD5::operator const char* () {
snprintf(pMD5String, sizeof(pMD5String), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", pMD5[0], pMD5[1], pMD5[2], pMD5[3], pMD5[4], pMD5[5], pMD5[6], pMD5[7], pMD5[8], pMD5[9], pMD5[10], pMD5[11], pMD5[12], pMD5[13], pMD5[14], pMD5[15]);
return pMD5String;
}
bool MD5::operator== (const MD5& iMD5) {
if (memcmp(pMD5, iMD5.pMD5, 16) == 0)
return true;
else
return false;
}
bool MD5::operator== (const int8* iMD5) {
if (memcmp(pMD5, iMD5, 16) == 0)
return true;
else
return false;
}
bool MD5::operator== (const char* iMD5String) {
char tmp[5] = { '0', 'x', 0, 0, 0 };
for (int i=0; i<16; i++) {
tmp[2] = iMD5String[i*2];
tmp[3] = iMD5String[(i*2) + 1];
if (pMD5[i] != hextoi(tmp))
return false;
}
return true;
}
MD5& MD5::operator= (const MD5& iMD5) {
memcpy(pMD5, iMD5.pMD5, 16);
return *this;
}
MD5* MD5::operator= (const MD5* iMD5) {
memcpy(pMD5, iMD5->pMD5, 16);
return this;
}
/* Byte-swap an array of words to little-endian. (Byte-sex independent) */
void MD5::byteSwap(uint32 *buf, uint32 words) {
int8 *p = (int8 *)buf;
do {
*buf++ = (uint32)((uint32)p[3]<<8 | p[2]) << 16 |
((uint32)p[1]<<8 | p[0]);
p += 4;
} while (--words);
}
void MD5::Generate(const int8* buf, uint32 len, int8 digest[16]) {
MD5Context ctx;
Init(&ctx);
Update(&ctx, buf, len);
Final(digest, &ctx);
}
/* Start MD5 accumulation. */
void MD5::Init(struct MD5Context *ctx) {
ctx->hash[0] = 0x67452301;
ctx->hash[1] = 0xefcdab89;
ctx->hash[2] = 0x98badcfe;
ctx->hash[3] = 0x10325476;
ctx->bytes[1] = ctx->bytes[0] = 0;
}
/* Update ctx to reflect the addition of another buffer full of bytes. */
void MD5::Update(struct MD5Context *ctx, int8 const *buf, uint32 len) {
uint32 t = ctx->bytes[0];
if ((ctx->bytes[0] = t + len) < t) /* Update 64-bit byte count */
ctx->bytes[1]++; /* Carry from low to high */
t = 64 - (t & 0x3f); /* Bytes available in ctx->input (>= 1) */
if (t > len) {
memcpy((int8*)ctx->input+64-t, buf, len);
return;
}
/* First chunk is an odd size */
memcpy((int8*)ctx->input+64-t, buf, t);
byteSwap(ctx->input, 16);
Transform(ctx->hash, ctx->input);
buf += t;
len -= t;
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->input, buf, 64);
byteSwap(ctx->input, 16);
Transform(ctx->hash, ctx->input);
buf += 64;
len -= 64;
}
/* Buffer any remaining bytes of data */
memcpy(ctx->input, buf, len);
}
/* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, LSB-first) */
void MD5::Final(int8 digest[16], MD5Context *ctx) {
int count = ctx->bytes[0] & 0x3F; /* Bytes mod 64 */
int8 *p = (int8*)ctx->input + count;
/* Set the first byte of padding to 0x80. There is always room. */
*p++ = 0x80;
/* Bytes of zero padding needed to make 56 bytes (-8..55) */
count = 56 - 1 - count;
if (count < 0) { /* Padding forces an extra block */
memset(p, 0, count+8);
byteSwap(ctx->input, 16);
Transform(ctx->hash, ctx->input);
p = (int8*)ctx->input;
count = 56;
}
memset(p, 0, count);
byteSwap(ctx->input, 14);
/* Append 8 bytes of length in *bits* and transform */
ctx->input[14] = ctx->bytes[0] << 3;
ctx->input[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
Transform(ctx->hash, ctx->input);
byteSwap(ctx->hash, 4);
memcpy(digest, ctx->hash, 16);
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
/* The four core functions */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f,w,x,y,z,in,s) (w += f(x,y,z)+in, w = (w<<s | w>>(32-s)) + x)
/* The heart of the MD5 algorithm. */
void MD5::Transform(uint32 hash[4], const uint32 input[16]) {
uint32 a = hash[0], b = hash[1], c = hash[2], d = hash[3];
MD5STEP(F1, a, b, c, d, input[ 0]+0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, input[ 1]+0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, input[ 2]+0x242070db, 17);
MD5STEP(F1, b, c, d, a, input[ 3]+0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, input[ 4]+0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, input[ 5]+0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, input[ 6]+0xa8304613, 17);
MD5STEP(F1, b, c, d, a, input[ 7]+0xfd469501, 22);
MD5STEP(F1, a, b, c, d, input[ 8]+0x698098d8, 7);
MD5STEP(F1, d, a, b, c, input[ 9]+0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, input[10]+0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, input[11]+0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, input[12]+0x6b901122, 7);
MD5STEP(F1, d, a, b, c, input[13]+0xfd987193, 12);
MD5STEP(F1, c, d, a, b, input[14]+0xa679438e, 17);
MD5STEP(F1, b, c, d, a, input[15]+0x49b40821, 22);
MD5STEP(F2, a, b, c, d, input[ 1]+0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, input[ 6]+0xc040b340, 9);
MD5STEP(F2, c, d, a, b, input[11]+0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, input[ 0]+0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, input[ 5]+0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, input[10]+0x02441453, 9);
MD5STEP(F2, c, d, a, b, input[15]+0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, input[ 4]+0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, input[ 9]+0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, input[14]+0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, input[ 3]+0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, input[ 8]+0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, input[13]+0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, input[ 2]+0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, input[ 7]+0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, input[12]+0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, input[ 5]+0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, input[ 8]+0x8771f681, 11);
MD5STEP(F3, c, d, a, b, input[11]+0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, input[14]+0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, input[ 1]+0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, input[ 4]+0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, input[ 7]+0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, input[10]+0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, input[13]+0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, input[ 0]+0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, input[ 3]+0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, input[ 6]+0x04881d05, 23);
MD5STEP(F3, a, b, c, d, input[ 9]+0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, input[12]+0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, input[15]+0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, input[ 2]+0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, input[ 0]+0xf4292244, 6);
MD5STEP(F4, d, a, b, c, input[ 7]+0x432aff97, 10);
MD5STEP(F4, c, d, a, b, input[14]+0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, input[ 5]+0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, input[12]+0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, input[ 3]+0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, input[10]+0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, input[ 1]+0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, input[ 8]+0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, input[15]+0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, input[ 6]+0xa3014314, 15);
MD5STEP(F4, b, c, d, a, input[13]+0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, input[ 4]+0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, input[11]+0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, input[ 2]+0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, input[ 9]+0xeb86d391, 21);
hash[0] += a; hash[1] += b; hash[2] += c; hash[3] += d;
}

64
old/md5.h Normal file
View File

@ -0,0 +1,64 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MD5_H
#define MD5_H
#include "../common/types.h"
class MD5 {
public:
struct MD5Context {
uint32 hash[4];
uint32 bytes[2];
uint32 input[16];
};
static void Generate(const int8* buf, uint32 len, int8 digest[16]);
static void Init(struct MD5Context *context);
static void Update(struct MD5Context *context, const int8 *buf, uint32 len);
static void Final(int8 digest[16], struct MD5Context *context);
MD5();
MD5(const uchar* buf, uint32 len);
MD5(const char* buf, uint32 len);
MD5(const int8 buf[16]);
MD5(const char* iMD5String);
void Generate(const char* iString);
void Generate(const int8* buf, uint32 len);
bool Set(const int8 buf[16]);
bool Set(const char* iMD5String);
bool operator== (const MD5& iMD5);
bool operator== (const int8 iMD5[16]);
bool operator== (const char* iMD5String);
MD5& operator= (const MD5& iMD5);
MD5* operator= (const MD5* iMD5);
MD5* operator= (const int8* iMD5);
operator const char* ();
protected:
int8 pMD5[16];
private:
static void byteSwap(uint32 *buf, uint32 words);
static void Transform(uint32 hash[4], const int32 input[16]);
char pMD5String[33];
};
#endif

305
old/misc.cpp Normal file
View File

@ -0,0 +1,305 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef WIN32
// VS6 doesn't like the length of STL generated names: disabling
#pragma warning(disable:4786)
#endif
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <map>
#include <iostream>
#include <zlib.h>
#include <time.h>
#include "misc.h"
#include "types.h"
using namespace std;
#define ENC(c) (((c) & 0x3f) + ' ')
#define DEC(c) (((c) - ' ') & 0x3f)
map<int,string> DBFieldNames;
#ifndef WIN32
#ifdef FREEBSD
int print_stacktrace()
{
printf("Insert stack trace here...\n");
return(0);
}
#else //!WIN32 && !FREEBSD == linux
#include <execinfo.h>
int print_stacktrace()
{
void *ba[20];
int n = backtrace (ba, 20);
if (n != 0)
{
char **names = backtrace_symbols (ba, n);
if (names != NULL)
{
int i;
cerr << "called from " << (char*)names[0] << endl;
for (i = 1; i < n; ++i)
cerr << " " << (char*)names[i] << endl;
free (names);
}
}
return(0);
}
#endif //!FREEBSD
#endif //!WIN32
int Deflate(unsigned char* in_data, int in_length, unsigned char* out_data, int max_out_length)
{
z_stream zstream;
int zerror;
zstream.next_in = in_data;
zstream.avail_in = in_length;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
deflateInit(&zstream, Z_FINISH);
zstream.next_out = out_data;
zstream.avail_out = max_out_length;
zerror = deflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END)
{
deflateEnd(&zstream);
return zstream.total_out;
}
else
{
cout << "Error: Deflate: deflate() returned " << zerror << " '";
if (zstream.msg)
cout << zstream.msg;
cout << "'" << endl;
zerror = deflateEnd(&zstream);
return 0;
}
}
int Inflate(unsigned char* indata, int indatalen, unsigned char* outdata, int outdatalen, bool iQuiet)
{
z_stream zstream;
int zerror = 0;
int i;
zstream.next_in = indata;
zstream.avail_in = indatalen;
zstream.next_out = outdata;
zstream.avail_out = outdatalen;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
i = inflateInit2( &zstream, 15 );
if (i != Z_OK) {
return 0;
}
zerror = inflate( &zstream, Z_FINISH );
if(zerror == Z_STREAM_END) {
inflateEnd( &zstream );
return zstream.total_out;
}
else {
if (!iQuiet) {
cout << "Error: Inflate: inflate() returned " << zerror << " '";
if (zstream.msg)
cout << zstream.msg;
cout << "'" << endl;
}
if (zerror == Z_DATA_ERROR || zerror == Z_ERRNO)
return -1;
if (zerror == Z_MEM_ERROR && zstream.msg == 0)
{
return 0;
}
zerror = inflateEnd( &zstream );
return 0;
}
}
void dump_message_column(unsigned char *buffer, unsigned long length, string leader, FILE *to)
{
unsigned long i,j;
unsigned long rows,offset=0;
rows=(length/16)+1;
for(i=0;i<rows;i++) {
fprintf(to, "%s%05ld: ",leader.c_str(),i*16);
for(j=0;j<16;j++) {
if(j == 8)
fprintf(to, "- ");
if (offset+j<length)
fprintf(to, "%02x ",*(buffer+offset+j));
else
fprintf(to, " ");
}
fprintf(to, "| ");
for(j=0;j<16;j++,offset++) {
if (offset<length) {
char c=*(buffer+offset);
fprintf(to, "%c",isprint(c) ? c : '.');
}
}
fprintf(to, "\n");
}
}
string long2ip(unsigned long ip)
{
char temp[16];
union { unsigned long ip; struct { unsigned char a,b,c,d; } octet;} ipoctet;
ipoctet.ip=ip;
sprintf(temp,"%d.%d.%d.%d",ipoctet.octet.a,ipoctet.octet.b,ipoctet.octet.c,ipoctet.octet.d);
return string(temp);
}
string string_from_time(string pattern, time_t now)
{
struct tm *now_tm;
char time_string[51];
if (!now)
time(&now);
now_tm=localtime(&now);
strftime(time_string,51,pattern.c_str(),now_tm);
return string(time_string);
}
string timestamp(time_t now)
{
return string_from_time("[%Y%m%d.%H%M%S] ",now);
}
string pop_arg(string &s, string seps, bool obey_quotes)
{
string ret;
unsigned long i;
bool in_quote=false;
unsigned long length=s.length();
for(i=0;i<length;i++) {
char c=s[i];
if (c=='"' && obey_quotes) {
in_quote=!in_quote;
}
if (in_quote)
continue;
if (seps.find(c)!=0xFFFFFFFF) {
break;
}
}
if (i==length) {
ret=s;
s="";
} else {
ret=s.substr(0,i);
s.erase(0,i+1);
}
return ret;
}
int EQsprintf(char *buffer, const char *pattern, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5, const char *arg6, const char *arg7, const char *arg8, const char *arg9)
{
const char *args[9],*ptr;
char *bptr;
args[0]=arg1;
args[1]=arg2;
args[2]=arg3;
args[3]=arg4;
args[4]=arg5;
args[5]=arg6;
args[6]=arg7;
args[7]=arg8;
args[8]=arg9;
for(ptr=pattern,bptr=buffer;*ptr;) {
switch (*ptr) {
case '%':
ptr++;
switch (*ptr) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
strcpy(bptr,args[*ptr-'0'-1]);
bptr+=strlen(args[*ptr-'0'-1]);
break;
}
break;
default:
*bptr=*ptr;
bptr++;
}
ptr++;
}
*bptr=0;
return (bptr-buffer);
}
bool alpha_check(unsigned char val){
if((val >= 0x41 && val <=0x5A) || (val >= 0x61 && val <=0x7A))
return true;
else
return false;
}
unsigned int GetSpellNameCrc(const char* src) {
if (!src)
return 0;
uLong crc = crc32(0L, Z_NULL, 0);
return crc32(crc, (unsigned const char*)src, strlen(src));
}
int GetItemNameCrc(string item_name){
const char *src = item_name.c_str();
uLong crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, (unsigned const char *)src,strlen(src)) + 1;
return sint32(crc) * -1;
}
unsigned int GetNameCrc(string name) {
const char* src = name.c_str();
uLong crc = crc32(0L, Z_NULL, 0);
crc = crc32(crc, (unsigned const char*)src, strlen(src)) + 1;
return int32(crc)-1;
}

65
old/misc.h Normal file
View File

@ -0,0 +1,65 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MISC_H
#define _MISC_H
#include <stdio.h>
#include <string>
#include <map>
using namespace std;
#define ITEMFIELDCOUNT 116
void Unprotect(string &s, char what);
void Protect(string &s, char what);
bool ItemParse(const char *data, int length, map<int,map<int,string> > &items, int id_pos, int name_pos, int max_field, int level=0);
int Tokenize(string s, map<int,string> & tokens, char delim='|');
void LoadItemDBFieldNames();
void encode_length(unsigned long length, char *out);
unsigned long decode_length(char *in);
unsigned long encode(char *in, unsigned long length, char *out);
void decode(char *in, char *out);
void encode_chunk(char *in, int len, char *out);
void decode_chunk(char *in, char *out);
int Deflate(unsigned char* in_data, int in_length, unsigned char* out_data, int max_out_length);
int Inflate(unsigned char* indata, int indatalen, unsigned char* outdata, int outdatalen, bool iQuiet=true);
#ifndef WIN32
int print_stacktrace();
#endif
bool alpha_check(unsigned char val);
void dump_message_column(unsigned char *buffer, unsigned long length, string leader="", FILE *to = stdout);
string string_from_time(string pattern, time_t now=0);
string timestamp(time_t now=0);
string long2ip(unsigned long ip);
string pop_arg(string &s, string seps, bool obey_quotes);
int EQsprintf(char *buffer, const char *pattern, const char *arg1, const char *arg2, const char *arg3, const char *arg4, const char *arg5, const char *arg6, const char *arg7, const char *arg8, const char *arg9);
unsigned int GetSpellNameCrc(const char* src);
int GetItemNameCrc(string item_name);
unsigned int GetNameCrc(string name);
#endif

44
old/op_codes.h Normal file
View File

@ -0,0 +1,44 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _OP_CODES_H
#define _OP_CODES_H
static const char OP_SessionRequest = 0x01;
static const char OP_SessionResponse = 0x02;
static const char OP_Combined = 0x03;
static const char OP_SessionDisconnect = 0x05;
static const char OP_KeepAlive = 0x06;
static const char OP_ServerKeyRequest = 0x07;
static const char OP_SessionStatResponse= 0x08;
static const char OP_Packet = 0x09;
static const char OP_Fragment = 0x0d;
static const char OP_OutOfOrderAck = 0x11;
static const char OP_Ack = 0x15;
static const char OP_AppCombined = 0x19;
static const char OP_OutOfSession = 0x1d;
#if defined(LOGIN) || defined(CHAT)
#define APP_OPCODE_SIZE 1
#else
#define APP_OPCODE_SIZE 2
#endif
#endif

350
old/opcodemgr.cpp Normal file
View File

@ -0,0 +1,350 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "debug.h"
#include <stdio.h>
#include <string.h>
#include "opcodemgr.h"
//#include "debug.h"
#include "emu_opcodes.h"
#include "../common/Log.h"
#if defined(SHARED_OPCODES) && !defined(EQ2)
#include "EMuShareMem.h"
extern LoadEMuShareMemDLL EMuShareMemDLL;
#endif
#include <map>
#include <string>
using namespace std;
//#define DEBUG_TRANSLATE
OpcodeManager::OpcodeManager() {
loaded = false;
}
bool OpcodeManager::LoadOpcodesMap(map<string, uint16>* eq, OpcodeSetStrategy *s, std::string* missingOpcodes){
//do the mapping and store them in the shared memory array
bool ret = true;
EmuOpcode emu_op;
map<string, uint16>::iterator res;
//stupid enum wont let me ++ on it...
for(emu_op = (EmuOpcode)(0); emu_op < _maxEmuOpcode; emu_op=(EmuOpcode)(emu_op+1)) {
//get the name of this emu opcode
const char *op_name = OpcodeNames[emu_op];
if(op_name[0] == '\0') {
break;
}
//find the opcode in the file
res = eq->find(op_name);
if(res == eq->end()) {
if(missingOpcodes) {
if(missingOpcodes->size() < 1) {
missingOpcodes->append(op_name);
}
else {
missingOpcodes->append(", " + std::string(op_name));
}
}
else {
LogWrite(OPCODE__WARNING, 1, "Opcode", "Opcode %s is missing from the opcodes table.", op_name);
}
s->Set(emu_op, 0xFFFF);
continue; //continue to give them a list of all missing opcodes
}
//ship the mapping off to shared mem.
s->Set(emu_op, res->second);
}
return ret;
}
bool OpcodeManager::LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s) {
FILE *opf = fopen(filename, "r");
if(opf == NULL) {
LogWrite(OPCODE__ERROR, 0, "Opcode", "Unable to open opcodes file '%s'. Thats bad.", filename);
return(false);
}
map<string, uint16> eq;
//load the opcode file into eq, could swap in a nice XML parser here
char line[2048];
int lineno = 0;
uint16 curop;
while(!feof(opf)) {
lineno++;
line[0] = '\0'; //for blank line at end of file
if(fgets(line, sizeof(line), opf) == NULL)
break;
//ignore any line that dosent start with OP_
if(line[0] != 'O' || line[1] != 'P' || line[2] != '_')
continue;
char *num = line+3; //skip OP_
//look for the = sign
while(*num != '=' && *num != '\0') {
num++;
}
//make sure we found =
if(*num != '=') {
LogWrite(OPCODE__ERROR, 0, "Opcode", "Malformed opcode line at %s:%d\n", filename, lineno);
continue;
}
*num = '\0'; //null terminate the name
num++; //num should point to the opcode
//read the opcode
if(sscanf(num, "0x%hx", &curop) != 1) {
LogWrite(OPCODE__ERROR, 0, "Opcode", "Malformed opcode at %s:%d\n", filename, lineno);
continue;
}
//we have a name and our opcode... stick it in the map
eq[line] = curop;
}
fclose(opf);
return LoadOpcodesMap(&eq, s);
}
//convenience routines
const char *OpcodeManager::EmuToName(const EmuOpcode emu_op) {
if(emu_op > _maxEmuOpcode)
return "OP_Unknown";
return(OpcodeNames[emu_op]);
}
const char *OpcodeManager::EQToName(const uint16 eq_op) {
//first must resolve the eq op to an emu op
EmuOpcode emu_op = EQToEmu(eq_op);
if(emu_op > _maxEmuOpcode)
return "OP_Unknown";
return(OpcodeNames[emu_op]);
}
EmuOpcode OpcodeManager::NameSearch(const char *name) {
EmuOpcode emu_op;
//stupid enum wont let me ++ on it...
for(emu_op = (EmuOpcode)(0); emu_op < _maxEmuOpcode; emu_op=(EmuOpcode)(emu_op+1)) {
//get the name of this emu opcode
const char *op_name = OpcodeNames[emu_op];
if(!strcasecmp(op_name, name)) {
return(emu_op);
}
}
return(OP_Unknown);
}
RegularOpcodeManager::RegularOpcodeManager()
: MutableOpcodeManager()
{
emu_to_eq = NULL;
eq_to_emu = NULL;
EQOpcodeCount = 0;
EmuOpcodeCount = 0;
}
RegularOpcodeManager::~RegularOpcodeManager() {
safe_delete_array(emu_to_eq);
safe_delete_array(eq_to_emu);
}
bool RegularOpcodeManager::LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes) {
NormalMemStrategy s;
s.it = this;
MOpcodes.lock();
loaded = true;
eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE];
emu_to_eq = new uint16[_maxEmuOpcode];
EQOpcodeCount = MAX_EQ_OPCODE;
EmuOpcodeCount = _maxEmuOpcode;
//dont need to set eq_to_emu cause every element should get a value
memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
memset(emu_to_eq, 0xCD, sizeof(uint16)*_maxEmuOpcode);
bool ret = LoadOpcodesMap(eq, &s, missingOpcodes);
MOpcodes.unlock();
return ret;
}
bool RegularOpcodeManager::LoadOpcodes(const char *filename) {
NormalMemStrategy s;
s.it = this;
MOpcodes.lock();
loaded = true;
eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE];
emu_to_eq = new uint16[_maxEmuOpcode];
EQOpcodeCount = MAX_EQ_OPCODE;
EmuOpcodeCount = _maxEmuOpcode;
//dont need to set eq_to_emu cause every element should get a value
memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
memset(emu_to_eq, 0xCD, sizeof(uint16)*_maxEmuOpcode);
bool ret = LoadOpcodesFile(filename, &s);
MOpcodes.unlock();
return ret;
}
bool RegularOpcodeManager::ReloadOpcodes(const char *filename) {
if(!loaded)
return(LoadOpcodes(filename));
NormalMemStrategy s;
s.it = this;
MOpcodes.lock();
memset(eq_to_emu, 0, sizeof(EmuOpcode)*MAX_EQ_OPCODE);
bool ret = LoadOpcodesFile(filename, &s);
MOpcodes.unlock();
return(ret);
}
uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
//opcode is checked for validity in GetEQOpcode
uint16 res;
MOpcodes.lock();
if(emu_op > _maxEmuOpcode)
res = 0;
else
res = emu_to_eq[emu_op];
MOpcodes.unlock();
#ifdef _DEBUG_TRANSLATE
fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res);
#endif
return(res);
}
EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) {
//opcode is checked for validity in GetEmuOpcode
//Disabled since current live EQ uses the entire uint16 bitspace for opcodes
// if(eq_op > MAX_EQ_OPCODE)
// return(OP_Unknown);
EmuOpcode res;
MOpcodes.lock();
if(eq_op >= MAX_EQ_OPCODE)
res = OP_Unknown;
else
res = eq_to_emu[eq_op];
MOpcodes.unlock();
#ifdef _DEBUG_TRANSLATE
fprintf(stderr, "M Translate EQ 0x%.4x to Emu %s (%d)\n", eq_op, OpcodeNames[res], res);
#endif
return(res);
}
void RegularOpcodeManager::SetOpcode(EmuOpcode emu_op, uint16 eq_op) {
//clear out old mapping
uint16 oldop = 0;
if(emu_op <= _maxEmuOpcode)
oldop = emu_to_eq[emu_op];
if(oldop != 0 && oldop < MAX_EQ_OPCODE)
eq_to_emu[oldop] = OP_Unknown;
//use our strategy, since we have it
NormalMemStrategy s;
s.it = this;
s.Set(emu_op, eq_op);
}
void RegularOpcodeManager::NormalMemStrategy::Set(EmuOpcode emu_op, uint16 eq_op) {
if(uint32(emu_op) >= it->EmuOpcodeCount || eq_op >= it->EQOpcodeCount)
return;
it->emu_to_eq[emu_op] = eq_op;
it->eq_to_emu[eq_op] = emu_op;
}
NullOpcodeManager::NullOpcodeManager()
: MutableOpcodeManager() {
}
bool NullOpcodeManager::LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes) {
return(true);
}
bool NullOpcodeManager::LoadOpcodes(const char *filename) {
return(true);
}
bool NullOpcodeManager::ReloadOpcodes(const char *filename) {
return(true);
}
uint16 NullOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
return(0);
}
EmuOpcode NullOpcodeManager::EQToEmu(const uint16 eq_op) {
return(OP_Unknown);
}
EmptyOpcodeManager::EmptyOpcodeManager()
: MutableOpcodeManager() {
}
bool EmptyOpcodeManager::LoadOpcodes(const char *filename) {
return(true);
}
bool EmptyOpcodeManager::LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes) {
return(true);
}
bool EmptyOpcodeManager::ReloadOpcodes(const char *filename) {
return(true);
}
uint16 EmptyOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
map<EmuOpcode, uint16>::iterator f;
f = emu_to_eq.find(emu_op);
return(f == emu_to_eq.end()? 0 : f->second);
}
EmuOpcode EmptyOpcodeManager::EQToEmu(const uint16 eq_op) {
map<uint16, EmuOpcode>::iterator f;
f = eq_to_emu.find(eq_op);
return(f == eq_to_emu.end()?OP_Unknown:f->second);
}
void EmptyOpcodeManager::SetOpcode(EmuOpcode emu_op, uint16 eq_op) {
emu_to_eq[emu_op] = eq_op;
eq_to_emu[eq_op] = emu_op;
}

162
old/opcodemgr.h Normal file
View File

@ -0,0 +1,162 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPCODE_MANAGER_H
#define OPCODE_MANAGER_H
#include "types.h"
#include "Mutex.h"
#include "emu_opcodes.h"
#include <map>
using namespace std;
class OpcodeManager {
public:
OpcodeManager();
virtual ~OpcodeManager() {}
virtual bool Mutable() { return(false); }
virtual bool LoadOpcodes(const char *filename) = 0;
virtual bool LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes = nullptr) = 0;
virtual bool ReloadOpcodes(const char *filename) = 0;
virtual uint16 EmuToEQ(const EmuOpcode emu_op) = 0;
virtual EmuOpcode EQToEmu(const uint16 eq_op) = 0;
static const char *EmuToName(const EmuOpcode emu_op);
const char *EQToName(const uint16 emu_op);
EmuOpcode NameSearch(const char *name);
//This has to be public for stupid visual studio
class OpcodeSetStrategy {
public:
virtual void Set(EmuOpcode emu_op, uint16 eq_op) = 0;
virtual ~OpcodeSetStrategy(){}
};
protected:
bool loaded; //true if all opcodes loaded
Mutex MOpcodes; //this only protects the local machine
//in a shared manager, this dosent protect others
static bool LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s);
static bool LoadOpcodesMap(map<string, uint16>* eq, OpcodeSetStrategy *s, std::string* missingOpcodes = nullptr);
};
class MutableOpcodeManager : public OpcodeManager {
public:
MutableOpcodeManager() : OpcodeManager() {}
virtual bool Mutable() { return(true); }
virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op) = 0;
};
#ifdef SHARED_OPCODES //quick toggle since only world and zone should possibly use this
//keeps opcodes in shared memory
class SharedOpcodeManager : public OpcodeManager {
public:
virtual ~SharedOpcodeManager() {}
virtual bool LoadOpcodes(const char *filename);
virtual bool LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes = nullptr);
virtual bool ReloadOpcodes(const char *filename);
virtual uint16 EmuToEQ(const EmuOpcode emu_op);
virtual EmuOpcode EQToEmu(const uint16 eq_op);
protected:
class SharedMemStrategy : public OpcodeManager::OpcodeSetStrategy {
public:
void Set(EmuOpcode emu_op, uint16 eq_op);
};
static bool DLLLoadOpcodesCallback(const char *filename);
};
#endif //SHARED_OPCODES
//keeps opcodes in regular heap memory
class RegularOpcodeManager : public MutableOpcodeManager {
public:
RegularOpcodeManager();
virtual ~RegularOpcodeManager();
virtual bool Editable() { return(true); }
virtual bool LoadOpcodes(const char *filename);
virtual bool LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes = nullptr);
virtual bool ReloadOpcodes(const char *filename);
virtual uint16 EmuToEQ(const EmuOpcode emu_op);
virtual EmuOpcode EQToEmu(const uint16 eq_op);
//implement our editing interface
virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op);
protected:
class NormalMemStrategy : public OpcodeManager::OpcodeSetStrategy {
public:
RegularOpcodeManager *it;
void Set(EmuOpcode emu_op, uint16 eq_op);
};
friend class NormalMemStrategy;
uint16 *emu_to_eq;
EmuOpcode *eq_to_emu;
uint32 EQOpcodeCount;
uint32 EmuOpcodeCount;
};
//always resolves everything to 0 or OP_Unknown
class NullOpcodeManager : public MutableOpcodeManager {
public:
NullOpcodeManager();
virtual bool LoadOpcodes(const char *filename);
virtual bool LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes = nullptr);
virtual bool ReloadOpcodes(const char *filename);
virtual uint16 EmuToEQ(const EmuOpcode emu_op);
virtual EmuOpcode EQToEmu(const uint16 eq_op);
//fake it, just used for testing anyways
virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op) {}
};
//starts as NullOpcodeManager, but remembers any mappings set
//could prolly have been implemented with an extension to regular,
//by overriding its load methods to be empty.
class EmptyOpcodeManager : public MutableOpcodeManager {
public:
EmptyOpcodeManager();
virtual bool LoadOpcodes(const char *filename);
virtual bool LoadOpcodes(map<string, uint16>* eq, std::string* missingOpcodes = nullptr);
virtual bool ReloadOpcodes(const char *filename);
virtual uint16 EmuToEQ(const EmuOpcode emu_op);
virtual EmuOpcode EQToEmu(const uint16 eq_op);
//fake it, just used for testing anyways
virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op);
protected:
map<EmuOpcode, uint16> emu_to_eq;
map<uint16, EmuOpcode> eq_to_emu;
};
#endif

195
old/packet_dump.cpp Normal file
View File

@ -0,0 +1,195 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../common/debug.h"
#include <iostream>
#include <iomanip>
#include <stdio.h>
using namespace std;
#include "packet_dump.h"
#include "EQStream.h"
#include "../common/servertalk.h"
void DumpPacketAscii(const uchar* buf, int32 size, int32 cols, int32 skip) {
// Output as ASCII
for(int32 i=skip; i<size; i++)
{
if ((i-skip)%cols==0)
{
cout << endl << setw(3) << setfill(' ') << i-skip << ":";
}
else if ((i-skip)%(cols/2)==0)
{
cout << " - ";
}
if (buf[i] > 32 && buf[i] < 127)
{
cout << buf[i];
}
else
{
cout << '.';
}
}
cout << endl << endl;
}
void DumpPacketHex(const uchar* buf, int32 size, int32 cols, int32 skip) {
if (size == 0 || size > 39565)
return;
// Output as HEX
char output[4];
int j = 0; char* ascii = new char[cols+1]; memset(ascii, 0, cols+1);
int32 i;
for(i=skip; i<size; i++)
{
if ((i-skip)%cols==0) {
if (i != skip)
cout << " | " << ascii << endl;
cout << setw(4) << setfill(' ') << i-skip << ": ";
memset(ascii, 0, cols+1);
j = 0;
}
else if ((i-skip)%(cols/2) == 0) {
cout << "- ";
}
sprintf(output, "%02X ", (unsigned char)buf[i]);
cout << output;
if (buf[i] >= 32 && buf[i] < 127) {
ascii[j++] = buf[i];
}
else {
ascii[j++] = '.';
}
// cout << setfill(0) << setw(2) << hex << (int)buf[i] << " ";
}
int32 k = ((i-skip)-1)%cols;
if (k < 8)
cout << " ";
for (int32 h = k+1; h < cols; h++) {
cout << " ";
}
cout << " | " << ascii << endl;
safe_delete_array(ascii);
}
void DumpPacket(const uchar* buf, int32 size)
{
DumpPacketHex(buf, size);
// DumpPacketAscii(buf,size);
}
void DumpPacket(const ServerPacket* pack, bool iShowInfo) {
if (iShowInfo) {
cout << "Dumping ServerPacket: 0x" << hex << setfill('0') << setw(4) << pack->opcode << dec;
cout << " size:" << pack->size << endl;
}
DumpPacketHex(pack->pBuffer, pack->size);
}
void DumpPacketBin(const ServerPacket* pack) {
DumpPacketBin(pack->pBuffer, pack->size);
}
void DumpPacketBin(int32 data) {
DumpPacketBin((uchar*)&data, sizeof(int32));
}
void DumpPacketBin(int16 data) {
DumpPacketBin((uchar*)&data, sizeof(int16));
}
void DumpPacketBin(int8 data) {
DumpPacketBin((uchar*)&data, sizeof(int8));
}
void DumpPacketBin(const void* iData, int32 len) {
if (!len)
return;
const int8* data = (const int8*) iData;
int32 k=0;
for (k=0; k<len; k++) {
if (k % 4 == 0) {
if (k != 0) {
cout << " | " << hex << setw(2) << setfill('0') << (int) data[k-4] << dec;
cout << " " << hex << setw(2) << setfill('0') << (int) data[k-3] << dec;
cout << " " << hex << setw(2) << setfill('0') << (int) data[k-2] << dec;
cout << " " << hex << setw(2) << setfill('0') << (int) data[k-1] << dec;
cout << endl;
}
cout << setw(4) << setfill('0') << k << ":";
}
else if (k % 2 == 0)
cout << " ";
cout << " ";
if (data[k] & 1)
cout << "1";
else
cout << "0";
if (data[k] & 2)
cout << "1";
else
cout << "0";
if (data[k] & 4)
cout << "1";
else
cout << "0";
if (data[k] & 8)
cout << "1";
else
cout << "0";
if (data[k] & 16)
cout << "1";
else
cout << "0";
if (data[k] & 32)
cout << "1";
else
cout << "0";
if (data[k] & 64)
cout << "1";
else
cout << "0";
if (data[k] & 128)
cout << "1";
else
cout << "0";
}
int8 tmp = (k % 4);
if (!tmp)
tmp = 4;
if (tmp <= 3)
cout << " ";
if (tmp <= 2)
cout << " ";
if (tmp <= 1)
cout << " ";
cout << " | " << hex << setw(2) << setfill('0') << (int) data[k-4] << dec;
if (tmp > 1)
cout << " " << hex << setw(2) << setfill('0') << (int) data[k-3] << dec;
if (tmp > 2)
cout << " " << hex << setw(2) << setfill('0') << (int) data[k-2] << dec;
if (tmp > 3)
cout << " " << hex << setw(2) << setfill('0') << (int) data[k-1] << dec;
cout << endl;
}

41
old/packet_dump.h Normal file
View File

@ -0,0 +1,41 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PACKET_DUMP_H
#define PACKET_DUMP_H
#include <iostream>
using namespace std;
#include "../common/types.h"
#include "EQPacket.h"
class ServerPacket;
void DumpPacketAscii(const uchar* buf, int32 size, int32 cols=16, int32 skip=0);
void DumpPacketHex(const uchar* buf, int32 size, int32 cols=16, int32 skip=0);
void DumpPacketBin(const void* data, int32 len);
void DumpPacket(const uchar* buf, int32 size);
void DumpPacket(const ServerPacket* pack, bool iShowInfo = false);
void DumpPacketBin(const ServerPacket* pack);
void DumpPacketBin(int32 data);
void DumpPacketBin(int16 data);
void DumpPacketBin(int8 data);
#endif

537
old/packet_functions.cpp Normal file
View File

@ -0,0 +1,537 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../common/debug.h"
#include <iostream>
#include <iomanip>
#include <string.h>
#include <zlib.h>
#include "packet_dump.h"
#include "EQStream.h"
#include "packet_functions.h"
#ifndef WIN32
#include <netinet/in.h>
#endif
using namespace std;
#define eqemu_alloc_func Z_NULL
#define eqemu_free_func Z_NULL
int DeflatePacket(unsigned char* in_data, int in_length, unsigned char* out_data, int max_out_length) {
#ifdef REUSE_ZLIB
static bool inited = false;
static z_stream zstream;
int zerror;
if(in_data == NULL && out_data == NULL && in_length == 0 && max_out_length == 0) {
//special delete state
deflateEnd(&zstream);
return(0);
}
if(!inited) {
zstream.zalloc = eqemu_alloc_func;
zstream.zfree = eqemu_free_func;
zstream.opaque = Z_NULL;
deflateInit(&zstream, Z_FINISH);
}
zstream.next_in = in_data;
zstream.avail_in = in_length;
/* zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.opaque = Z_NULL;
deflateInit(&zstream, Z_FINISH);*/
zstream.next_out = out_data;
zstream.avail_out = max_out_length;
zerror = deflate(&zstream, Z_FINISH);
deflateReset(&zstream);
if (zerror == Z_STREAM_END)
{
// deflateEnd(&zstream);
return zstream.total_out;
}
else
{
// zerror = deflateEnd(&zstream);
return 0;
}
#else
if(in_data == NULL) {
return(0);
}
z_stream zstream;
int zerror;
zstream.next_in = in_data;
zstream.avail_in = in_length;
zstream.zalloc = eqemu_alloc_func;
zstream.zfree = eqemu_free_func;
zstream.opaque = Z_NULL;
deflateInit(&zstream, Z_FINISH);
zstream.next_out = out_data;
zstream.avail_out = max_out_length;
zerror = deflate(&zstream, Z_FINISH);
if (zerror == Z_STREAM_END)
{
deflateEnd(&zstream);
return zstream.total_out;
}
else
{
zerror = deflateEnd(&zstream);
return 0;
}
#endif
}
uint32 InflatePacket(uchar* indata, uint32 indatalen, uchar* outdata, uint32 outdatalen, bool iQuiet) {
#ifdef REUSE_ZLIB
static bool inited = false;
static z_stream zstream;
int zerror;
if(indata == NULL && outdata == NULL && indatalen == 0 && outdatalen == 0) {
//special delete state
inflateEnd(&zstream);
return(0);
}
if(!inited) {
zstream.zalloc = eqemu_alloc_func;
zstream.zfree = eqemu_free_func;
zstream.opaque = Z_NULL;
inflateInit2(&zstream, 15);
}
zstream.next_in = indata;
zstream.avail_in = indatalen;
zstream.next_out = outdata;
zstream.avail_out = outdatalen;
zstream.zalloc = eqemu_alloc_func;
zstream.zfree = eqemu_free_func;
zstream.opaque = Z_NULL;
i = inflateInit2( &zstream, 15 );
if (i != Z_OK) {
return 0;
}
zerror = inflate( &zstream, Z_FINISH );
inflateReset(&zstream);
if(zerror == Z_STREAM_END) {
return zstream.total_out;
}
else {
if (!iQuiet) {
cout << "Error: InflatePacket: inflate() returned " << zerror << " '";
if (zstream.msg)
cout << zstream.msg;
cout << "'" << endl;
//DumpPacket(indata-16, indatalen+16);
}
if (zerror == -4 && zstream.msg == 0)
{
return 0;
}
return 0;
}
#else
if(indata == NULL)
return(0);
z_stream zstream;
int zerror = 0;
int i;
zstream.next_in = indata;
zstream.avail_in = indatalen;
zstream.next_out = outdata;
zstream.avail_out = outdatalen;
zstream.zalloc = eqemu_alloc_func;
zstream.zfree = eqemu_free_func;
zstream.opaque = Z_NULL;
i = inflateInit2( &zstream, 15 );
if (i != Z_OK) {
return 0;
}
zerror = inflate( &zstream, Z_FINISH );
if(zerror == Z_STREAM_END) {
inflateEnd( &zstream );
return zstream.total_out;
}
else {
if (!iQuiet) {
cout << "Error: InflatePacket: inflate() returned " << zerror << " '";
if (zstream.msg)
cout << zstream.msg;
cout << "'" << endl;
//DumpPacket(indata-16, indatalen+16);
}
if (zerror == -4 && zstream.msg == 0)
{
return 0;
}
zerror = inflateEnd( &zstream );
return 0;
}
#endif
}
int32 roll(int32 in, int8 bits) {
return ((in << bits) | (in >> (32-bits)));
}
int64 roll(int64 in, int8 bits) {
return ((in << bits) | (in >> (64-bits)));
}
int32 rorl(int32 in, int8 bits) {
return ((in >> bits) | (in << (32-bits)));
}
int64 rorl(int64 in, int8 bits) {
return ((in >> bits) | (in << (64-bits)));
}
int32 CRCLookup(uchar idx) {
if (idx == 0)
return 0x00000000;
if (idx == 1)
return 0x77073096;
if (idx == 2)
return roll(CRCLookup(1), 1);
if (idx == 4)
return 0x076DC419;
for (uchar b=7; b>0; b--) {
uchar bv = 1 << b;
if (!(idx ^ bv)) {
// bit is only one set
return ( roll(CRCLookup (4), b - 2) );
}
if (idx&bv) {
// bit is set
return( CRCLookup(bv) ^ CRCLookup(idx&(bv - 1)) );
}
}
//Failure
return false;
}
uint32 GenerateCRC(int32 b, int32 bufsize, uchar *buf) {
int32 CRC = (b ^ 0xFFFFFFFF);
int32 bufremain = bufsize;
uchar* bufptr = buf;
while (bufremain--) {
CRC = CRCLookup((uchar)(*(bufptr++)^ (CRC&0xFF))) ^ (CRC >> 8);
}
return (htonl (CRC ^ 0xFFFFFFFF));
}
long int CRCArray[] = {
0,
1996959894,
3993919788,
2567524794,
124634137,
1886057615,
3915621685,
2657392035,
249268274,
2044508324,
3772115230,
2547177864,
162941995,
2125561021,
3887607047,
2428444049,
498536548,
1789927666,
4089016648,
2227061214,
450548861,
1843258603,
4107580753,
2211677639,
325883990,
1684777152,
4251122042,
2321926636,
335633487,
1661365465,
4195302755,
2366115317,
997073096,
1281953886,
3579855332,
2724688242,
1006888145,
1258607687,
3524101629,
2768942443,
901097722,
1119000684,
3686517206,
2898065728,
853044451,
1172266101,
3705015759,
2882616665,
651767980,
1373503546,
3369554304,
3218104598,
565507253,
1454621731,
3485111705,
3099436303,
671266974,
1594198024,
3322730930,
2970347812,
795835527,
1483230225,
3244367275,
3060149565,
1994146192,
31158534,
2563907772,
4023717930,
1907459465,
112637215,
2680153253,
3904427059,
2013776290,
251722036,
2517215374,
3775830040,
2137656763,
141376813,
2439277719,
3865271297,
1802195444,
476864866,
2238001368,
4066508878,
1812370925,
453092731,
2181625025,
4111451223,
1706088902,
314042704,
2344532202,
4240017532,
1658658271,
366619977,
2362670323,
4224994405,
1303535960,
984961486,
2747007092,
3569037538,
1256170817,
1037604311,
2765210733,
3554079995,
1131014506,
879679996,
2909243462,
3663771856,
1141124467,
855842277,
2852801631,
3708648649,
1342533948,
654459306,
3188396048,
3373015174,
1466479909,
544179635,
3110523913,
3462522015,
1591671054,
702138776,
2966460450,
3352799412,
1504918807,
783551873,
3082640443,
3233442989,
3988292384,
2596254646,
62317068,
1957810842,
3939845945,
2647816111,
81470997,
1943803523,
3814918930,
2489596804,
225274430,
2053790376,
3826175755,
2466906013,
167816743,
2097651377,
4027552580,
2265490386,
503444072,
1762050814,
4150417245,
2154129355,
426522225,
1852507879,
4275313526,
2312317920,
282753626,
1742555852,
4189708143,
2394877945,
397917763,
1622183637,
3604390888,
2714866558,
953729732,
1340076626,
3518719985,
2797360999,
1068828381,
1219638859,
3624741850,
2936675148,
906185462,
1090812512,
3747672003,
2825379669,
829329135,
1181335161,
3412177804,
3160834842,
628085408,
1382605366,
3423369109,
3138078467,
570562233,
1426400815,
3317316542,
2998733608,
733239954,
1555261956,
3268935591,
3050360625,
752459403,
1541320221,
2607071920,
3965973030,
1969922972,
40735498,
2617837225,
3943577151,
1913087877,
83908371,
2512341634,
3803740692,
2075208622,
213261112,
2463272603,
3855990285,
2094854071,
198958881,
2262029012,
4057260610,
1759359992,
534414190,
2176718541,
4139329115,
1873836001,
414664567,
2282248934,
4279200368,
1711684554,
285281116,
2405801727,
4167216745,
1634467795,
376229701,
2685067896,
3608007406,
1308918612,
956543938,
2808555105,
3495958263,
1231636301,
1047427035,
2932959818,
3654703836,
1088359270,
936918000,
2847714899,
3736837829,
1202900863,
817233897,
3183342108,
3401237130,
1404277552,
615818150,
3134207493,
3453421203,
1423857449,
601450431,
3009837614,
3294710456,
1567103746,
711928724,
3020668471,
3272380065,
1510334235,
755167117};
uint32 GenerateCRCRecipe(uint32 initial, void* buf, uint32 len)
{
uint32 c = 0xFFFFFFFF;
sint8* u = static_cast<sint8*>(buf);
for (size_t i = 0; i < len; ++i)
{
c = CRCArray[(c ^ u[i]) & 0xFF] ^ (c >> 8);
}
return c;
}

45
old/packet_functions.h Normal file
View File

@ -0,0 +1,45 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PACKET_FUNCTIONS_H
#define PACKET_FUNCTIONS_H
#include "types.h"
#include "EQPacket.h"
int32 roll(int32 in, int8 bits);
int64 roll(int64 in, int8 bits);
int32 rorl(int32 in, int8 bits);
int64 rorl(int64 in, int8 bits);
void EncryptProfilePacket(EQApplicationPacket* app);
void EncryptProfilePacket(uchar* pBuffer, int32 size);
#define EncryptSpawnPacket EncryptZoneSpawnPacket
//void EncryptSpawnPacket(EQApplicationPacket* app);
//void EncryptSpawnPacket(uchar* pBuffer, int32 size);
void EncryptZoneSpawnPacket(EQApplicationPacket* app);
void EncryptZoneSpawnPacket(uchar* pBuffer, int32 size);
int DeflatePacket(unsigned char* in_data, int in_length, unsigned char* out_data, int max_out_length);
uint32 InflatePacket(uchar* indata, uint32 indatalen, uchar* outdata, uint32 outdatalen, bool iQuiet = false);
uint32 GenerateCRC(int32 b, int32 bufsize, uchar *buf);
uint32 GenerateCRCRecipe(uint32 b, void* buf, uint32 bufsize);
#endif

128
old/queue.h Normal file
View File

@ -0,0 +1,128 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QUEUE_H
#define QUEUE_H
template<class T>
class MyQueue;
template<class T>
class MyQueueNode
{
public:
MyQueueNode(T* data)
{
next = 0;
this->data = data;
}
friend class MyQueue<T>;
private:
T* data;
MyQueueNode<T>* next;
};
template<class T>
class MyQueue
{
public:
MyQueue()
{
head = tail = 0;
}
~MyQueue() {
clear();
}
void push(T* data)
{
if (head == 0)
{
tail = head = new MyQueueNode<T>(data);
}
else
{
tail->next = new MyQueueNode<T>(data);
tail = tail->next;
}
}
T* pop()
{
if (head == 0)
{
return 0;
}
T* data = head->data;
MyQueueNode<T>* next_node = head->next;
delete head;
head = next_node;
return data;
}
T* top()
{
if (head == 0)
{
return 0;
}
return head->data;
}
bool empty()
{
if (head == 0)
{
return true;
}
return false;
}
void clear()
{
T* d = 0;
while((d = pop())) {
delete d;
}
return;
}
int count()
{
int count = 0;
MyQueueNode<T>* d = head;
while(d != 0) {
count++;
d = d->next;
}
return(count);
}
private:
MyQueueNode<T>* head;
MyQueueNode<T>* tail;
};
#endif

165
old/seperator.h Normal file
View File

@ -0,0 +1,165 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
// This class will split up a string smartly at the div character (default is space and tab)
// Seperator.arg[i] is a copy of the string chopped at the divs
// Seperator.argplus[i] is a pointer to the original string so it doesnt end at the div
// Written by Quagmire
#ifndef SEPERATOR_H
#define SEPERATOR_H
#include <string.h>
#include <stdlib.h>
class Seperator
{
public:
Seperator(const char* message, char div = ' ', int16 in_maxargnum = 10, int16 arglen = 100, bool iObeyQuotes = false, char div2 = '\t', char div3 = 0, bool iSkipEmpty = true) {
int i;
argnum = 0;
msg = strdup(message);
this->maxargnum = in_maxargnum;
argplus = new const char *[maxargnum+1];
arg = new char *[maxargnum+1];
for (i=0; i<=maxargnum; i++) {
argplus[i]=arg[i] = new char[arglen+1];
memset(arg[i], 0, arglen+1);
}
int len = strlen(message);
int s = 0, l = 0;
bool inarg = (!iSkipEmpty || !(message[0] == div || message[0] == div2 || message[0] == div3));
bool inquote = (iObeyQuotes && (message[0] == '\"' || message[0] == '\''));
argplus[0] = message;
if (len == 0)
return;
for (i=0; i<len; i++) {
// cout << i << ": 0x" << hex << (int) message[i] << dec << " " << message[i] << endl;
if (inarg) {
if ((inquote == false && (message[i] == div || message[i] == div2 || message[i] == div3)) || (inquote && (message[i] == '\'' || message[i] == '\"') && (message[i+1] == div || message[i+1] == div2 || message[i+1] == div3 || message[i+1] == 0))) {
inquote = false;
l = i-s;
if (l >= arglen)
l = arglen;
if (l){
if(l > 1 && (argplus[argnum][0] == '\'' || argplus[argnum][0] == '\"')){
l--;
memcpy(arg[argnum], argplus[argnum]+1, l);
}
else
memcpy(arg[argnum], argplus[argnum], l);
}
arg[argnum][l] = 0;
argnum++;
if (iSkipEmpty)
inarg = false;
else {
s=i+1;
argplus[argnum] = &message[s];
}
}
}
else if (iObeyQuotes && (message[i] == '\"' || message[i] == '\'')) {
inquote = true;
}
else {
s = i;
argplus[argnum] = &message[s];
if (!(message[i] == div || message[i] == div2 || message[i] == div3)) {
inarg = true;
}
}
if (argnum > maxargnum)
break;
}
if (inarg && argnum <= maxargnum) {
l = i-s;
if (l >= arglen)
l = arglen;
if (l)
memcpy(arg[argnum], argplus[argnum], l);
}
}
~Seperator() {
for (int i=0; i<=maxargnum; i++)
safe_delete_array(arg[i]);
safe_delete_array(arg);
safe_delete_array(argplus);
if (msg)
free(msg);
}
int16 argnum;
char** arg;
const char** argplus;
char * msg;
bool IsSet(int num) const {
return IsSet(arg[num]);
}
bool IsNumber(int num) const {
return IsNumber(arg[num]);
}
bool IsHexNumber(int num) const {
return IsHexNumber(arg[num]);
}
static bool IsSet(const char *check) {
return check[0] != '\0';
}
static bool IsNumber(const char* check) {
bool SeenDec = false;
int len = strlen(check);
if (len == 0) {
return false;
}
int i;
for (i = 0; i < len; i++) {
if (check[i] < '0' || check[i] > '9') {
if (check[i] == '.' && !SeenDec) {
SeenDec = true;
}
else if (i == 0 && (check[i] == '-' || check[i] == '+') && !check[i+1] == 0) {
// this is ok, do nothin
}
else {
return false;
}
}
}
return true;
}
static bool IsHexNumber(char* check) {
int len = strlen(check);
if (len < 3)
return false;
if (check[0] != '0' || (check[1] != 'x' && check[1] != 'X'))
return false;
for (int i=2; i<len; i++) {
if ((check[i] < '0' || check[i] > '9') && (check[i] < 'A' || check[i] > 'F') && (check[i] < 'a' || check[i] > 'f'))
return false;
}
return true;
}
inline int16 GetMaxArgNum() const { return maxargnum; }
inline int16 GetArgNumber() const { return argnum; }
private:
int16 maxargnum;
};
#endif

754
old/servertalk.h Normal file
View File

@ -0,0 +1,754 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EQ_SOPCODES_H
#define EQ_SOPCODES_H
#define EQEMU_PROTOCOL_VERSION "0.5.0"
#include "types.h"
#include "packet_functions.h"
#include <vector>
#define SERVER_TIMEOUT 45000 // how often keepalive gets sent
#define INTERSERVER_TIMER 10000
#define LoginServer_StatusUpdateInterval 15000
#define LoginServer_AuthStale 60000
#define AUTHCHANGE_TIMEOUT 900 // in seconds
#define ServerOP_KeepAlive 0x0001 // packet to test if port is still open
#define ServerOP_ChannelMessage 0x0002 // broadcast/guildsay
#define ServerOP_SetZone 0x0003 // client -> server zoneinfo
#define ServerOP_ShutdownAll 0x0004 // exit(0);
#define ServerOP_ZoneShutdown 0x0005 // unload all data, goto sleep mode
#define ServerOP_ZoneBootup 0x0006 // come out of sleep mode and load zone specified
#define ServerOP_ZoneStatus 0x0007 // Shows status of all zones
#define ServerOP_SetConnectInfo 0x0008 // Tells server address and port #
#define ServerOP_EmoteMessage 0x0009 // Worldfarts
#define ServerOP_ClientList 0x000A // Update worldserver's client list, for #whos
#define ServerOP_Who 0x000B // #who
#define ServerOP_ZonePlayer 0x000C // #zone, or #summon
#define ServerOP_KickPlayer 0x000D // #kick
#define ServerOP_RefreshGuild 0x000E // Notice to all zoneservers to refresh their guild cache for ID# in packet
#define ServerOP_GuildKickAll 0x000F // Remove all clients from this guild
#define ServerOP_GuildInvite 0x0010
#define ServerOP_GuildRemove 0x0011
#define ServerOP_GuildPromote 0x0012
#define ServerOP_GuildDemote 0x0013
#define ServerOP_GuildLeader 0x0014
#define ServerOP_GuildGMSet 0x0015
#define ServerOP_GuildGMSetRank 0x0016
#define ServerOP_FlagUpdate 0x0018 // GM Flag updated for character, refresh the memory cache
#define ServerOP_GMGoto 0x0019
#define ServerOP_MultiLineMsg 0x001A
#define ServerOP_Lock 0x001B // For #lock/#unlock inside server
#define ServerOP_Motd 0x001C // For changing MoTD inside server.
#define ServerOP_Uptime 0x001D
#define ServerOP_Petition 0x001E
#define ServerOP_KillPlayer 0x001F
#define ServerOP_UpdateGM 0x0020
#define ServerOP_RezzPlayer 0x0021
#define ServerOP_ZoneReboot 0x0022
#define ServerOP_ZoneToZoneRequest 0x0023
#define ServerOP_AcceptWorldEntrance 0x0024
#define ServerOP_ZAAuth 0x0025
#define ServerOP_ZAAuthFailed 0x0026
#define ServerOP_ZoneIncClient 0x0027 // Incomming client
#define ServerOP_ClientListKA 0x0028
#define ServerOP_ChangeWID 0x0029
#define ServerOP_IPLookup 0x002A
#define ServerOP_LockZone 0x002B
#define ServerOP_ItemStatus 0x002C
#define ServerOP_OOCMute 0x002D
#define ServerOP_Revoke 0x002E
#define ServerOP_GuildJoin 0x002F
#define ServerOP_GroupIDReq 0x0030
#define ServerOP_GroupIDReply 0x0031
#define ServerOP_GroupLeave 0x0032 // for disbanding out of zone folks
#define ServerOP_RezzPlayerAccept 0x0033
#define ServerOP_SpawnCondition 0x0034
#define ServerOP_SpawnEvent 0x0035
#define UpdateServerOP_Verified 0x5090
#define UpdateServerOP_DisplayMsg 0x5091
#define UpdateServerOP_Completed 0x5092
#define ServerOP_LSInfo 0x1000
#define ServerOP_LSStatus 0x1001
#define ServerOP_LSClientAuth 0x1002
#define ServerOP_LSFatalError 0x1003
#define ServerOP_SystemwideMessage 0x1005
#define ServerOP_ListWorlds 0x1006
#define ServerOP_PeerConnect 0x1007
#define ServerOP_LSZoneInfo 0x3001
#define ServerOP_LSZoneStart 0x3002
#define ServerOP_LSZoneBoot 0x3003
#define ServerOP_LSZoneShutdown 0x3004
#define ServerOP_LSZoneSleep 0x3005
#define ServerOP_LSPlayerLeftWorld 0x3006
#define ServerOP_LSPlayerJoinWorld 0x3007
#define ServerOP_LSPlayerZoneChange 0x3008
#define ServerOP_UsertoWorldReq 0xAB00
#define ServerOP_UsertoWorldResp 0xAB01
#define ServerOP_EncapPacket 0x2007 // Packet within a packet
#define ServerOP_WorldListUpdate 0x2008
#define ServerOP_WorldListRemove 0x2009
#define ServerOP_TriggerWorldListRefresh 0x200A
#define ServerOP_WhoAll 0x0210
#define ServerOP_SetWorldTime 0x200B
#define ServerOP_GetWorldTime 0x200C
#define ServerOP_SyncWorldTime 0x200E
//EQ2 Opcodes
#define ServerOP_CharTimeStamp 0x200F
#define ServerOP_NameFilterCheck 0x2011
#define ServerOP_BasicCharUpdate 0x2012
#define ServerOP_CharacterCreate 0x2013
#define ServerOP_NameCharUpdate 0x2014
#define ServerOP_GetLatestTables 0x2015
#define ServerOP_GetTableQuery 0x2016
#define ServerOP_GetTableData 0x2017
#define ServerOP_RaceUpdate 0x2018
#define ServerOP_ZoneUpdate 0x2019
#define ServerOP_BugReport 0x201A
#define ServerOP_ResetDatabase 0x201B
#define ServerOP_ZoneUpdates 0x201C
#define ServerOP_LoginEquipment 0x201D // updates charater select screen item appearances (gear appear)
#define ServerOP_CharacterPicture 0x201E
/************ PACKET RELATED STRUCT ************/
class ServerPacket
{
public:
~ServerPacket() { safe_delete_array(pBuffer); }
ServerPacket(int16 in_opcode = 0, int32 in_size = 0) {
this->compressed = false;
size = in_size;
opcode = in_opcode;
if (size == 0) {
pBuffer = 0;
}
else {
pBuffer = new uchar[size];
memset(pBuffer, 0, size);
}
destination = 0;
InflatedSize = 0;
}
ServerPacket* Copy() {
if (this == 0) {
return 0;
}
ServerPacket* ret = new ServerPacket(this->opcode, this->size);
if (this->size)
memcpy(ret->pBuffer, this->pBuffer, this->size);
ret->compressed = this->compressed;
ret->InflatedSize = this->InflatedSize;
return ret;
}
bool Deflate() {
if (compressed)
return false;
if ((!this->pBuffer) || (!this->size))
return false;
uchar* tmp = new uchar[this->size + 128];
int32 tmpsize = DeflatePacket(this->pBuffer, this->size, tmp, this->size + 128);
if (!tmpsize) {
safe_delete_array(tmp);
return false;
}
this->compressed = true;
this->InflatedSize = this->size;
this->size = tmpsize;
uchar* new_buffer = new uchar[this->size];
memcpy(new_buffer, tmp, this->size);
safe_delete_array(tmp);
uchar* tmpdel = this->pBuffer;
this->pBuffer = new_buffer;
safe_delete_array(tmpdel);
return true;
}
bool Inflate() {
if (!compressed)
return false;
if ((!this->pBuffer) || (!this->size))
return false;
uchar* tmp = new uchar[InflatedSize];
int32 tmpsize = InflatePacket(this->pBuffer, this->size, tmp, InflatedSize);
if (!tmpsize) {
safe_delete_array(tmp);
return false;
}
compressed = false;
this->size = tmpsize;
uchar* tmpdel = this->pBuffer;
this->pBuffer = tmp;
safe_delete_array(tmpdel);
return true;
}
int32 size;
int16 opcode;
uchar* pBuffer;
bool compressed;
int32 InflatedSize;
int32 destination;
};
#pragma pack(1)
struct GetLatestTables_Struct{
float table_version;
float data_version;
};
struct ServerLSInfo_Struct {
char name[201]; // name the worldserver wants
char address[250]; // DNS address of the server
char account[31]; // account name for the worldserver
char password[256]; // password for the name
char protocolversion[25]; // Major protocol version number
char serverversion[64]; // minor server software version number
int8 servertype; // 0=world, 1=chat, 2=login, 3=MeshLogin, 4=World Debug
int32 dbversion; // database major+minor version from version.h (for PatchServer)
};
struct ServerLSStatus_Struct {
sint32 status;
sint32 num_players;
sint32 num_zones;
int8 world_max_level;
};
struct ServerSystemwideMessage {
int32 lsaccount_id;
char key[30]; // sessionID key for verification
int32 type;
char message[0];
};
struct ServerSyncWorldList_Struct {
int32 RemoteID;
int32 ip;
sint32 status;
char name[201];
char address[250];
char account[31];
int32 accountid;
int8 authlevel;
int8 servertype; // 0=world, 1=chat, 2=login
int32 adminid;
int8 showdown;
sint32 num_players;
sint32 num_zones;
bool placeholder;
};
struct UsertoWorldRequest_Struct {
int32 lsaccountid;
int32 char_id;
int32 worldid;
int32 FromID;
int32 ToID;
char ip_address[21];
};
struct UsertoWorldResponse_Struct {
int32 lsaccountid;
int32 char_id;
int32 worldid;
int32 access_key;
int8 response;
char ip_address[80];
int32 port;
int32 FromID;
int32 ToID;
};
struct ServerEncapPacket_Struct {
int32 ToID; // ID number of the LWorld on the other server
int16 opcode;
int16 size;
uchar data[0];
};
struct ServerEmoteMessage_Struct {
char to[64];
int32 guilddbid;
sint16 minstatus;
int32 type;
char message[0];
};
/*struct TableVersion{
char name[64];
int32 version;
int32 max_table_version;
int32 max_data_version;
sint32 data_version;
int8 last;
char column_names[1000];
};*/
typedef struct {
char name[256];
unsigned int name_len;
unsigned int version;
unsigned int data_version;
} TableVersion;
template<class Type> void AddPtrData(string* buffer, Type& data){
buffer->append((char*)&data, sizeof(Type));
}
template<class Type> void AddPtrData(string* buffer, Type* data, int16 size){
buffer->append(data, size);
}
class LatestTableVersions {
public:
LatestTableVersions(){
tables = 0;
current_index = 0;
total_tables = 0;
data_version = 0;
}
~LatestTableVersions(){
safe_delete_array(tables);
}
void SetTableSize(int16 size){
total_tables = size;
tables = new TableVersion[total_tables];
}
void AddTable(char* name, int32 version, int32 data_version){
strcpy(tables[current_index].name, name);
tables[current_index].version = version;
tables[current_index].data_version = data_version;
current_index++;
}
int16 GetTotalSize(){
return total_tables * sizeof(TableVersion) + sizeof(int16);
}
int16 GetTotalTables(){
return total_tables;
}
TableVersion* GetTables(){
return tables;
}
TableVersion GetTable(int16 index){
return tables[index];
}
string Serialize(){
AddPtrData(&buffer, total_tables);
for(int16 i=0;i<total_tables;i++){
AddPtrData(&buffer, tables[i].name, sizeof(tables[i].name));
AddPtrData(&buffer, tables[i].version);
AddPtrData(&buffer, tables[i].data_version);
}
return buffer;
}
void DeSerialize(uchar* data){
uchar* ptr = data;
memcpy(&total_tables, ptr, sizeof(total_tables));
ptr+= sizeof(total_tables);
tables = new TableVersion[total_tables];
for(int16 i=0;i<total_tables;i++){
memcpy(&tables[i].name, ptr, sizeof(tables[i].name));
ptr+= sizeof(tables[i].name);
memcpy(&tables[i].version, ptr, sizeof(tables[i].version));
ptr+= sizeof(tables[i].version);
memcpy(&tables[i].data_version, ptr, sizeof(tables[i].data_version));
ptr+= sizeof(tables[i].data_version);
}
}
int32 data_version;
private:
int16 current_index;
int16 total_tables;
TableVersion* tables;
string buffer;
};
struct TableData{
int16 size;
char* query;
};
class TableQuery {
public:
TableQuery(){
try_delete = true;
num_queries = 0;
data_version = 0;
current_index = 0;
latest_version = 0;
your_version = 0;
total_size = sizeof(num_queries) + sizeof(latest_version) + sizeof(your_version) + sizeof(tablename);
}
~TableQuery(){
if(try_delete){
for(int16 i=0;i<tmp_queries.size();i++){
safe_delete_array(tmp_queries[i]);
}
}
}
string GetQueriesString(){
string query_string ;
for(int32 i=0;i<tmp_queries.size();i++){
query_string.append(tmp_queries[i]).append("\n");
}
return query_string;
}
void AddQuery(char* query){
num_queries++;
total_size += strlen(query) + 1;
tmp_queries.push_back(query);
}
int16 GetTotalSize(){
return total_size;
}
int16 GetTotalQueries(){
return num_queries;
}
char* GetQuery(int16 index){
return tmp_queries[index];
}
string Serialize(){
num_queries = tmp_queries.size();
AddPtrData(&buffer, num_queries);
AddPtrData(&buffer, latest_version);
AddPtrData(&buffer, your_version);
AddPtrData(&buffer, data_version);
AddPtrData(&buffer, tablename, sizeof(tablename));
for(int16 i=0;i<GetTotalQueries();i++)
AddPtrData(&buffer, tmp_queries[i], strlen(tmp_queries[i]) + 1);
return buffer;
}
void DeSerialize(uchar* data){
try_delete = false;
uchar* ptr = data;
memcpy(&num_queries, ptr, sizeof(num_queries));
ptr+= sizeof(num_queries);
memcpy(&latest_version, ptr, sizeof(latest_version));
ptr+= sizeof(latest_version);
memcpy(&your_version, ptr, sizeof(your_version));
ptr+= sizeof(your_version);
memcpy(&data_version, ptr, sizeof(data_version));
ptr+= sizeof(data_version);
memcpy(&tablename, ptr, sizeof(tablename));
ptr+= sizeof(tablename);
for(int16 i=0;i<GetTotalQueries();i++){
tmp_queries.push_back((char*)ptr);
ptr += strlen((char*)ptr) + 1;
}
}
int16 current_index;
int16 num_queries;
int32 latest_version;
int32 your_version;
int32 data_version;
bool try_delete;
char tablename[64];
int32 total_size;
string buffer;
private:
vector<char*> tmp_queries;
};
class TableDataQuery{
public:
TableDataQuery(char* table_name){
if( strlen(table_name) >= sizeof(tablename) )
return;
strcpy(tablename, table_name);
num_queries = 0;
columns_size = 0;
columns = 0;
version = 0;
table_size = 0;
}
TableDataQuery(){
num_queries = 0;
columns_size = 0;
columns = 0;
version = 0;
table_size = 0;
}
~TableDataQuery(){
safe_delete_array(columns);
for(int32 i=0;i<num_queries;i++){
safe_delete_array(queries[i]->query);
safe_delete(queries[i]);
}
}
int32 GetTotalQueries(){
return num_queries;
}
string* Serialize(){
buffer = "";
num_queries = queries.size();
if(GetTotalQueries() == 0)
return 0;
table_size = strlen(tablename);
AddPtrData(&buffer, table_size);
AddPtrData(&buffer, tablename, table_size + 1);
AddPtrData(&buffer, version);
if(num_queries > 200){
int32 max_queries = 200;
AddPtrData(&buffer, max_queries);
}
else
AddPtrData(&buffer, num_queries);
AddPtrData(&buffer, columns_size);
AddPtrData(&buffer, columns, columns_size);
vector<TableData*>::iterator query_iterator;
int16 count = 0;
for(int i=GetTotalQueries() - 1;i >=0 && count < 200;i--){
AddPtrData(&buffer, queries[i]->size);
AddPtrData(&buffer, queries[i]->query, queries[i]->size);
safe_delete_array(queries[i]->query);
safe_delete(queries[i]);
queries.pop_back();
count++;
}
return &buffer;
}
void DeSerialize(uchar* data){
uchar* ptr = data;
memcpy(&table_size, ptr, sizeof(table_size));
ptr+= sizeof(table_size);
memcpy(&tablename, ptr, table_size + 1);
ptr+= table_size + 1;
memcpy(&version, ptr, sizeof(version));
ptr+= sizeof(version);
memcpy(&num_queries, ptr, sizeof(num_queries));
ptr+= sizeof(num_queries);
memcpy(&columns_size, ptr, sizeof(columns_size));
ptr+= sizeof(columns_size);
columns = new char[columns_size + 1];
memcpy(columns, ptr, columns_size + 1);
ptr+= columns_size;
for(int32 i=0;i<GetTotalQueries();i++)
{
TableData* new_query = new TableData;
try {
memcpy(&new_query->size, ptr, sizeof(new_query->size));
ptr+= sizeof(new_query->size);
new_query->query = new char[new_query->size + 1];
memcpy(new_query->query, ptr, new_query->size);
ptr+= new_query->size;
queries.push_back(new_query);
}
catch( bad_alloc &ba )
{
cout << ba.what() << endl;
if( NULL != new_query )
delete new_query;
}
}
}
string buffer;
int32 num_queries;
int32 version;
int16 table_size;
char tablename[64];
int16 columns_size;
char* columns;
vector<TableData*> queries;
};
// Max number of equipment updates to send at once
struct EquipmentUpdateRequest_Struct
{
int16 max_per_batch;
};
// Login's structure of equipment data
struct LoginEquipmentUpdate
{
int32 world_char_id;
int16 equip_type;
int8 red;
int8 green;
int8 blue;
int8 highlight_red;
int8 highlight_green;
int8 highlight_blue;
int32 slot;
};
// World's structure of equipment data
struct EquipmentUpdate_Struct
{
int32 id; // unique record identifier per world
int32 world_char_id;
int16 equip_type;
int8 red;
int8 green;
int8 blue;
int8 highlight_red;
int8 highlight_green;
int8 highlight_blue;
int32 slot;
};
// How many equipmment updates are there to send?
struct EquipmentUpdateList_Struct
{
sint16 total_updates;
};
struct ZoneUpdateRequest_Struct{
int16 max_per_batch;
};
struct LoginZoneUpdate{
string name;
string description;
};
struct ZoneUpdate_Struct{
int32 zone_id;
int8 zone_name_length;
int8 zone_desc_length;
char data[0];
};
struct ZoneUpdateList_Struct{
uint16 total_updates;
char data[0];
};
//EQ2 Specific Structures Login -> World (Image)
struct CharacterTimeStamp_Struct {
int32 char_id;
int32 account_id;
int32 unix_timestamp;
};
//EQ2 Specific Structures World -> Login (Image)
/**UPDATE_FIELD TYPES**
These will be stored beside the timestamp on the world server to determine what has changed on between the timestamp, when the update is sent, it will remove the flag.
8 bits in a byte:
Example: 01001100
0 Level Flag
1 Race Flag
0 Class Flag
0 Gender Flag
1 Zone Flag
1 Armor Flag
0 Name Flag
0 Delete Flag
**/
#define LEVEL_UPDATE_FLAG 1
#define RACE_UPDATE_FLAG 2
#define CLASS_UPDATE_FLAG 4
#define GENDER_UPDATE_FLAG 8
#define ZONE_UPDATE_FLAG 16
#define ARMOR_UPDATE_FLAG 32
#define NAME_UPDATE_FLAG 64
#define DELETE_UPDATE_FLAG 128
//This structure used for basic changes such as level,class,gender, and deletes that are not able to be backed up
struct CharDataUpdate_Struct {
int32 account_id;
int32 char_id;
int8 update_field;
int32 update_data;
};
struct BugReport{
char category[64];
char subcategory[64];
char causes_crash[64];
char reproducible[64];
char summary[128];
char description[2000];
char version[32];
char player[64];
int32 account_id;
char spawn_name[64];
int32 spawn_id;
int32 zone_id;
};
struct RaceUpdate_Struct {
int32 account_id;
int32 char_id;
int16 model_type;
int8 race;
};
//If this structure comes in with more than 74 bytes, should probably discard (leaves 65 bytes for new_name)
#define CHARNAMEUPDATESTRUCT_MAXSIZE 74
struct CharNameUpdate_Struct {
int32 account_id;
int32 char_id;
int8 name_length; // If its longer than 64, something is wrong :-/
char new_name[0];
};
//If this structure comes in with more than 78 bytes, should probably discard (leaves 65 bytes for new_zone)
#define CHARZONESTRUCT_MAXSIZE 78
struct CharZoneUpdate_Struct {
int32 account_id;
int32 char_id;
int32 zone_id;
int8 zone_length; // If its longer than 64, something is wrong :-/
char new_zone[0];
};
struct WorldCharCreate_Struct {
int32 account_id;
int32 char_id;
int16 model_type;
int16 char_size;
uchar character[0];
};
struct WorldCharNameFilter_Struct {
int32 account_id;
int16 name_length;
uchar name[0];
};
struct WorldCharNameFilterResponse_Struct {
int32 account_id;
int32 char_id;
int8 response;
};
#define CHARPICSTRUCT_MINSIZE 10
// Should only be used for the headshot picture
struct CharPictureUpdate_Struct {
int32 account_id;
int32 char_id;
int16 pic_size;
char pic[0];
};
#pragma pack()
#endif

155
old/sha512.cpp Normal file
View File

@ -0,0 +1,155 @@
#include <cstring>
#include <fstream>
#include "sha512.h"
const unsigned long long SHA512::sha512_k[80] = //ULL = uint64
{0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
void SHA512::transform(const unsigned char *message, unsigned int block_nb)
{
uint64 w[80];
uint64 wv[8];
uint64 t1, t2;
const unsigned char *sub_block;
int i, j;
for (i = 0; i < (int) block_nb; i++) {
sub_block = message + (i << 7);
for (j = 0; j < 16; j++) {
SHA2_PACK64(&sub_block[j << 3], &w[j]);
}
for (j = 16; j < 80; j++) {
w[j] = SHA512_F4(w[j - 2]) + w[j - 7] + SHA512_F3(w[j - 15]) + w[j - 16];
}
for (j = 0; j < 8; j++) {
wv[j] = m_h[j];
}
for (j = 0; j < 80; j++) {
t1 = wv[7] + SHA512_F2(wv[4]) + SHA2_CH(wv[4], wv[5], wv[6])
+ sha512_k[j] + w[j];
t2 = SHA512_F1(wv[0]) + SHA2_MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; j++) {
m_h[j] += wv[j];
}
}
}
void SHA512::init()
{
m_h[0] = 0x6a09e667f3bcc908ULL;
m_h[1] = 0xbb67ae8584caa73bULL;
m_h[2] = 0x3c6ef372fe94f82bULL;
m_h[3] = 0xa54ff53a5f1d36f1ULL;
m_h[4] = 0x510e527fade682d1ULL;
m_h[5] = 0x9b05688c2b3e6c1fULL;
m_h[6] = 0x1f83d9abfb41bd6bULL;
m_h[7] = 0x5be0cd19137e2179ULL;
m_len = 0;
m_tot_len = 0;
}
void SHA512::update(const unsigned char *message, unsigned int len)
{
unsigned int block_nb;
unsigned int new_len, rem_len, tmp_len;
const unsigned char *shifted_message;
tmp_len = SHA384_512_BLOCK_SIZE - m_len;
rem_len = len < tmp_len ? len : tmp_len;
memcpy(&m_block[m_len], message, rem_len);
if (m_len + len < SHA384_512_BLOCK_SIZE) {
m_len += len;
return;
}
new_len = len - rem_len;
block_nb = new_len / SHA384_512_BLOCK_SIZE;
shifted_message = message + rem_len;
transform(m_block, 1);
transform(shifted_message, block_nb);
rem_len = new_len % SHA384_512_BLOCK_SIZE;
memcpy(m_block, &shifted_message[block_nb << 7], rem_len);
m_len = rem_len;
m_tot_len += (block_nb + 1) << 7;
}
void SHA512::final(unsigned char *digest)
{
unsigned int block_nb;
unsigned int pm_len;
unsigned int len_b;
int i;
block_nb = 1 + ((SHA384_512_BLOCK_SIZE - 17)
< (m_len % SHA384_512_BLOCK_SIZE));
len_b = (m_tot_len + m_len) << 3;
pm_len = block_nb << 7;
memset(m_block + m_len, 0, pm_len - m_len);
m_block[m_len] = 0x80;
SHA2_UNPACK32(len_b, m_block + pm_len - 4);
transform(m_block, block_nb);
for (i = 0 ; i < 8; i++) {
SHA2_UNPACK64(m_h[i], &digest[i << 3]);
}
}
std::string sha512(std::string input)
{
unsigned char digest[SHA512::DIGEST_SIZE];
memset(digest,0,SHA512::DIGEST_SIZE);
SHA512 ctx = SHA512();
ctx.init();
ctx.update((unsigned char*)input.c_str(), input.length());
ctx.final(digest);
char buf[2*SHA512::DIGEST_SIZE+1];
buf[2*SHA512::DIGEST_SIZE] = 0;
for (int i = 0; i < SHA512::DIGEST_SIZE; i++)
sprintf(buf+i*2, "%02x", digest[i]);
return std::string(buf);
}

71
old/sha512.h Normal file
View File

@ -0,0 +1,71 @@
#ifndef SHA512_H
#define SHA512_H
#include <string>
class SHA512
{
protected:
typedef unsigned char uint8;
typedef unsigned int uint32;
typedef unsigned long long uint64;
const static uint64 sha512_k[];
static const unsigned int SHA384_512_BLOCK_SIZE = (1024/8);
public:
void init();
void update(const unsigned char *message, unsigned int len);
void final(unsigned char *digest);
static const unsigned int DIGEST_SIZE = ( 512 / 8);
protected:
void transform(const unsigned char *message, unsigned int block_nb);
unsigned int m_tot_len;
unsigned int m_len;
unsigned char m_block[2 * SHA384_512_BLOCK_SIZE];
uint64 m_h[8];
};
std::string sha512(std::string input);
#define SHA2_SHFR(x, n) (x >> n)
#define SHA2_ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
#define SHA2_ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
#define SHA2_CH(x, y, z) ((x & y) ^ (~x & z))
#define SHA2_MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define SHA512_F1(x) (SHA2_ROTR(x, 28) ^ SHA2_ROTR(x, 34) ^ SHA2_ROTR(x, 39))
#define SHA512_F2(x) (SHA2_ROTR(x, 14) ^ SHA2_ROTR(x, 18) ^ SHA2_ROTR(x, 41))
#define SHA512_F3(x) (SHA2_ROTR(x, 1) ^ SHA2_ROTR(x, 8) ^ SHA2_SHFR(x, 7))
#define SHA512_F4(x) (SHA2_ROTR(x, 19) ^ SHA2_ROTR(x, 61) ^ SHA2_SHFR(x, 6))
#define SHA2_UNPACK32(x, str) \
{ \
*((str) + 3) = (uint8) ((x) ); \
*((str) + 2) = (uint8) ((x) >> 8); \
*((str) + 1) = (uint8) ((x) >> 16); \
*((str) + 0) = (uint8) ((x) >> 24); \
}
#define SHA2_UNPACK64(x, str) \
{ \
*((str) + 7) = (uint8) ((x) ); \
*((str) + 6) = (uint8) ((x) >> 8); \
*((str) + 5) = (uint8) ((x) >> 16); \
*((str) + 4) = (uint8) ((x) >> 24); \
*((str) + 3) = (uint8) ((x) >> 32); \
*((str) + 2) = (uint8) ((x) >> 40); \
*((str) + 1) = (uint8) ((x) >> 48); \
*((str) + 0) = (uint8) ((x) >> 56); \
}
#define SHA2_PACK64(str, x) \
{ \
*(x) = ((uint64) *((str) + 7) ) \
| ((uint64) *((str) + 6) << 8) \
| ((uint64) *((str) + 5) << 16) \
| ((uint64) *((str) + 4) << 24) \
| ((uint64) *((str) + 3) << 32) \
| ((uint64) *((str) + 2) << 40) \
| ((uint64) *((str) + 1) << 48) \
| ((uint64) *((str) + 0) << 56); \
}
#endif

529
old/string_util.cpp Normal file
View File

@ -0,0 +1,529 @@
/*
* Copyright 2013 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "string_util.h"
#include <algorithm>
#ifdef _WINDOWS
#include <windows.h>
#define snprintf _snprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
#else
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#endif
#ifndef va_copy
#define va_copy(d,s) ((d) = (s))
#endif
// original source:
// https://github.com/facebook/folly/blob/master/folly/String.cpp
//
const std::string vStringFormat(const char* format, va_list args)
{
std::string output;
va_list tmpargs;
va_copy(tmpargs,args);
int characters_used = vsnprintf(nullptr, 0, format, tmpargs);
va_end(tmpargs);
// Looks like we have a valid format string.
if (characters_used > 0) {
output.resize(characters_used + 1);
va_copy(tmpargs,args);
characters_used = vsnprintf(&output[0], output.capacity(), format, tmpargs);
va_end(tmpargs);
output.resize(characters_used);
// We shouldn't have a format error by this point, but I can't imagine what error we
// could have by this point. Still, return empty string;
if (characters_used < 0)
output.clear();
}
return output;
}
const std::string str_tolower(std::string s)
{
std::transform(
s.begin(), s.end(), s.begin(),
[](unsigned char c) { return ::tolower(c); }
);
return s;
}
std::vector<std::string> split(std::string str_to_split, char delimiter)
{
std::stringstream ss(str_to_split);
std::string item;
std::vector<std::string> exploded_values;
while (std::getline(ss, item, delimiter)) {
exploded_values.push_back(item);
}
return exploded_values;
}
const std::string str_toupper(std::string s)
{
std::transform(
s.begin(), s.end(), s.begin(),
[](unsigned char c) { return ::toupper(c); }
);
return s;
}
const std::string ucfirst(std::string s)
{
std::string output = s;
if (!s.empty())
output[0] = static_cast<char>(::toupper(s[0]));
return output;
}
const std::string StringFormat(const char *format, ...)
{
va_list args;
va_start(args, format);
std::string output = vStringFormat(format, args);
va_end(args);
return output;
}
std::vector<std::string> SplitString(const std::string &str, char delim) {
std::vector<std::string> ret;
std::stringstream ss(str);
std::string item;
while(std::getline(ss, item, delim)) {
ret.push_back(item);
}
return ret;
}
std::string implode(std::string glue, std::vector<std::string> src)
{
if (src.empty()) {
return {};
}
std::ostringstream output;
std::vector<std::string>::iterator src_iter;
for (src_iter = src.begin(); src_iter != src.end(); src_iter++) {
output << *src_iter << glue;
}
std::string final_output = output.str();
final_output.resize (output.str().size () - glue.size());
return final_output;
}
std::string EscapeString(const std::string &s) {
std::string ret;
size_t sz = s.length();
for(size_t i = 0; i < sz; ++i) {
char c = s[i];
switch(c) {
case '\x00':
ret += "\\x00";
break;
case '\n':
ret += "\\n";
break;
case '\r':
ret += "\\r";
break;
case '\\':
ret += "\\\\";
break;
case '\'':
ret += "\\'";
break;
case '\"':
ret += "\\\"";
break;
case '\x1a':
ret += "\\x1a";
break;
default:
ret.push_back(c);
break;
}
}
return ret;
}
std::string EscapeString(const char *src, size_t sz) {
std::string ret;
for(size_t i = 0; i < sz; ++i) {
char c = src[i];
switch(c) {
case '\x00':
ret += "\\x00";
break;
case '\n':
ret += "\\n";
break;
case '\r':
ret += "\\r";
break;
case '\\':
ret += "\\\\";
break;
case '\'':
ret += "\\'";
break;
case '\"':
ret += "\\\"";
break;
case '\x1a':
ret += "\\x1a";
break;
default:
ret.push_back(c);
break;
}
}
return ret;
}
bool StringIsNumber(const std::string &s) {
try {
auto r = stod(s);
return true;
}
catch (std::exception &) {
return false;
}
}
void ToLowerString(std::string &s) {
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
}
void ToUpperString(std::string &s) {
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
}
std::string JoinString(const std::vector<std::string>& ar, const std::string &delim) {
std::string ret;
for (size_t i = 0; i < ar.size(); ++i) {
if (i != 0) {
ret += delim;
}
ret += ar[i];
}
return ret;
}
void find_replace(std::string &string_subject, const std::string &search_string, const std::string &replace_string)
{
if (string_subject.find(search_string) == std::string::npos) {
return;
}
size_t start_pos = 0;
while((start_pos = string_subject.find(search_string, start_pos)) != std::string::npos) {
string_subject.replace(start_pos, search_string.length(), replace_string);
start_pos += replace_string.length();
}
}
void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver)
{
auto split = SplitString(s, ':');
if (split.size() == 2) {
loginserver = split[0];
account = split[1];
}
else if(split.size() == 1) {
account = split[0];
}
}
//Const char based
// normal strncpy doesnt put a null term on copied strings, this one does
// ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp
char* strn0cpy(char* dest, const char* source, uint32 size) {
if (!dest)
return 0;
if (size == 0 || source == 0) {
dest[0] = 0;
return dest;
}
strncpy(dest, source, size);
dest[size - 1] = 0;
return dest;
}
// String N w/null Copy Truncated?
// return value =true if entire string(source) fit, false if it was truncated
bool strn0cpyt(char* dest, const char* source, uint32 size) {
if (!dest)
return 0;
if (size == 0 || source == 0) {
dest[0] = 0;
return false;
}
strncpy(dest, source, size);
dest[size - 1] = 0;
return (bool)(source[strlen(dest)] == 0);
}
const char *MakeLowerString(const char *source) {
static char str[128];
if (!source)
return nullptr;
MakeLowerString(source, str);
return str;
}
void MakeLowerString(const char *source, char *target) {
if (!source || !target) {
*target = 0;
return;
}
while (*source)
{
*target = tolower(*source);
target++; source++;
}
*target = 0;
}
int MakeAnyLenString(char** ret, const char* format, ...) {
int buf_len = 128;
int chars = -1;
va_list argptr, tmpargptr;
va_start(argptr, format);
while (chars == -1 || chars >= buf_len) {
safe_delete_array(*ret);
if (chars == -1)
buf_len *= 2;
else
buf_len = chars + 1;
*ret = new char[buf_len];
va_copy(tmpargptr, argptr);
chars = vsnprintf(*ret, buf_len, format, tmpargptr);
}
va_end(argptr);
return chars;
}
uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...) {
if (*bufsize == 0)
*bufsize = 256;
if (*ret == 0)
*strlen = 0;
int chars = -1;
char* oldret = 0;
va_list argptr, tmpargptr;
va_start(argptr, format);
while (chars == -1 || chars >= (int32)(*bufsize - *strlen)) {
if (chars == -1)
*bufsize += 256;
else
*bufsize += chars + 25;
oldret = *ret;
*ret = new char[*bufsize];
if (oldret) {
if (*strlen)
memcpy(*ret, oldret, *strlen);
safe_delete_array(oldret);
}
va_copy(tmpargptr, argptr);
chars = vsnprintf(&(*ret)[*strlen], (*bufsize - *strlen), format, tmpargptr);
}
va_end(argptr);
*strlen += chars;
return *strlen;
}
uint32 hextoi(const char* num) {
if (num == nullptr)
return 0;
int len = strlen(num);
if (len < 3)
return 0;
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
return 0;
uint32 ret = 0;
int mul = 1;
for (int i = len - 1; i >= 2; i--) {
if (num[i] >= 'A' && num[i] <= 'F')
ret += ((num[i] - 'A') + 10) * mul;
else if (num[i] >= 'a' && num[i] <= 'f')
ret += ((num[i] - 'a') + 10) * mul;
else if (num[i] >= '0' && num[i] <= '9')
ret += (num[i] - '0') * mul;
else
return 0;
mul *= 16;
}
return ret;
}
uint64 hextoi64(const char* num) {
if (num == nullptr)
return 0;
int len = strlen(num);
if (len < 3)
return 0;
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
return 0;
uint64 ret = 0;
int mul = 1;
for (int i = len - 1; i >= 2; i--) {
if (num[i] >= 'A' && num[i] <= 'F')
ret += ((num[i] - 'A') + 10) * mul;
else if (num[i] >= 'a' && num[i] <= 'f')
ret += ((num[i] - 'a') + 10) * mul;
else if (num[i] >= '0' && num[i] <= '9')
ret += (num[i] - '0') * mul;
else
return 0;
mul *= 16;
}
return ret;
}
bool atobool(const char* iBool) {
if (iBool == nullptr)
return false;
if (!strcasecmp(iBool, "true"))
return true;
if (!strcasecmp(iBool, "false"))
return false;
if (!strcasecmp(iBool, "yes"))
return true;
if (!strcasecmp(iBool, "no"))
return false;
if (!strcasecmp(iBool, "on"))
return true;
if (!strcasecmp(iBool, "off"))
return false;
if (!strcasecmp(iBool, "enable"))
return true;
if (!strcasecmp(iBool, "disable"))
return false;
if (!strcasecmp(iBool, "enabled"))
return true;
if (!strcasecmp(iBool, "disabled"))
return false;
if (!strcasecmp(iBool, "y"))
return true;
if (!strcasecmp(iBool, "n"))
return false;
if (atoi(iBool))
return true;
return false;
}
// removes the crap and turns the underscores into spaces.
char *CleanMobName(const char *in, char *out)
{
unsigned i, j;
for (i = j = 0; i < strlen(in); i++)
{
// convert _ to space.. any other conversions like this? I *think* this
// is the only non alpha char that's not stripped but converted.
if (in[i] == '_')
{
out[j++] = ' ';
}
else
{
if (isalpha(in[i]) || (in[i] == '`')) // numbers, #, or any other crap just gets skipped
out[j++] = in[i];
}
}
out[j] = 0; // terimnate the string before returning it
return out;
}
void RemoveApostrophes(std::string &s)
{
for (unsigned int i = 0; i < s.length(); ++i)
if (s[i] == '\'')
s[i] = '_';
}
char *RemoveApostrophes(const char *s)
{
auto NewString = new char[strlen(s) + 1];
strcpy(NewString, s);
for (unsigned int i = 0; i < strlen(NewString); ++i)
if (NewString[i] == '\'')
NewString[i] = '_';
return NewString;
}
const char *ConvertArray(int input, char *returnchar)
{
sprintf(returnchar, "%i", input);
return returnchar;
}
const char *ConvertArrayF(float input, char *returnchar)
{
sprintf(returnchar, "%0.2f", input);
return returnchar;
}
bool isAlphaNumeric(const char *text)
{
for (unsigned int charIndex = 0; charIndex<strlen(text); charIndex++) {
if ((text[charIndex] < 'a' || text[charIndex] > 'z') &&
(text[charIndex] < 'A' || text[charIndex] > 'Z') &&
(text[charIndex] < '0' || text[charIndex] > '9'))
return false;
}
return true;
}

193
old/string_util.h Normal file
View File

@ -0,0 +1,193 @@
/*
* Copyright 2013 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _STRINGUTIL_H_
#define _STRINGUTIL_H_
#include <sstream>
#include <string.h>
#include <vector>
#include <cstdarg>
#include <tuple>
#ifndef _WIN32
// this doesn't appear to affect linux-based systems..need feedback for _WIN64
#include <fmt/format.h>
#endif
#ifdef _WINDOWS
#include <ctype.h>
#include <functional>
#include <algorithm>
#endif
#include "types.h"
//std::string based
const std::string str_tolower(std::string s);
const std::string str_toupper(std::string s);
const std::string ucfirst(std::string s);
std::vector<std::string> split(std::string str_to_split, char delimiter);
const std::string StringFormat(const char* format, ...);
const std::string vStringFormat(const char* format, va_list args);
std::string implode(std::string glue, std::vector<std::string> src);
/**
* @param str
* @param chars
* @return
*/
inline std::string &ltrim(std::string &str, const std::string &chars = "\t\n\v\f\r ")
{
str.erase(0, str.find_first_not_of(chars));
return str;
}
/**
* @param str
* @param chars
* @return
*/
inline std::string &rtrim(std::string &str, const std::string &chars = "\t\n\v\f\r ")
{
str.erase(str.find_last_not_of(chars) + 1);
return str;
}
/**
* @param str
* @param chars
* @return
*/
inline std::string &trim(std::string &str, const std::string &chars = "\t\n\v\f\r ")
{
return ltrim(rtrim(str, chars), chars);
}
template <typename T>
std::string implode(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<T> &src)
{
if (src.empty()) {
return {};
}
std::ostringstream oss;
for (const T &src_iter : src) {
oss << encapsulation.first << src_iter << encapsulation.second << glue;
}
std::string output(oss.str());
output.resize(output.size() - glue.size());
return output;
}
// _WIN32 builds require that #include<fmt/format.h> be included in whatever code file the invocation is made from (no header files)
template <typename T1, typename T2>
std::vector<std::string> join_pair(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<std::pair<T1, T2>> &src)
{
if (src.empty()) {
return {};
}
std::vector<std::string> output;
for (const std::pair<T1, T2> &src_iter : src) {
output.push_back(
fmt::format(
"{}{}{}{}{}{}{}",
encapsulation.first,
src_iter.first,
encapsulation.second,
glue,
encapsulation.first,
src_iter.second,
encapsulation.second
)
);
}
return output;
}
// _WIN32 builds require that #include<fmt/format.h> be included in whatever code file the invocation is made from (no header files)
template <typename T1, typename T2, typename T3, typename T4>
std::vector<std::string> join_tuple(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<std::tuple<T1, T2, T3, T4>> &src)
{
if (src.empty()) {
return {};
}
std::vector<std::string> output;
for (const std::tuple<T1, T2, T3, T4> &src_iter : src) {
output.push_back(
fmt::format(
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
encapsulation.first,
std::get<0>(src_iter),
encapsulation.second,
glue,
encapsulation.first,
std::get<1>(src_iter),
encapsulation.second,
glue,
encapsulation.first,
std::get<2>(src_iter),
encapsulation.second,
glue,
encapsulation.first,
std::get<3>(src_iter),
encapsulation.second
)
);
}
return output;
}
std::vector<std::string> SplitString(const std::string &s, char delim);
std::string EscapeString(const char *src, size_t sz);
std::string EscapeString(const std::string &s);
bool StringIsNumber(const std::string &s);
void ToLowerString(std::string &s);
void ToUpperString(std::string &s);
std::string JoinString(const std::vector<std::string>& ar, const std::string &delim);
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string);
void ParseAccountString(const std::string &s, std::string &account, std::string &loginserver);
//const char based
bool atobool(const char* iBool);
bool isAlphaNumeric(const char *text);
bool strn0cpyt(char* dest, const char* source, uint32 size);
char *CleanMobName(const char *in, char *out);
char *RemoveApostrophes(const char *s);
char* strn0cpy(char* dest, const char* source, uint32 size);
const char *ConvertArray(int input, char *returnchar);
const char *ConvertArrayF(float input, char *returnchar);
const char *MakeLowerString(const char *source);
int MakeAnyLenString(char** ret, const char* format, ...);
uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...);
uint32 hextoi(const char* num);
uint64 hextoi64(const char* num);
void MakeLowerString(const char *source, char *target);
void RemoveApostrophes(std::string &s);
#endif

207
old/timer.cpp Normal file
View File

@ -0,0 +1,207 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../common/debug.h"
// Disgrace: for windows compile
#ifndef WIN32
#include <sys/time.h>
#else
#include <sys/timeb.h>
#endif
#include <iostream>
using namespace std;
#include "timer.h"
int32 started_unix_timestamp = 0;
int32 current_time = 0;
int32 last_time = 0;
Timer::Timer(){
timer_time = 30000; //default to 30 seconds
start_time = current_time;
set_at_trigger = timer_time;
pUseAcurateTiming = false;
enabled = false;
}
Timer::Timer(int32 in_timer_time, bool iUseAcurateTiming) {
timer_time = in_timer_time;
start_time = current_time;
set_at_trigger = timer_time;
pUseAcurateTiming = iUseAcurateTiming;
if (timer_time == 0) {
enabled = false;
}
else {
enabled = true;
}
}
Timer::Timer(int32 start, int32 timer, bool iUseAcurateTiming = false) {
timer_time = timer;
start_time = start;
set_at_trigger = timer_time;
pUseAcurateTiming = iUseAcurateTiming;
if (timer_time == 0) {
enabled = false;
}
else {
enabled = true;
}
}
/* Reimplemented for MSVC - Bounce */
#ifdef WIN32
int gettimeofday (timeval *tp, ...)
{
timeb tb;
ftime (&tb);
tp->tv_sec = tb.time;
tp->tv_usec = tb.millitm * 1000;
return 0;
}
#endif
/* This function checks if the timer triggered */
bool Timer::Check(bool iReset)
{
if (enabled && current_time-start_time > timer_time) {
if (iReset) {
if (pUseAcurateTiming)
start_time += timer_time;
else
start_time = current_time; // Reset timer
timer_time = set_at_trigger;
}
return true;
}
return false;
}
/* This function disables the timer */
void Timer::Disable() {
enabled = false;
}
void Timer::Enable() {
enabled = true;
}
/* This function set the timer and restart it */
void Timer::Start(int32 set_timer_time, bool ChangeResetTimer) {
start_time = current_time;
enabled = true;
if (set_timer_time != 0)
{
timer_time = set_timer_time;
if (ChangeResetTimer)
set_at_trigger = set_timer_time;
}
}
/* This timer updates the timer without restarting it */
void Timer::SetTimer(int32 set_timer_time) {
/* If we were disabled before => restart the timer */
if (!enabled) {
start_time = current_time;
enabled = true;
}
if (set_timer_time != 0) {
timer_time = set_timer_time;
set_at_trigger = set_timer_time;
}
}
int32 Timer::GetElapsedTime(){
if (enabled) {
return current_time - start_time;
}
else {
return 0xFFFFFFFF;
}
}
int32 Timer::GetRemainingTime() {
if (enabled) {
if (current_time-start_time > timer_time)
return 0;
else
return (start_time + timer_time) - current_time;
}
else {
return 0xFFFFFFFF;
}
}
void Timer::SetAtTrigger(int32 in_set_at_trigger, bool iEnableIfDisabled) {
set_at_trigger = in_set_at_trigger;
if (!Enabled() && iEnableIfDisabled) {
Enable();
}
}
void Timer::Trigger()
{
enabled = true;
timer_time = set_at_trigger;
start_time = current_time-timer_time-1;
}
const int32& Timer::GetCurrentTime2()
{
return current_time;
}
const int32& Timer::SetCurrentTime()
{
struct timeval read_time;
int32 this_time;
gettimeofday(&read_time,0);
if(started_unix_timestamp == 0)
started_unix_timestamp = read_time.tv_sec;
this_time = (read_time.tv_sec - started_unix_timestamp) * 1000 + read_time.tv_usec / 1000;
if (last_time == 0)
{
current_time = 0;
}
else
{
current_time += this_time - last_time;
}
last_time = this_time;
// cerr << "Current time:" << current_time << endl;
return current_time;
}
int32 Timer::GetUnixTimeStamp(){
struct timeval read_time;
gettimeofday(&read_time,0);
return read_time.tv_sec;
}

88
old/timer.h Normal file
View File

@ -0,0 +1,88 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TIMER_H
#define TIMER_H
#include "types.h"
#include <chrono>
// Disgrace: for windows compile
#ifdef WIN32
#include <WinSock2.h>
#include <windows.h>
int gettimeofday (timeval *tp, ...);
#endif
class Timer
{
public:
Timer();
Timer(int32 timer_time, bool iUseAcurateTiming = false);
Timer(int32 start, int32 timer, bool iUseAcurateTiming);
~Timer() { }
bool Check(bool iReset = true);
void Enable();
void Disable();
void Start(int32 set_timer_time=0, bool ChangeResetTimer = true);
void SetTimer(int32 set_timer_time=0);
int32 GetRemainingTime();
int32 GetElapsedTime();
inline const int32& GetTimerTime() { return timer_time; }
inline const int32& GetSetAtTrigger() { return set_at_trigger; }
void Trigger();
void SetAtTrigger(int32 set_at_trigger, bool iEnableIfDisabled = false);
inline bool Enabled() { return enabled; }
inline int32 GetStartTime() { return(start_time); }
inline int32 GetDuration() { return(timer_time); }
static const int32& SetCurrentTime();
static const int32& GetCurrentTime2();
static int32 GetUnixTimeStamp();
private:
int32 start_time;
int32 timer_time;
bool enabled;
int32 set_at_trigger;
// Tells the timer to be more acurate about happening every X ms.
// Instead of Check() setting the start_time = now,
// it it sets it to start_time += timer_time
bool pUseAcurateTiming;
// static int32 current_time;
// static int32 last_time;
};
struct BenchTimer
{
typedef std::chrono::high_resolution_clock clock;
BenchTimer() : start_time(clock::now()) {}
void reset() { start_time = clock::now(); }
// this is seconds
double elapsed() { return std::chrono::duration<double>(clock::now() - start_time).count(); }
private:
std::chrono::time_point<std::chrono::high_resolution_clock> start_time;
};
#endif

191
old/types.h Normal file
View File

@ -0,0 +1,191 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TYPES_H
#define TYPES_H
#include <string>
using namespace std;
//atoi is not int32 or uint32 safe!!!!
#define atoul(str) strtoul(str, NULL, 10)
#ifdef WIN32
#define atoi64(str) _atoi64(str)
#else
#define atoi64(str) strtoll(str, NULL, 10)
#endif
typedef unsigned char int8;
typedef unsigned short int16;
typedef unsigned int int32;
typedef unsigned char uint8;
typedef signed char sint8;
typedef unsigned short uint16;
typedef signed short sint16;
typedef unsigned int uint32;
typedef signed int sint32;
#ifdef WIN32
#if defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64
typedef unsigned __int64 int64;
typedef unsigned __int64 uint64;
typedef signed __int64 sint64;
#else
#error __int64 not supported
#endif
#else
typedef unsigned long long int64;
typedef unsigned long long uint64;
typedef signed long long sint64;
//typedef __u64 int64;
//typedef __u64 uint64;
//typedef __s64 sint64;
#endif
typedef unsigned long ulong;
typedef unsigned short ushort;
typedef unsigned char uchar;
#ifdef WIN32
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define strncasecmp _strnicmp
#define strcasecmp _stricmp
typedef void ThreadReturnType;
// #define THREAD_RETURN(x) return;
#define THREAD_RETURN(x) _endthread(); return;
#else
typedef void* ThreadReturnType;
typedef int SOCKET;
#define THREAD_RETURN(x) return(x);
#endif
#define safe_delete(d) if(d) { delete d; d=0; }
#define safe_delete_array(d) if(d) { delete[] d; d=0; }
#define L32(i) ((int32) i)
#define H32(i) ((int32) (i >> 32))
#define L16(i) ((int16) i)
#ifndef WIN32
// More WIN32 compatability
typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef char CHAR;
typedef unsigned short WORD;
typedef float FLOAT;
typedef FLOAT *PFLOAT;
typedef BYTE *PBYTE,*LPBYTE;
typedef int *PINT,*LPINT;
typedef WORD *PWORD,*LPWORD;
typedef long *LPLONG, LONG;
typedef DWORD *PDWORD,*LPDWORD;
typedef int INT;
typedef unsigned int UINT,*PUINT,*LPUINT;
#endif
#ifdef WIN32
#define DLLFUNC extern "C" __declspec(dllexport)
#else
#define DLLFUNC extern "C"
#endif
#pragma pack(1)
struct uint16_breakdown {
union {
uint16 all;
struct {
uint8 b1;
uint8 b2;
} bytes;
};
inline uint16& operator=(const uint16& val) { return (all=val); }
inline uint16* operator&() { return &all; }
inline operator uint16&() { return all; }
inline uint8& b1() { return bytes.b1; }
inline uint8& b2() { return bytes.b2; }
};
struct uint32_breakdown {
union {
uint32 all;
struct {
uint16 w1;
uint16 w2;
} words;
struct {
uint8 b1;
union {
struct {
uint8 b2;
uint8 b3;
} middle;
uint16 w2_3; // word bytes 2 to 3
};
uint8 b4;
} bytes;
};
inline uint32& operator=(const uint32& val) { return (all=val); }
inline uint32* operator&() { return &all; }
inline operator uint32&() { return all; }
inline uint16& w1() { return words.w1; }
inline uint16& w2() { return words.w2; }
inline uint16& w2_3() { return bytes.w2_3; }
inline uint8& b1() { return bytes.b1; }
inline uint8& b2() { return bytes.middle.b2; }
inline uint8& b3() { return bytes.middle.b3; }
inline uint8& b4() { return bytes.b4; }
};
struct EQ2_32BitString{
int32 size;
string data;
};
struct EQ2_16BitString{
int16 size;
string data;
};
struct EQ2_8BitString{
int8 size;
string data;
};
struct EQ2_Color{
int8 red;
int8 green;
int8 blue;
};
struct WorldTime{
int16 year;
int month;
int day;
int hour;
int minute;
};
typedef enum QUERY_TYPE{ Q_SELECT, Q_UPDATE, Q_REPLACE, Q_INSERT, Q_DELETE, Q_DBMS} QUERY_TYPE;
#pragma pack()
#endif

45
old/unix.cpp Normal file
View File

@ -0,0 +1,45 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "unix.h"
#include <string.h>
#include <ctype.h>
void Sleep(unsigned int x) {
if (x > 0)
usleep(x*1000);
}
char* strupr(char* tmp) {
int l = strlen(tmp);
for (int x = 0; x < l; x++) {
tmp[x] = toupper(tmp[x]);
}
return tmp;
}
char* strlwr(char* tmp) {
int l = strlen(tmp);
for (int x = 0; x < l; x++) {
tmp[x] = tolower(tmp[x]);
}
return tmp;
}

34
old/unix.h Normal file
View File

@ -0,0 +1,34 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WIN32
#ifndef __UNIX_H__
#define __UNIX_H__
#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER}
#endif
#include <unistd.h>
typedef int SOCKET;
void Sleep(unsigned int x);
char* strupr(char* tmp);
char* strlwr(char* tmp);
#endif
#endif

56
old/version.h Normal file
View File

@ -0,0 +1,56 @@
/*
EQ2Emulator: Everquest II Server Emulator
Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
This file is part of EQ2Emulator.
EQ2Emulator 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 3 of the License, or
(at your option) any later version.
EQ2Emulator 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 EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LogTypes.h"
#ifndef VERSION_H
#define VERSION_H
#define CURRENT_DATABASE_MINORVERSION 43
#define CURRENT_DATABASE_MAJORVERSION 730
#if defined(LOGIN)
#define EQ2EMU_MODULE "EQ2EMu LoginServer"
#elif defined(PATCHER)
#define EQ2EMU_MODULE "EQ2EMu PatchServer"
#elif defined(CHAT)
#define EQ2EMU_MODULE "EQ2EMu ChatServer"
#elif defined(ZONE)
#define EQ2EMU_MODULE "EQ2EMu ZoneServer"
#else
#define EQ2EMU_MODULE "EQ2EMu WorldServer"
#endif
#if defined(LOGIN)
#define CURRENT_VERSION "0.9.9-Nebula"
#elif defined(WORLD)
#define CURRENT_VERSION "0.9.9-Nebula"
#else
#define CURRENT_VERSION "0.9.9-Nebula"
#endif
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
#ifndef WIN32
#define LAST_MODIFIED __TIME__
#else
#define LAST_MODIFIED __TIMESTAMP__
#endif
#endif

2974
old/xmlParser.cpp Normal file

File diff suppressed because it is too large Load Diff

732
old/xmlParser.h Normal file
View File

@ -0,0 +1,732 @@
/****************************************************************************/
/*! \mainpage XMLParser library
* \section intro_sec Introduction
*
* This is a basic XML parser written in ANSI C++ for portability.
* It works by using recursion and a node tree for breaking
* down the elements of an XML document.
*
* @version V2.44
* @author Frank Vanden Berghen
*
* Copyright (c) 2002, Frank Vanden Berghen - All rights reserved.<br/>
* Commercialized by <a href="http://www.Business-Insight.com">Business-Insight</a><br/>
* See the file <a href="../../AFPL-license.txt">AFPL-license.txt</a> about the licensing terms
*
* \section tutorial First Tutorial
* You can follow a simple <a href="../../xmlParser.html">Tutorial</a> to know the basics...
*
* \section usage General usage: How to include the XMLParser library inside your project.
*
* The library is composed of two files: <a href="../../xmlParser.cpp">xmlParser.cpp</a> and
* <a href="../../xmlParser.h">xmlParser.h</a>. These are the ONLY 2 files that you need when
* using the library inside your own projects.
*
* All the functions of the library are documented inside the comments of the file
* <a href="../../xmlParser.h">xmlParser.h</a>. These comments can be transformed in
* full-fledged HTML documentation using the DOXYGEN software: simply type: "doxygen doxy.cfg"
*
* By default, the XMLParser library uses (char*) for string representation.To use the (wchar_t*)
* version of the library, you need to define the "_UNICODE" preprocessor definition variable
* (this is usually done inside your project definition file) (This is done automatically for you
* when using Visual Studio).
*
* \section example Advanced Tutorial and Many Examples of usage.
*
* Some very small introductory examples are described inside the Tutorial file
* <a href="../../xmlParser.html">xmlParser.html</a>
*
* Some additional small examples are also inside the file <a href="../../xmlTest.cpp">xmlTest.cpp</a>
* (for the "char*" version of the library) and inside the file
* <a href="../../xmlTestUnicode.cpp">xmlTestUnicode.cpp</a> (for the "wchar_t*"
* version of the library). If you have a question, please review these additionnal examples
* before sending an e-mail to the author.
*
* To build the examples:
* - linux/unix: type "make"
* - solaris: type "make -f makefile.solaris"
* - windows: Visual Studio: double-click on xmlParser.dsw
* (under Visual Studio .NET, the .dsp and .dsw files will be automatically converted to .vcproj and .sln files)
*
* In order to build the examples you need some additional files:
* - linux/unix: makefile
* - solaris: makefile.solaris
* - windows: Visual Studio: *.dsp, xmlParser.dsw and also xmlParser.lib and xmlParser.dll
*
* \section debugging Debugging with the XMLParser library
*
* \subsection debugwin Debugging under WINDOWS
*
* Inside Visual C++, the "debug versions" of the memory allocation functions are
* very slow: Do not forget to compile in "release mode" to get maximum speed.
* When I had to debug a software that was using the XMLParser Library, it was usually
* a nightmare because the library was sooOOOoooo slow in debug mode (because of the
* slow memory allocations in Debug mode). To solve this
* problem, during all the debugging session, I am now using a very fast DLL version of the
* XMLParser Library (the DLL is compiled in release mode). Using the DLL version of
* the XMLParser Library allows me to have lightening XML parsing speed even in debug!
* Other than that, the DLL version is useless: In the release version of my tool,
* I always use the normal, ".cpp"-based, XMLParser Library (I simply include the
* <a href="../../xmlParser.cpp">xmlParser.cpp</a> and
* <a href="../../xmlParser.h">xmlParser.h</a> files into the project).
*
* The file <a href="../../XMLNodeAutoexp.txt">XMLNodeAutoexp.txt</a> contains some
* "tweaks" that improve substancially the display of the content of the XMLNode objects
* inside the Visual Studio Debugger. Believe me, once you have seen inside the debugger
* the "smooth" display of the XMLNode objects, you cannot live without it anymore!
*
* \subsection debuglinux Debugging under LINUX/UNIX
*
* The speed of the debug version of the XMLParser library is tolerable so no extra
* work.has been done.
*
****************************************************************************/
#ifndef __INCLUDE_XML_NODE__
#define __INCLUDE_XML_NODE__
#include <stdlib.h>
#if defined(UNICODE) || defined(_UNICODE)
// If you comment the next "define" line then the library will never "switch to" _UNICODE (wchar_t*) mode (16/32 bits per characters).
// This is useful when you get error messages like:
// 'XMLNode::openFileHelper' : cannot convert parameter 2 from 'const char [5]' to 'const wchar_t *'
// The _XMLWIDECHAR preprocessor variable force the XMLParser library into either utf16/32-mode (the proprocessor variable
// must be defined) or utf8-mode(the pre-processor variable must be undefined).
#define _XMLWIDECHAR
#endif
#if defined(WIN32) || defined(UNDER_CE) || defined(_WIN32) || defined(WIN64) || defined(__BORLANDC__)
// comment the next line if you are under windows and the compiler is not Microsoft Visual Studio (6.0 or .NET) or Borland
#define _XMLWINDOWS
#endif
#ifdef XMLDLLENTRY
#undef XMLDLLENTRY
#endif
#ifdef _USE_XMLPARSER_DLL
#ifdef _DLL_EXPORTS_
#define XMLDLLENTRY __declspec(dllexport)
#else
#define XMLDLLENTRY __declspec(dllimport)
#endif
#else
#define XMLDLLENTRY
#endif
// uncomment the next line if you want no support for wchar_t* (no need for the <wchar.h> or <tchar.h> libraries anymore to compile)
//#define XML_NO_WIDE_CHAR
#ifdef XML_NO_WIDE_CHAR
#undef _XMLWINDOWS
#undef _XMLWIDECHAR
#endif
#ifdef _XMLWINDOWS
#include <tchar.h>
#else
#define XMLDLLENTRY
#ifndef XML_NO_WIDE_CHAR
#include <wchar.h> // to have 'wcsrtombs' for ANSI version
// to have 'mbsrtowcs' for WIDECHAR version
#endif
#endif
// Some common types for char set portable code
#ifdef _XMLWIDECHAR
#define _CXML(c) L ## c
#define XMLCSTR const wchar_t *
#define XMLSTR wchar_t *
#define XMLCHAR wchar_t
#else
#define _CXML(c) c
#define XMLCSTR const char *
#define XMLSTR char *
#define XMLCHAR char
#endif
#ifndef FALSE
#define FALSE 0
#endif /* FALSE */
#ifndef TRUE
#define TRUE 1
#endif /* TRUE */
/// Enumeration for XML parse errors.
typedef enum XMLError
{
eXMLErrorNone = 0,
eXMLErrorMissingEndTag,
eXMLErrorNoXMLTagFound,
eXMLErrorEmpty,
eXMLErrorMissingTagName,
eXMLErrorMissingEndTagName,
eXMLErrorUnmatchedEndTag,
eXMLErrorUnmatchedEndClearTag,
eXMLErrorUnexpectedToken,
eXMLErrorNoElements,
eXMLErrorFileNotFound,
eXMLErrorFirstTagNotFound,
eXMLErrorUnknownCharacterEntity,
eXMLErrorCharacterCodeAbove255,
eXMLErrorCharConversionError,
eXMLErrorCannotOpenWriteFile,
eXMLErrorCannotWriteFile,
eXMLErrorBase64DataSizeIsNotMultipleOf4,
eXMLErrorBase64DecodeIllegalCharacter,
eXMLErrorBase64DecodeTruncatedData,
eXMLErrorBase64DecodeBufferTooSmall
} XMLError;
/// Enumeration used to manage type of data. Use in conjunction with structure XMLNodeContents
typedef enum XMLElementType
{
eNodeChild=0,
eNodeAttribute=1,
eNodeText=2,
eNodeClear=3,
eNodeNULL=4
} XMLElementType;
/// Structure used to obtain error details if the parse fails.
typedef struct XMLResults
{
enum XMLError error;
int nLine,nColumn;
} XMLResults;
/// Structure for XML clear (unformatted) node (usually comments)
typedef struct XMLClear {
XMLCSTR lpszValue; XMLCSTR lpszOpenTag; XMLCSTR lpszCloseTag;
} XMLClear;
/// Structure for XML attribute.
typedef struct XMLAttribute {
XMLCSTR lpszName; XMLCSTR lpszValue;
} XMLAttribute;
/// XMLElementPosition are not interchangeable with simple indexes
typedef int XMLElementPosition;
struct XMLNodeContents;
/** @defgroup XMLParserGeneral The XML parser */
/// Main Class representing a XML node
/**
* All operations are performed using this class.
* \note The constructors of the XMLNode class are protected, so use instead one of these four methods to get your first instance of XMLNode:
* <ul>
* <li> XMLNode::parseString </li>
* <li> XMLNode::parseFile </li>
* <li> XMLNode::openFileHelper </li>
* <li> XMLNode::createXMLTopNode (or XMLNode::createXMLTopNode_WOSD)</li>
* </ul> */
typedef struct XMLDLLENTRY XMLNode
{
private:
struct XMLNodeDataTag;
/// Constructors are protected, so use instead one of: XMLNode::parseString, XMLNode::parseFile, XMLNode::openFileHelper, XMLNode::createXMLTopNode
XMLNode(struct XMLNodeDataTag *pParent, XMLSTR lpszName, char isDeclaration);
/// Constructors are protected, so use instead one of: XMLNode::parseString, XMLNode::parseFile, XMLNode::openFileHelper, XMLNode::createXMLTopNode
XMLNode(struct XMLNodeDataTag *p);
public:
static XMLCSTR getVersion();///< Return the XMLParser library version number
/** @defgroup conversions Parsing XML files/strings to an XMLNode structure and Rendering XMLNode's to files/string.
* @ingroup XMLParserGeneral
* @{ */
/// Parse an XML string and return the root of a XMLNode tree representing the string.
static XMLNode parseString (XMLCSTR lpXMLString, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
/**< The "parseString" function parse an XML string and return the root of a XMLNode tree. The "opposite" of this function is
* the function "createXMLString" that re-creates an XML string from an XMLNode tree. If the XML document is corrupted, the
* "parseString" method will initialize the "pResults" variable with some information that can be used to trace the error.
* If you still want to parse the file, you can use the APPROXIMATE_PARSING option as explained inside the note at the
* beginning of the "xmlParser.cpp" file.
*
* @param lpXMLString the XML string to parse
* @param tag the name of the first tag inside the XML file. If the tag parameter is omitted, this function returns a node that represents the head of the xml document including the declaration term (<? ... ?>).
* @param pResults a pointer to a XMLResults variable that will contain some information that can be used to trace the XML parsing error. You can have a user-friendly explanation of the parsing error with the "getError" function.
*/
/// Parse an XML file and return the root of a XMLNode tree representing the file.
static XMLNode parseFile (XMLCSTR filename, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
/**< The "parseFile" function parse an XML file and return the root of a XMLNode tree. The "opposite" of this function is
* the function "writeToFile" that re-creates an XML file from an XMLNode tree. If the XML document is corrupted, the
* "parseFile" method will initialize the "pResults" variable with some information that can be used to trace the error.
* If you still want to parse the file, you can use the APPROXIMATE_PARSING option as explained inside the note at the
* beginning of the "xmlParser.cpp" file.
*
* @param filename the path to the XML file to parse
* @param tag the name of the first tag inside the XML file. If the tag parameter is omitted, this function returns a node that represents the head of the xml document including the declaration term (<? ... ?>).
* @param pResults a pointer to a XMLResults variable that will contain some information that can be used to trace the XML parsing error. You can have a user-friendly explanation of the parsing error with the "getError" function.
*/
/// Parse an XML file and return the root of a XMLNode tree representing the file. A very crude error checking is made. An attempt to guess the Char Encoding used in the file is made.
static XMLNode openFileHelper(XMLCSTR filename, XMLCSTR tag=NULL);
/**< The "openFileHelper" function reports to the screen all the warnings and errors that occurred during parsing of the XML file.
* This function also tries to guess char Encoding (UTF-8, ASCII or SHIT-JIS) based on the first 200 bytes of the file. Since each
* application has its own way to report and deal with errors, you should rather use the "parseFile" function to parse XML files
* and program yourself thereafter an "error reporting" tailored for your needs (instead of using the very crude "error reporting"
* mechanism included inside the "openFileHelper" function).
*
* If the XML document is corrupted, the "openFileHelper" method will:
* - display an error message on the console (or inside a messageBox for windows).
* - stop execution (exit).
*
* I strongly suggest that you write your own "openFileHelper" method tailored to your needs. If you still want to parse
* the file, you can use the APPROXIMATE_PARSING option as explained inside the note at the beginning of the "xmlParser.cpp" file.
*
* @param filename the path of the XML file to parse.
* @param tag the name of the first tag inside the XML file. If the tag parameter is omitted, this function returns a node that represents the head of the xml document including the declaration term (<? ... ?>).
*/
static XMLCSTR getError(XMLError error); ///< this gives you a user-friendly explanation of the parsing error
/// Create an XML string starting from the current XMLNode.
XMLSTR createXMLString(int nFormat=1, int *pnSize=NULL) const;
/**< The returned string should be free'd using the "freeXMLString" function.
*
* If nFormat==0, no formatting is required otherwise this returns an user friendly XML string from a given element
* with appropriate white spaces and carriage returns. if pnSize is given it returns the size in character of the string. */
/// Save the content of an xmlNode inside a file
XMLError writeToFile(XMLCSTR filename,
const char *encoding=NULL,
char nFormat=1) const;
/**< If nFormat==0, no formatting is required otherwise this returns an user friendly XML string from a given element with appropriate white spaces and carriage returns.
* If the global parameter "characterEncoding==encoding_UTF8", then the "encoding" parameter is ignored and always set to "utf-8".
* If the global parameter "characterEncoding==encoding_ShiftJIS", then the "encoding" parameter is ignored and always set to "SHIFT-JIS".
* If "_XMLWIDECHAR=1", then the "encoding" parameter is ignored and always set to "utf-16".
* If no "encoding" parameter is given the "ISO-8859-1" encoding is used. */
/** @} */
/** @defgroup navigate Navigate the XMLNode structure
* @ingroup XMLParserGeneral
* @{ */
XMLCSTR getName() const; ///< name of the node
XMLCSTR getText(int i=0) const; ///< return ith text field
int nText() const; ///< nbr of text field
XMLNode getParentNode() const; ///< return the parent node
XMLNode getChildNode(int i=0) const; ///< return ith child node
XMLNode getChildNode(XMLCSTR name, int i) const; ///< return ith child node with specific name (return an empty node if failing). If i==-1, this returns the last XMLNode with the given name.
XMLNode getChildNode(XMLCSTR name, int *i=NULL) const; ///< return next child node with specific name (return an empty node if failing)
XMLNode getChildNodeWithAttribute(XMLCSTR tagName,
XMLCSTR attributeName,
XMLCSTR attributeValue=NULL,
int *i=NULL) const; ///< return child node with specific name/attribute (return an empty node if failing)
XMLNode getChildNodeByPath(XMLCSTR path, char createNodeIfMissing=0, XMLCHAR sep='/');
///< return the first child node with specific path
XMLNode getChildNodeByPathNonConst(XMLSTR path, char createNodeIfMissing=0, XMLCHAR sep='/');
///< return the first child node with specific path.
int nChildNode(XMLCSTR name) const; ///< return the number of child node with specific name
int nChildNode() const; ///< nbr of child node
XMLAttribute getAttribute(int i=0) const; ///< return ith attribute
XMLCSTR getAttributeName(int i=0) const; ///< return ith attribute name
XMLCSTR getAttributeValue(int i=0) const; ///< return ith attribute value
char isAttributeSet(XMLCSTR name) const; ///< test if an attribute with a specific name is given
XMLCSTR getAttribute(XMLCSTR name, int i) const; ///< return ith attribute content with specific name (return a NULL if failing)
XMLCSTR getAttribute(XMLCSTR name, int *i=NULL) const; ///< return next attribute content with specific name (return a NULL if failing)
int nAttribute() const; ///< nbr of attribute
XMLClear getClear(int i=0) const; ///< return ith clear field (comments)
int nClear() const; ///< nbr of clear field
XMLNodeContents enumContents(XMLElementPosition i) const; ///< enumerate all the different contents (attribute,child,text, clear) of the current XMLNode. The order is reflecting the order of the original file/string. NOTE: 0 <= i < nElement();
int nElement() const; ///< nbr of different contents for current node
char isEmpty() const; ///< is this node Empty?
char isDeclaration() const; ///< is this node a declaration <? .... ?>
XMLNode deepCopy() const; ///< deep copy (duplicate/clone) a XMLNode
static XMLNode emptyNode(); ///< return XMLNode::emptyXMLNode;
/** @} */
~XMLNode();
XMLNode(const XMLNode &A); ///< to allow shallow/fast copy:
XMLNode& operator=( const XMLNode& A ); ///< to allow shallow/fast copy:
XMLNode(): d(NULL){};
static XMLNode emptyXMLNode;
static XMLClear emptyXMLClear;
static XMLAttribute emptyXMLAttribute;
/** @defgroup xmlModify Create or Update the XMLNode structure
* @ingroup XMLParserGeneral
* The functions in this group allows you to create from scratch (or update) a XMLNode structure. Start by creating your top
* node with the "createXMLTopNode" function and then add new nodes with the "addChild" function. The parameter 'pos' gives
* the position where the childNode, the text or the XMLClearTag will be inserted. The default value (pos=-1) inserts at the
* end. The value (pos=0) insert at the beginning (Insertion at the beginning is slower than at the end). <br>
*
* REMARK: 0 <= pos < nChild()+nText()+nClear() <br>
*/
/** @defgroup creation Creating from scratch a XMLNode structure
* @ingroup xmlModify
* @{ */
static XMLNode createXMLTopNode(XMLCSTR lpszName, char isDeclaration=FALSE); ///< Create the top node of an XMLNode structure
XMLNode addChild(XMLCSTR lpszName, char isDeclaration=FALSE, XMLElementPosition pos=-1); ///< Add a new child node
XMLNode addChild(XMLNode nodeToAdd, XMLElementPosition pos=-1); ///< If the "nodeToAdd" has some parents, it will be detached from it's parents before being attached to the current XMLNode
XMLAttribute *addAttribute(XMLCSTR lpszName, XMLCSTR lpszValuev); ///< Add a new attribute
XMLCSTR addText(XMLCSTR lpszValue, XMLElementPosition pos=-1); ///< Add a new text content
XMLClear *addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, XMLElementPosition pos=-1);
/**< Add a new clear tag
* @param lpszOpen default value "<![CDATA["
* @param lpszClose default value "]]>"
*/
/** @} */
/** @defgroup xmlUpdate Updating Nodes
* @ingroup xmlModify
* Some update functions:
* @{
*/
XMLCSTR updateName(XMLCSTR lpszName); ///< change node's name
XMLAttribute *updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute); ///< if the attribute to update is missing, a new one will be added
XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName=NULL,int i=0); ///< if the attribute to update is missing, a new one will be added
XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName);///< set lpszNewName=NULL if you don't want to change the name of the attribute if the attribute to update is missing, a new one will be added
XMLCSTR updateText(XMLCSTR lpszNewValue, int i=0); ///< if the text to update is missing, a new one will be added
XMLCSTR updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue); ///< if the text to update is missing, a new one will be added
XMLClear *updateClear(XMLCSTR lpszNewContent, int i=0); ///< if the clearTag to update is missing, a new one will be added
XMLClear *updateClear(XMLClear *newP,XMLClear *oldP); ///< if the clearTag to update is missing, a new one will be added
XMLClear *updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue); ///< if the clearTag to update is missing, a new one will be added
/** @} */
/** @defgroup xmlDelete Deleting Nodes or Attributes
* @ingroup xmlModify
* Some deletion functions:
* @{
*/
/// The "deleteNodeContent" function forces the deletion of the content of this XMLNode and the subtree.
void deleteNodeContent();
/**< \note The XMLNode instances that are referring to the part of the subtree that has been deleted CANNOT be used anymore!!. Unexpected results will occur if you continue using them. */
void deleteAttribute(int i=0); ///< Delete the ith attribute of the current XMLNode
void deleteAttribute(XMLCSTR lpszName); ///< Delete the attribute with the given name (the "strcmp" function is used to find the right attribute)
void deleteAttribute(XMLAttribute *anAttribute); ///< Delete the attribute with the name "anAttribute->lpszName" (the "strcmp" function is used to find the right attribute)
void deleteText(int i=0); ///< Delete the Ith text content of the current XMLNode
void deleteText(XMLCSTR lpszValue); ///< Delete the text content "lpszValue" inside the current XMLNode (direct "pointer-to-pointer" comparison is used to find the right text)
void deleteClear(int i=0); ///< Delete the Ith clear tag inside the current XMLNode
void deleteClear(XMLCSTR lpszValue); ///< Delete the clear tag "lpszValue" inside the current XMLNode (direct "pointer-to-pointer" comparison is used to find the clear tag)
void deleteClear(XMLClear *p); ///< Delete the clear tag "p" inside the current XMLNode (direct "pointer-to-pointer" comparison on the lpszName of the clear tag is used to find the clear tag)
/** @} */
/** @defgroup xmlWOSD ???_WOSD functions.
* @ingroup xmlModify
* The strings given as parameters for the "add" and "update" methods that have a name with
* the postfix "_WOSD" (that means "WithOut String Duplication")(for example "addText_WOSD")
* will be free'd by the XMLNode class. For example, it means that this is incorrect:
* \code
* xNode.addText_WOSD("foo");
* xNode.updateAttribute_WOSD("#newcolor" ,NULL,"color");
* \endcode
* In opposition, this is correct:
* \code
* xNode.addText("foo");
* xNode.addText_WOSD(stringDup("foo"));
* xNode.updateAttribute("#newcolor" ,NULL,"color");
* xNode.updateAttribute_WOSD(stringDup("#newcolor"),NULL,"color");
* \endcode
* Typically, you will never do:
* \code
* char *b=(char*)malloc(...);
* xNode.addText(b);
* free(b);
* \endcode
* ... but rather:
* \code
* char *b=(char*)malloc(...);
* xNode.addText_WOSD(b);
* \endcode
* ('free(b)' is performed by the XMLNode class)
* @{ */
static XMLNode createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration=FALSE); ///< Create the top node of an XMLNode structure
XMLNode addChild_WOSD(XMLSTR lpszName, char isDeclaration=FALSE, XMLElementPosition pos=-1); ///< Add a new child node
XMLAttribute *addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValue); ///< Add a new attribute
XMLCSTR addText_WOSD(XMLSTR lpszValue, XMLElementPosition pos=-1); ///< Add a new text content
XMLClear *addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, XMLElementPosition pos=-1); ///< Add a new clear Tag
XMLCSTR updateName_WOSD(XMLSTR lpszName); ///< change node's name
XMLAttribute *updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute); ///< if the attribute to update is missing, a new one will be added
XMLAttribute *updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName=NULL,int i=0); ///< if the attribute to update is missing, a new one will be added
XMLAttribute *updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,XMLCSTR lpszOldName); ///< set lpszNewName=NULL if you don't want to change the name of the attribute if the attribute to update is missing, a new one will be added
XMLCSTR updateText_WOSD(XMLSTR lpszNewValue, int i=0); ///< if the text to update is missing, a new one will be added
XMLCSTR updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue); ///< if the text to update is missing, a new one will be added
XMLClear *updateClear_WOSD(XMLSTR lpszNewContent, int i=0); ///< if the clearTag to update is missing, a new one will be added
XMLClear *updateClear_WOSD(XMLClear *newP,XMLClear *oldP); ///< if the clearTag to update is missing, a new one will be added
XMLClear *updateClear_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue); ///< if the clearTag to update is missing, a new one will be added
/** @} */
/** @defgroup xmlPosition Position helper functions (use in conjunction with the update&add functions
* @ingroup xmlModify
* These are some useful functions when you want to insert a childNode, a text or a XMLClearTag in the
* middle (at a specified position) of a XMLNode tree already constructed. The value returned by these
* methods is to be used as last parameter (parameter 'pos') of addChild, addText or addClear.
* @{ */
XMLElementPosition positionOfText(int i=0) const;
XMLElementPosition positionOfText(XMLCSTR lpszValue) const;
XMLElementPosition positionOfClear(int i=0) const;
XMLElementPosition positionOfClear(XMLCSTR lpszValue) const;
XMLElementPosition positionOfClear(XMLClear *a) const;
XMLElementPosition positionOfChildNode(int i=0) const;
XMLElementPosition positionOfChildNode(XMLNode x) const;
XMLElementPosition positionOfChildNode(XMLCSTR name, int i=0) const; ///< return the position of the ith childNode with the specified name if (name==NULL) return the position of the ith childNode
/** @} */
/// Enumeration for XML character encoding.
typedef enum XMLCharEncoding
{
char_encoding_error=0,
char_encoding_UTF8=1,
char_encoding_legacy=2,
char_encoding_ShiftJIS=3,
char_encoding_GB2312=4,
char_encoding_Big5=5,
char_encoding_GBK=6 // this is actually the same as Big5
} XMLCharEncoding;
/** \addtogroup conversions
* @{ */
/// Sets the global options for the conversions
static char setGlobalOptions(XMLCharEncoding characterEncoding=XMLNode::char_encoding_UTF8, char guessWideCharChars=1,
char dropWhiteSpace=1, char removeCommentsInMiddleOfText=1);
/**< The "setGlobalOptions" function allows you to change four global parameters that affect string & file
* parsing. First of all, you most-probably will never have to change these 3 global parameters.
*
* @param guessWideCharChars If "guessWideCharChars"=1 and if this library is compiled in WideChar mode, then the
* XMLNode::parseFile and XMLNode::openFileHelper functions will test if the file contains ASCII
* characters. If this is the case, then the file will be loaded and converted in memory to
* WideChar before being parsed. If 0, no conversion will be performed.
*
* @param guessWideCharChars If "guessWideCharChars"=1 and if this library is compiled in ASCII/UTF8/char* mode, then the
* XMLNode::parseFile and XMLNode::openFileHelper functions will test if the file contains WideChar
* characters. If this is the case, then the file will be loaded and converted in memory to
* ASCII/UTF8/char* before being parsed. If 0, no conversion will be performed.
*
* @param characterEncoding This parameter is only meaningful when compiling in char* mode (multibyte character mode).
* In wchar_t* (wide char mode), this parameter is ignored. This parameter should be one of the
* three currently recognized encodings: XMLNode::encoding_UTF8, XMLNode::encoding_ascii,
* XMLNode::encoding_ShiftJIS.
*
* @param dropWhiteSpace In most situations, text fields containing only white spaces (and carriage returns)
* are useless. Even more, these "empty" text fields are annoying because they increase the
* complexity of the user's code for parsing. So, 99% of the time, it's better to drop
* the "empty" text fields. However The XML specification indicates that no white spaces
* should be lost when parsing the file. So to be perfectly XML-compliant, you should set
* dropWhiteSpace=0. A note of caution: if you set "dropWhiteSpace=0", the parser will be
* slower and your code will be more complex.
*
* @param removeCommentsInMiddleOfText To explain this parameter, let's consider this code:
* \code
* XMLNode x=XMLNode::parseString("<a>foo<!-- hello -->bar<!DOCTYPE world >chu</a>","a");
* \endcode
* If removeCommentsInMiddleOfText=0, then we will have:
* \code
* x.getText(0) -> "foo"
* x.getText(1) -> "bar"
* x.getText(2) -> "chu"
* x.getClear(0) --> "<!-- hello -->"
* x.getClear(1) --> "<!DOCTYPE world >"
* \endcode
* If removeCommentsInMiddleOfText=1, then we will have:
* \code
* x.getText(0) -> "foobar"
* x.getText(1) -> "chu"
* x.getClear(0) --> "<!DOCTYPE world >"
* \endcode
*
* \return "0" when there are no errors. If you try to set an unrecognized encoding then the return value will be "1" to signal an error.
*
* \note Sometime, it's useful to set "guessWideCharChars=0" to disable any conversion
* because the test to detect the file-type (ASCII/UTF8/char* or WideChar) may fail (rarely). */
/// Guess the character encoding of the string (ascii, utf8 or shift-JIS)
static XMLCharEncoding guessCharEncoding(void *buffer, int bufLen, char useXMLEncodingAttribute=1);
/**< The "guessCharEncoding" function try to guess the character encoding. You most-probably will never
* have to use this function. It then returns the appropriate value of the global parameter
* "characterEncoding" described in the XMLNode::setGlobalOptions. The guess is based on the content of a buffer of length
* "bufLen" bytes that contains the first bytes (minimum 25 bytes; 200 bytes is a good value) of the
* file to be parsed. The XMLNode::openFileHelper function is using this function to automatically compute
* the value of the "characterEncoding" global parameter. There are several heuristics used to do the
* guess. One of the heuristic is based on the "encoding" attribute. The original XML specifications
* forbids to use this attribute to do the guess but you can still use it if you set
* "useXMLEncodingAttribute" to 1 (this is the default behavior and the behavior of most parsers).
* If an inconsistency in the encoding is detected, then the return value is "0". */
/** @} */
private:
// these are functions and structures used internally by the XMLNode class (don't bother about them):
typedef struct XMLNodeDataTag // to allow shallow copy and "intelligent/smart" pointers (automatic delete):
{
XMLCSTR lpszName; // Element name (=NULL if root)
int nChild, // Number of child nodes
nText, // Number of text fields
nClear, // Number of Clear fields (comments)
nAttribute; // Number of attributes
char isDeclaration; // Whether node is an XML declaration - '<?xml ?>'
struct XMLNodeDataTag *pParent; // Pointer to parent element (=NULL if root)
XMLNode *pChild; // Array of child nodes
XMLCSTR *pText; // Array of text fields
XMLClear *pClear; // Array of clear fields
XMLAttribute *pAttribute; // Array of attributes
int *pOrder; // order of the child_nodes,text_fields,clear_fields
int ref_count; // for garbage collection (smart pointers)
} XMLNodeData;
XMLNodeData *d;
char parseClearTag(void *px, void *pa);
char maybeAddTxT(void *pa, XMLCSTR tokenPStr);
int ParseXMLElement(void *pXML);
void *addToOrder(int memInc, int *_pos, int nc, void *p, int size, XMLElementType xtype);
int indexText(XMLCSTR lpszValue) const;
int indexClear(XMLCSTR lpszValue) const;
XMLNode addChild_priv(int,XMLSTR,char,int);
XMLAttribute *addAttribute_priv(int,XMLSTR,XMLSTR);
XMLCSTR addText_priv(int,XMLSTR,int);
XMLClear *addClear_priv(int,XMLSTR,XMLCSTR,XMLCSTR,int);
void emptyTheNode(char force);
static inline XMLElementPosition findPosition(XMLNodeData *d, int index, XMLElementType xtype);
static int CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat);
static int removeOrderElement(XMLNodeData *d, XMLElementType t, int index);
static void exactMemory(XMLNodeData *d);
static int detachFromParent(XMLNodeData *d);
} XMLNode;
/// This structure is given by the function XMLNode::enumContents.
typedef struct XMLNodeContents
{
/// This dictates what's the content of the XMLNodeContent
enum XMLElementType etype;
/**< should be an union to access the appropriate data. Compiler does not allow union of object with constructor... too bad. */
XMLNode child;
XMLAttribute attrib;
XMLCSTR text;
XMLClear clear;
} XMLNodeContents;
/** @defgroup StringAlloc String Allocation/Free functions
* @ingroup xmlModify
* @{ */
/// Duplicate (copy in a new allocated buffer) the source string.
XMLDLLENTRY XMLSTR stringDup(XMLCSTR source, int cbData=-1);
/**< This is
* a very handy function when used with all the "XMLNode::*_WOSD" functions (\link xmlWOSD \endlink).
* @param cbData If !=0 then cbData is the number of chars to duplicate. New strings allocated with
* this function should be free'd using the "freeXMLString" function. */
/// to free the string allocated inside the "stringDup" function or the "createXMLString" function.
XMLDLLENTRY void freeXMLString(XMLSTR t); // {free(t);}
/** @} */
/** @defgroup atoX ato? like functions
* @ingroup XMLParserGeneral
* The "xmlto?" functions are equivalents to the atoi, atol, atof functions.
* The only difference is: If the variable "xmlString" is NULL, than the return value
* is "defautValue". These 6 functions are only here as "convenience" functions for the
* user (they are not used inside the XMLparser). If you don't need them, you can
* delete them without any trouble.
*
* @{ */
XMLDLLENTRY char xmltob(XMLCSTR xmlString,char defautValue=0);
XMLDLLENTRY int xmltoi(XMLCSTR xmlString,int defautValue=0);
XMLDLLENTRY long long xmltol(XMLCSTR xmlString,long long defautValue=0);
XMLDLLENTRY double xmltof(XMLCSTR xmlString,double defautValue=.0);
XMLDLLENTRY XMLCSTR xmltoa(XMLCSTR xmlString,XMLCSTR defautValue=_CXML(""));
XMLDLLENTRY XMLCHAR xmltoc(XMLCSTR xmlString,const XMLCHAR defautValue=_CXML('\0'));
/** @} */
/** @defgroup ToXMLStringTool Helper class to create XML files using "printf", "fprintf", "cout",... functions.
* @ingroup XMLParserGeneral
* @{ */
/// Helper class to create XML files using "printf", "fprintf", "cout",... functions.
/** The ToXMLStringTool class helps you creating XML files using "printf", "fprintf", "cout",... functions.
* The "ToXMLStringTool" class is processing strings so that all the characters
* &,",',<,> are replaced by their XML equivalent:
* \verbatim &amp;, &quot;, &apos;, &lt;, &gt; \endverbatim
* Using the "ToXMLStringTool class" and the "fprintf function" is THE most efficient
* way to produce VERY large XML documents VERY fast.
* \note If you are creating from scratch an XML file using the provided XMLNode class
* you must not use the "ToXMLStringTool" class (because the "XMLNode" class does the
* processing job for you during rendering).*/
typedef struct XMLDLLENTRY ToXMLStringTool
{
public:
ToXMLStringTool(): buf(NULL),buflen(0){}
~ToXMLStringTool();
void freeBuffer();///<call this function when you have finished using this object to release memory used by the internal buffer.
XMLSTR toXML(XMLCSTR source);///< returns a pointer to an internal buffer that contains a XML-encoded string based on the "source" parameter.
/** The "toXMLUnSafe" function is deprecated because there is a possibility of
* "destination-buffer-overflow". It converts the string
* "source" to the string "dest". */
static XMLSTR toXMLUnSafe(XMLSTR dest,XMLCSTR source); ///< deprecated: use "toXML" instead
static int lengthXMLString(XMLCSTR source); ///< deprecated: use "toXML" instead
private:
XMLSTR buf;
int buflen;
} ToXMLStringTool;
/** @} */
/** @defgroup XMLParserBase64Tool Helper class to include binary data inside XML strings using "Base64 encoding".
* @ingroup XMLParserGeneral
* @{ */
/// Helper class to include binary data inside XML strings using "Base64 encoding".
/** The "XMLParserBase64Tool" class allows you to include any binary data (images, sounds,...)
* into an XML document using "Base64 encoding". This class is completely
* separated from the rest of the xmlParser library and can be removed without any problem.
* To include some binary data into an XML file, you must convert the binary data into
* standard text (using "encode"). To retrieve the original binary data from the
* b64-encoded text included inside the XML file, use "decode". Alternatively, these
* functions can also be used to "encrypt/decrypt" some critical data contained inside
* the XML (it's not a strong encryption at all, but sometimes it can be useful). */
typedef struct XMLDLLENTRY XMLParserBase64Tool
{
public:
XMLParserBase64Tool(): buf(NULL),buflen(0){}
~XMLParserBase64Tool();
void freeBuffer();///< Call this function when you have finished using this object to release memory used by the internal buffer.
/**
* @param formatted If "formatted"=true, some space will be reserved for a carriage-return every 72 chars. */
static int encodeLength(int inBufLen, char formatted=0); ///< return the length of the base64 string that encodes a data buffer of size inBufLen bytes.
/**
* The "base64Encode" function returns a string containing the base64 encoding of "inByteLen" bytes
* from "inByteBuf". If "formatted" parameter is true, then there will be a carriage-return every 72 chars.
* The string will be free'd when the XMLParserBase64Tool object is deleted.
* All returned strings are sharing the same memory space. */
XMLSTR encode(unsigned char *inByteBuf, unsigned int inByteLen, char formatted=0); ///< returns a pointer to an internal buffer containing the base64 string containing the binary data encoded from "inByteBuf"
/// returns the number of bytes which will be decoded from "inString".
static unsigned int decodeSize(XMLCSTR inString, XMLError *xe=NULL);
/**
* The "decode" function returns a pointer to a buffer containing the binary data decoded from "inString"
* The output buffer will be free'd when the XMLParserBase64Tool object is deleted.
* All output buffer are sharing the same memory space.
* @param inString If "instring" is malformed, NULL will be returned */
unsigned char* decode(XMLCSTR inString, int *outByteLen=NULL, XMLError *xe=NULL); ///< returns a pointer to an internal buffer containing the binary data decoded from "inString"
/**
* decodes data from "inString" to "outByteBuf". You need to provide the size (in byte) of "outByteBuf"
* in "inMaxByteOutBuflen". If "outByteBuf" is not large enough or if data is malformed, then "FALSE"
* will be returned; otherwise "TRUE". */
static unsigned char decode(XMLCSTR inString, unsigned char *outByteBuf, int inMaxByteOutBuflen, XMLError *xe=NULL); ///< deprecated.
private:
void *buf;
int buflen;
void alloc(int newsize);
}XMLParserBase64Tool;
/** @} */
#undef XMLDLLENTRY
#endif