• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Kicking via WWW

slaw

Software Developer
Joined
Aug 27, 2007
Messages
3,784
Solutions
133
Reaction score
1,275
Location
Germany
GitHub
slawkens
Sometimes player get kicked by his net, and he cant login becouse of known "You are already logged in". Or when someone is hacked he cant login.

So i want make option, that you can kick your player on page. When you are logged in, there will be option "Kick me". So is there any way to do, that page (only from localhost) is sending to server request to kick player X?

Someone can make it? :D

Thanks.
 
Best way would probably be to add that possibility in admin protocol if it isn't already possible (never really used the admin protocol), and then use the PHP 'system' function to execute the admin tool with parameters to kick the player. There might be a better function than 'system' to use in PHP, I'm not more than a newbie in PHP, but 'system' should work atleast.
 
*bump*
I was lasy to compare and post here step by step.
Anyway here it is, 100% working:

admin.cpp
Code:
//////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
// 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; either version 2
// of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//////////////////////////////////////////////////////////////////////
#include "otpch.h"

#include "admin.h"
#include "game.h"
#include "connection.h"
#include "networkmessage.h"
#include "configmanager.h"
#include "house.h"
#include "ban.h"
#include "tools.h"
#include "rsa.h"

#include "logger.h"

static void addLogLine(ProtocolAdmin* conn, eLogType type, int level, std::string message);

extern Game g_game;
extern ConfigManager g_config;
extern Ban g_bans;

AdminProtocolConfig* g_adminConfig = NULL;

ProtocolAdmin::ProtocolAdmin(Connection* connection) :
Protocol(connection)
{
	m_state = NO_CONNECTED;
	m_loginTries = 0;
	m_lastCommand = 0;
	m_startTime = time(NULL);
}

void ProtocolAdmin::onRecvFirstMessage(NetworkMessage& msg)
{
	//is the remote admin protocol enabled?
	if(!g_adminConfig->isEnabled())
	{
		getConnection()->closeConnection();
		return;
	}
	
	m_state = NO_CONNECTED;
	//is allowed this ip?
	if(!g_adminConfig->allowIP(getIP()))
	{
		addLogLine(this, LOGTYPE_EVENT, 1, "ip not allowed");
		getConnection()->closeConnection();
		return;
	}
	
	//max connections limit
	if(!g_adminConfig->addConnection())
	{
		addLogLine(this, LOGTYPE_EVENT, 1, "cannot add new connection");
		getConnection()->closeConnection();
		return;
	}
	
	addLogLine(this, LOGTYPE_EVENT, 1, "sending HELLO");

	//send hello
	OutputMessage* output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
	output->AddByte(AP_MSG_HELLO);
	output->AddU32(1); //version
	output->AddString("OTADMIN");
	output->AddU16(g_adminConfig->getProtocolPolicy()); //security policy
	output->AddU32(g_adminConfig->getProtocolOptions()); //protocol options(encryption, ...)
	OutputMessagePool::getInstance()->send(output);

	m_lastCommand = time(NULL);
	m_state = ENCRYPTION_NO_SET;
}

void ProtocolAdmin::deleteProtocolTask()
{
	addLogLine(NULL, LOGTYPE_EVENT, 1, "end connection");
	g_adminConfig->removeConnection();
	Protocol::deleteProtocolTask();
}

