mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 12:41:30 +00:00
Console initial implementation
This commit is contained in:
parent
3acd845a79
commit
18d28ae8d3
@ -73,6 +73,8 @@ SET(common_sources
|
||||
platform.cpp
|
||||
event/event_loop.cpp
|
||||
json/jsoncpp.cpp
|
||||
net/console_server.cpp
|
||||
net/console_server_connection.cpp
|
||||
net/crc32.cpp
|
||||
net/daybreak_connection.cpp
|
||||
net/eqstream.cpp
|
||||
@ -207,6 +209,8 @@ SET(common_headers
|
||||
event/timer.h
|
||||
json/json.h
|
||||
json/json-forwards.h
|
||||
net/console_server.h
|
||||
net/console_server_connection.h
|
||||
net/crc32.h
|
||||
net/daybreak_connection.h
|
||||
net/daybreak_structs.h
|
||||
@ -270,6 +274,10 @@ SOURCE_GROUP(Json FILES
|
||||
)
|
||||
|
||||
SOURCE_GROUP(Net FILES
|
||||
net/console_server.cpp
|
||||
net/console_server.h
|
||||
net/console_server_connection.cpp
|
||||
net/console_server_connection.h
|
||||
net/crc32.cpp
|
||||
net/crc32.h
|
||||
net/daybreak_connection.cpp
|
||||
|
||||
78
common/net/console_server.cpp
Normal file
78
common/net/console_server.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
#include "console_server.h"
|
||||
#include "../string_util.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
EQ::Net::ConsoleServer::ConsoleServer(const std::string &addr, int port)
|
||||
{
|
||||
m_server.reset(new EQ::Net::TCPServer());
|
||||
m_server->Listen(addr, port, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||
ConsoleServerConnection *c = new ConsoleServerConnection(this, connection);
|
||||
m_connections.insert(std::make_pair(c->GetUUID(), std::unique_ptr<ConsoleServerConnection>(c)));
|
||||
});
|
||||
}
|
||||
|
||||
EQ::Net::ConsoleServer::~ConsoleServer()
|
||||
{
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServer::RegisterCall(const std::string &command, int status_required, const std::string& help_definition, ConsoleServerCallback fn)
|
||||
{
|
||||
m_commands[command] = { fn, status_required, help_definition };
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServer::RegisterLogin(ConsoleServerLoginCallback fn)
|
||||
{
|
||||
m_login = fn;
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServer::ConnectionDisconnected(ConsoleServerConnection *c)
|
||||
{
|
||||
auto iter = m_connections.find(c->GetUUID());
|
||||
if (iter != m_connections.end()) {
|
||||
m_connections.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServer::ProcessCommand(ConsoleServerConnection *c, const std::string &cmd)
|
||||
{
|
||||
auto split = SplitString(cmd, ' ');
|
||||
|
||||
if (split.size() > 0) {
|
||||
auto command = split[0];
|
||||
ToLowerString(command);
|
||||
|
||||
if (command == "help" || command == "?") {
|
||||
c->SendLine("Commands:");
|
||||
for (auto &cmd_def : m_commands) {
|
||||
if (cmd_def.second.status_required <= c->Admin()) {
|
||||
auto display = fmt::format(" {0}", cmd_def.second.help_definition);
|
||||
c->SendLine(display);
|
||||
}
|
||||
}
|
||||
|
||||
c->SendPrompt();
|
||||
return;
|
||||
}
|
||||
|
||||
split.erase(split.begin(), split.begin() + 1);
|
||||
|
||||
auto cmd_def = m_commands.find(command);
|
||||
if (cmd_def != m_commands.end()) {
|
||||
if (c->Admin() >= cmd_def->second.status_required) {
|
||||
cmd_def->second.fn(c, command, split);
|
||||
c->SendPrompt();
|
||||
}
|
||||
else {
|
||||
c->SendLine(fmt::format("Access denied for command: {0}", command));
|
||||
c->SendPrompt();
|
||||
}
|
||||
}
|
||||
else {
|
||||
c->SendLine(fmt::format("Command not found: {0}", command));
|
||||
c->SendPrompt();
|
||||
}
|
||||
}
|
||||
else {
|
||||
c->SendPrompt();
|
||||
}
|
||||
}
|
||||
49
common/net/console_server.h
Normal file
49
common/net/console_server.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "console_server_connection.h"
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
namespace Net
|
||||
{
|
||||
struct ConsoleLoginStatus
|
||||
{
|
||||
int status;
|
||||
int account_id;
|
||||
std::string account_name;
|
||||
};
|
||||
|
||||
class ConsoleServer
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(ConsoleServerConnection*, const std::string&, const std::vector<std::string>&)> ConsoleServerCallback;
|
||||
typedef std::function<struct ConsoleLoginStatus(const std::string&, const std::string&)> ConsoleServerLoginCallback;
|
||||
ConsoleServer(const std::string &addr, int port);
|
||||
~ConsoleServer();
|
||||
|
||||
void RegisterCall(const std::string& command, int status_required, const std::string& help_definition, ConsoleServerCallback fn);
|
||||
void RegisterLogin(ConsoleServerLoginCallback fn);
|
||||
|
||||
private:
|
||||
void ConnectionDisconnected(ConsoleServerConnection *c);
|
||||
void ProcessCommand(ConsoleServerConnection *c, const std::string& cmd);
|
||||
|
||||
std::unique_ptr<TCPServer> m_server;
|
||||
|
||||
std::map<std::string, std::unique_ptr<ConsoleServerConnection>> m_connections;
|
||||
|
||||
struct ConsoleServerCommand
|
||||
{
|
||||
ConsoleServerCallback fn;
|
||||
int status_required;
|
||||
std::string help_definition;
|
||||
};
|
||||
|
||||
std::map<std::string, ConsoleServerCommand> m_commands;
|
||||
ConsoleServerLoginCallback m_login;
|
||||
friend class ConsoleServerConnection;
|
||||
};
|
||||
}
|
||||
}
|
||||
221
common/net/console_server_connection.cpp
Normal file
221
common/net/console_server_connection.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
#include "console_server.h"
|
||||
#include "../common/util/uuid.h"
|
||||
#include "../common/net/packet.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_connection = connection;
|
||||
m_uuid = EQ::Util::UUID::Generate().ToString();
|
||||
m_cursor = 0;
|
||||
memset(m_line, 0, MaxConsoleLineLength);
|
||||
m_accept_messages = false;
|
||||
m_user_id = 0;
|
||||
m_admin = 0;
|
||||
|
||||
m_connection->OnRead(std::bind(&ConsoleServerConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
m_connection->OnDisconnect(std::bind(&ConsoleServerConnection::OnDisconnect, this, std::placeholders::_1));
|
||||
m_connection->Start();
|
||||
ClearBuffer();
|
||||
|
||||
auto addr = m_connection->RemoteIP();
|
||||
|
||||
SendLine(fmt::format("Establishing connection from: {0}:{1}", addr, m_connection->RemotePort()));
|
||||
|
||||
if (addr.find("127.0.0.1") != std::string::npos || addr.find("::0") != std::string::npos) {
|
||||
SendLine("Connection established from localhost, assuming admin");
|
||||
m_status = ConsoleStatusLoggedIn;
|
||||
m_admin = 255;
|
||||
SendPrompt();
|
||||
}
|
||||
else {
|
||||
m_status = ConsoleStatusWaitingForLogin;
|
||||
Send("Username: ");
|
||||
}
|
||||
}
|
||||
|
||||
EQ::Net::ConsoleServerConnection::~ConsoleServerConnection()
|
||||
{
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServerConnection::SendClear()
|
||||
{
|
||||
EQ::Net::DynamicPacket clear;
|
||||
clear.PutUInt8(0, 0);
|
||||
m_connection->Write((const char*)clear.Data(), clear.Length());
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServerConnection::Send(const std::string &msg)
|
||||
{
|
||||
m_connection->Write(msg.c_str(), msg.length());
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServerConnection::SendLine(const std::string &line)
|
||||
{
|
||||
Send(line);
|
||||
SendNewLine();
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServerConnection::SendNewLine()
|
||||
{
|
||||
EQ::Net::DynamicPacket newline;
|
||||
newline.PutUInt8(0, 10);
|
||||
newline.PutUInt8(1, 13);
|
||||
m_connection->Write((const char*)newline.Data(), newline.Length());
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServerConnection::QueueMessage(const std::string &msg)
|
||||
{
|
||||
if (!m_accept_messages) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_cursor == 0) {
|
||||
size_t len = m_user.length() + 2;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
Send("\x08");
|
||||
}
|
||||
|
||||
SendLine(msg);
|
||||
SendPrompt();
|
||||
}
|
||||
else {
|
||||
std::string cmd(m_line, m_line + m_cursor);
|
||||
|
||||
size_t len = m_user.length() + 2 + cmd.length();
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
Send("\x08");
|
||||
}
|
||||
|
||||
if (msg.length() < cmd.length()) {
|
||||
Send(msg);
|
||||
size_t blank_spaces = 2 + cmd.length() - msg.length();
|
||||
|
||||
for (size_t i = 0; i < blank_spaces; ++i) {
|
||||
Send(" ");
|
||||
}
|
||||
|
||||
SendNewLine();
|
||||
}
|
||||
else {
|
||||
SendLine(msg);
|
||||
}
|
||||
|
||||
SendPrompt();
|
||||
Send(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServerConnection::OnRead(TCPConnection *c, const unsigned char *data, size_t sz)
|
||||
{
|
||||
for (size_t i = 0; i < sz; ++i) {
|
||||
unsigned char c = data[i];
|
||||
|
||||
switch (c) {
|
||||
case 0:
|
||||
m_cursor = 0;
|
||||
break;
|
||||
case 10: // \n
|
||||
{
|
||||
if (m_cursor > 0) {
|
||||
std::string cmd(m_line, m_line + m_cursor);
|
||||
ProcessCommand(cmd);
|
||||
m_cursor = 0;
|
||||
}
|
||||
else {
|
||||
ProcessCommand("");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 13: // \r
|
||||
break;
|
||||
case 8:
|
||||
if (m_cursor > 0) {
|
||||
m_cursor--;
|
||||
}
|
||||
break;
|
||||
case 255:
|
||||
//255 is always followed by a character
|
||||
i++;
|
||||
if (i < sz) {
|
||||
unsigned char c = data[i];
|
||||
|
||||
if (c == 255) {
|
||||
//Escaped 255
|
||||
if (m_cursor < MaxConsoleLineLength && isprint(c)) {
|
||||
m_line[m_cursor] = c;
|
||||
m_cursor++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == 251 || c == 252 || c == 253 || c == 254) {
|
||||
//Option code is always followed by an extra character
|
||||
|
||||
//We don't really care about negotiation tho.
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
default:
|
||||
if (m_cursor < MaxConsoleLineLength && isprint(c)) {
|
||||
m_line[m_cursor] = c;
|
||||
m_cursor++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServerConnection::OnDisconnect(TCPConnection *c)
|
||||
{
|
||||
m_parent->ConnectionDisconnected(this);
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServerConnection::ProcessCommand(const std::string &cmd)
|
||||
{
|
||||
if (m_status == ConsoleStatusWaitingForLogin) {
|
||||
m_user = cmd;
|
||||
m_status = ConsoleStatusWaitingForPassword;
|
||||
Send("Password: ");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_status == ConsoleStatusWaitingForPassword) {
|
||||
auto status = m_parent->m_login(m_user, cmd);
|
||||
if (status.account_id == 0) {
|
||||
m_status = ConsoleStatusFailedLogin;
|
||||
SendLine("Access denied");
|
||||
m_connection->Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
if (status.status < ConsoleLoginStatus) {
|
||||
m_status = ConsoleStatusFailedLogin;
|
||||
SendLine("Access denied");
|
||||
m_connection->Disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
m_user = status.account_name;
|
||||
m_user_id = status.account_id;
|
||||
m_admin = status.status;
|
||||
m_status = ConsoleStatusLoggedIn;
|
||||
SendPrompt();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_status == ConsoleStatusLoggedIn) {
|
||||
m_parent->ProcessCommand(this, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::ConsoleServerConnection::SendPrompt()
|
||||
{
|
||||
Send(fmt::format("{0}> ", m_user));
|
||||
}
|
||||
63
common/net/console_server_connection.h
Normal file
63
common/net/console_server_connection.h
Normal file
@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "tcp_server.h"
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
namespace Net
|
||||
{
|
||||
enum ConsoleConnectionStatus
|
||||
{
|
||||
ConsoleStatusWaitingForLogin,
|
||||
ConsoleStatusWaitingForPassword,
|
||||
ConsoleStatusLoggedIn,
|
||||
ConsoleStatusFailedLogin
|
||||
};
|
||||
|
||||
const int MaxConsoleLineLength = 512;
|
||||
const int ConsoleLoginStatus = 50;
|
||||
class ConsoleServer;
|
||||
class ConsoleServerConnection
|
||||
{
|
||||
public:
|
||||
ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr<TCPConnection> connection);
|
||||
~ConsoleServerConnection();
|
||||
|
||||
std::string GetUUID() const { return m_uuid; }
|
||||
void ClearBuffer() { m_cursor = 0; }
|
||||
void Close() { m_connection->Disconnect(); }
|
||||
|
||||
void SendClear();
|
||||
void Send(const std::string &msg);
|
||||
void SendLine(const std::string &line);
|
||||
void SendNewLine();
|
||||
void SendPrompt();
|
||||
ConsoleConnectionStatus Status() const { return m_status; }
|
||||
std::string UserName() const { return m_user; }
|
||||
int UserId() const { return m_user_id; }
|
||||
int Admin() const { return m_admin; }
|
||||
|
||||
bool AcceptMessages() const { return m_accept_messages; }
|
||||
void SetAcceptMessages(bool v) { m_accept_messages = v; }
|
||||
void QueueMessage(const std::string &msg);
|
||||
private:
|
||||
void OnRead(TCPConnection* c, const unsigned char* data, size_t sz);
|
||||
void OnDisconnect(TCPConnection* c);
|
||||
void ProcessCommand(const std::string &cmd);
|
||||
|
||||
ConsoleServer *m_parent;
|
||||
std::shared_ptr<TCPConnection> m_connection;
|
||||
std::string m_uuid;
|
||||
ConsoleConnectionStatus m_status;
|
||||
std::string m_user;
|
||||
int m_user_id;
|
||||
int m_admin;
|
||||
bool m_accept_messages;
|
||||
|
||||
size_t m_cursor;
|
||||
char m_line[MaxConsoleLineLength];
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,16 @@ EQ::Net::TCPServer::~TCPServer() {
|
||||
}
|
||||
|
||||
void EQ::Net::TCPServer::Listen(int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb)
|
||||
{
|
||||
if (ipv6) {
|
||||
Listen("::", port, ipv6, cb);
|
||||
}
|
||||
else {
|
||||
Listen("0.0.0.0", port, ipv6, cb);
|
||||
}
|
||||
}
|
||||
|
||||
void EQ::Net::TCPServer::Listen(const std::string &addr, int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb)
|
||||
{
|
||||
if (m_socket) {
|
||||
return;
|
||||
@ -29,10 +39,10 @@ void EQ::Net::TCPServer::Listen(int port, bool ipv6, std::function<void(std::sha
|
||||
|
||||
sockaddr_storage iaddr;
|
||||
if (ipv6) {
|
||||
uv_ip6_addr("::", port, (sockaddr_in6*)&iaddr);
|
||||
uv_ip6_addr(addr.c_str(), port, (sockaddr_in6*)&iaddr);
|
||||
}
|
||||
else {
|
||||
uv_ip4_addr("0.0.0.0", port, (sockaddr_in*)&iaddr);
|
||||
uv_ip4_addr(addr.c_str(), port, (sockaddr_in*)&iaddr);
|
||||
}
|
||||
|
||||
uv_tcp_bind(m_socket, (sockaddr*)&iaddr, 0);
|
||||
|
||||
@ -13,6 +13,7 @@ namespace EQ
|
||||
~TCPServer();
|
||||
|
||||
void Listen(int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb);
|
||||
void Listen(const std::string &addr, int port, bool ipv6, std::function<void(std::shared_ptr<TCPConnection>)> cb);
|
||||
void Close();
|
||||
void AddClient(uv_tcp_t *c);
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "string_util.h"
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#include <windows.h>
|
||||
@ -71,246 +72,6 @@ const std::string StringFormat(const char* format, ...)
|
||||
return output;
|
||||
}
|
||||
|
||||
// normal strncpy doesnt put a null term on copied strings, this one does
|
||||
// ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp
|
||||
char* strn0cpy(char* dest, const char* source, uint32 size) {
|
||||
if (!dest)
|
||||
return 0;
|
||||
if (size == 0 || source == 0) {
|
||||
dest[0] = 0;
|
||||
return dest;
|
||||
}
|
||||
strncpy(dest, source, size);
|
||||
dest[size - 1] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
// String N w/null Copy Truncated?
|
||||
// return value =true if entire string(source) fit, false if it was truncated
|
||||
bool strn0cpyt(char* dest, const char* source, uint32 size) {
|
||||
if (!dest)
|
||||
return 0;
|
||||
if (size == 0 || source == 0) {
|
||||
dest[0] = 0;
|
||||
return false;
|
||||
}
|
||||
strncpy(dest, source, size);
|
||||
dest[size - 1] = 0;
|
||||
return (bool) (source[strlen(dest)] == 0);
|
||||
}
|
||||
|
||||
const char *MakeLowerString(const char *source) {
|
||||
static char str[128];
|
||||
if (!source)
|
||||
return nullptr;
|
||||
MakeLowerString(source, str);
|
||||
return str;
|
||||
}
|
||||
|
||||
void MakeLowerString(const char *source, char *target) {
|
||||
if (!source || !target) {
|
||||
*target=0;
|
||||
return;
|
||||
}
|
||||
while (*source)
|
||||
{
|
||||
*target = tolower(*source);
|
||||
target++;source++;
|
||||
}
|
||||
*target = 0;
|
||||
}
|
||||
|
||||
int MakeAnyLenString(char** ret, const char* format, ...) {
|
||||
int buf_len = 128;
|
||||
int chars = -1;
|
||||
va_list argptr, tmpargptr;
|
||||
va_start(argptr, format);
|
||||
while (chars == -1 || chars >= buf_len) {
|
||||
safe_delete_array(*ret);
|
||||
if (chars == -1)
|
||||
buf_len *= 2;
|
||||
else
|
||||
buf_len = chars + 1;
|
||||
*ret = new char[buf_len];
|
||||
va_copy(tmpargptr, argptr);
|
||||
chars = vsnprintf(*ret, buf_len, format, tmpargptr);
|
||||
}
|
||||
va_end(argptr);
|
||||
return chars;
|
||||
}
|
||||
|
||||
uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...) {
|
||||
if (*bufsize == 0)
|
||||
*bufsize = 256;
|
||||
if (*ret == 0)
|
||||
*strlen = 0;
|
||||
int chars = -1;
|
||||
char* oldret = 0;
|
||||
va_list argptr, tmpargptr;
|
||||
va_start(argptr, format);
|
||||
while (chars == -1 || chars >= (int32)(*bufsize-*strlen)) {
|
||||
if (chars == -1)
|
||||
*bufsize += 256;
|
||||
else
|
||||
*bufsize += chars + 25;
|
||||
oldret = *ret;
|
||||
*ret = new char[*bufsize];
|
||||
if (oldret) {
|
||||
if (*strlen)
|
||||
memcpy(*ret, oldret, *strlen);
|
||||
safe_delete_array(oldret);
|
||||
}
|
||||
va_copy(tmpargptr, argptr);
|
||||
chars = vsnprintf(&(*ret)[*strlen], (*bufsize-*strlen), format, tmpargptr);
|
||||
}
|
||||
va_end(argptr);
|
||||
*strlen += chars;
|
||||
return *strlen;
|
||||
}
|
||||
|
||||
uint32 hextoi(const char* num) {
|
||||
if (num == nullptr)
|
||||
return 0;
|
||||
|
||||
int len = strlen(num);
|
||||
if (len < 3)
|
||||
return 0;
|
||||
|
||||
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
|
||||
return 0;
|
||||
|
||||
uint32 ret = 0;
|
||||
int mul = 1;
|
||||
for (int i=len-1; i>=2; i--) {
|
||||
if (num[i] >= 'A' && num[i] <= 'F')
|
||||
ret += ((num[i] - 'A') + 10) * mul;
|
||||
else if (num[i] >= 'a' && num[i] <= 'f')
|
||||
ret += ((num[i] - 'a') + 10) * mul;
|
||||
else if (num[i] >= '0' && num[i] <= '9')
|
||||
ret += (num[i] - '0') * mul;
|
||||
else
|
||||
return 0;
|
||||
mul *= 16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64 hextoi64(const char* num) {
|
||||
if (num == nullptr)
|
||||
return 0;
|
||||
|
||||
int len = strlen(num);
|
||||
if (len < 3)
|
||||
return 0;
|
||||
|
||||
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
|
||||
return 0;
|
||||
|
||||
uint64 ret = 0;
|
||||
int mul = 1;
|
||||
for (int i=len-1; i>=2; i--) {
|
||||
if (num[i] >= 'A' && num[i] <= 'F')
|
||||
ret += ((num[i] - 'A') + 10) * mul;
|
||||
else if (num[i] >= 'a' && num[i] <= 'f')
|
||||
ret += ((num[i] - 'a') + 10) * mul;
|
||||
else if (num[i] >= '0' && num[i] <= '9')
|
||||
ret += (num[i] - '0') * mul;
|
||||
else
|
||||
return 0;
|
||||
mul *= 16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool atobool(const char* iBool) {
|
||||
|
||||
if (iBool == nullptr)
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "true"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "false"))
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "yes"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "no"))
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "on"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "off"))
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "enable"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "disable"))
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "enabled"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "disabled"))
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "y"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "n"))
|
||||
return false;
|
||||
if (atoi(iBool))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// removes the crap and turns the underscores into spaces.
|
||||
char *CleanMobName(const char *in, char *out)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
for(i = j = 0; i < strlen(in); i++)
|
||||
{
|
||||
// convert _ to space.. any other conversions like this? I *think* this
|
||||
// is the only non alpha char that's not stripped but converted.
|
||||
if(in[i] == '_')
|
||||
{
|
||||
out[j++] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isalpha(in[i]) || (in[i] == '`')) // numbers, #, or any other crap just gets skipped
|
||||
out[j++] = in[i];
|
||||
}
|
||||
}
|
||||
out[j] = 0; // terimnate the string before returning it
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void RemoveApostrophes(std::string &s)
|
||||
{
|
||||
for(unsigned int i = 0; i < s.length(); ++i)
|
||||
if(s[i] == '\'')
|
||||
s[i] = '_';
|
||||
}
|
||||
|
||||
char *RemoveApostrophes(const char *s)
|
||||
{
|
||||
auto NewString = new char[strlen(s) + 1];
|
||||
|
||||
strcpy(NewString, s);
|
||||
|
||||
for(unsigned int i = 0 ; i < strlen(NewString); ++i)
|
||||
if(NewString[i] == '\'')
|
||||
NewString[i] = '_';
|
||||
|
||||
return NewString;
|
||||
}
|
||||
|
||||
const char *ConvertArray(int input, char *returnchar)
|
||||
{
|
||||
sprintf(returnchar, "%i" ,input);
|
||||
return returnchar;
|
||||
}
|
||||
|
||||
const char *ConvertArrayF(float input, char *returnchar)
|
||||
{
|
||||
sprintf(returnchar, "%0.2f", input);
|
||||
return returnchar;
|
||||
}
|
||||
|
||||
std::vector<std::string> SplitString(const std::string &str, char delim) {
|
||||
std::vector<std::string> ret;
|
||||
std::stringstream ss(str);
|
||||
@ -396,16 +157,35 @@ std::string EscapeString(const char *src, size_t sz) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool isAlphaNumeric(const char *text)
|
||||
{
|
||||
for (unsigned int charIndex=0; charIndex<strlen(text); charIndex++) {
|
||||
if ((text[charIndex] < 'a' || text[charIndex] > 'z') &&
|
||||
(text[charIndex] < 'A' || text[charIndex] > 'Z') &&
|
||||
(text[charIndex] < '0' || text[charIndex] > '9'))
|
||||
return false;
|
||||
bool StringIsNumber(const std::string &s) {
|
||||
try {
|
||||
auto r = stod(s);
|
||||
return true;
|
||||
}
|
||||
catch (std::exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ToLowerString(std::string &s) {
|
||||
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
|
||||
}
|
||||
|
||||
void ToUpperString(std::string &s) {
|
||||
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
|
||||
}
|
||||
|
||||
std::string JoinString(const std::vector<std::string>& ar, const std::string &delim) {
|
||||
std::string ret;
|
||||
for (size_t i = 0; i < ar.size(); ++i) {
|
||||
if (i != 0) {
|
||||
ret += delim;
|
||||
}
|
||||
|
||||
ret += ar[i];
|
||||
}
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string) {
|
||||
@ -415,3 +195,257 @@ void find_replace(std::string& string_subject, const std::string& search_string,
|
||||
index = string_subject.find_first_of(search_string);
|
||||
}
|
||||
}
|
||||
|
||||
//Const char based
|
||||
|
||||
// normal strncpy doesnt put a null term on copied strings, this one does
|
||||
// ref: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecrt/htm/_wcecrt_strncpy_wcsncpy.asp
|
||||
char* strn0cpy(char* dest, const char* source, uint32 size) {
|
||||
if (!dest)
|
||||
return 0;
|
||||
if (size == 0 || source == 0) {
|
||||
dest[0] = 0;
|
||||
return dest;
|
||||
}
|
||||
strncpy(dest, source, size);
|
||||
dest[size - 1] = 0;
|
||||
return dest;
|
||||
}
|
||||
|
||||
// String N w/null Copy Truncated?
|
||||
// return value =true if entire string(source) fit, false if it was truncated
|
||||
bool strn0cpyt(char* dest, const char* source, uint32 size) {
|
||||
if (!dest)
|
||||
return 0;
|
||||
if (size == 0 || source == 0) {
|
||||
dest[0] = 0;
|
||||
return false;
|
||||
}
|
||||
strncpy(dest, source, size);
|
||||
dest[size - 1] = 0;
|
||||
return (bool)(source[strlen(dest)] == 0);
|
||||
}
|
||||
|
||||
const char *MakeLowerString(const char *source) {
|
||||
static char str[128];
|
||||
if (!source)
|
||||
return nullptr;
|
||||
MakeLowerString(source, str);
|
||||
return str;
|
||||
}
|
||||
|
||||
void MakeLowerString(const char *source, char *target) {
|
||||
if (!source || !target) {
|
||||
*target = 0;
|
||||
return;
|
||||
}
|
||||
while (*source)
|
||||
{
|
||||
*target = tolower(*source);
|
||||
target++; source++;
|
||||
}
|
||||
*target = 0;
|
||||
}
|
||||
|
||||
int MakeAnyLenString(char** ret, const char* format, ...) {
|
||||
int buf_len = 128;
|
||||
int chars = -1;
|
||||
va_list argptr, tmpargptr;
|
||||
va_start(argptr, format);
|
||||
while (chars == -1 || chars >= buf_len) {
|
||||
safe_delete_array(*ret);
|
||||
if (chars == -1)
|
||||
buf_len *= 2;
|
||||
else
|
||||
buf_len = chars + 1;
|
||||
*ret = new char[buf_len];
|
||||
va_copy(tmpargptr, argptr);
|
||||
chars = vsnprintf(*ret, buf_len, format, tmpargptr);
|
||||
}
|
||||
va_end(argptr);
|
||||
return chars;
|
||||
}
|
||||
|
||||
uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...) {
|
||||
if (*bufsize == 0)
|
||||
*bufsize = 256;
|
||||
if (*ret == 0)
|
||||
*strlen = 0;
|
||||
int chars = -1;
|
||||
char* oldret = 0;
|
||||
va_list argptr, tmpargptr;
|
||||
va_start(argptr, format);
|
||||
while (chars == -1 || chars >= (int32)(*bufsize - *strlen)) {
|
||||
if (chars == -1)
|
||||
*bufsize += 256;
|
||||
else
|
||||
*bufsize += chars + 25;
|
||||
oldret = *ret;
|
||||
*ret = new char[*bufsize];
|
||||
if (oldret) {
|
||||
if (*strlen)
|
||||
memcpy(*ret, oldret, *strlen);
|
||||
safe_delete_array(oldret);
|
||||
}
|
||||
va_copy(tmpargptr, argptr);
|
||||
chars = vsnprintf(&(*ret)[*strlen], (*bufsize - *strlen), format, tmpargptr);
|
||||
}
|
||||
va_end(argptr);
|
||||
*strlen += chars;
|
||||
return *strlen;
|
||||
}
|
||||
|
||||
uint32 hextoi(const char* num) {
|
||||
if (num == nullptr)
|
||||
return 0;
|
||||
|
||||
int len = strlen(num);
|
||||
if (len < 3)
|
||||
return 0;
|
||||
|
||||
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
|
||||
return 0;
|
||||
|
||||
uint32 ret = 0;
|
||||
int mul = 1;
|
||||
for (int i = len - 1; i >= 2; i--) {
|
||||
if (num[i] >= 'A' && num[i] <= 'F')
|
||||
ret += ((num[i] - 'A') + 10) * mul;
|
||||
else if (num[i] >= 'a' && num[i] <= 'f')
|
||||
ret += ((num[i] - 'a') + 10) * mul;
|
||||
else if (num[i] >= '0' && num[i] <= '9')
|
||||
ret += (num[i] - '0') * mul;
|
||||
else
|
||||
return 0;
|
||||
mul *= 16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64 hextoi64(const char* num) {
|
||||
if (num == nullptr)
|
||||
return 0;
|
||||
|
||||
int len = strlen(num);
|
||||
if (len < 3)
|
||||
return 0;
|
||||
|
||||
if (num[0] != '0' || (num[1] != 'x' && num[1] != 'X'))
|
||||
return 0;
|
||||
|
||||
uint64 ret = 0;
|
||||
int mul = 1;
|
||||
for (int i = len - 1; i >= 2; i--) {
|
||||
if (num[i] >= 'A' && num[i] <= 'F')
|
||||
ret += ((num[i] - 'A') + 10) * mul;
|
||||
else if (num[i] >= 'a' && num[i] <= 'f')
|
||||
ret += ((num[i] - 'a') + 10) * mul;
|
||||
else if (num[i] >= '0' && num[i] <= '9')
|
||||
ret += (num[i] - '0') * mul;
|
||||
else
|
||||
return 0;
|
||||
mul *= 16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool atobool(const char* iBool) {
|
||||
|
||||
if (iBool == nullptr)
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "true"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "false"))
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "yes"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "no"))
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "on"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "off"))
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "enable"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "disable"))
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "enabled"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "disabled"))
|
||||
return false;
|
||||
if (!strcasecmp(iBool, "y"))
|
||||
return true;
|
||||
if (!strcasecmp(iBool, "n"))
|
||||
return false;
|
||||
if (atoi(iBool))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// removes the crap and turns the underscores into spaces.
|
||||
char *CleanMobName(const char *in, char *out)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
for (i = j = 0; i < strlen(in); i++)
|
||||
{
|
||||
// convert _ to space.. any other conversions like this? I *think* this
|
||||
// is the only non alpha char that's not stripped but converted.
|
||||
if (in[i] == '_')
|
||||
{
|
||||
out[j++] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isalpha(in[i]) || (in[i] == '`')) // numbers, #, or any other crap just gets skipped
|
||||
out[j++] = in[i];
|
||||
}
|
||||
}
|
||||
out[j] = 0; // terimnate the string before returning it
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void RemoveApostrophes(std::string &s)
|
||||
{
|
||||
for (unsigned int i = 0; i < s.length(); ++i)
|
||||
if (s[i] == '\'')
|
||||
s[i] = '_';
|
||||
}
|
||||
|
||||
char *RemoveApostrophes(const char *s)
|
||||
{
|
||||
auto NewString = new char[strlen(s) + 1];
|
||||
|
||||
strcpy(NewString, s);
|
||||
|
||||
for (unsigned int i = 0; i < strlen(NewString); ++i)
|
||||
if (NewString[i] == '\'')
|
||||
NewString[i] = '_';
|
||||
|
||||
return NewString;
|
||||
}
|
||||
|
||||
const char *ConvertArray(int input, char *returnchar)
|
||||
{
|
||||
sprintf(returnchar, "%i", input);
|
||||
return returnchar;
|
||||
}
|
||||
|
||||
const char *ConvertArrayF(float input, char *returnchar)
|
||||
{
|
||||
sprintf(returnchar, "%0.2f", input);
|
||||
return returnchar;
|
||||
}
|
||||
|
||||
bool isAlphaNumeric(const char *text)
|
||||
{
|
||||
for (unsigned int charIndex = 0; charIndex<strlen(text); charIndex++) {
|
||||
if ((text[charIndex] < 'a' || text[charIndex] > 'z') &&
|
||||
(text[charIndex] < 'A' || text[charIndex] > 'Z') &&
|
||||
(text[charIndex] < '0' || text[charIndex] > '9'))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -23,34 +23,34 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
//std::string based
|
||||
const std::string StringFormat(const char* format, ...);
|
||||
const std::string vStringFormat(const char* format, va_list args);
|
||||
std::vector<std::string> SplitString(const std::string &s, char delim);
|
||||
std::string EscapeString(const char *src, size_t sz);
|
||||
std::string EscapeString(const std::string &s);
|
||||
bool StringIsNumber(const std::string &s);
|
||||
void ToLowerString(std::string &s);
|
||||
void ToUpperString(std::string &s);
|
||||
std::string JoinString(const std::vector<std::string>& ar, const std::string &delim);
|
||||
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string);
|
||||
|
||||
//const char based
|
||||
|
||||
bool atobool(const char* iBool);
|
||||
bool isAlphaNumeric(const char *text);
|
||||
bool strn0cpyt(char* dest, const char* source, uint32 size);
|
||||
|
||||
char *CleanMobName(const char *in, char *out);
|
||||
char *RemoveApostrophes(const char *s);
|
||||
char* strn0cpy(char* dest, const char* source, uint32 size);
|
||||
|
||||
const char *ConvertArray(int input, char *returnchar);
|
||||
const char *ConvertArrayF(float input, char *returnchar);
|
||||
const char *MakeLowerString(const char *source);
|
||||
const std::string StringFormat(const char* format, ...);
|
||||
const std::string vStringFormat(const char* format, va_list args);
|
||||
|
||||
int MakeAnyLenString(char** ret, const char* format, ...);
|
||||
|
||||
std::string EscapeString(const char *src, size_t sz);
|
||||
std::string EscapeString(const std::string &s);
|
||||
|
||||
std::vector<std::string> SplitString(const std::string &s, char delim);
|
||||
|
||||
uint32 AppendAnyLenString(char** ret, uint32* bufsize, uint32* strlen, const char* format, ...);
|
||||
uint32 hextoi(const char* num);
|
||||
|
||||
uint64 hextoi64(const char* num);
|
||||
|
||||
void MakeLowerString(const char *source, char *target);
|
||||
void RemoveApostrophes(std::string &s);
|
||||
void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string);
|
||||
|
||||
#endif
|
||||
|
||||
@ -20,6 +20,7 @@ SET(world_sources
|
||||
web_interface_eqw.cpp
|
||||
wguild_mgr.cpp
|
||||
world_config.cpp
|
||||
world_console_connection.cpp
|
||||
worlddb.cpp
|
||||
zonelist.cpp
|
||||
zoneserver.cpp
|
||||
@ -47,6 +48,8 @@ SET(world_headers
|
||||
web_interface_eqw.h
|
||||
wguild_mgr.h
|
||||
world_config.h
|
||||
world_console_connection.h
|
||||
world_tcp_connection.h
|
||||
worlddb.h
|
||||
zonelist.h
|
||||
zoneserver.h
|
||||
|
||||
@ -1010,27 +1010,27 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
else
|
||||
AppendAnyLenString(&output, &outsize, &outlen, "\n");
|
||||
iterator.Reset();
|
||||
while(iterator.MoreElements()) {
|
||||
while (iterator.MoreElements()) {
|
||||
cle = iterator.GetData();
|
||||
const char* tmpZone = database.GetZoneName(cle->zone());
|
||||
if (
|
||||
(cle->Online() >= CLE_Status_Zoning)
|
||||
&& (whom == 0 || (
|
||||
((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
(whom->lvllow == 0xFFFF || (cle->level() >= whom->lvllow && cle->level() <= whom->lvlhigh)) &&
|
||||
(whom->wclass == 0xFFFF || cle->class_() == whom->wclass) &&
|
||||
(whom->wrace == 0xFFFF || cle->race() == whom->wrace) &&
|
||||
(whomlen == 0 || (
|
||||
(tmpZone != 0 && strncasecmp(tmpZone, whom->whom, whomlen) == 0) ||
|
||||
strncasecmp(cle->name(),whom->whom, whomlen) == 0 ||
|
||||
(strncasecmp(guild_mgr.GetGuildName(cle->GuildID()), whom->whom, whomlen) == 0) ||
|
||||
(admin >= 100 && strncasecmp(cle->AccountName(), whom->whom, whomlen) == 0)
|
||||
))
|
||||
))
|
||||
) {
|
||||
(cle->Online() >= CLE_Status_Zoning)
|
||||
&& (whom == 0 || (
|
||||
((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
|
||||
(whom->lvllow == 0xFFFF || (cle->level() >= whom->lvllow && cle->level() <= whom->lvlhigh)) &&
|
||||
(whom->wclass == 0xFFFF || cle->class_() == whom->wclass) &&
|
||||
(whom->wrace == 0xFFFF || cle->race() == whom->wrace) &&
|
||||
(whomlen == 0 || (
|
||||
(tmpZone != 0 && strncasecmp(tmpZone, whom->whom, whomlen) == 0) ||
|
||||
strncasecmp(cle->name(), whom->whom, whomlen) == 0 ||
|
||||
(strncasecmp(guild_mgr.GetGuildName(cle->GuildID()), whom->whom, whomlen) == 0) ||
|
||||
(admin >= 100 && strncasecmp(cle->AccountName(), whom->whom, whomlen) == 0)
|
||||
))
|
||||
))
|
||||
) {
|
||||
line[0] = 0;
|
||||
// MYRA - use new (5.x) Status labels in who for telnet connection
|
||||
if (cle->Admin() >=250)
|
||||
// MYRA - use new (5.x) Status labels in who for telnet connection
|
||||
if (cle->Admin() >= 250)
|
||||
strcpy(tmpgm, "* GM-Impossible * ");
|
||||
else if (cle->Admin() >= 200)
|
||||
strcpy(tmpgm, "* GM-Mgmt * ");
|
||||
@ -1062,11 +1062,12 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
strcpy(tmpgm, "* Steward * ");
|
||||
else
|
||||
tmpgm[0] = 0;
|
||||
// end Myra
|
||||
// end Myra
|
||||
|
||||
if (guild_mgr.GuildExists(cle->GuildID())) {
|
||||
snprintf(tmpguild, 36, " <%s>", guild_mgr.GetGuildName(cle->GuildID()));
|
||||
} else
|
||||
}
|
||||
else
|
||||
tmpguild[0] = 0;
|
||||
|
||||
if (cle->LFG())
|
||||
@ -1082,7 +1083,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
|
||||
if (cle->Anon() == 2) { // Roleplay
|
||||
if (admin >= 100 && admin >= cle->Admin())
|
||||
sprintf(line, " %s[RolePlay %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(),cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
|
||||
sprintf(line, " %s[RolePlay %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(), cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
|
||||
else if (cle->Admin() >= 80 && admin < 80 && cle->GetGM()) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
@ -1092,7 +1093,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
}
|
||||
else if (cle->Anon() == 1) { // Anon
|
||||
if (admin >= 100 && admin >= cle->Admin())
|
||||
sprintf(line, " %s[ANON %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(),cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
|
||||
sprintf(line, " %s[ANON %i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(), cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
|
||||
else if (cle->Admin() >= 80 && cle->GetGM()) {
|
||||
iterator.Advance();
|
||||
continue;
|
||||
@ -1101,7 +1102,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
sprintf(line, " %s[ANONYMOUS] %s%s%s", tmpgm, cle->name(), LFG, accinfo);
|
||||
}
|
||||
else
|
||||
sprintf(line, " %s[%i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(),cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
|
||||
sprintf(line, " %s[%i %s] %s (%s)%s zone: %s%s%s", tmpgm, cle->level(), GetClassIDName(cle->class_(), cle->level()), cle->name(), GetRaceIDName(cle->race()), tmpguild, tmpZone, LFG, accinfo);
|
||||
|
||||
AppendAnyLenString(&output, &outsize, &outlen, line);
|
||||
if (outlen >= 3584) {
|
||||
@ -1132,6 +1133,8 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
|
||||
AppendAnyLenString(&output, &outsize, &outlen, "\r\n");
|
||||
else
|
||||
AppendAnyLenString(&output, &outsize, &outlen, "\n");
|
||||
|
||||
//console_list.SendConsoleWho(connection, to, admin, &output, &outsize, &outlen);
|
||||
}
|
||||
if (output)
|
||||
connection->SendEmoteMessageRaw(to, 0, 0, 10, output);
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "../common/rulesys.h"
|
||||
#include "../common/servertalk.h"
|
||||
#include "../common/event/timer.h"
|
||||
#include "../common/net/console_server_connection.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
@ -1,103 +1,505 @@
|
||||
#include "console.h"
|
||||
#include "../common/eqemu_config.h"
|
||||
#include "../common/util/uuid.h"
|
||||
#include "../common/eqemu_logsys.h"
|
||||
#include "../common//net/packet.h"
|
||||
#include "clientlist.h"
|
||||
#include "login_server.h"
|
||||
#include "login_server_list.h"
|
||||
#include "world_config.h"
|
||||
#include "world_console_connection.h"
|
||||
#include "worlddb.h"
|
||||
#include "zonelist.h"
|
||||
#include "zoneserver.h"
|
||||
#include "../common/string_util.h"
|
||||
#include "../common/md5.h"
|
||||
|
||||
ConsoleConnection::ConsoleConnection(ConsoleServer *parent, std::shared_ptr<EQ::Net::TCPConnection> connection)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_connection = connection;
|
||||
m_uuid = EQ::Util::UUID::Generate().ToString();
|
||||
extern ClientList client_list;
|
||||
extern ZSList zoneserver_list;
|
||||
extern LoginServerList loginserverlist;
|
||||
|
||||
m_connection->OnRead(std::bind(&ConsoleConnection::OnRead, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
m_connection->OnDisconnect(std::bind(&ConsoleConnection::OnDisconnect, this, std::placeholders::_1));
|
||||
m_connection->Start();
|
||||
Clear();
|
||||
struct EQ::Net::ConsoleLoginStatus CheckLogin(const std::string& username, const std::string& password) {
|
||||
struct EQ::Net::ConsoleLoginStatus ret;
|
||||
ret.account_id = database.CheckLogin(username.c_str(), password.c_str());
|
||||
if (ret.account_id == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
char account_name[64];
|
||||
database.GetAccountName(ret.account_id, account_name);
|
||||
|
||||
ret.account_name = account_name;
|
||||
ret.status = database.CheckStatus(ret.account_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ConsoleConnection::~ConsoleConnection()
|
||||
{
|
||||
void ConsoleNull(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
}
|
||||
|
||||
void ConsoleConnection::Clear()
|
||||
{
|
||||
EQ::Net::DynamicPacket clear;
|
||||
clear.PutUInt8(0, 0);
|
||||
m_connection->Write((const char*)clear.Data(), clear.Length());
|
||||
void ConsoleWhoami(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
connection->SendLine(fmt::format("You are logged in as '{0}'", connection->UserName()));
|
||||
connection->SendLine(fmt::format("You are known as '*{0}'", connection->UserName()));
|
||||
connection->SendLine(fmt::format("AccessLevel: '{0}'", connection->Admin()));
|
||||
}
|
||||
|
||||
void ConsoleConnection::SendLine(const std::string &line)
|
||||
{
|
||||
m_connection->Write(line.c_str(), line.length());
|
||||
SendNewLine();
|
||||
void ConsoleZoneStatus(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
WorldConsoleTCPConnection console_connection(connection);
|
||||
zoneserver_list.SendZoneStatus(0, connection->Admin(), &console_connection);
|
||||
}
|
||||
|
||||
void ConsoleConnection::SendNewLine()
|
||||
{
|
||||
EQ::Net::DynamicPacket newline;
|
||||
newline.PutUInt8(0, 10);
|
||||
newline.PutUInt8(1, 13);
|
||||
m_connection->Write((const char*)newline.Data(), newline.Length());
|
||||
void ConsoleWho(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
Who_All_Struct whom;
|
||||
memset(&whom, 0, sizeof(whom));
|
||||
whom.lvllow = 0xFFFF;
|
||||
whom.lvlhigh = 0xFFFF;
|
||||
whom.wclass = 0xFFFF;
|
||||
whom.wrace = 0xFFFF;
|
||||
whom.gmlookup = 0xFFFF;
|
||||
|
||||
for (auto &arg : args) {
|
||||
if (strcasecmp(arg.c_str(), "gm") == 0) {
|
||||
whom.gmlookup = 1;
|
||||
}
|
||||
else if (StringIsNumber(arg)) {
|
||||
if (whom.lvllow == 0xFFFF) {
|
||||
whom.lvllow = atoi(arg.c_str());
|
||||
whom.lvlhigh = whom.lvllow;
|
||||
}
|
||||
else if (atoi(arg.c_str()) > int(whom.lvllow))
|
||||
whom.lvlhigh = atoi(arg.c_str());
|
||||
else
|
||||
whom.lvllow = atoi(arg.c_str());
|
||||
}
|
||||
else {
|
||||
strn0cpy(whom.whom, arg.c_str(), sizeof(whom.whom));
|
||||
}
|
||||
}
|
||||
|
||||
WorldConsoleTCPConnection console_connection(connection);
|
||||
client_list.ConsoleSendWhoAll(0, connection->Admin(), &whom, &console_connection);
|
||||
}
|
||||
|
||||
void ConsoleConnection::OnRead(EQ::Net::TCPConnection *c, const unsigned char *data, size_t sz)
|
||||
{
|
||||
m_buffer.insert(m_buffer.end(), (const char*)data, (const char*)data + sz);
|
||||
ProcessReadBuffer();
|
||||
void ConsoleUptime(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringIsNumber(args[0]) && atoi(args[0].c_str()) > 0) {
|
||||
auto pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct));
|
||||
ServerUptime_Struct* sus = (ServerUptime_Struct*)pack->pBuffer;
|
||||
snprintf(sus->adminname, sizeof(sus->adminname), "*%s", connection->UserName());
|
||||
sus->zoneserverid = atoi(args[0].c_str());
|
||||
ZoneServer* zs = zoneserver_list.FindByID(sus->zoneserverid);
|
||||
if (zs)
|
||||
zs->SendPacket(pack);
|
||||
else
|
||||
connection->SendLine("Zoneserver not found.");
|
||||
delete pack;
|
||||
}
|
||||
else {
|
||||
WorldConsoleTCPConnection console_connection(connection);
|
||||
ZSList::ShowUpTime(&console_connection);
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleConnection::ProcessReadBuffer()
|
||||
{
|
||||
size_t buffer_start = 0;
|
||||
for (size_t i = 0; i < m_buffer.size(); ++i) {
|
||||
char c = m_buffer[i];
|
||||
void ConsoleMd5(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8 md5[16];
|
||||
MD5::Generate((const uchar*)args[0].c_str(), strlen(args[0].c_str()), md5);
|
||||
connection->SendLine(StringFormat("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
md5[0], md5[1], md5[2], md5[3], md5[4], md5[5], md5[6], md5[7], md5[8], md5[9], md5[10], md5[11], md5[12], md5[13], md5[14], md5[15]));
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 0:
|
||||
//Clear buffer
|
||||
break;
|
||||
case 10:
|
||||
case 13:
|
||||
//New Line
|
||||
break;
|
||||
case 8:
|
||||
//Backspace
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
void ConsoleEmote(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto join_args = args;
|
||||
join_args.erase(join_args.begin(), join_args.begin() + 2);
|
||||
|
||||
if (strcasecmp(args[0].c_str(), "world") == 0)
|
||||
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, atoi(args[1].c_str()), JoinString(join_args, " ").c_str());
|
||||
else {
|
||||
ZoneServer* zs = zoneserver_list.FindByName(args[0].c_str());
|
||||
if (zs != 0)
|
||||
zs->SendEmoteMessageRaw(0, 0, 0, atoi(args[1].c_str()), JoinString(join_args, " ").c_str());
|
||||
else
|
||||
zoneserver_list.SendEmoteMessageRaw(args[0].c_str(), 0, 0, atoi(args[1].c_str()), JoinString(join_args, " ").c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleAcceptMessages(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 1) {
|
||||
connection->SendLine("Usage: acceptmessages [on/off]");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(args[0].c_str(), "on") == 0)
|
||||
connection->SetAcceptMessages(true);
|
||||
else if (strcasecmp(args[0].c_str(), "off") == 0)
|
||||
connection->SetAcceptMessages(false);
|
||||
else
|
||||
connection->SendLine("Usage: acceptmessages [on/off]");
|
||||
}
|
||||
|
||||
void ConsoleTell(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
std::string to = args[0];
|
||||
|
||||
auto join_args = args;
|
||||
join_args.erase(join_args.begin(), join_args.begin() + 1);
|
||||
|
||||
zoneserver_list.SendChannelMessage(tmpname, to.c_str(), 7, 0, JoinString(join_args, " ").c_str());
|
||||
}
|
||||
|
||||
void ConsoleBroadcast(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, JoinString(args, " ").c_str());
|
||||
}
|
||||
|
||||
void ConsoleGMSay(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, JoinString(args, " ").c_str());
|
||||
}
|
||||
|
||||
void ConsoleOOC(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, JoinString(args, " ").c_str());
|
||||
}
|
||||
|
||||
void ConsoleAuction(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, JoinString(args, " ").c_str());
|
||||
}
|
||||
|
||||
void ConsoleKick(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
auto pack = new ServerPacket;
|
||||
pack->opcode = ServerOP_KickPlayer;
|
||||
pack->size = sizeof(ServerKickPlayer_Struct);
|
||||
pack->pBuffer = new uchar[pack->size];
|
||||
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*)pack->pBuffer;
|
||||
strcpy(skp->adminname, tmpname);
|
||||
strcpy(skp->name, args[0].c_str());
|
||||
skp->adminrank = connection->Admin();
|
||||
zoneserver_list.SendPacket(pack);
|
||||
delete pack;
|
||||
}
|
||||
|
||||
void ConsoleLock(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
WorldConfig::LockWorld();
|
||||
if (loginserverlist.Connected()) {
|
||||
loginserverlist.SendStatus();
|
||||
connection->SendLine("World locked.");
|
||||
}
|
||||
else {
|
||||
connection->SendLine("World locked, but login server not connected.");
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleUnlock(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
WorldConfig::UnlockWorld();
|
||||
if (loginserverlist.Connected()) {
|
||||
loginserverlist.SendStatus();
|
||||
connection->SendLine("World unlocked.");
|
||||
}
|
||||
else {
|
||||
connection->SendLine("World unlocked, but login server not connected.");
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleZoneShutdown(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 1) {
|
||||
connection->SendLine("Usage: zoneshutdown zoneshortname");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[0].length() == 0) {
|
||||
connection->SendLine("Usage: zoneshutdown zoneshortname");
|
||||
}
|
||||
else {
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
|
||||
auto pack = new ServerPacket;
|
||||
pack->size = sizeof(ServerZoneStateChange_struct);
|
||||
pack->pBuffer = new uchar[pack->size];
|
||||
memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_struct));
|
||||
ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *)pack->pBuffer;
|
||||
pack->opcode = ServerOP_ZoneShutdown;
|
||||
strcpy(s->adminname, tmpname);
|
||||
if (StringIsNumber(args[0]))
|
||||
s->ZoneServerID = atoi(args[0].c_str());
|
||||
else
|
||||
s->zoneid = database.GetZoneID(args[0].c_str());
|
||||
|
||||
ZoneServer* zs = 0;
|
||||
if (s->ZoneServerID != 0)
|
||||
zs = zoneserver_list.FindByID(s->ZoneServerID);
|
||||
else if (s->zoneid != 0)
|
||||
zs = zoneserver_list.FindByName(database.GetZoneName(s->zoneid));
|
||||
else
|
||||
connection->SendLine("Error: ZoneShutdown: neither ID nor name specified");
|
||||
|
||||
if (zs == 0)
|
||||
connection->SendLine("Error: ZoneShutdown: zoneserver not found");
|
||||
else
|
||||
zs->SendPacket(pack);
|
||||
|
||||
delete pack;
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleZoneBootup(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[1].length() == 0 || !StringIsNumber(args[0])) {
|
||||
connection->SendLine("Usage: zonebootup ZoneServerID# zoneshortname");
|
||||
}
|
||||
else {
|
||||
char tmpname[64];
|
||||
tmpname[0] = '*';
|
||||
strcpy(&tmpname[1], connection->UserName().c_str());
|
||||
|
||||
Log(Logs::Detail, Logs::World_Server, "Console ZoneBootup: %s, %s, %s", tmpname, args[1].c_str(), args[0].c_str());
|
||||
|
||||
if (args.size() > 2) {
|
||||
zoneserver_list.SOPZoneBootup(tmpname, atoi(args[0].c_str()), args[1].c_str(), (bool)(strcasecmp(args[1].c_str(), "static") == 0));
|
||||
}
|
||||
else {
|
||||
zoneserver_list.SOPZoneBootup(tmpname, atoi(args[0].c_str()), args[1].c_str(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleConnection::ProcessCommand(const std::string &cmd)
|
||||
{
|
||||
}
|
||||
void ConsoleZoneLock(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(args[0].c_str(), "list") == 0) {
|
||||
WorldConsoleTCPConnection console_connection(connection);
|
||||
zoneserver_list.ListLockedZones(0, &console_connection);
|
||||
}
|
||||
else if (strcasecmp(args[0].c_str(), "lock") == 0 && connection->Admin() >= 101) {
|
||||
if (args.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
void ConsoleConnection::OnDisconnect(EQ::Net::TCPConnection *c)
|
||||
{
|
||||
m_parent->ConnectionDisconnected(this);
|
||||
}
|
||||
|
||||
ConsoleServer::ConsoleServer()
|
||||
{
|
||||
auto config = EQEmuConfig::get();
|
||||
|
||||
m_server.reset(new EQ::Net::TCPServer());
|
||||
m_server->Listen(config->TelnetTCPPort, false, [this](std::shared_ptr<EQ::Net::TCPConnection> connection) {
|
||||
ConsoleConnection *c = new ConsoleConnection(this, connection);
|
||||
m_connections.insert(std::make_pair(c->GetUUID(), std::unique_ptr<ConsoleConnection>(c)));
|
||||
});
|
||||
}
|
||||
|
||||
ConsoleServer::~ConsoleServer()
|
||||
{
|
||||
}
|
||||
|
||||
void ConsoleServer::ConnectionDisconnected(ConsoleConnection *c)
|
||||
{
|
||||
auto iter = m_connections.find(c->GetUUID());
|
||||
if (iter != m_connections.end()) {
|
||||
m_connections.erase(iter);
|
||||
uint16 tmp = database.GetZoneID(args[1].c_str());
|
||||
if (tmp) {
|
||||
if (zoneserver_list.SetLockedZone(tmp, true))
|
||||
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone locked: %s", database.GetZoneName(tmp));
|
||||
else
|
||||
connection->SendLine("Failed to change lock");
|
||||
}
|
||||
else
|
||||
connection->SendLine("Usage: #zonelock lock [zonename]");
|
||||
}
|
||||
else if (strcasecmp(args[0].c_str(), "unlock") == 0 && connection->Admin() >= 101) {
|
||||
if (args.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 tmp = database.GetZoneID(args[1].c_str());
|
||||
if (tmp) {
|
||||
if (zoneserver_list.SetLockedZone(tmp, false))
|
||||
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone unlocked: %s", database.GetZoneName(tmp));
|
||||
else
|
||||
connection->SendLine("Failed to change lock");
|
||||
}
|
||||
else
|
||||
connection->SendLine("Usage: #zonelock unlock [zonename]");
|
||||
}
|
||||
else {
|
||||
connection->SendLine("#zonelock sub-commands");
|
||||
connection->SendLine(" list");
|
||||
if (connection->Admin() >= 101) {
|
||||
connection->SendLine(" lock [zonename]");
|
||||
connection->SendLine(" unlock [zonename]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleFlag(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[1].length() == 0 || !StringIsNumber(args[0]))
|
||||
connection->SendLine("Usage: flag [status] [accountname]");
|
||||
else
|
||||
{
|
||||
if (atoi(args[0].c_str()) > connection->Admin())
|
||||
connection->SendLine("You cannot set people's status to higher than your own");
|
||||
else if (!database.SetAccountStatus(args[1].c_str(), atoi(args[0].c_str())))
|
||||
connection->SendLine("Unable to flag account!");
|
||||
else
|
||||
connection->SendLine("Account Flaged");
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleSetPass(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() != 2) {
|
||||
connection->SendLine("Format: setpass accountname password");
|
||||
}
|
||||
else {
|
||||
int16 tmpstatus = 0;
|
||||
uint32 tmpid = database.GetAccountIDByName(args[0].c_str(), &tmpstatus);
|
||||
if (!tmpid)
|
||||
connection->SendLine("Error: Account not found");
|
||||
else if (tmpstatus > connection->Admin())
|
||||
connection->SendLine("Cannot change password: Account's status is higher than yours");
|
||||
else if (database.SetLocalPassword(tmpid, args[1].c_str()))
|
||||
connection->SendLine("Password changed.");
|
||||
else
|
||||
connection->SendLine("Error changing password.");
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleVersion(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
connection->SendLine(StringFormat("Current version information."));
|
||||
connection->SendLine(StringFormat(" %s", CURRENT_VERSION));
|
||||
connection->SendLine(StringFormat(" Compiled on: %s at %s", COMPILE_DATE, COMPILE_TIME));
|
||||
connection->SendLine(StringFormat(" Last modified on: %s", LAST_MODIFIED));
|
||||
}
|
||||
|
||||
void ConsoleWorldShutdown(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() == 2) {
|
||||
int32 time, interval;
|
||||
if (StringIsNumber(args[0]) && StringIsNumber(args[1]) && ((time = atoi(args[0].c_str()))>0) && ((interval = atoi(args[1].c_str()))>0)) {
|
||||
zoneserver_list.WorldShutDown(time, interval);
|
||||
}
|
||||
else {
|
||||
connection->SendLine("Usage: worldshutdown [now] [disable] ([time] [interval])");
|
||||
}
|
||||
}
|
||||
else if(args.size() == 1) {
|
||||
if (strcasecmp(args[0].c_str(), "now") == 0) {
|
||||
zoneserver_list.WorldShutDown(0, 0);
|
||||
}
|
||||
else if (strcasecmp(args[0].c_str(), "disable") == 0) {
|
||||
connection->SendLine("<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World shutdown aborted.");
|
||||
zoneserver_list.SendEmoteMessage(0, 0, 0, 15, "<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World shutdown aborted.");
|
||||
zoneserver_list.shutdowntimer->Disable();
|
||||
zoneserver_list.reminder->Disable();
|
||||
}
|
||||
else {
|
||||
connection->SendLine("Usage: worldshutdown [now] [disable] ([time] [interval])");
|
||||
}
|
||||
}
|
||||
else {
|
||||
connection->SendLine("Usage: worldshutdown [now] [disable] ([time] [interval])");
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleIpLookup(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() > 0) {
|
||||
WorldConsoleTCPConnection console_connection(connection);
|
||||
client_list.SendCLEList(connection->Admin(), 0, &console_connection, args[0].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleSignalCharByName(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
if (args.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
connection->SendLine(StringFormat("Signal Sent to %s with ID %i", (char*) args[0].c_str(), atoi(args[1].c_str())));
|
||||
uint32 message_len = strlen((char*) args[0].c_str()) + 1;
|
||||
auto pack = new ServerPacket(ServerOP_CZSignalClientByName,
|
||||
sizeof(CZClientSignalByName_Struct) + message_len);
|
||||
CZClientSignalByName_Struct* CZSC = (CZClientSignalByName_Struct*) pack->pBuffer;
|
||||
strn0cpy(CZSC->Name, (char*) args[0].c_str(), 64);
|
||||
CZSC->data = atoi(args[1].c_str());
|
||||
zoneserver_list.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
void ConsoleReloadWorld(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
connection->SendLine("Reloading World...");
|
||||
auto pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct));
|
||||
ReloadWorld_Struct* RW = (ReloadWorld_Struct*)pack->pBuffer;
|
||||
RW->Option = 1;
|
||||
zoneserver_list.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
void ConsoleQuit(EQ::Net::ConsoleServerConnection* connection, const std::string& command, const std::vector<std::string>& args) {
|
||||
connection->SendLine("Exiting...");
|
||||
connection->Close();
|
||||
}
|
||||
|
||||
void RegisterConsoleFunctions(std::unique_ptr<EQ::Net::ConsoleServer>& console)
|
||||
{
|
||||
console->RegisterLogin(std::bind(CheckLogin, std::placeholders::_1, std::placeholders::_2));
|
||||
console->RegisterCall("whoami", 50, "whoami", std::bind(ConsoleWhoami, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("who", 50, "who", std::bind(ConsoleWho, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("zonestatus", 50, "zonestatus", std::bind(ConsoleZoneStatus, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("uptime", 50, "uptime [zoneID#]", std::bind(ConsoleUptime, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("md5", 50, "md5", std::bind(ConsoleMd5, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("emote", 50, "emote [zonename or charname or world] [type] [message]", std::bind(ConsoleEmote, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("echo", 50, "echo [on/off]", std::bind(ConsoleNull, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("acceptmessages", 50, "acceptmessages [on/off]", std::bind(ConsoleAcceptMessages, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("tell", 50, "tell [name] [message]", std::bind(ConsoleTell, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("broadcast", 50, "broadcast [message]", std::bind(ConsoleBroadcast, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("gmsay", 50, "gmsay [message]", std::bind(ConsoleGMSay, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("ooc", 50, "ooc [message]", std::bind(ConsoleOOC, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("auction", 50, "auction [message]", std::bind(ConsoleAuction, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("kick", 150, "kick [charname]", std::bind(ConsoleKick, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("lock", 150, "lock", std::bind(ConsoleLock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("unlock", 150, "unlock", std::bind(ConsoleUnlock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("zoneshutdown", 150, "zoneshutdown [zonename or ZoneServerID]", std::bind(ConsoleZoneShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("zonebootup", 150, "zonebootup [ZoneServerID] [zonename]", std::bind(ConsoleZoneBootup, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("zonelock", 150, "zonelock [list|lock|unlock] [zonename]", std::bind(ConsoleZoneLock, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("flag", 200, "flag [status] [accountname]", std::bind(ConsoleFlag, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("setpass", 200, "setpass [accountname] [newpass]", std::bind(ConsoleSetPass, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("version", 50, "version", std::bind(ConsoleVersion, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("worldshutdown", 200, "worldshutdown", std::bind(ConsoleWorldShutdown, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("iplookup", 50, "IPLookup [name]", std::bind(ConsoleIpLookup, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("lsreconnect", 50, "LSReconnect", std::bind(ConsoleNull, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("signalcharbyname", 50, "signalcharbyname charname ID", std::bind(ConsoleSignalCharByName, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("reloadworld", 200, "reloadworld", std::bind(ConsoleReloadWorld, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("ping", 50, "ping", std::bind(ConsoleNull, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("quit", 50, "quit", std::bind(ConsoleQuit, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
console->RegisterCall("exit", 50, "exit", std::bind(ConsoleQuit, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
}
|
||||
|
||||
@ -1,45 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../common/net/tcp_server.h"
|
||||
#include "../common/event/timer.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "../common/net/console_server.h"
|
||||
|
||||
class ConsoleServer;
|
||||
class ConsoleConnection
|
||||
{
|
||||
public:
|
||||
ConsoleConnection(ConsoleServer *parent, std::shared_ptr<EQ::Net::TCPConnection> connection);
|
||||
~ConsoleConnection();
|
||||
|
||||
std::string GetUUID() const { return m_uuid; }
|
||||
|
||||
void Clear();
|
||||
void SendLine(const std::string &line);
|
||||
void SendNewLine();
|
||||
private:
|
||||
void OnRead(EQ::Net::TCPConnection* c, const unsigned char* data, size_t sz);
|
||||
void ProcessReadBuffer();
|
||||
void ProcessCommand(const std::string& cmd);
|
||||
void OnDisconnect(EQ::Net::TCPConnection* c);
|
||||
|
||||
ConsoleServer *m_parent;
|
||||
std::shared_ptr<EQ::Net::TCPConnection> m_connection;
|
||||
std::string m_uuid;
|
||||
|
||||
std::vector<char> m_buffer;
|
||||
};
|
||||
|
||||
class ConsoleServer
|
||||
{
|
||||
public:
|
||||
ConsoleServer();
|
||||
~ConsoleServer();
|
||||
|
||||
void ConnectionDisconnected(ConsoleConnection *c);
|
||||
private:
|
||||
|
||||
std::unique_ptr<EQ::Net::TCPServer> m_server;
|
||||
std::map<std::string, std::unique_ptr<ConsoleConnection>> m_connections;
|
||||
friend class ConsoleConnection;
|
||||
};
|
||||
void RegisterConsoleFunctions(std::unique_ptr<EQ::Net::ConsoleServer> &console);
|
||||
|
||||
@ -83,7 +83,6 @@ union semun {
|
||||
#include "web_interface.h"
|
||||
#include "console.h"
|
||||
|
||||
#include "../common/net/tcp_server.h"
|
||||
#include "../common/net/servertalk_server.h"
|
||||
|
||||
ClientList client_list;
|
||||
@ -376,10 +375,11 @@ int main(int argc, char** argv) {
|
||||
database.LoadCharacterCreateAllocations();
|
||||
database.LoadCharacterCreateCombos();
|
||||
|
||||
std::unique_ptr<ConsoleServer> console;
|
||||
std::unique_ptr<EQ::Net::ConsoleServer> console;
|
||||
if (Config->TelnetEnabled) {
|
||||
Log(Logs::General, Logs::World_Server, "Console (TCP) listener started.");
|
||||
console.reset(new ConsoleServer());
|
||||
console.reset(new EQ::Net::ConsoleServer(Config->TelnetIP, Config->TelnetTCPPort));
|
||||
RegisterConsoleFunctions(console);
|
||||
}
|
||||
|
||||
std::unique_ptr<EQ::Net::ServertalkServer> server_connection;
|
||||
|
||||
19
world/world_console_connection.cpp
Normal file
19
world/world_console_connection.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "world_console_connection.h"
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
void WorldConsoleTCPConnection::SendEmoteMessage(const char *to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char *message, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char buffer[1024];
|
||||
|
||||
va_start(argptr, message);
|
||||
vsnprintf(buffer, sizeof(buffer), message, argptr);
|
||||
va_end(argptr);
|
||||
SendEmoteMessageRaw(to, to_guilddbid, to_minstatus, type, buffer);
|
||||
}
|
||||
|
||||
void WorldConsoleTCPConnection::SendEmoteMessageRaw(const char *to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char *message)
|
||||
{
|
||||
m_connection->SendLine(message);
|
||||
}
|
||||
36
world/world_console_connection.h
Normal file
36
world/world_console_connection.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2017 EQEMu Development Team (http://eqemu.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "world_tcp_connection.h"
|
||||
#include "../common/net/console_server_connection.h"
|
||||
|
||||
class WorldConsoleTCPConnection : public WorldTCPConnection
|
||||
{
|
||||
public:
|
||||
WorldConsoleTCPConnection(EQ::Net::ConsoleServerConnection *c) { m_connection = c; }
|
||||
virtual ~WorldConsoleTCPConnection() { }
|
||||
virtual void SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...);
|
||||
virtual void SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message);
|
||||
|
||||
virtual inline bool IsConsole() { return true; }
|
||||
virtual inline bool IsZoneServer() { return false; }
|
||||
private:
|
||||
EQ::Net::ConsoleServerConnection *m_connection;
|
||||
};
|
||||
|
||||
@ -481,9 +481,10 @@ int main(int argc, char** argv) {
|
||||
worldwasconnected = true;
|
||||
}
|
||||
else {
|
||||
if (worldwasconnected && is_zone_loaded)
|
||||
if (worldwasconnected && is_zone_loaded) {
|
||||
entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost");
|
||||
worldwasconnected = false;
|
||||
worldwasconnected = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_zone_loaded) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user