mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 10:31: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>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define snprintf _snprintf
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
#define snprintf _snprintf
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef va_copy
|
||||
#define va_copy(d,s) ((d) = (s))
|
||||
#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)
|
||||
const std::string vStringFormat(const char *format, va_list args)
|
||||
{
|
||||
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);
|
||||
va_end(tmpargs);
|
||||
|
||||
@ -52,7 +53,7 @@ const std::string vStringFormat(const char* format, va_list args)
|
||||
if (characters_used > 0) {
|
||||
output.resize(characters_used + 1);
|
||||
|
||||
va_copy(tmpargs,args);
|
||||
va_copy(tmpargs, args);
|
||||
characters_used = vsnprintf(&output[0], output.capacity(), format, 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
|
||||
// could have by this point. Still, return empty string;
|
||||
if (characters_used < 0)
|
||||
if (characters_used < 0) {
|
||||
output.clear();
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@ -87,8 +89,9 @@ const std::string str_toupper(std::string s)
|
||||
const std::string ucfirst(std::string s)
|
||||
{
|
||||
std::string output = s;
|
||||
if (!s.empty())
|
||||
if (!s.empty()) {
|
||||
output[0] = static_cast<char>(::toupper(s[0]));
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
@ -102,18 +105,20 @@ const std::string StringFormat(const char *format, ...)
|
||||
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::string::size_type start = 0;
|
||||
auto end = str.find(delim);
|
||||
std::string::size_type start = 0;
|
||||
auto end = str.find(delim);
|
||||
while (end != std::string::npos) {
|
||||
ret.emplace_back(str, start, end - start);
|
||||
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
|
||||
if (str.length() > start)
|
||||
if (str.length() > start) {
|
||||
ret.emplace_back(str, start, str.length() - start);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -153,14 +158,16 @@ std::string get_between(const std::string &s, std::string start_delim, std::stri
|
||||
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
|
||||
auto pos = haystack.find(needle);
|
||||
while (pos != std::string::npos) {
|
||||
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;
|
||||
}
|
||||
pos = haystack.find(needle, pos + needle.length());
|
||||
}
|
||||
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();
|
||||
final_output.resize (output.str().size () - glue.size());
|
||||
final_output.resize(output.str().size() - glue.size());
|
||||
|
||||
return final_output;
|
||||
}
|
||||
@ -202,80 +209,83 @@ std::vector<std::string> wrap(std::vector<std::string> &src, std::string charact
|
||||
return new_vector;
|
||||
}
|
||||
|
||||
std::string EscapeString(const std::string &s) {
|
||||
std::string EscapeString(const std::string &s)
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
size_t sz = s.length();
|
||||
for(size_t i = 0; i < sz; ++i) {
|
||||
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;
|
||||
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 EscapeString(const char *src, size_t sz)
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
for(size_t i = 0; i < sz; ++i) {
|
||||
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;
|
||||
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) {
|
||||
bool StringIsNumber(const std::string &s)
|
||||
{
|
||||
try {
|
||||
auto r = stod(s);
|
||||
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);
|
||||
}
|
||||
|
||||
void ToUpperString(std::string &s) {
|
||||
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 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) {
|
||||
@ -313,7 +326,7 @@ void find_replace(std::string &string_subject, const std::string &search_string,
|
||||
}
|
||||
|
||||
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);
|
||||
start_pos += replace_string.length();
|
||||
}
|
||||
@ -334,9 +347,9 @@ void ParseAccountString(const std::string &s, std::string &account, std::string
|
||||
auto split = SplitString(s, ':');
|
||||
if (split.size() == 2) {
|
||||
loginserver = split[0];
|
||||
account = split[1];
|
||||
account = split[1];
|
||||
}
|
||||
else if(split.size() == 1) {
|
||||
else if (split.size() == 1) {
|
||||
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
|
||||
// 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)
|
||||
char *strn0cpy(char *dest, const char *source, uint32 size)
|
||||
{
|
||||
if (!dest) {
|
||||
return 0;
|
||||
}
|
||||
if (size == 0 || source == 0) {
|
||||
dest[0] = 0;
|
||||
return dest;
|
||||
@ -359,123 +374,159 @@ char* strn0cpy(char* dest, const char* source, uint32 size) {
|
||||
|
||||
// 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)
|
||||
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);
|
||||
return (bool) (source[strlen(dest)] == 0);
|
||||
}
|
||||
|
||||
const char *MakeLowerString(const char *source) {
|
||||
const char *MakeLowerString(const char *source)
|
||||
{
|
||||
static char str[128];
|
||||
if (!source)
|
||||
if (!source) {
|
||||
return nullptr;
|
||||
}
|
||||
MakeLowerString(source, str);
|
||||
return str;
|
||||
}
|
||||
|
||||
void MakeLowerString(const char *source, char *target) {
|
||||
void MakeLowerString(const char *source, char *target)
|
||||
{
|
||||
if (!source || !target) {
|
||||
*target = 0;
|
||||
return;
|
||||
}
|
||||
while (*source)
|
||||
{
|
||||
while (*source) {
|
||||
*target = tolower(*source);
|
||||
target++; source++;
|
||||
target++;
|
||||
source++;
|
||||
}
|
||||
*target = 0;
|
||||
}
|
||||
|
||||
uint32 hextoi(const char* num) {
|
||||
if (num == nullptr)
|
||||
uint32 hextoi(const char *num)
|
||||
{
|
||||
if (num == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len = strlen(num);
|
||||
if (len < 3)
|
||||
if (len < 3) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
|
||||
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')
|
||||
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')
|
||||
}
|
||||
else if (num[i] >= 'a' && num[i] <= 'f') {
|
||||
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;
|
||||
else
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
mul *= 16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64 hextoi64(const char* num) {
|
||||
if (num == nullptr)
|
||||
uint64 hextoi64(const char *num)
|
||||
{
|
||||
if (num == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len = strlen(num);
|
||||
if (len < 3)
|
||||
if (len < 3) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
|
||||
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')
|
||||
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')
|
||||
}
|
||||
else if (num[i] >= 'a' && num[i] <= 'f') {
|
||||
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;
|
||||
else
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
mul *= 16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool atobool(const char* iBool) {
|
||||
bool atobool(const char *iBool)
|
||||
{
|
||||
|
||||
if (iBool == nullptr)
|
||||
if (iBool == nullptr) {
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "true"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "true")) {
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "false"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "false")) {
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "yes"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "yes")) {
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "no"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "no")) {
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "on"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "on")) {
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "off"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "off")) {
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "enable"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "enable")) {
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "disable"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "disable")) {
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "enabled"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "enabled")) {
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "disabled"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "disabled")) {
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "y"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "y")) {
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "n"))
|
||||
}
|
||||
if (!strcasecmp(iBool, "n")) {
|
||||
return false;
|
||||
if (atoi(iBool))
|
||||
}
|
||||
if (atoi(iBool)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -484,21 +535,19 @@ char *CleanMobName(const char *in, char *out)
|
||||
{
|
||||
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
|
||||
// is the only non alpha char that's not stripped but converted.
|
||||
if (in[i] == '_')
|
||||
{
|
||||
if (in[i] == '_') {
|
||||
out[j++] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isalpha(in[i]) || (in[i] == '`')) // numbers, #, or any other crap just gets skipped
|
||||
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
|
||||
out[j] = 0; // terimnate the string before returning it
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -506,8 +555,9 @@ char *CleanMobName(const char *in, char *out)
|
||||
void RemoveApostrophes(std::string &s)
|
||||
{
|
||||
for (unsigned int i = 0; i < s.length(); ++i)
|
||||
if (s[i] == '\'')
|
||||
if (s[i] == '\'') {
|
||||
s[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
char *RemoveApostrophes(const char *s)
|
||||
@ -517,8 +567,9 @@ char *RemoveApostrophes(const char *s)
|
||||
strcpy(NewString, s);
|
||||
|
||||
for (unsigned int i = 0; i < strlen(NewString); ++i)
|
||||
if (NewString[i] == '\'')
|
||||
if (NewString[i] == '\'') {
|
||||
NewString[i] = '_';
|
||||
}
|
||||
|
||||
return NewString;
|
||||
}
|
||||
@ -537,11 +588,12 @@ const char *ConvertArrayF(float input, char *returnchar)
|
||||
|
||||
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') &&
|
||||
(text[charIndex] < 'A' || text[charIndex] > 'Z') &&
|
||||
(text[charIndex] < '0' || text[charIndex] > '9'))
|
||||
(text[charIndex] < '0' || text[charIndex] > '9')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -596,11 +648,10 @@ std::string numberToWords(unsigned long long int n)
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (!formatted.empty())
|
||||
{
|
||||
if (!formatted.empty()) {
|
||||
std::transform(formatted.begin(), formatted.end(), formatted.begin(), ::tolower);
|
||||
formatted[0] = ::toupper(formatted[0]);
|
||||
}
|
||||
@ -620,6 +671,12 @@ bool IsAllowedWorldServerCharacterList(char c)
|
||||
void SanitizeWorldServerName(char *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(
|
||||
std::remove_if(
|
||||
server_long_name.begin(),
|
||||
@ -632,5 +689,333 @@ void SanitizeWorldServerName(char *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 numberToWords(unsigned long long int n);
|
||||
std::string FormatName(const std::string& char_name);
|
||||
bool IsAllowedWorldServerCharacterList(char c);
|
||||
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>
|
||||
auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result)
|
||||
|
||||
@ -22,7 +22,7 @@ SET(eqlogin_headers
|
||||
loginserver_command_handler.h
|
||||
loginserver_webserver.h
|
||||
login_server.h
|
||||
login_structures.h
|
||||
login_types.h
|
||||
options.h
|
||||
server_manager.h
|
||||
world_server.h
|
||||
|
||||
@ -7,44 +7,9 @@
|
||||
#include "../common/eq_stream_intf.h"
|
||||
#include "../common/net/dns.h"
|
||||
#include "../common/net/daybreak_connection.h"
|
||||
#include "login_structures.h"
|
||||
#include "login_types.h"
|
||||
#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
|
||||
*/
|
||||
|
||||
@ -4,39 +4,34 @@
|
||||
#pragma pack(1)
|
||||
|
||||
// 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, ...)
|
||||
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)
|
||||
int32_t unk3; // unused?
|
||||
};
|
||||
|
||||
struct LoginBaseReplyMessage_Struct
|
||||
{
|
||||
struct LoginBaseReplyMessage_Struct {
|
||||
bool success; // 0: failure (shows error string) 1: success
|
||||
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)
|
||||
};
|
||||
|
||||
struct LoginHandShakeReply_Struct
|
||||
{
|
||||
LoginBaseMessage_Struct base_header;
|
||||
struct LoginHandShakeReply_Struct {
|
||||
LoginBaseMessage_Struct base_header;
|
||||
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)
|
||||
struct PlayerLogin_Struct
|
||||
{
|
||||
struct PlayerLogin_Struct {
|
||||
LoginBaseMessage_Struct base_header;
|
||||
char username[1];
|
||||
char password[1];
|
||||
char username[1];
|
||||
char password[1];
|
||||
};
|
||||
|
||||
// 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
|
||||
//LoginBaseMessage_Struct base_header;
|
||||
LoginBaseReplyMessage_Struct base_reply;
|
||||
@ -59,8 +54,7 @@ struct PlayerLoginReply_Struct
|
||||
};
|
||||
|
||||
// variable length, for reference
|
||||
struct LoginClientServerData_Struct
|
||||
{
|
||||
struct LoginClientServerData_Struct {
|
||||
char ip[1];
|
||||
int32_t server_type; // legends, preferred, standard
|
||||
int32_t server_id;
|
||||
@ -72,29 +66,78 @@ struct LoginClientServerData_Struct
|
||||
};
|
||||
|
||||
// variable length, for reference
|
||||
struct ServerListReply_Struct
|
||||
{
|
||||
LoginBaseMessage_Struct base_header;
|
||||
struct ServerListReply_Struct {
|
||||
LoginBaseMessage_Struct base_header;
|
||||
LoginBaseReplyMessage_Struct base_reply;
|
||||
|
||||
int32_t server_count;
|
||||
int32_t server_count;
|
||||
LoginClientServerData_Struct servers[0];
|
||||
};
|
||||
|
||||
struct PlayEverquestRequest_Struct {
|
||||
LoginBaseMessage_Struct base_header;
|
||||
uint32 server_number;
|
||||
uint32 server_number;
|
||||
};
|
||||
|
||||
// SCJoinServerReply
|
||||
struct PlayEverquestResponse_Struct {
|
||||
LoginBaseMessage_Struct base_header;
|
||||
LoginBaseMessage_Struct base_header;
|
||||
LoginBaseReplyMessage_Struct base_reply;
|
||||
uint32 server_number;
|
||||
uint32 server_number;
|
||||
};
|
||||
|
||||
|
||||
#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
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
"worldservers": {
|
||||
"unregistered_allowed": true,
|
||||
"show_player_count": false,
|
||||
"dev_test_servers_list_bottom": false,
|
||||
"special_character_start_list_bottom": false,
|
||||
"reject_duplicate_servers": false
|
||||
},
|
||||
"web_api": {
|
||||
|
||||
@ -62,9 +62,30 @@ void LoadServerConfig()
|
||||
"worldservers",
|
||||
"reject_duplicate_servers",
|
||||
false
|
||||
));
|
||||
server.options.AllowUnregistered(server.config.GetVariableBool("worldservers", "unregistered_allowed", true));
|
||||
)
|
||||
);
|
||||
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
|
||||
@ -242,6 +263,14 @@ int main(int argc, char **argv)
|
||||
LogInfo("[Config] [WorldServer] IsRejectingDuplicateServers [{0}]", server.options.IsRejectingDuplicateServers());
|
||||
LogInfo("[Config] [WorldServer] IsUnregisteredAllowed [{0}]", server.options.IsUnregisteredAllowed());
|
||||
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] IsTokenLoginAllowed [{0}]", server.options.IsTokenLoginAllowed());
|
||||
LogInfo("[Config] [Security] IsPasswordLoginAllowed [{0}]", server.options.IsPasswordLoginAllowed());
|
||||
|
||||
@ -121,6 +121,20 @@ public:
|
||||
{
|
||||
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:
|
||||
bool allow_unregistered;
|
||||
@ -129,6 +143,8 @@ private:
|
||||
bool dump_in_packets;
|
||||
bool dump_out_packets;
|
||||
bool reject_duplicate_servers;
|
||||
bool world_dev_test_servers_list_bottom;
|
||||
bool world_special_character_start_list_bottom;
|
||||
bool allow_token_login;
|
||||
bool allow_password_login;
|
||||
bool show_player_count;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "server_manager.h"
|
||||
#include "login_server.h"
|
||||
#include "login_structures.h"
|
||||
#include "login_types.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "world_server.h"
|
||||
#include "login_server.h"
|
||||
#include "login_structures.h"
|
||||
#include "login_types.h"
|
||||
#include "../common/ip_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");
|
||||
}
|
||||
|
||||
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);
|
||||
Client *client = server.client_manager->GetClient(user_to_world_response->lsaccountid, "eqemu");
|
||||
LogDebug("Trying to find client with user id of [{0}]", r->lsaccountid);
|
||||
Client *client = server.client_manager->GetClient(r->lsaccountid, "eqemu");
|
||||
if (client) {
|
||||
|
||||
LogDebug(
|
||||
"Found client with user id of [{0}] and account name of [{1}]",
|
||||
user_to_world_response->lsaccountid,
|
||||
r->lsaccountid,
|
||||
client->GetAccountName()
|
||||
);
|
||||
|
||||
@ -217,9 +217,9 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne
|
||||
|
||||
auto *per = (PlayEverquestResponse_Struct *) outapp->pBuffer;
|
||||
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;
|
||||
SendClientAuth(
|
||||
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:
|
||||
per->base_reply.error_str_id = 101;
|
||||
per->base_reply.error_str_id = LS::ErrStr::NO_ERROR;
|
||||
break;
|
||||
case UserToWorldStatusWorldUnavail:
|
||||
per->base_reply.error_str_id = 326;
|
||||
per->base_reply.error_str_id = LS::ErrStr::SERVER_UNAVAILABLE;
|
||||
break;
|
||||
case UserToWorldStatusSuspended:
|
||||
per->base_reply.error_str_id = 337;
|
||||
per->base_reply.error_str_id = LS::ErrStr::ACCOUNT_SUSPENDED;
|
||||
break;
|
||||
case UserToWorldStatusBanned:
|
||||
per->base_reply.error_str_id = 338;
|
||||
per->base_reply.error_str_id = LS::ErrStr::ACCOUNT_BANNED;
|
||||
break;
|
||||
case UserToWorldStatusWorldAtCapacity:
|
||||
per->base_reply.error_str_id = 339;
|
||||
per->base_reply.error_str_id = LS::ErrStr::WORLD_MAX_CAPACITY;
|
||||
break;
|
||||
case UserToWorldStatusAlreadyOnline:
|
||||
per->base_reply.error_str_id = 111;
|
||||
per->base_reply.error_str_id = LS::ErrStr::ERROR_1018_ACTIVE_CHARACTER;
|
||||
break;
|
||||
default:
|
||||
per->base_reply.error_str_id = 102;
|
||||
per->base_reply.error_str_id = LS::ErrStr::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
if (server.options.IsWorldTraceOn()) {
|
||||
@ -275,7 +275,7 @@ void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Ne
|
||||
else {
|
||||
LogError(
|
||||
"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;
|
||||
per->base_header.sequence = client->GetPlaySequence();
|
||||
per->server_number = client->GetPlayServerID();
|
||||
per->server_number = client->GetPlayServerID();
|
||||
|
||||
LogDebug(
|
||||
"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) {
|
||||
case UserToWorldStatusSuccess:
|
||||
per->base_reply.error_str_id = 101;
|
||||
per->base_reply.error_str_id = LS::ErrStr::NO_ERROR;
|
||||
break;
|
||||
case UserToWorldStatusWorldUnavail:
|
||||
per->base_reply.error_str_id = 326;
|
||||
per->base_reply.error_str_id = LS::ErrStr::SERVER_UNAVAILABLE;
|
||||
break;
|
||||
case UserToWorldStatusSuspended:
|
||||
per->base_reply.error_str_id = 337;
|
||||
per->base_reply.error_str_id = LS::ErrStr::ACCOUNT_SUSPENDED;
|
||||
break;
|
||||
case UserToWorldStatusBanned:
|
||||
per->base_reply.error_str_id = 338;
|
||||
per->base_reply.error_str_id = LS::ErrStr::ACCOUNT_BANNED;
|
||||
break;
|
||||
case UserToWorldStatusWorldAtCapacity:
|
||||
per->base_reply.error_str_id = 339;
|
||||
per->base_reply.error_str_id = LS::ErrStr::WORLD_MAX_CAPACITY;
|
||||
break;
|
||||
case UserToWorldStatusAlreadyOnline:
|
||||
per->base_reply.error_str_id = 111;
|
||||
per->base_reply.error_str_id = LS::ErrStr::ERROR_1018_ACTIVE_CHARACTER;
|
||||
break;
|
||||
default:
|
||||
per->base_reply.error_str_id = 102;
|
||||
per->base_reply.error_str_id = LS::ErrStr::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
if (server.options.IsTraceOn()) {
|
||||
@ -571,6 +571,12 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct *new_world_server_info
|
||||
GetServerLongName(),
|
||||
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;
|
||||
}
|
||||
|
||||
void WorldServer::SerializeForClientServerList(SerializeBuffer& out, bool use_local_ip) const
|
||||
void WorldServer::SerializeForClientServerList(SerializeBuffer &out, bool use_local_ip) const
|
||||
{
|
||||
// see LoginClientServerData_Struct
|
||||
if (use_local_ip) {
|
||||
out.WriteString(GetLocalIP());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
out.WriteString(GetRemoteIP());
|
||||
}
|
||||
|
||||
switch (GetServerListID())
|
||||
{
|
||||
case 1:
|
||||
switch (GetServerListID()) {
|
||||
case LS::ServerType::Legends:
|
||||
out.WriteInt32(LS::ServerTypeFlags::Legends);
|
||||
break;
|
||||
case 2:
|
||||
case LS::ServerType::Preferred:
|
||||
out.WriteInt32(LS::ServerTypeFlags::Preferred);
|
||||
break;
|
||||
default:
|
||||
@ -1348,3 +1354,37 @@ void WorldServer::OnKeepAlive(EQ::Timer *t)
|
||||
ServerPacket pack(ServerOP_KeepAlive, 0);
|
||||
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);
|
||||
std::unique_ptr<EQ::Timer> m_keepalive;
|
||||
|
||||
static void FormatWorldServerName(char *name, int8 server_list_type);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -603,8 +603,6 @@ void LoginServer::SendInfo()
|
||||
WorldConfig::SetLocalAddress(l->local_ip_address);
|
||||
}
|
||||
|
||||
SanitizeWorldServerName(l->server_long_name);
|
||||
|
||||
LogInfo(
|
||||
"[LoginServer::SendInfo] protocol_version [{}] server_version [{}] long_name [{}] short_name [{}] account_name [{}] remote_ip_address [{}] local_ip [{}]",
|
||||
l->protocol_version,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user