void ProtocolAdmin::parsePacket(NetworkMessage& msg)
{
	uint8_t recvbyte = msg.GetByte();
	
	OutputMessagePool* outputPool = OutputMessagePool::getInstance();

	OutputMessage* output = outputPool->getOutputMessage(this, false);
	
	switch(m_state)
	{
		case ENCRYPTION_NO_SET:
		{
			if(g_adminConfig->requireEncryption())
			{
				if((time(NULL) - m_startTime) > 30000)
				{
					addLogLine(this, LOGTYPE_WARNING, 1, "encryption timeout");
					outputPool->releaseMessage(output);
					getConnection()->closeConnection();
					return;
				}
			
				if(recvbyte != AP_MSG_ENCRYPTION && recvbyte != AP_MSG_KEY_EXCHANGE)
				{
					output->AddByte(AP_MSG_ERROR);
					output->AddString("encryption needed");
					outputPool->send(output);
					addLogLine(this, LOGTYPE_WARNING, 1, "wrong command while ENCRYPTION_NO_SET");
					return;
				}
				break;
			}
			else
				m_state = NO_LOGGED_IN;
		}
		case NO_LOGGED_IN:
		{
			if(g_adminConfig->requireLogin())
			{
				if((time(NULL) - m_startTime) > 30000)
				{
					//login timeout
					addLogLine(this, LOGTYPE_WARNING, 1, "login timeout");
					getConnection()->closeConnection();
					return;
				}
	
				if(m_loginTries > 3)
 				{
					output->AddByte(AP_MSG_ERROR);
					output->AddString("too many login tries");
					outputPool->send(output);
					addLogLine(this, LOGTYPE_WARNING, 1, "too many login tries");
					getConnection()->closeConnection();
					return;
				}
	
				if(recvbyte != AP_MSG_LOGIN)
				{
					output->AddByte(AP_MSG_ERROR);
					output->AddString("you are not logged in");
					outputPool->send(output);
					addLogLine(this, LOGTYPE_WARNING, 1, "wrong command while NO_LOGGED_IN");
					return;
				}
				break;
			}
			else
				m_state = LOGGED_IN;
		}
		case LOGGED_IN:
		{
			break;
		}
		default:
		{
			addLogLine(this, LOGTYPE_ERROR, 1, "no valid connection state!!!");
			getConnection()->closeConnection();
			return;
		}
	}
		
	m_lastCommand = time(NULL);
	switch(recvbyte)
	{
		case AP_MSG_LOGIN:
		{
			if(m_state == NO_LOGGED_IN && g_adminConfig->requireLogin())
			{
				std::string password = msg.GetString();
				if(g_adminConfig->passwordMatch(password))
				{
					m_state = LOGGED_IN;
					output->AddByte(AP_MSG_LOGIN_OK);
					addLogLine(this, LOGTYPE_EVENT, 1, "login ok");
				}
				else
				{
					m_loginTries++;
					output->AddByte(AP_MSG_LOGIN_FAILED);
					output->AddString("wrong password");
					addLogLine(this, LOGTYPE_WARNING, 1, "login failed.("+ password + ")");
				}
			}
			else
			{
				output->AddByte(AP_MSG_LOGIN_FAILED);
				output->AddString("can not login");
				addLogLine(this, LOGTYPE_WARNING, 1, "wrong state at login");
			}
			break;
		}
		case AP_MSG_ENCRYPTION:
		{
			if(m_state == ENCRYPTION_NO_SET && g_adminConfig->requireEncryption())
			{
				uint8_t keyType = msg.GetByte();
				switch(keyType)
				{
					case ENCRYPTION_RSA1024XTEA:
					{
						RSA* rsa = g_adminConfig->getRSAKey(ENCRYPTION_RSA1024XTEA);
						if(!rsa)
						{
							output->AddByte(AP_MSG_ENCRYPTION_FAILED);
							addLogLine(this, LOGTYPE_WARNING, 1, "No valid server key type.");
							break;
						}
					
						if(RSA_decrypt(rsa, msg))
						{
							m_state = NO_LOGGED_IN;
							uint32_t k[4];
							k[0] = msg.GetU32();
							k[1] = msg.GetU32();
							k[2] = msg.GetU32();
							k[3] = msg.GetU32();

							//use for in/out the new key we have
							enableXTEAEncryption();
							setXTEAKey(k);
							output->AddByte(AP_MSG_ENCRYPTION_OK);
							addLogLine(this, LOGTYPE_EVENT, 1, "encryption ok");
						}
						else
						{
							output->AddByte(AP_MSG_ENCRYPTION_FAILED);
							output->AddString("Wrong encrypted packet.");
							addLogLine(this, LOGTYPE_WARNING, 1, "Wrong encrypted packet.");
						}
						break;
					}
					default:
						output->AddByte(AP_MSG_ENCRYPTION_FAILED);
						output->AddString("No valid key type.");
						addLogLine(this, LOGTYPE_WARNING, 1, "No valid client key type.");
						break;
				}
			}
			else
			{
				output->AddByte(AP_MSG_ENCRYPTION_FAILED);
				output->AddString("Can not set encryption.");
				addLogLine(this, LOGTYPE_EVENT, 1, "Can not set encryption.");
			}
			break;
		}
		case AP_MSG_KEY_EXCHANGE:
		{
			if(m_state == ENCRYPTION_NO_SET && g_adminConfig->requireEncryption())
			{
				uint8_t keyType = msg.GetByte();
				switch(keyType)
				{
					case ENCRYPTION_RSA1024XTEA:
					{
						RSA* rsa = g_adminConfig->getRSAKey(ENCRYPTION_RSA1024XTEA);
						if(!rsa)
						{
							output->AddByte(AP_MSG_KEY_EXCHANGE);
							addLogLine(this, LOGTYPE_WARNING, 1, "No valid server key type.");
							break;
						}
				
						output->AddByte(AP_MSG_KEY_EXCHANGE_OK);
						output->AddByte(ENCRYPTION_RSA1024XTEA);
						char RSAPublicKey[128];
						rsa->getPublicKey(RSAPublicKey);
						output->AddBytes(RSAPublicKey, 128);
						break;
					}
					default:
						output->AddByte(AP_MSG_KEY_EXCHANGE_FAILED);
						addLogLine(this, LOGTYPE_WARNING, 1, "No valid client key type.");
						break;
				}
			}
			else
			{
				output->AddByte(AP_MSG_KEY_EXCHANGE_FAILED);
				output->AddString("Can not get public key.");
				addLogLine(this, LOGTYPE_WARNING, 1, "Can not get public key.");
			}
			break;
		}
		case AP_MSG_COMMAND:
		{
			if(m_state != LOGGED_IN)
			{
				addLogLine(this, LOGTYPE_ERROR, 1, "recvbyte == AP_MSG_COMMAND && m_state != LOGGED_IN !!!");
				//never should reach this point!!
				break;
			}

			uint8_t command = msg.GetByte();
			switch(command)
			{
				case CMD_BROADCAST:
				{
					const std::string message = msg.GetString();
					addLogLine(this, LOGTYPE_EVENT, 1, "broadcast: " + message);
					Dispatcher::getDispatcher().addTask(createTask(boost::bind(&Game::broadcastMessage, &g_game, message, MSG_STATUS_WARNING)));
					output->AddByte(AP_MSG_COMMAND_OK);
					break;
				}
				case CMD_KICK_PLAYER:
				{
					const std::string param = msg.GetString();
					addLogLine(this, LOGTYPE_EVENT, 1, "kick: " + param);
					Dispatcher::getDispatcher().addTask(createTask(boost::bind(&ProtocolAdmin::adminSubCommandKickPlayer, this, param)));
					output->AddByte(AP_MSG_COMMAND_OK);
					break;
				}
				case CMD_CLOSE_SERVER:
				{
					Dispatcher::getDispatcher().addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandCloseServer, this)));
					break;
				}
				case CMD_PAY_HOUSES:
				{
					Dispatcher::getDispatcher().addTask(createTask(boost::bind(&ProtocolAdmin::adminCommandPayHouses, this)));
					break;
				}
				case CMD_SHUTDOWN_SERVER:
				{
					Dispatcher::getDispatcher().addTask(
						createTask(boost::bind(&ProtocolAdmin::adminCommandShutdownServer, this)));
					getConnection()->closeConnection();
					return;
					break;
				}
				default:
				{
					output->AddByte(AP_MSG_COMMAND_FAILED);
					output->AddString("Not known server command.");
					addLogLine(this, LOGTYPE_WARNING, 1, "Not known server command.");
				}
			}
			break;
		}
		case AP_MSG_PING:
			output->AddByte(AP_MSG_PING_OK);
			break;
		default:
			output->AddByte(AP_MSG_ERROR);
			output->AddString("Not known command byte.");
			addLogLine(this, LOGTYPE_WARNING, 1, "Not known command byte.");
			break;
	}
	if(output->getMessageLength() > 0)
		outputPool->send(output);
	else
		outputPool->releaseMessage(output);
}

