mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-15 16:41:29 +00:00
[Loginserver] Worldserver Name Sanitization (#1739)
* Sanitize bad words in server names * Add config options and enforcement for dev/test servers and servers starting with a special character * Refine bad word logic * Add installer to dev/test servers * Change server prefixes * Special char prefix * Formatting * Remove multi words * Add server types enum * Add error constants * Remove sanitize from world level * Use strn0cpy
This commit is contained in:
parent
8b83a13560
commit
a9d1034298
@ -19,32 +19,33 @@
|
|||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#define strncasecmp _strnicmp
|
#define strncasecmp _strnicmp
|
||||||
#define strcasecmp _stricmp
|
#define strcasecmp _stricmp
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef va_copy
|
#ifndef va_copy
|
||||||
#define va_copy(d,s) ((d) = (s))
|
#define va_copy(d,s) ((d) = (s))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// original source:
|
// original source:
|
||||||
// https://github.com/facebook/folly/blob/master/folly/String.cpp
|
// https://github.com/facebook/folly/blob/master/folly/String.cpp
|
||||||
//
|
//
|
||||||
const std::string vStringFormat(const char* format, va_list args)
|
const std::string vStringFormat(const char *format, va_list args)
|
||||||
{
|
{
|
||||||
std::string output;
|
std::string output;
|
||||||
va_list tmpargs;
|
va_list tmpargs;
|
||||||
|
|
||||||
va_copy(tmpargs,args);
|
va_copy(tmpargs, args);
|
||||||
int characters_used = vsnprintf(nullptr, 0, format, tmpargs);
|
int characters_used = vsnprintf(nullptr, 0, format, tmpargs);
|
||||||
va_end(tmpargs);
|
va_end(tmpargs);
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ const std::string vStringFormat(const char* format, va_list args)
|
|||||||
if (characters_used > 0) {
|
if (characters_used > 0) {
|
||||||
output.resize(characters_used + 1);
|
output.resize(characters_used + 1);
|
||||||
|
|
||||||
va_copy(tmpargs,args);
|
va_copy(tmpargs, args);
|
||||||
characters_used = vsnprintf(&output[0], output.capacity(), format, tmpargs);
|
characters_used = vsnprintf(&output[0], output.capacity(), format, tmpargs);
|
||||||
va_end(tmpargs);
|
va_end(tmpargs);
|
||||||
|
|
||||||
@ -60,8 +61,9 @@ const std::string vStringFormat(const char* format, va_list args)
|
|||||||
|
|
||||||
// We shouldn't have a format error by this point, but I can't imagine what error we
|
// 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;
|
// could have by this point. Still, return empty string;
|
||||||
if (characters_used < 0)
|
if (characters_used < 0) {
|
||||||
output.clear();
|
output.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@ -87,8 +89,9 @@ const std::string str_toupper(std::string s)
|
|||||||
const std::string ucfirst(std::string s)
|
const std::string ucfirst(std::string s)
|
||||||
{
|
{
|
||||||
std::string output = s;
|
std::string output = s;
|
||||||
if (!s.empty())
|
if (!s.empty()) {
|
||||||
output[0] = static_cast<char>(::toupper(s[0]));
|
output[0] = static_cast<char>(::toupper(s[0]));
|
||||||
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@ -102,18 +105,20 @@ const std::string StringFormat(const char *format, ...)
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> SplitString(const std::string &str, const char delim) {
|
std::vector<std::string> SplitString(const std::string &str, const char delim)
|
||||||
|
{
|
||||||
std::vector<std::string> ret;
|
std::vector<std::string> ret;
|
||||||
std::string::size_type start = 0;
|
std::string::size_type start = 0;
|
||||||
auto end = str.find(delim);
|
auto end = str.find(delim);
|
||||||
while (end != std::string::npos) {
|
while (end != std::string::npos) {
|
||||||
ret.emplace_back(str, start, end - start);
|
ret.emplace_back(str, start, end - start);
|
||||||
start = end + 1;
|
start = end + 1;
|
||||||
end = str.find(delim, start);
|
end = str.find(delim, start);
|
||||||
}
|
}
|
||||||
// this will catch the last word since the string is unlikely to end with a delimiter
|
// this will catch the last word since the string is unlikely to end with a delimiter
|
||||||
if (str.length() > start)
|
if (str.length() > start) {
|
||||||
ret.emplace_back(str, start, str.length() - start);
|
ret.emplace_back(str, start, str.length() - start);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,14 +158,16 @@ std::string get_between(const std::string &s, std::string start_delim, std::stri
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string::size_type search_deliminated_string(const std::string &haystack, const std::string &needle, const char deliminator)
|
std::string::size_type
|
||||||
|
search_deliminated_string(const std::string &haystack, const std::string &needle, const char deliminator)
|
||||||
{
|
{
|
||||||
// this shouldn't go out of bounds, even without obvious bounds checks
|
// this shouldn't go out of bounds, even without obvious bounds checks
|
||||||
auto pos = haystack.find(needle);
|
auto pos = haystack.find(needle);
|
||||||
while (pos != std::string::npos) {
|
while (pos != std::string::npos) {
|
||||||
auto c = haystack[pos + needle.length()];
|
auto c = haystack[pos + needle.length()];
|
||||||
if ((c == '\0' || c == deliminator) && (pos == 0 || haystack[pos - 1] == deliminator))
|
if ((c == '\0' || c == deliminator) && (pos == 0 || haystack[pos - 1] == deliminator)) {
|
||||||
return pos;
|
return pos;
|
||||||
|
}
|
||||||
pos = haystack.find(needle, pos + needle.length());
|
pos = haystack.find(needle, pos + needle.length());
|
||||||
}
|
}
|
||||||
return std::string::npos;
|
return std::string::npos;
|
||||||
@ -180,7 +187,7 @@ std::string implode(std::string glue, std::vector<std::string> src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string final_output = output.str();
|
std::string final_output = output.str();
|
||||||
final_output.resize (output.str().size () - glue.size());
|
final_output.resize(output.str().size() - glue.size());
|
||||||
|
|
||||||
return final_output;
|
return final_output;
|
||||||
}
|
}
|
||||||
@ -202,80 +209,83 @@ std::vector<std::string> wrap(std::vector<std::string> &src, std::string charact
|
|||||||
return new_vector;
|
return new_vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EscapeString(const std::string &s) {
|
std::string EscapeString(const std::string &s)
|
||||||
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
|
||||||
size_t sz = s.length();
|
size_t sz = s.length();
|
||||||
for(size_t i = 0; i < sz; ++i) {
|
for (size_t i = 0; i < sz; ++i) {
|
||||||
char c = s[i];
|
char c = s[i];
|
||||||
switch(c) {
|
switch (c) {
|
||||||
case '\x00':
|
case '\x00':
|
||||||
ret += "\\x00";
|
ret += "\\x00";
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case '\n':
|
||||||
ret += "\\n";
|
ret += "\\n";
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
ret += "\\r";
|
ret += "\\r";
|
||||||
break;
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
ret += "\\\\";
|
ret += "\\\\";
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case '\'':
|
||||||
ret += "\\'";
|
ret += "\\'";
|
||||||
break;
|
break;
|
||||||
case '\"':
|
case '\"':
|
||||||
ret += "\\\"";
|
ret += "\\\"";
|
||||||
break;
|
break;
|
||||||
case '\x1a':
|
case '\x1a':
|
||||||
ret += "\\x1a";
|
ret += "\\x1a";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret.push_back(c);
|
ret.push_back(c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EscapeString(const char *src, size_t sz) {
|
std::string EscapeString(const char *src, size_t sz)
|
||||||
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
|
||||||
for(size_t i = 0; i < sz; ++i) {
|
for (size_t i = 0; i < sz; ++i) {
|
||||||
char c = src[i];
|
char c = src[i];
|
||||||
switch(c) {
|
switch (c) {
|
||||||
case '\x00':
|
case '\x00':
|
||||||
ret += "\\x00";
|
ret += "\\x00";
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case '\n':
|
||||||
ret += "\\n";
|
ret += "\\n";
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
ret += "\\r";
|
ret += "\\r";
|
||||||
break;
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
ret += "\\\\";
|
ret += "\\\\";
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case '\'':
|
||||||
ret += "\\'";
|
ret += "\\'";
|
||||||
break;
|
break;
|
||||||
case '\"':
|
case '\"':
|
||||||
ret += "\\\"";
|
ret += "\\\"";
|
||||||
break;
|
break;
|
||||||
case '\x1a':
|
case '\x1a':
|
||||||
ret += "\\x1a";
|
ret += "\\x1a";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret.push_back(c);
|
ret.push_back(c);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringIsNumber(const std::string &s) {
|
bool StringIsNumber(const std::string &s)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
auto r = stod(s);
|
auto r = stod(s);
|
||||||
return true;
|
return true;
|
||||||
@ -285,15 +295,18 @@ bool StringIsNumber(const std::string &s) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToLowerString(std::string &s) {
|
void ToLowerString(std::string &s)
|
||||||
|
{
|
||||||
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToUpperString(std::string &s) {
|
void ToUpperString(std::string &s)
|
||||||
|
{
|
||||||
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
|
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string JoinString(const std::vector<std::string>& ar, const std::string &delim) {
|
std::string JoinString(const std::vector<std::string> &ar, const std::string &delim)
|
||||||
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
for (size_t i = 0; i < ar.size(); ++i) {
|
for (size_t i = 0; i < ar.size(); ++i) {
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
@ -313,7 +326,7 @@ void find_replace(std::string &string_subject, const std::string &search_string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t start_pos = 0;
|
size_t start_pos = 0;
|
||||||
while((start_pos = string_subject.find(search_string, start_pos)) != std::string::npos) {
|
while ((start_pos = string_subject.find(search_string, start_pos)) != std::string::npos) {
|
||||||
string_subject.replace(start_pos, search_string.length(), replace_string);
|
string_subject.replace(start_pos, search_string.length(), replace_string);
|
||||||
start_pos += replace_string.length();
|
start_pos += replace_string.length();
|
||||||
}
|
}
|
||||||
@ -334,9 +347,9 @@ void ParseAccountString(const std::string &s, std::string &account, std::string
|
|||||||
auto split = SplitString(s, ':');
|
auto split = SplitString(s, ':');
|
||||||
if (split.size() == 2) {
|
if (split.size() == 2) {
|
||||||
loginserver = split[0];
|
loginserver = split[0];
|
||||||
account = split[1];
|
account = split[1];
|
||||||
}
|
}
|
||||||
else if(split.size() == 1) {
|
else if (split.size() == 1) {
|
||||||
account = split[0];
|
account = split[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -345,9 +358,11 @@ void ParseAccountString(const std::string &s, std::string &account, std::string
|
|||||||
|
|
||||||
// normal strncpy doesnt put a null term on copied strings, this one does
|
// 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
|
// 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) {
|
char *strn0cpy(char *dest, const char *source, uint32 size)
|
||||||
if (!dest)
|
{
|
||||||
|
if (!dest) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
if (size == 0 || source == 0) {
|
if (size == 0 || source == 0) {
|
||||||
dest[0] = 0;
|
dest[0] = 0;
|
||||||
return dest;
|
return dest;
|
||||||
@ -359,123 +374,159 @@ char* strn0cpy(char* dest, const char* source, uint32 size) {
|
|||||||
|
|
||||||
// String N w/null Copy Truncated?
|
// String N w/null Copy Truncated?
|
||||||
// return value =true if entire string(source) fit, false if it was truncated
|
// return value =true if entire string(source) fit, false if it was truncated
|
||||||
bool strn0cpyt(char* dest, const char* source, uint32 size) {
|
bool strn0cpyt(char *dest, const char *source, uint32 size)
|
||||||
if (!dest)
|
{
|
||||||
|
if (!dest) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
if (size == 0 || source == 0) {
|
if (size == 0 || source == 0) {
|
||||||
dest[0] = 0;
|
dest[0] = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
strncpy(dest, source, size);
|
strncpy(dest, source, size);
|
||||||
dest[size - 1] = 0;
|
dest[size - 1] = 0;
|
||||||
return (bool)(source[strlen(dest)] == 0);
|
return (bool) (source[strlen(dest)] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *MakeLowerString(const char *source) {
|
const char *MakeLowerString(const char *source)
|
||||||
|
{
|
||||||
static char str[128];
|
static char str[128];
|
||||||
if (!source)
|
if (!source) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
MakeLowerString(source, str);
|
MakeLowerString(source, str);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeLowerString(const char *source, char *target) {
|
void MakeLowerString(const char *source, char *target)
|
||||||
|
{
|
||||||
if (!source || !target) {
|
if (!source || !target) {
|
||||||
*target = 0;
|
*target = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (*source)
|
while (*source) {
|
||||||
{
|
|
||||||
*target = tolower(*source);
|
*target = tolower(*source);
|
||||||
target++; source++;
|
target++;
|
||||||
|
source++;
|
||||||
}
|
}
|
||||||
*target = 0;
|
*target = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 hextoi(const char* num) {
|
uint32 hextoi(const char *num)
|
||||||
if (num == nullptr)
|
{
|
||||||
|
if (num == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int len = strlen(num);
|
int len = strlen(num);
|
||||||
if (len < 3)
|
if (len < 3) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
|
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X')) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 ret = 0;
|
uint32 ret = 0;
|
||||||
int mul = 1;
|
int mul = 1;
|
||||||
for (int i = len - 1; i >= 2; i--) {
|
for (int i = len - 1; i >= 2; i--) {
|
||||||
if (num[i] >= 'A' && num[i] <= 'F')
|
if (num[i] >= 'A' && num[i] <= 'F') {
|
||||||
ret += ((num[i] - 'A') + 10) * mul;
|
ret += ((num[i] - 'A') + 10) * mul;
|
||||||
else if (num[i] >= 'a' && num[i] <= 'f')
|
}
|
||||||
|
else if (num[i] >= 'a' && num[i] <= 'f') {
|
||||||
ret += ((num[i] - 'a') + 10) * mul;
|
ret += ((num[i] - 'a') + 10) * mul;
|
||||||
else if (num[i] >= '0' && num[i] <= '9')
|
}
|
||||||
|
else if (num[i] >= '0' && num[i] <= '9') {
|
||||||
ret += (num[i] - '0') * mul;
|
ret += (num[i] - '0') * mul;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
mul *= 16;
|
mul *= 16;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 hextoi64(const char* num) {
|
uint64 hextoi64(const char *num)
|
||||||
if (num == nullptr)
|
{
|
||||||
|
if (num == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int len = strlen(num);
|
int len = strlen(num);
|
||||||
if (len < 3)
|
if (len < 3) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
|
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X')) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint64 ret = 0;
|
uint64 ret = 0;
|
||||||
int mul = 1;
|
int mul = 1;
|
||||||
for (int i = len - 1; i >= 2; i--) {
|
for (int i = len - 1; i >= 2; i--) {
|
||||||
if (num[i] >= 'A' && num[i] <= 'F')
|
if (num[i] >= 'A' && num[i] <= 'F') {
|
||||||
ret += ((num[i] - 'A') + 10) * mul;
|
ret += ((num[i] - 'A') + 10) * mul;
|
||||||
else if (num[i] >= 'a' && num[i] <= 'f')
|
}
|
||||||
|
else if (num[i] >= 'a' && num[i] <= 'f') {
|
||||||
ret += ((num[i] - 'a') + 10) * mul;
|
ret += ((num[i] - 'a') + 10) * mul;
|
||||||
else if (num[i] >= '0' && num[i] <= '9')
|
}
|
||||||
|
else if (num[i] >= '0' && num[i] <= '9') {
|
||||||
ret += (num[i] - '0') * mul;
|
ret += (num[i] - '0') * mul;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
mul *= 16;
|
mul *= 16;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool atobool(const char* iBool) {
|
bool atobool(const char *iBool)
|
||||||
|
{
|
||||||
|
|
||||||
if (iBool == nullptr)
|
if (iBool == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
if (!strcasecmp(iBool, "true"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "true")) {
|
||||||
return true;
|
return true;
|
||||||
if (!strcasecmp(iBool, "false"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "false")) {
|
||||||
return false;
|
return false;
|
||||||
if (!strcasecmp(iBool, "yes"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "yes")) {
|
||||||
return true;
|
return true;
|
||||||
if (!strcasecmp(iBool, "no"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "no")) {
|
||||||
return false;
|
return false;
|
||||||
if (!strcasecmp(iBool, "on"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "on")) {
|
||||||
return true;
|
return true;
|
||||||
if (!strcasecmp(iBool, "off"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "off")) {
|
||||||
return false;
|
return false;
|
||||||
if (!strcasecmp(iBool, "enable"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "enable")) {
|
||||||
return true;
|
return true;
|
||||||
if (!strcasecmp(iBool, "disable"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "disable")) {
|
||||||
return false;
|
return false;
|
||||||
if (!strcasecmp(iBool, "enabled"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "enabled")) {
|
||||||
return true;
|
return true;
|
||||||
if (!strcasecmp(iBool, "disabled"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "disabled")) {
|
||||||
return false;
|
return false;
|
||||||
if (!strcasecmp(iBool, "y"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "y")) {
|
||||||
return true;
|
return true;
|
||||||
if (!strcasecmp(iBool, "n"))
|
}
|
||||||
|
if (!strcasecmp(iBool, "n")) {
|
||||||
return false;
|
return false;
|
||||||
if (atoi(iBool))
|
}
|
||||||
|
if (atoi(iBool)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,21 +535,19 @@ char *CleanMobName(const char *in, char *out)
|
|||||||
{
|
{
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
|
|
||||||
for (i = j = 0; i < strlen(in); i++)
|
for (i = j = 0; i < strlen(in); i++) {
|
||||||
{
|
|
||||||
// convert _ to space.. any other conversions like this? I *think* this
|
// convert _ to space.. any other conversions like this? I *think* this
|
||||||
// is the only non alpha char that's not stripped but converted.
|
// is the only non alpha char that's not stripped but converted.
|
||||||
if (in[i] == '_')
|
if (in[i] == '_') {
|
||||||
{
|
|
||||||
out[j++] = ' ';
|
out[j++] = ' ';
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
if (isalpha(in[i]) || (in[i] == '`')) { // numbers, #, or any other crap just gets skipped
|
||||||
if (isalpha(in[i]) || (in[i] == '`')) // numbers, #, or any other crap just gets skipped
|
|
||||||
out[j++] = in[i];
|
out[j++] = in[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out[j] = 0; // terimnate the string before returning it
|
out[j] = 0; // terimnate the string before returning it
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,8 +555,9 @@ char *CleanMobName(const char *in, char *out)
|
|||||||
void RemoveApostrophes(std::string &s)
|
void RemoveApostrophes(std::string &s)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < s.length(); ++i)
|
for (unsigned int i = 0; i < s.length(); ++i)
|
||||||
if (s[i] == '\'')
|
if (s[i] == '\'') {
|
||||||
s[i] = '_';
|
s[i] = '_';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *RemoveApostrophes(const char *s)
|
char *RemoveApostrophes(const char *s)
|
||||||
@ -517,8 +567,9 @@ char *RemoveApostrophes(const char *s)
|
|||||||
strcpy(NewString, s);
|
strcpy(NewString, s);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < strlen(NewString); ++i)
|
for (unsigned int i = 0; i < strlen(NewString); ++i)
|
||||||
if (NewString[i] == '\'')
|
if (NewString[i] == '\'') {
|
||||||
NewString[i] = '_';
|
NewString[i] = '_';
|
||||||
|
}
|
||||||
|
|
||||||
return NewString;
|
return NewString;
|
||||||
}
|
}
|
||||||
@ -537,11 +588,12 @@ const char *ConvertArrayF(float input, char *returnchar)
|
|||||||
|
|
||||||
bool isAlphaNumeric(const char *text)
|
bool isAlphaNumeric(const char *text)
|
||||||
{
|
{
|
||||||
for (unsigned int charIndex = 0; charIndex<strlen(text); charIndex++) {
|
for (unsigned int charIndex = 0; charIndex < strlen(text); charIndex++) {
|
||||||
if ((text[charIndex] < 'a' || text[charIndex] > 'z') &&
|
if ((text[charIndex] < 'a' || text[charIndex] > 'z') &&
|
||||||
(text[charIndex] < 'A' || text[charIndex] > 'Z') &&
|
(text[charIndex] < 'A' || text[charIndex] > 'Z') &&
|
||||||
(text[charIndex] < '0' || text[charIndex] > '9'))
|
(text[charIndex] < '0' || text[charIndex] > '9')) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -596,11 +648,10 @@ std::string numberToWords(unsigned long long int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// first letter capitalized and rest made lower case
|
// first letter capitalized and rest made lower case
|
||||||
std::string FormatName(const std::string& char_name)
|
std::string FormatName(const std::string &char_name)
|
||||||
{
|
{
|
||||||
std::string formatted(char_name);
|
std::string formatted(char_name);
|
||||||
if (!formatted.empty())
|
if (!formatted.empty()) {
|
||||||
{
|
|
||||||
std::transform(formatted.begin(), formatted.end(), formatted.begin(), ::tolower);
|
std::transform(formatted.begin(), formatted.end(), formatted.begin(), ::tolower);
|
||||||
formatted[0] = ::toupper(formatted[0]);
|
formatted[0] = ::toupper(formatted[0]);
|
||||||
}
|
}
|
||||||
@ -620,6 +671,12 @@ bool IsAllowedWorldServerCharacterList(char c)
|
|||||||
void SanitizeWorldServerName(char *name)
|
void SanitizeWorldServerName(char *name)
|
||||||
{
|
{
|
||||||
std::string server_long_name = name;
|
std::string server_long_name = name;
|
||||||
|
|
||||||
|
strcpy(name, SanitizeWorldServerName(server_long_name).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SanitizeWorldServerName(std::string server_long_name)
|
||||||
|
{
|
||||||
server_long_name.erase(
|
server_long_name.erase(
|
||||||
std::remove_if(
|
std::remove_if(
|
||||||
server_long_name.begin(),
|
server_long_name.begin(),
|
||||||
@ -632,5 +689,333 @@ void SanitizeWorldServerName(char *name)
|
|||||||
|
|
||||||
server_long_name = trim(server_long_name);
|
server_long_name = trim(server_long_name);
|
||||||
|
|
||||||
strcpy(name, server_long_name.c_str());
|
// bad word filter
|
||||||
|
for (auto &piece: split_string(server_long_name, " ")) {
|
||||||
|
for (auto &word: GetBadWords()) {
|
||||||
|
// for shorter words that can actually be part of legitimate words
|
||||||
|
// make sure that it isn't part of another word by matching on a space
|
||||||
|
if (str_tolower(piece) == word) {
|
||||||
|
find_replace(
|
||||||
|
server_long_name,
|
||||||
|
piece,
|
||||||
|
repeat("*", (int) word.length())
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pos = str_tolower(piece).find(word);
|
||||||
|
if (str_tolower(piece).find(word) != std::string::npos && piece.length() > 4 && word.length() > 4) {
|
||||||
|
auto found_word = piece.substr(pos, word.length());
|
||||||
|
std::string replaced_piece = piece.substr(pos, word.length());
|
||||||
|
|
||||||
|
find_replace(
|
||||||
|
server_long_name,
|
||||||
|
replaced_piece,
|
||||||
|
repeat("*", (int) word.length())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return server_long_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string repeat(std::string s, int n)
|
||||||
|
{
|
||||||
|
std::string s1 = s;
|
||||||
|
for (int i = 1; i < n; i++) {
|
||||||
|
s += s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> GetBadWords()
|
||||||
|
{
|
||||||
|
return std::vector<std::string>{
|
||||||
|
"2g1c",
|
||||||
|
"acrotomophilia",
|
||||||
|
"anal",
|
||||||
|
"anilingus",
|
||||||
|
"anus",
|
||||||
|
"apeshit",
|
||||||
|
"arsehole",
|
||||||
|
"ass",
|
||||||
|
"asshole",
|
||||||
|
"assmunch",
|
||||||
|
"autoerotic",
|
||||||
|
"babeland",
|
||||||
|
"bangbros",
|
||||||
|
"bangbus",
|
||||||
|
"bareback",
|
||||||
|
"barenaked",
|
||||||
|
"bastard",
|
||||||
|
"bastardo",
|
||||||
|
"bastinado",
|
||||||
|
"bbw",
|
||||||
|
"bdsm",
|
||||||
|
"beaner",
|
||||||
|
"beaners",
|
||||||
|
"beaver",
|
||||||
|
"beastiality",
|
||||||
|
"bestiality",
|
||||||
|
"bimbos",
|
||||||
|
"birdlock",
|
||||||
|
"bitch",
|
||||||
|
"bitches",
|
||||||
|
"blowjob",
|
||||||
|
"blumpkin",
|
||||||
|
"bollocks",
|
||||||
|
"bondage",
|
||||||
|
"boner",
|
||||||
|
"boob",
|
||||||
|
"boobs",
|
||||||
|
"bukkake",
|
||||||
|
"bulldyke",
|
||||||
|
"bullshit",
|
||||||
|
"bung",
|
||||||
|
"bunghole",
|
||||||
|
"busty",
|
||||||
|
"butt",
|
||||||
|
"buttcheeks",
|
||||||
|
"butthole",
|
||||||
|
"camel toe",
|
||||||
|
"camgirl",
|
||||||
|
"camslut",
|
||||||
|
"camwhore",
|
||||||
|
"carpetmuncher",
|
||||||
|
"cialis",
|
||||||
|
"circlejerk",
|
||||||
|
"clit",
|
||||||
|
"clitoris",
|
||||||
|
"clusterfuck",
|
||||||
|
"cock",
|
||||||
|
"cocks",
|
||||||
|
"coprolagnia",
|
||||||
|
"coprophilia",
|
||||||
|
"cornhole",
|
||||||
|
"coon",
|
||||||
|
"coons",
|
||||||
|
"creampie",
|
||||||
|
"cum",
|
||||||
|
"cumming",
|
||||||
|
"cumshot",
|
||||||
|
"cumshots",
|
||||||
|
"cunnilingus",
|
||||||
|
"cunt",
|
||||||
|
"darkie",
|
||||||
|
"daterape",
|
||||||
|
"deepthroat",
|
||||||
|
"dendrophilia",
|
||||||
|
"dick",
|
||||||
|
"dildo",
|
||||||
|
"dingleberry",
|
||||||
|
"dingleberries",
|
||||||
|
"doggiestyle",
|
||||||
|
"doggystyle",
|
||||||
|
"dolcett",
|
||||||
|
"domination",
|
||||||
|
"dominatrix",
|
||||||
|
"dommes",
|
||||||
|
"hump",
|
||||||
|
"dvda",
|
||||||
|
"ecchi",
|
||||||
|
"ejaculation",
|
||||||
|
"erotic",
|
||||||
|
"erotism",
|
||||||
|
"escort",
|
||||||
|
"eunuch",
|
||||||
|
"fag",
|
||||||
|
"faggot",
|
||||||
|
"fecal",
|
||||||
|
"felch",
|
||||||
|
"fellatio",
|
||||||
|
"feltch",
|
||||||
|
"femdom",
|
||||||
|
"figging",
|
||||||
|
"fingerbang",
|
||||||
|
"fingering",
|
||||||
|
"fisting",
|
||||||
|
"footjob",
|
||||||
|
"frotting",
|
||||||
|
"fuck",
|
||||||
|
"fuckin",
|
||||||
|
"fucking",
|
||||||
|
"fucktards",
|
||||||
|
"fudgepacker",
|
||||||
|
"futanari",
|
||||||
|
"gangbang",
|
||||||
|
"gangbang",
|
||||||
|
"gaysex",
|
||||||
|
"genitals",
|
||||||
|
"goatcx",
|
||||||
|
"goatse",
|
||||||
|
"gokkun",
|
||||||
|
"goodpoop",
|
||||||
|
"goregasm",
|
||||||
|
"grope",
|
||||||
|
"g-spot",
|
||||||
|
"guro",
|
||||||
|
"handjob",
|
||||||
|
"hentai",
|
||||||
|
"homoerotic",
|
||||||
|
"honkey",
|
||||||
|
"hooker",
|
||||||
|
"horny",
|
||||||
|
"humping",
|
||||||
|
"incest",
|
||||||
|
"intercourse",
|
||||||
|
"jailbait",
|
||||||
|
"jigaboo",
|
||||||
|
"jiggaboo",
|
||||||
|
"jiggerboo",
|
||||||
|
"jizz",
|
||||||
|
"juggs",
|
||||||
|
"kike",
|
||||||
|
"kinbaku",
|
||||||
|
"kinkster",
|
||||||
|
"kinky",
|
||||||
|
"knobbing",
|
||||||
|
"livesex",
|
||||||
|
"lolita",
|
||||||
|
"lovemaking",
|
||||||
|
"masturbate",
|
||||||
|
"masturbating",
|
||||||
|
"masturbation",
|
||||||
|
"milf",
|
||||||
|
"mong",
|
||||||
|
"motherfucker",
|
||||||
|
"muffdiving",
|
||||||
|
"nambla",
|
||||||
|
"nawashi",
|
||||||
|
"negro",
|
||||||
|
"neonazi",
|
||||||
|
"nigga",
|
||||||
|
"nigger",
|
||||||
|
"nimphomania",
|
||||||
|
"nipple",
|
||||||
|
"nipples",
|
||||||
|
"nsfw",
|
||||||
|
"nude",
|
||||||
|
"nudity",
|
||||||
|
"nutten",
|
||||||
|
"nympho",
|
||||||
|
"nymphomania",
|
||||||
|
"octopussy",
|
||||||
|
"omorashi",
|
||||||
|
"orgasm",
|
||||||
|
"orgy",
|
||||||
|
"paedophile",
|
||||||
|
"paki",
|
||||||
|
"panties",
|
||||||
|
"panty",
|
||||||
|
"pedobear",
|
||||||
|
"pedophile",
|
||||||
|
"pegging",
|
||||||
|
"penis",
|
||||||
|
"pikey",
|
||||||
|
"pissing",
|
||||||
|
"pisspig",
|
||||||
|
"playboy",
|
||||||
|
"ponyplay",
|
||||||
|
"poof",
|
||||||
|
"poon",
|
||||||
|
"poontang",
|
||||||
|
"punany",
|
||||||
|
"poopchute",
|
||||||
|
"porn",
|
||||||
|
"porno",
|
||||||
|
"pornography",
|
||||||
|
"pthc",
|
||||||
|
"pubes",
|
||||||
|
"pussy",
|
||||||
|
"queaf",
|
||||||
|
"queef",
|
||||||
|
"quim",
|
||||||
|
"raghead",
|
||||||
|
"rape",
|
||||||
|
"raping",
|
||||||
|
"rapist",
|
||||||
|
"rectum",
|
||||||
|
"rimjob",
|
||||||
|
"rimming",
|
||||||
|
"sadism",
|
||||||
|
"santorum",
|
||||||
|
"scat",
|
||||||
|
"schlong",
|
||||||
|
"scissoring",
|
||||||
|
"semen",
|
||||||
|
"sex",
|
||||||
|
"sexcam",
|
||||||
|
"sexo",
|
||||||
|
"sexy",
|
||||||
|
"sexual",
|
||||||
|
"sexually",
|
||||||
|
"sexuality",
|
||||||
|
"shemale",
|
||||||
|
"shibari",
|
||||||
|
"shit",
|
||||||
|
"shitblimp",
|
||||||
|
"shitty",
|
||||||
|
"shota",
|
||||||
|
"shrimping",
|
||||||
|
"skeet",
|
||||||
|
"slanteye",
|
||||||
|
"slut",
|
||||||
|
"s&m",
|
||||||
|
"smut",
|
||||||
|
"snatch",
|
||||||
|
"snowballing",
|
||||||
|
"sodomize",
|
||||||
|
"sodomy",
|
||||||
|
"spastic",
|
||||||
|
"spic",
|
||||||
|
"splooge",
|
||||||
|
"spooge",
|
||||||
|
"spunk",
|
||||||
|
"strapon",
|
||||||
|
"strappado",
|
||||||
|
"suck",
|
||||||
|
"sucks",
|
||||||
|
"swastika",
|
||||||
|
"swinger",
|
||||||
|
"threesome",
|
||||||
|
"throating",
|
||||||
|
"thumbzilla",
|
||||||
|
"tight white",
|
||||||
|
"tit",
|
||||||
|
"tits",
|
||||||
|
"titties",
|
||||||
|
"titty",
|
||||||
|
"topless",
|
||||||
|
"tosser",
|
||||||
|
"towelhead",
|
||||||
|
"tranny",
|
||||||
|
"tribadism",
|
||||||
|
"tubgirl",
|
||||||
|
"tushy",
|
||||||
|
"twat",
|
||||||
|
"twink",
|
||||||
|
"twinkie",
|
||||||
|
"undressing",
|
||||||
|
"upskirt",
|
||||||
|
"urophilia",
|
||||||
|
"vagina",
|
||||||
|
"viagra",
|
||||||
|
"vibrator",
|
||||||
|
"vorarephilia",
|
||||||
|
"voyeur",
|
||||||
|
"voyeurweb",
|
||||||
|
"voyuer",
|
||||||
|
"vulva",
|
||||||
|
"wank",
|
||||||
|
"wetback",
|
||||||
|
"whore",
|
||||||
|
"worldsex",
|
||||||
|
"xx",
|
||||||
|
"xxx",
|
||||||
|
"yaoi",
|
||||||
|
"yiffy",
|
||||||
|
"zoophilia"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -208,7 +208,11 @@ void RemoveApostrophes(std::string &s);
|
|||||||
std::string convert2digit(int n, std::string suffix);
|
std::string convert2digit(int n, std::string suffix);
|
||||||
std::string numberToWords(unsigned long long int n);
|
std::string numberToWords(unsigned long long int n);
|
||||||
std::string FormatName(const std::string& char_name);
|
std::string FormatName(const std::string& char_name);
|
||||||
|
bool IsAllowedWorldServerCharacterList(char c);
|
||||||
void SanitizeWorldServerName(char *name);
|
void SanitizeWorldServerName(char *name);
|
||||||
|
std::string SanitizeWorldServerName(std::string server_long_name);
|
||||||
|
std::string repeat(std::string s, int n);
|
||||||
|
std::vector<std::string> GetBadWords();
|
||||||
|
|
||||||
template<typename InputIterator, typename OutputIterator>
|
template<typename InputIterator, typename OutputIterator>
|
||||||
auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result)
|
auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result)
|
||||||
|
|||||||
@ -22,7 +22,7 @@ SET(eqlogin_headers
|
|||||||
loginserver_command_handler.h
|
loginserver_command_handler.h
|
||||||
loginserver_webserver.h
|
loginserver_webserver.h
|
||||||
login_server.h
|
login_server.h
|
||||||
login_structures.h
|
login_types.h
|
||||||
options.h
|
options.h
|
||||||
server_manager.h
|
server_manager.h
|
||||||
world_server.h
|
world_server.h
|
||||||
|
|||||||
@ -7,44 +7,9 @@
|
|||||||
#include "../common/eq_stream_intf.h"
|
#include "../common/eq_stream_intf.h"
|
||||||
#include "../common/net/dns.h"
|
#include "../common/net/dns.h"
|
||||||
#include "../common/net/daybreak_connection.h"
|
#include "../common/net/daybreak_connection.h"
|
||||||
#include "login_structures.h"
|
#include "login_types.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
enum LSClientVersion {
|
|
||||||
cv_titanium,
|
|
||||||
cv_sod
|
|
||||||
};
|
|
||||||
|
|
||||||
enum LSClientStatus {
|
|
||||||
cs_not_sent_session_ready,
|
|
||||||
cs_waiting_for_login,
|
|
||||||
cs_creating_account,
|
|
||||||
cs_failed_to_login,
|
|
||||||
cs_logged_in
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace LS {
|
|
||||||
namespace ServerStatusFlags {
|
|
||||||
enum eServerStatusFlags {
|
|
||||||
Up = 0, // default
|
|
||||||
Down = 1,
|
|
||||||
Unused = 2,
|
|
||||||
Locked = 4 // can be combined with Down to show "Locked (Down)"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ServerTypeFlags {
|
|
||||||
enum eServerTypeFlags {
|
|
||||||
None = 0,
|
|
||||||
Standard = 1,
|
|
||||||
Unknown2 = 2,
|
|
||||||
Unknown4 = 4,
|
|
||||||
Preferred = 8,
|
|
||||||
Legends = 16 // can be combined with Preferred flag to override color in Legends section with Preferred color (green)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client class, controls a single client and it's connection to the login server
|
* Client class, controls a single client and it's connection to the login server
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -4,39 +4,34 @@
|
|||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
// unencrypted base message header in all packets
|
// unencrypted base message header in all packets
|
||||||
struct LoginBaseMessage_Struct
|
struct LoginBaseMessage_Struct {
|
||||||
{
|
|
||||||
int32_t sequence; // request type/login sequence (2: handshake, 3: login, 4: serverlist, ...)
|
int32_t sequence; // request type/login sequence (2: handshake, 3: login, 4: serverlist, ...)
|
||||||
bool compressed; // true: deflated
|
bool compressed; // true: deflated
|
||||||
int8_t encrypt_type; // 1: invert (unused) 2: des (2 for encrypted player logins and order expansions) (client uses what it sent, ignores in reply)
|
int8_t encrypt_type; // 1: invert (unused) 2: des (2 for encrypted player logins and order expansions) (client uses what it sent, ignores in reply)
|
||||||
int32_t unk3; // unused?
|
int32_t unk3; // unused?
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LoginBaseReplyMessage_Struct
|
struct LoginBaseReplyMessage_Struct {
|
||||||
{
|
|
||||||
bool success; // 0: failure (shows error string) 1: success
|
bool success; // 0: failure (shows error string) 1: success
|
||||||
int32_t error_str_id; // last error eqlsstr id, default: 101 (no error)
|
int32_t error_str_id; // last error eqlsstr id, default: 101 (no error)
|
||||||
char str[1]; // variable length, unknown (may be unused, this struct is a common pattern elsewhere)
|
char str[1]; // variable length, unknown (may be unused, this struct is a common pattern elsewhere)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LoginHandShakeReply_Struct
|
struct LoginHandShakeReply_Struct {
|
||||||
{
|
LoginBaseMessage_Struct base_header;
|
||||||
LoginBaseMessage_Struct base_header;
|
|
||||||
LoginBaseReplyMessage_Struct base_reply;
|
LoginBaseReplyMessage_Struct base_reply;
|
||||||
char unknown[1]; // variable length string
|
char unknown[1]; // variable length string
|
||||||
};
|
};
|
||||||
|
|
||||||
// for reference, login buffer is variable (minimum size 8 due to encryption)
|
// for reference, login buffer is variable (minimum size 8 due to encryption)
|
||||||
struct PlayerLogin_Struct
|
struct PlayerLogin_Struct {
|
||||||
{
|
|
||||||
LoginBaseMessage_Struct base_header;
|
LoginBaseMessage_Struct base_header;
|
||||||
char username[1];
|
char username[1];
|
||||||
char password[1];
|
char password[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
// variable length, can use directly if not serializing strings
|
// variable length, can use directly if not serializing strings
|
||||||
struct PlayerLoginReply_Struct
|
struct PlayerLoginReply_Struct {
|
||||||
{
|
|
||||||
// base header excluded to make struct data easier to encrypt
|
// base header excluded to make struct data easier to encrypt
|
||||||
//LoginBaseMessage_Struct base_header;
|
//LoginBaseMessage_Struct base_header;
|
||||||
LoginBaseReplyMessage_Struct base_reply;
|
LoginBaseReplyMessage_Struct base_reply;
|
||||||
@ -59,8 +54,7 @@ struct PlayerLoginReply_Struct
|
|||||||
};
|
};
|
||||||
|
|
||||||
// variable length, for reference
|
// variable length, for reference
|
||||||
struct LoginClientServerData_Struct
|
struct LoginClientServerData_Struct {
|
||||||
{
|
|
||||||
char ip[1];
|
char ip[1];
|
||||||
int32_t server_type; // legends, preferred, standard
|
int32_t server_type; // legends, preferred, standard
|
||||||
int32_t server_id;
|
int32_t server_id;
|
||||||
@ -72,29 +66,78 @@ struct LoginClientServerData_Struct
|
|||||||
};
|
};
|
||||||
|
|
||||||
// variable length, for reference
|
// variable length, for reference
|
||||||
struct ServerListReply_Struct
|
struct ServerListReply_Struct {
|
||||||
{
|
LoginBaseMessage_Struct base_header;
|
||||||
LoginBaseMessage_Struct base_header;
|
|
||||||
LoginBaseReplyMessage_Struct base_reply;
|
LoginBaseReplyMessage_Struct base_reply;
|
||||||
|
|
||||||
int32_t server_count;
|
int32_t server_count;
|
||||||
LoginClientServerData_Struct servers[0];
|
LoginClientServerData_Struct servers[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayEverquestRequest_Struct {
|
struct PlayEverquestRequest_Struct {
|
||||||
LoginBaseMessage_Struct base_header;
|
LoginBaseMessage_Struct base_header;
|
||||||
uint32 server_number;
|
uint32 server_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
// SCJoinServerReply
|
// SCJoinServerReply
|
||||||
struct PlayEverquestResponse_Struct {
|
struct PlayEverquestResponse_Struct {
|
||||||
LoginBaseMessage_Struct base_header;
|
LoginBaseMessage_Struct base_header;
|
||||||
LoginBaseReplyMessage_Struct base_reply;
|
LoginBaseReplyMessage_Struct base_reply;
|
||||||
uint32 server_number;
|
uint32 server_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
|
enum LSClientVersion {
|
||||||
|
cv_titanium,
|
||||||
|
cv_sod
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LSClientStatus {
|
||||||
|
cs_not_sent_session_ready,
|
||||||
|
cs_waiting_for_login,
|
||||||
|
cs_creating_account,
|
||||||
|
cs_failed_to_login,
|
||||||
|
cs_logged_in
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace LS {
|
||||||
|
namespace ServerStatusFlags {
|
||||||
|
enum eServerStatusFlags {
|
||||||
|
Up = 0, // default
|
||||||
|
Down = 1,
|
||||||
|
Unused = 2,
|
||||||
|
Locked = 4 // can be combined with Down to show "Locked (Down)"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ServerTypeFlags {
|
||||||
|
enum eServerTypeFlags {
|
||||||
|
None = 0,
|
||||||
|
Standard = 1,
|
||||||
|
Unknown2 = 2,
|
||||||
|
Unknown4 = 4,
|
||||||
|
Preferred = 8,
|
||||||
|
Legends = 16 // can be combined with Preferred flag to override color in Legends section with Preferred color (green)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ServerType {
|
||||||
|
Standard = 3,
|
||||||
|
Preferred = 2,
|
||||||
|
Legends = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ErrStr {
|
||||||
|
constexpr static int NO_ERROR = 101; // No Error
|
||||||
|
constexpr static int SERVER_UNAVAILABLE = 326; // That server is currently unavailable. Please check the EverQuest webpage for current server status and try again later.
|
||||||
|
constexpr static int ACCOUNT_SUSPENDED = 337; // This account is currently suspended. Please contact customer service for more information.
|
||||||
|
constexpr static int ACCOUNT_BANNED = 338; // This account is currently banned. Please contact customer service for more information.
|
||||||
|
constexpr static int WORLD_MAX_CAPACITY = 339; // The world server is currently at maximum capacity and not allowing further logins until the number of players online decreases. Please try again later.
|
||||||
|
constexpr static int ERROR_1018_ACTIVE_CHARACTER = 111; // Error 1018: You currently have an active character on that EverQuest Server, please allow a minute for synchronization and try again.
|
||||||
|
constexpr static int UNKNOWN_ERROR = 102; // Error - Unknown Error Occurred
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -12,6 +12,8 @@
|
|||||||
"worldservers": {
|
"worldservers": {
|
||||||
"unregistered_allowed": true,
|
"unregistered_allowed": true,
|
||||||
"show_player_count": false,
|
"show_player_count": false,
|
||||||
|
"dev_test_servers_list_bottom": false,
|
||||||
|
"special_character_start_list_bottom": false,
|
||||||
"reject_duplicate_servers": false
|
"reject_duplicate_servers": false
|
||||||
},
|
},
|
||||||
"web_api": {
|
"web_api": {
|
||||||
|
|||||||
@ -62,9 +62,30 @@ void LoadServerConfig()
|
|||||||
"worldservers",
|
"worldservers",
|
||||||
"reject_duplicate_servers",
|
"reject_duplicate_servers",
|
||||||
false
|
false
|
||||||
));
|
)
|
||||||
server.options.AllowUnregistered(server.config.GetVariableBool("worldservers", "unregistered_allowed", true));
|
);
|
||||||
server.options.SetShowPlayerCount(server.config.GetVariableBool("worldservers", "show_player_count", false));
|
server.options.SetShowPlayerCount(server.config.GetVariableBool("worldservers", "show_player_count", false));
|
||||||
|
server.options.AllowUnregistered(
|
||||||
|
server.config.GetVariableBool(
|
||||||
|
"worldservers",
|
||||||
|
"unregistered_allowed",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
server.options.SetWorldDevTestServersListBottom(
|
||||||
|
server.config.GetVariableBool(
|
||||||
|
"worldservers",
|
||||||
|
"dev_test_servers_list_bottom",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
server.options.SetWorldSpecialCharacterStartListBottom(
|
||||||
|
server.config.GetVariableBool(
|
||||||
|
"worldservers",
|
||||||
|
"special_character_start_list_bottom",
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account
|
* Account
|
||||||
@ -242,6 +263,14 @@ int main(int argc, char **argv)
|
|||||||
LogInfo("[Config] [WorldServer] IsRejectingDuplicateServers [{0}]", server.options.IsRejectingDuplicateServers());
|
LogInfo("[Config] [WorldServer] IsRejectingDuplicateServers [{0}]", server.options.IsRejectingDuplicateServers());
|
||||||
LogInfo("[Config] [WorldServer] IsUnregisteredAllowed [{0}]", server.options.IsUnregisteredAllowed());
|
LogInfo("[Config] [WorldServer] IsUnregisteredAllowed [{0}]", server.options.IsUnregisteredAllowed());
|
||||||
LogInfo("[Config] [WorldServer] ShowPlayerCount [{0}]", server.options.IsShowPlayerCountEnabled());
|
LogInfo("[Config] [WorldServer] ShowPlayerCount [{0}]", server.options.IsShowPlayerCountEnabled());
|
||||||
|
LogInfo(
|
||||||
|
"[Config] [WorldServer] DevAndTestServersListBottom [{0}]",
|
||||||
|
server.options.IsWorldDevTestServersListBottom()
|
||||||
|
);
|
||||||
|
LogInfo(
|
||||||
|
"[Config] [WorldServer] SpecialCharactersStartListBottom [{0}]",
|
||||||
|
server.options.IsWorldSpecialCharacterStartListBottom()
|
||||||
|
);
|
||||||
LogInfo("[Config] [Security] GetEncryptionMode [{0}]", server.options.GetEncryptionMode());
|
LogInfo("[Config] [Security] GetEncryptionMode [{0}]", server.options.GetEncryptionMode());
|
||||||
LogInfo("[Config] [Security] IsTokenLoginAllowed [{0}]", server.options.IsTokenLoginAllowed());
|
LogInfo("[Config] [Security] IsTokenLoginAllowed [{0}]", server.options.IsTokenLoginAllowed());
|
||||||
LogInfo("[Config] [Security] IsPasswordLoginAllowed [{0}]", server.options.IsPasswordLoginAllowed());
|
LogInfo("[Config] [Security] IsPasswordLoginAllowed [{0}]", server.options.IsPasswordLoginAllowed());
|
||||||
|
|||||||
@ -121,6 +121,20 @@ public:
|
|||||||
{
|
{
|
||||||
Options::show_player_count = show_player_count;
|
Options::show_player_count = show_player_count;
|
||||||
}
|
}
|
||||||
|
inline bool IsWorldDevTestServersListBottom() const { return world_dev_test_servers_list_bottom; }
|
||||||
|
inline void SetWorldDevTestServersListBottom(bool dev_test_servers_list_bottom)
|
||||||
|
{
|
||||||
|
Options::world_dev_test_servers_list_bottom = dev_test_servers_list_bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsWorldSpecialCharacterStartListBottom() const
|
||||||
|
{
|
||||||
|
return world_special_character_start_list_bottom;
|
||||||
|
}
|
||||||
|
inline void SetWorldSpecialCharacterStartListBottom(bool world_special_character_start_list_bottom)
|
||||||
|
{
|
||||||
|
Options::world_special_character_start_list_bottom = world_special_character_start_list_bottom;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool allow_unregistered;
|
bool allow_unregistered;
|
||||||
@ -129,6 +143,8 @@ private:
|
|||||||
bool dump_in_packets;
|
bool dump_in_packets;
|
||||||
bool dump_out_packets;
|
bool dump_out_packets;
|
||||||
bool reject_duplicate_servers;
|
bool reject_duplicate_servers;
|
||||||
|
bool world_dev_test_servers_list_bottom;
|
||||||
|
bool world_special_character_start_list_bottom;
|
||||||
bool allow_token_login;
|
bool allow_token_login;
|
||||||
bool allow_password_login;
|
bool allow_password_login;
|
||||||
bool show_player_count;
|
bool show_player_count;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include "server_manager.h"
|
#include "server_manager.h"
|
||||||
#include "login_server.h"
|
#include "login_server.h"
|
||||||
#include "login_structures.h"
|
#include "login_types.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "../common/eqemu_logsys.h"
|
#include "../common/eqemu_logsys.h"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include "world_server.h"
|
#include "world_server.h"
|
||||||
#include "login_server.h"
|
#include "login_server.h"
|
||||||
#include "login_structures.h"
|
#include "login_types.h"
|
||||||
#include "../common/ip_util.h"
|
#include "../common/ip_util.h"
|
||||||
#include "../common/string_util.h"
|
#include "../common/string_util.h"
|
||||||
|
|
||||||
@ -198,15 +198,15 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne
|
|||||||
LogDebug("User-To-World Response received");
|
LogDebug("User-To-World Response received");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *user_to_world_response = (UsertoWorldResponseLegacy_Struct *) packet.Data();
|
auto *r = (UsertoWorldResponseLegacy_Struct *) packet.Data();
|
||||||
|
|
||||||
LogDebug("Trying to find client with user id of [{0}]", user_to_world_response->lsaccountid);
|
LogDebug("Trying to find client with user id of [{0}]", r->lsaccountid);
|
||||||
Client *client = server.client_manager->GetClient(user_to_world_response->lsaccountid, "eqemu");
|
Client *client = server.client_manager->GetClient(r->lsaccountid, "eqemu");
|
||||||
if (client) {
|
if (client) {
|
||||||
|
|
||||||
LogDebug(
|
LogDebug(
|
||||||
"Found client with user id of [{0}] and account name of [{1}]",
|
"Found client with user id of [{0}] and account name of [{1}]",
|
||||||
user_to_world_response->lsaccountid,
|
r->lsaccountid,
|
||||||
client->GetAccountName()
|
client->GetAccountName()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -217,9 +217,9 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne
|
|||||||
|
|
||||||
auto *per = (PlayEverquestResponse_Struct *) outapp->pBuffer;
|
auto *per = (PlayEverquestResponse_Struct *) outapp->pBuffer;
|
||||||
per->base_header.sequence = client->GetPlaySequence();
|
per->base_header.sequence = client->GetPlaySequence();
|
||||||
per->server_number = client->GetPlayServerID();
|
per->server_number = client->GetPlayServerID();
|
||||||
|
|
||||||
if (user_to_world_response->response > 0) {
|
if (r->response > 0) {
|
||||||
per->base_reply.success = true;
|
per->base_reply.success = true;
|
||||||
SendClientAuth(
|
SendClientAuth(
|
||||||
client->GetConnection()->GetRemoteAddr(),
|
client->GetConnection()->GetRemoteAddr(),
|
||||||
@ -230,27 +230,27 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (user_to_world_response->response) {
|
switch (r->response) {
|
||||||
case UserToWorldStatusSuccess:
|
case UserToWorldStatusSuccess:
|
||||||
per->base_reply.error_str_id = 101;
|
per->base_reply.error_str_id = LS::ErrStr::NO_ERROR;
|
||||||
break;
|
break;
|
||||||
case UserToWorldStatusWorldUnavail:
|
case UserToWorldStatusWorldUnavail:
|
||||||
per->base_reply.error_str_id = 326;
|
per->base_reply.error_str_id = LS::ErrStr::SERVER_UNAVAILABLE;
|
||||||
break;
|
break;
|
||||||
case UserToWorldStatusSuspended:
|
case UserToWorldStatusSuspended:
|
||||||
per->base_reply.error_str_id = 337;
|
per->base_reply.error_str_id = LS::ErrStr::ACCOUNT_SUSPENDED;
|
||||||
break;
|
break;
|
||||||
case UserToWorldStatusBanned:
|
case UserToWorldStatusBanned:
|
||||||
per->base_reply.error_str_id = 338;
|
per->base_reply.error_str_id = LS::ErrStr::ACCOUNT_BANNED;
|
||||||
break;
|
break;
|
||||||
case UserToWorldStatusWorldAtCapacity:
|
case UserToWorldStatusWorldAtCapacity:
|
||||||
per->base_reply.error_str_id = 339;
|
per->base_reply.error_str_id = LS::ErrStr::WORLD_MAX_CAPACITY;
|
||||||
break;
|
break;
|
||||||
case UserToWorldStatusAlreadyOnline:
|
case UserToWorldStatusAlreadyOnline:
|
||||||
per->base_reply.error_str_id = 111;
|
per->base_reply.error_str_id = LS::ErrStr::ERROR_1018_ACTIVE_CHARACTER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
per->base_reply.error_str_id = 102;
|
per->base_reply.error_str_id = LS::ErrStr::UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server.options.IsWorldTraceOn()) {
|
if (server.options.IsWorldTraceOn()) {
|
||||||
@ -275,7 +275,7 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne
|
|||||||
else {
|
else {
|
||||||
LogError(
|
LogError(
|
||||||
"Received User-To-World Response for [{0}] but could not find the client referenced!",
|
"Received User-To-World Response for [{0}] but could not find the client referenced!",
|
||||||
user_to_world_response->lsaccountid
|
r->lsaccountid
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -335,7 +335,7 @@ void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Pac
|
|||||||
|
|
||||||
auto *per = (PlayEverquestResponse_Struct *) outapp->pBuffer;
|
auto *per = (PlayEverquestResponse_Struct *) outapp->pBuffer;
|
||||||
per->base_header.sequence = client->GetPlaySequence();
|
per->base_header.sequence = client->GetPlaySequence();
|
||||||
per->server_number = client->GetPlayServerID();
|
per->server_number = client->GetPlayServerID();
|
||||||
|
|
||||||
LogDebug(
|
LogDebug(
|
||||||
"Found sequence and play of [{0}] [{1}]",
|
"Found sequence and play of [{0}] [{1}]",
|
||||||
@ -358,25 +358,25 @@ void WorldServer::ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Pac
|
|||||||
|
|
||||||
switch (user_to_world_response->response) {
|
switch (user_to_world_response->response) {
|
||||||
case UserToWorldStatusSuccess:
|
case UserToWorldStatusSuccess:
|
||||||
per->base_reply.error_str_id = 101;
|
per->base_reply.error_str_id = LS::ErrStr::NO_ERROR;
|
||||||
break;
|
break;
|
||||||
case UserToWorldStatusWorldUnavail:
|
case UserToWorldStatusWorldUnavail:
|
||||||
per->base_reply.error_str_id = 326;
|
per->base_reply.error_str_id = LS::ErrStr::SERVER_UNAVAILABLE;
|
||||||
break;
|
break;
|
||||||
case UserToWorldStatusSuspended:
|
case UserToWorldStatusSuspended:
|
||||||
per->base_reply.error_str_id = 337;
|
per->base_reply.error_str_id = LS::ErrStr::ACCOUNT_SUSPENDED;
|
||||||
break;
|
break;
|
||||||
case UserToWorldStatusBanned:
|
case UserToWorldStatusBanned:
|
||||||
per->base_reply.error_str_id = 338;
|
per->base_reply.error_str_id = LS::ErrStr::ACCOUNT_BANNED;
|
||||||
break;
|
break;
|
||||||
case UserToWorldStatusWorldAtCapacity:
|
case UserToWorldStatusWorldAtCapacity:
|
||||||
per->base_reply.error_str_id = 339;
|
per->base_reply.error_str_id = LS::ErrStr::WORLD_MAX_CAPACITY;
|
||||||
break;
|
break;
|
||||||
case UserToWorldStatusAlreadyOnline:
|
case UserToWorldStatusAlreadyOnline:
|
||||||
per->base_reply.error_str_id = 111;
|
per->base_reply.error_str_id = LS::ErrStr::ERROR_1018_ACTIVE_CHARACTER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
per->base_reply.error_str_id = 102;
|
per->base_reply.error_str_id = LS::ErrStr::UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server.options.IsTraceOn()) {
|
if (server.options.IsTraceOn()) {
|
||||||
@ -571,6 +571,12 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct *new_world_server_info
|
|||||||
GetServerLongName(),
|
GetServerLongName(),
|
||||||
GetRemoteIp()
|
GetRemoteIp()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
WorldServer::FormatWorldServerName(
|
||||||
|
new_world_server_info_packet->server_long_name,
|
||||||
|
world_registration.server_list_type
|
||||||
|
);
|
||||||
|
SetLongName(new_world_server_info_packet->server_long_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1025,21 +1031,21 @@ bool WorldServer::ValidateWorldServerAdminLogin(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldServer::SerializeForClientServerList(SerializeBuffer& out, bool use_local_ip) const
|
void WorldServer::SerializeForClientServerList(SerializeBuffer &out, bool use_local_ip) const
|
||||||
{
|
{
|
||||||
// see LoginClientServerData_Struct
|
// see LoginClientServerData_Struct
|
||||||
if (use_local_ip) {
|
if (use_local_ip) {
|
||||||
out.WriteString(GetLocalIP());
|
out.WriteString(GetLocalIP());
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
out.WriteString(GetRemoteIP());
|
out.WriteString(GetRemoteIP());
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (GetServerListID())
|
switch (GetServerListID()) {
|
||||||
{
|
case LS::ServerType::Legends:
|
||||||
case 1:
|
|
||||||
out.WriteInt32(LS::ServerTypeFlags::Legends);
|
out.WriteInt32(LS::ServerTypeFlags::Legends);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case LS::ServerType::Preferred:
|
||||||
out.WriteInt32(LS::ServerTypeFlags::Preferred);
|
out.WriteInt32(LS::ServerTypeFlags::Preferred);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1348,3 +1354,37 @@ void WorldServer::OnKeepAlive(EQ::Timer *t)
|
|||||||
ServerPacket pack(ServerOP_KeepAlive, 0);
|
ServerPacket pack(ServerOP_KeepAlive, 0);
|
||||||
m_connection->SendPacket(&pack);
|
m_connection->SendPacket(&pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WorldServer::FormatWorldServerName(char *name, int8 server_list_type)
|
||||||
|
{
|
||||||
|
std::string server_long_name = name;
|
||||||
|
server_long_name = trim(server_long_name);
|
||||||
|
|
||||||
|
bool name_set_to_bottom = false;
|
||||||
|
if (server_list_type == LS::ServerType::Standard) {
|
||||||
|
if (server.options.IsWorldDevTestServersListBottom()) {
|
||||||
|
std::string s = str_tolower(server_long_name);
|
||||||
|
if (s.find("dev") != std::string::npos) {
|
||||||
|
server_long_name = fmt::format("|D| {}", server_long_name);
|
||||||
|
name_set_to_bottom = true;
|
||||||
|
}
|
||||||
|
else if (s.find("test") != std::string::npos) {
|
||||||
|
server_long_name = fmt::format("|T| {}", server_long_name);
|
||||||
|
name_set_to_bottom = true;
|
||||||
|
}
|
||||||
|
else if (s.find("installer") != std::string::npos) {
|
||||||
|
server_long_name = fmt::format("|I| {}", server_long_name);
|
||||||
|
name_set_to_bottom = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (server.options.IsWorldSpecialCharacterStartListBottom() && !name_set_to_bottom) {
|
||||||
|
auto first_char = server_long_name.c_str()[0];
|
||||||
|
if (IsAllowedWorldServerCharacterList(first_char) && first_char != '|') {
|
||||||
|
server_long_name = fmt::format("|*| {}", server_long_name);
|
||||||
|
name_set_to_bottom = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strn0cpy(name, server_long_name.c_str(), 201);
|
||||||
|
}
|
||||||
|
|||||||
@ -194,6 +194,7 @@ private:
|
|||||||
void OnKeepAlive(EQ::Timer *t);
|
void OnKeepAlive(EQ::Timer *t);
|
||||||
std::unique_ptr<EQ::Timer> m_keepalive;
|
std::unique_ptr<EQ::Timer> m_keepalive;
|
||||||
|
|
||||||
|
static void FormatWorldServerName(char *name, int8 server_list_type);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -603,8 +603,6 @@ void LoginServer::SendInfo()
|
|||||||
WorldConfig::SetLocalAddress(l->local_ip_address);
|
WorldConfig::SetLocalAddress(l->local_ip_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
SanitizeWorldServerName(l->server_long_name);
|
|
||||||
|
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"[LoginServer::SendInfo] protocol_version [{}] server_version [{}] long_name [{}] short_name [{}] account_name [{}] remote_ip_address [{}] local_ip [{}]",
|
"[LoginServer::SendInfo] protocol_version [{}] server_version [{}] long_name [{}] short_name [{}] account_name [{}] remote_ip_address [{}] local_ip [{}]",
|
||||||
l->protocol_version,
|
l->protocol_version,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user