bool ProtocolAdmin::adminSubCommandKickPlayer(const std::string& player)
{
	Player* paramPlayer = g_game.getPlayerByName(player);
	if(paramPlayer)
	{
		paramPlayer->kickPlayer(true);
		return true;
	}
	return false;
}

void ProtocolAdmin::adminCommandCloseServer()
{
	g_game.setGameState(GAME_STATE_CLOSED);
	AutoList<Player>::listiterator it = Player::listPlayer.list.begin();
	while(it != Player::listPlayer.list.end())
	{
		if(!(*it).second->hasFlag(PlayerFlag_CanAlwaysLogin))
		{
			(*it).second->kickPlayer(true);
			it = Player::listPlayer.list.begin();
		}
		else
			++it;
	}
	
	OutputMessage* output = OutputMessagePool::getInstance()->getOutputMessage(this, false);

	if(!g_bans.saveBans())
	{
		addLogLine(this, LOGTYPE_WARNING, 1, "close server fail - Bans");
		output->AddByte(AP_MSG_COMMAND_FAILED);
		output->AddString("Bans");
		OutputMessagePool::getInstance()->send(output);
		return;
	}
	
	if(!g_game.getMap()->saveMap())
	{
		addLogLine(this, LOGTYPE_WARNING, 1, "close server fail - Map");
		output->AddByte(AP_MSG_COMMAND_FAILED);
		output->AddString("Map");
		OutputMessagePool::getInstance()->send(output);
		return;
	}

	addLogLine(this, LOGTYPE_EVENT, 1, "close server ok");

	output->AddByte(AP_MSG_COMMAND_OK);
	OutputMessagePool::getInstance()->send(output);
}

void ProtocolAdmin::adminCommandShutdownServer()
{
	g_game.setGameState(GAME_STATE_SHUTDOWN);

	addLogLine(this, LOGTYPE_EVENT, 1, "start server shutdown");

	OutputMessage* output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
	output->AddByte(AP_MSG_COMMAND_OK);
	OutputMessagePool::getInstance()->send(output);
}

void ProtocolAdmin::adminCommandPayHouses()
{
	OutputMessage* output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
	if(Houses::getInstance().payHouses())
	{
		addLogLine(this, LOGTYPE_EVENT, 1, "pay houses ok");
		output->AddByte(AP_MSG_COMMAND_OK);
	}
	else
	{
		addLogLine(this, LOGTYPE_WARNING, 1, "pay houses fail");
		output->AddByte(AP_MSG_COMMAND_FAILED);
		output->AddString(" ");
	}
	OutputMessagePool::getInstance()->send(output);

	return;
}

/////////////////////////////////////////////

AdminProtocolConfig::AdminProtocolConfig()
{
	m_enabled = true;
	m_onlyLocalHost = true;
	m_maxConnections = 1;
	m_currrentConnections = 0;
	m_password = "";
	m_key_RSA1024XTEA = NULL;
	m_requireLogin = true;
	m_requireEncryption = false;
}

AdminProtocolConfig::~AdminProtocolConfig()
{
	delete m_key_RSA1024XTEA;
}

bool AdminProtocolConfig::loadXMLConfig()
{
	xmlDocPtr doc = xmlParseFile("data/XML/admin.xml");
	if(!doc)
		return false;

	xmlNodePtr root, p, q;
	root = xmlDocGetRootElement(doc);
	
	if(!xmlStrEqual(root->name,(const xmlChar*)"otadmin"))
	{
		xmlFreeDoc(doc);
		return false;
	}
		
	int enabled;
	if(readXMLInteger(root, "enabled", enabled))
	{
		if(enabled)
			m_enabled = true;
		else
			m_enabled = false;
	}
		
	int value;
	p = root->children;
	while(p)
	{
		if(xmlStrEqual(p->name, (const xmlChar*)"security"))
		{
			if(readXMLInteger(p, "onlylocalhost", value))
			{
				if(value)
					m_onlyLocalHost = true;
				else
					m_onlyLocalHost = false;
			}
			if(readXMLInteger(p, "maxconnections", value) && value > 0)
				m_maxConnections = value;
			if(readXMLInteger(p, "loginrequired", value))
			{
				if(value)
					m_requireLogin = true;
				else
					m_requireLogin = false;
			}
			std::string password;
			if(readXMLString(p, "loginpassword", password))
				m_password = password;
			else
			{
				if(m_requireLogin)
					std::cout << "Security warning: require login but use default password." << std::endl;
			}
		}
		else if(xmlStrEqual(p->name, (const xmlChar*)"encryption"))
		{
			if(readXMLInteger(p, "required", value))
			{
				if(value)
					m_requireEncryption = true;
				else
					m_requireEncryption = false;
			}
			q = p->children;
			while(q)
			{
				if(xmlStrEqual(q->name, (const xmlChar*)"key"))
				{
					std::string str;
					if(readXMLString(q, "type", str))
					{
						if(str == "RSA1024XTEA")
						{
							if(readXMLString(q, "file", str))
							{
								m_key_RSA1024XTEA = new RSA();
								if(!m_key_RSA1024XTEA->setKey("data/XML/" + str))
								{
									delete m_key_RSA1024XTEA;
									m_key_RSA1024XTEA = NULL;
									std::cout << "Can not load key from data/XML/" << str << std::endl;
								}
							}
							else
								std::cout << "Missing file for RSA1024XTEA key." << std::endl;
						}
						else
							std::cout << str << " is not a valid key type." << std::endl;
					}
				}
				q = q->next;
			}
		}
		p = p->next;
	}
	xmlFreeDoc(doc);
	return true;
}

bool AdminProtocolConfig::isEnabled()
{
	return m_enabled;
}

bool AdminProtocolConfig::onlyLocalHost()
{
	return m_onlyLocalHost;
}

bool AdminProtocolConfig::addConnection()
{
	if(m_currrentConnections >= m_maxConnections)
		return false;
	else
	{
		m_currrentConnections++;
		return true;
	}
}

void AdminProtocolConfig::removeConnection()
{
	if(m_currrentConnections > 0)
		m_currrentConnections--;
}

bool AdminProtocolConfig::passwordMatch(std::string& password)
{
	if(m_password == "")
		return false;
	return password == m_password;
}

bool AdminProtocolConfig::allowIP(uint32_t ip)
{
	if(m_onlyLocalHost)
	{
		if(ip == 0x0100007F) //127.0.0.1
			return true;
		else
		{
			char str_ip[32];
			formatIP(ip, str_ip);
			addLogLine(NULL, LOGTYPE_WARNING, 1, std::string("Forbidden connection attempt from ") + str_ip);
			return false;
		}
	}
	else
		return !g_bans.isIpDisabled(ip);
}

bool AdminProtocolConfig::requireLogin()
{
	return m_requireLogin;
}

bool AdminProtocolConfig::requireEncryption()
{
	return m_requireEncryption;
}

uint16_t AdminProtocolConfig::getProtocolPolicy()
{
	uint16_t policy = 0;
	if(requireLogin())
		policy = policy | REQUIRE_LOGIN;
	if(requireEncryption())
		policy = policy | REQUIRE_ENCRYPTION;
	return policy;
}

uint32_t AdminProtocolConfig::getProtocolOptions()
{
	uint32_t ret = 0;
	if(requireEncryption())
	{
		if(m_key_RSA1024XTEA)
			ret = ret | ENCRYPTION_RSA1024XTEA;
	}
	return ret;
}

RSA* AdminProtocolConfig::getRSAKey(uint8_t type)
{
	switch(type)
	{
		case ENCRYPTION_RSA1024XTEA:
			return m_key_RSA1024XTEA;
		default:
			return NULL;
	}
}

/////////////////////////////////////////////

static void addLogLine(ProtocolAdmin* conn, eLogType type, int level, std::string message)
{
	if(g_config.getString(ConfigManager::ADMIN_LOGS_ENABLED) == "yes")
	{
		std::string logMsg;
		if(conn)
		{
			uint32_t ip = conn->getIP();
			char buffer[32];
			formatIP(ip, buffer);
			logMsg = buffer;
			logMsg = "[" + logMsg + "] - ";
		}
		logMsg = logMsg + message;
		LOG_MESSAGE((char*)"OTADMIN", type, level, logMsg);
	}
}

admin.h
Code:
//////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
// 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; either version 2
// of the License, or (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//////////////////////////////////////////////////////////////////////

#ifndef __OTSERV_ADMIN_H__
#define __OTSERV_ADMIN_H__

// -> server
// command(1 byte) | size(2 bytes) | parameters(size bytes)
// commands:
//	login
//		password(string)
//  encryption
//		encryption type(1 byte)
//			RSA1024+XTEA
//				:128 bytes encrypted using 1024 bytes public key
//				16 bytes XTEA key
//  key-exchange
//		public_key_type(1 byte)
//			RSA1024+XTEA
//  command
//		command + paramters(string)
//	no_operation/ping
//		nothing
//
// <- server
// ret-code(1 byte)| size(2 bytes) | parameters(size bytes)
// ret-codes:
//	hello
//		server_version(4 bytes)
//		server_string(string)
//		security_policy(2 bytes flags)
//			required_login
//			required_encryption
//		accepted_encryptions(4 bytes flags)
//			RSA1024+XTEA
//	key-exchange-ok
//		public_key_type(1 byte)
//			RSA1024+XTEA
//				:128 bytes public key modulus
//	key-exchange-failed
//		reason(string)
//  login-ok
//		nothing
//  login-failed
//		reason(string)
//  command-ok
//		command result(string)
//  command-failed
//		reason(string)
//  encryption-ok
//		nothing
//  encryption-failed
//		reason(string)
//	no_operation-ok
//		nothing
//	message
//		message(string)
//  error
//		message(string)
//

#include "otsystem.h"
#include "player.h"
#include "logger.h"
#include <string>

class NetworkMessage;
class RSA;

enum
{
	AP_MSG_LOGIN = 1,
	AP_MSG_ENCRYPTION = 2,
	AP_MSG_KEY_EXCHANGE = 3,
	AP_MSG_COMMAND = 4,
	AP_MSG_PING = 5,
	//
	AP_MSG_HELLO = 1,
	AP_MSG_KEY_EXCHANGE_OK = 2,
	AP_MSG_KEY_EXCHANGE_FAILED = 3,
	AP_MSG_LOGIN_OK = 4,
	AP_MSG_LOGIN_FAILED = 5,
	AP_MSG_COMMAND_OK = 6,
	AP_MSG_COMMAND_FAILED = 7,
	AP_MSG_ENCRYPTION_OK = 8,
	AP_MSG_ENCRYPTION_FAILED = 9,
	AP_MSG_PING_OK = 10,
	AP_MSG_MESSAGE = 11,
	AP_MSG_ERROR = 12,
};

enum
{
	CMD_BROADCAST = 1,
	CMD_CLOSE_SERVER = 2,
	CMD_PAY_HOUSES = 3,
	CMD_SHUTDOWN_SERVER = 5,
	CMD_KICK_PLAYER = 13
};

enum
{
	REQUIRE_LOGIN = 1,
	REQUIRE_ENCRYPTION = 2,
};

enum
{
	ENCRYPTION_RSA1024XTEA = 1,
};

class AdminProtocolConfig
{
	public:
		AdminProtocolConfig();
		~AdminProtocolConfig();

		bool loadXMLConfig();

		bool isEnabled();

		bool onlyLocalHost();
		bool addConnection();
		void removeConnection();

		bool requireLogin();
		bool requireEncryption();

		uint16_t getProtocolPolicy();
		uint32_t getProtocolOptions();

		bool allowIP(uint32_t ip);

		bool passwordMatch(std::string& password);

		RSA* getRSAKey(uint8_t type);

	protected:
		bool m_enabled;
		bool m_onlyLocalHost;
		int32_t m_maxConnections;
		int32_t m_currrentConnections;

		std::string m_password;

		bool m_requireLogin;
		bool m_requireEncryption;

		RSA* m_key_RSA1024XTEA;
};
	
class ProtocolAdmin : public Protocol
{
	public:
		ProtocolAdmin(Connection* connection);
		virtual ~ProtocolAdmin() {}

		virtual void parsePacket(NetworkMessage& msg);

		virtual void onRecvFirstMessage(NetworkMessage& msg);

		virtual void deleteProtocolTask();

		bool adminSubCommandKickPlayer(const std::string& player);
		void adminCommandCloseServer();
		void adminCommandShutdownServer();
		void adminCommandPayHouses();

		enum ConnectionState_t
		{
			NO_CONNECTED,
			ENCRYPTION_NO_SET,
			ENCRYPTION_OK,
			NO_LOGGED_IN,
			LOGGED_IN,
		};

	private:
		int32_t m_loginTries;
		ConnectionState_t m_state;
		uint32_t m_lastCommand;
		uint32_t m_startTime;
};
	
#endif

Now download my attachment [sources included] (check for viruses if you wanna)
And use by site will be something like:
PHP:
shell_exec("/path/to/TFSAdmin 	'server localhost 7171' \
			'connect PASSWORD' \
			'kick ".$_GET['player']."' \
			disconnect
");

But it has alot of disadvantages (at least for current moment coded by me :p). Player can be kicked when he has PZ, whats stupid, 'Cause people will remove themselves when they'll have White Skull.
I'll try to improve it tomorrow.
 

Attachments

Last edited:
woow, thx! But yes, its true, that will be little not useful becouse player can be kicked in PZ, so please fix it tommorow :D
 
Btw...
I didn't mention, but I've added there also payHouses command.
I got several ideas, but I have something to do atm (migrating to new server...), so I'll post it like afternoon.
Of course, i need to finish first :D Not mentioning about starting... :p
 
Sre reply in Polish :P

Ty, a nie dało by sie tego jakoś wmontować do TFS? Żeby bez dodatkowych programow to chodziło? A i w ogóle to teraz chyba nie będzie możliwości sprawdzenia czy ma pz? Więc bez edycji TFS sie nie obędzie? ;>
 
Polish:
To jest w TFSie. TFSAdmin, vel OTadmin poprostu obsługuje ten protokół.
Za pomocą php nie dasz rady wysłać bitów do samego serwera, tutaj potrzebny jest skrypt .cgi - a takowy narazie nie istnieje i nie zanosi się, że powstanie, gdyż np uzycie samego OTadmina jest naprawde znikome.
Zresztą, poczytaj na ******.
Jeśli chodzi o tę obsługę kicka, to ja jestem jej autorem - z nikąd nie skopiowałem.
Pozatym, nie rozumiem o co Ci dokladnie chodzi z Więc bez edycji TFS się nie obędzie? ;> - przecież już bez tego sprawdzacza pz zmieniony został TFS.
Owa funkcja (kick) nie istniała, wiec trzeba było ją dopisać. Wszystkie zmiany w plikach admin.cpp i admin.h, które dałem wyżej.
Modifykacja w TFSie jak i w Adminie jest banalnie prosta, przynajmniej w takiej formie, w jakiej teraz widnieje.
Napisałem, że jutro usiąde, i zrobie, aby przed wykopaniem sprawdzało, czy gracz ma PZ.
Jeżeli tak - zostawia, jeżeli nie - wykopuje.
Chociaż i tak uważam, że skrypt ma swoje wady i nie za bardzo da się go rozwinąć...
Bo co, gdy osoba hackująca postać, specjalnie nabije skulla/pz? Wtedy dupa, nie wykopiesz.
Ale pobawić się można ; )
Jak napisałem, jutro sie tym zajme.


Sorry guys, I'll translate this tomorrow, I got fever and huge headache, and I can't think clearly
 
@pl

Tak to jest jak sie pisze po ciemaku ;<

Chyba i tak wprowadze taką opcje, która będzie troche kosztować, ale za to będzie kickać zawsze.

btw. co robi te płacenie domków?

@en

?
 
Slawkens: If you're going to post something in polish, you could use a translator so everyone else can understand it a little bit.

Ontopic: mabye is it possible if the system check if you are connected to the server (with ip) if not then you can kick yourself.
 
Last edited:
@Slawkens (in Polish):
Nie uda mi się dziś tego napisać, ponieważ jestem chory. Wczoraj też w sumie byłem, ale nie aż taki zmęczony o podobnej godzinie.
Postaram się jutro.
Komenda 'payHouses' w adminie sprawdza domki i ewentualnie pobiera opłaty.
To samo co przy /close czy serverSave'ie, tylko, że bardziej 'manualne' - kiedy chcesz i nie potrzebujesz kopać graczy z serwera.
#####################

@Marjke:
Its the best solution! But... I dont know how to decode[?] players IP (since it isn't like 127.0.0.1 :p) :D
If Tala could give me some tip, I would try to do it like that.
kick PARAM1 would require second param PARAM2, where PARAM1 would be player name, and PARAM2 specified IP (for php script You could use $_SERVER['REMOTE_ADDR'] ;))
 
You can try to make it in LUA with LUASQL. It will take more CPU/hdd (send query every x seconds). I'll add options like "kick player", "teleport player", "put in jail" (teleport player to "jail position" and teleport to tample after xx seconds [saved in storage]) in my acc. maker :>
 
I've been away for few days.

I got a problem with comparing parameter send via otadmin with some value, since its a a text and value a number (/me is nub here? Can't think clearly).
I'll seek on google for it.

@Gesior:
Not bad idea - if someone doesnt care for lags :D
If I wont finish this (sorry guys, I got too much work to focus on one thing), I'll surely make a LUA :)
- Script would check every 5 seconds in a custom table, compare actions id for players, remove the records and so...
Im lazy to check lua functions list, but I'm almost sure there's thing to check pZ :>

@Nightmare:
Thanks, I copied ipText(databaseIP) from commands.cpp - simple definition.
Though - thanks :)
 
I tried use Replace Kick from another engine. Doesnt work. I DONT know how! :) If you know how to do this, then please post it.
 
Back
Top