Finished the reset of the major rewrite
This commit is contained in:
parent
b90f0fbd9f
commit
c7cf109425
|
@ -48,7 +48,9 @@ jar.archive.disabled=${jnlp.enabled}
|
|||
jar.compress=false
|
||||
jar.index=${jnlp.enabled}
|
||||
javac.classpath=\
|
||||
${libs.Bukkit.classpath}
|
||||
${libs.Bukkit.classpath}:\
|
||||
${libs.Log4J-core.classpath}:\
|
||||
${libs.Log4J-api.classpath}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=-Xlint:unchecked
|
||||
javac.deprecation=false
|
||||
|
|
|
@ -1,513 +0,0 @@
|
|||
package me.StevenLawson.BukkitTelnet;
|
||||
|
||||
import me.StevenLawson.BukkitTelnet.api.TelnetPreLoginEvent;
|
||||
import me.StevenLawson.BukkitTelnet.api.TelnetCommandEvent;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.Socket;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.server.RemoteServerCommandEvent;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
public final class BT_ClientSession extends Thread
|
||||
{
|
||||
public enum FilterMode
|
||||
{
|
||||
FULL, NONCHAT_ONLY, CHAT_ONLY
|
||||
}
|
||||
private static final Pattern NONASCII_FILTER = Pattern.compile("[^\\x20-\\x7E]");
|
||||
private static final Pattern AUTH_INPUT_FILTER = Pattern.compile("[^a-zA-Z0-9]");
|
||||
private static final Pattern COMMAND_INPUT_FILTER = Pattern.compile("^[^a-zA-Z0-9/\\?!\\.]+");
|
||||
//
|
||||
private final Socket clientSocket;
|
||||
private final String clientAddress;
|
||||
//
|
||||
public static FilterMode filter_mode = FilterMode.FULL;
|
||||
private SessionLogHandler sessionLogHandler;
|
||||
private SessionCommandSender sessionCommandSender;
|
||||
private BufferedWriter writer;
|
||||
private BufferedReader reader;
|
||||
private String userName;
|
||||
private boolean hasTerminated = false;
|
||||
|
||||
public BT_ClientSession(Socket clientSocket)
|
||||
{
|
||||
this.clientSocket = clientSocket;
|
||||
this.clientAddress = this.clientSocket.getInetAddress().getHostAddress();
|
||||
this.userName = this.clientAddress;
|
||||
|
||||
BT_Log.info("Client connected: " + this.clientAddress);
|
||||
}
|
||||
|
||||
public boolean isConnected()
|
||||
{
|
||||
synchronized (this.clientSocket)
|
||||
{
|
||||
return !this.clientSocket.isClosed();
|
||||
}
|
||||
}
|
||||
|
||||
public void terminateSession()
|
||||
{
|
||||
if (this.hasTerminated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.hasTerminated = true;
|
||||
|
||||
BT_Log.info("Closing connection: " + this.clientAddress);
|
||||
|
||||
if (this.sessionLogHandler != null)
|
||||
{
|
||||
BT_Log.getLogger(true).removeHandler(this.sessionLogHandler);
|
||||
}
|
||||
|
||||
synchronized (this.clientSocket)
|
||||
{
|
||||
if (this.clientSocket != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
writeOutFormatted("Closing connection.", true);
|
||||
this.clientSocket.close();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getUserName()
|
||||
{
|
||||
return this.userName;
|
||||
}
|
||||
|
||||
public void writeOut(String message)
|
||||
{
|
||||
if (this.writer != null && this.isConnected())
|
||||
{
|
||||
try
|
||||
{
|
||||
this.writer.write(ChatColor.stripColor(message));
|
||||
this.writer.flush();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void writeOutFormatted(String message, boolean newLine)
|
||||
{
|
||||
writeOut("[BukkitTelnet (Console)]: " + message + (newLine ? "\r\n:" : ""));
|
||||
}
|
||||
|
||||
public void flush()
|
||||
{
|
||||
if (this.writer != null && this.isConnected())
|
||||
{
|
||||
try
|
||||
{
|
||||
this.writer.flush();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendBukkitCommand(final String command)
|
||||
{
|
||||
final CommandSender sender = getCommandSender();
|
||||
|
||||
try
|
||||
{
|
||||
new BukkitRunnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
final Server server = Bukkit.getServer();
|
||||
|
||||
final TelnetCommandEvent telnetEvent = new TelnetCommandEvent(sender, command);
|
||||
server.getPluginManager().callEvent(telnetEvent);
|
||||
|
||||
if (telnetEvent.isCancelled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
final RemoteServerCommandEvent serverEvent = new RemoteServerCommandEvent(telnetEvent.getSender(), telnetEvent.getCommand());
|
||||
server.getPluginManager().callEvent(serverEvent);
|
||||
|
||||
final String command = serverEvent.getCommand();
|
||||
if (command != null && !command.isEmpty())
|
||||
{
|
||||
server.dispatchCommand(sender, command);
|
||||
}
|
||||
}
|
||||
}.runTask(BukkitTelnet.plugin);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
BT_Log.severe(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public CommandSender getCommandSender()
|
||||
{
|
||||
if (this.sessionCommandSender == null)
|
||||
{
|
||||
this.sessionCommandSender = new SessionCommandSender(this);
|
||||
}
|
||||
return this.sessionCommandSender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized (this.clientSocket)
|
||||
{
|
||||
this.reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
|
||||
this.writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
BT_Log.severe(ex);
|
||||
}
|
||||
|
||||
if (this.reader == null || this.writer == null)
|
||||
{
|
||||
terminateSession();
|
||||
return;
|
||||
}
|
||||
|
||||
writeOut(":");
|
||||
|
||||
writeOutFormatted("Session Started.", true);
|
||||
|
||||
if (authenticateSession())
|
||||
{
|
||||
sessionMainLoop();
|
||||
}
|
||||
else
|
||||
{
|
||||
writeOutFormatted("Authentication failed.", true);
|
||||
}
|
||||
|
||||
terminateSession();
|
||||
}
|
||||
|
||||
private boolean authenticateSession()
|
||||
{
|
||||
if (this.hasTerminated)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
boolean isPreAuthenticated = false;
|
||||
|
||||
if (this.clientAddress != null)
|
||||
{
|
||||
final Iterator<Map.Entry<String, List<String>>> it = BT_Config.getInstance().getConfigEntries().getAdmins().entrySet().iterator();
|
||||
adminMapLoop:
|
||||
while (it.hasNext())
|
||||
{
|
||||
final Map.Entry<String, List<String>> entry = it.next();
|
||||
final List<String> adminIPs = entry.getValue();
|
||||
if (adminIPs != null)
|
||||
{
|
||||
for (final String ip : adminIPs)
|
||||
{
|
||||
if (fuzzyIpMatch(ip, this.clientAddress, 3))
|
||||
{
|
||||
isPreAuthenticated = true;
|
||||
this.userName = entry.getKey();
|
||||
break adminMapLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final TelnetPreLoginEvent event = new TelnetPreLoginEvent(this.clientAddress, isPreAuthenticated ? this.userName : null, isPreAuthenticated);
|
||||
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
if (event.isCancelled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.canBypassPassword())
|
||||
{
|
||||
this.userName = event.getName();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean gotValidUsername = false;
|
||||
int tries = 0;
|
||||
while (tries++ < 3)
|
||||
{
|
||||
try
|
||||
{
|
||||
writeOutFormatted("Username: ", false);
|
||||
|
||||
String _userName = reader.readLine();
|
||||
writeOut(":");
|
||||
|
||||
if (_userName != null && !_userName.isEmpty())
|
||||
{
|
||||
_userName = AUTH_INPUT_FILTER.matcher(_userName).replaceAll("").trim();
|
||||
}
|
||||
|
||||
if (_userName != null && !_userName.isEmpty())
|
||||
{
|
||||
this.userName = _userName;
|
||||
gotValidUsername = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
writeOutFormatted("Invalid username.", true);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (!gotValidUsername)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
tries = 0;
|
||||
while (tries++ < 3)
|
||||
{
|
||||
try
|
||||
{
|
||||
writeOutFormatted("Password: ", false);
|
||||
|
||||
String _password = reader.readLine();
|
||||
writeOut(":");
|
||||
|
||||
if (_password != null && !_password.isEmpty())
|
||||
{
|
||||
_password = AUTH_INPUT_FILTER.matcher(_password).replaceAll("").trim();
|
||||
}
|
||||
|
||||
if (_password != null && !_password.isEmpty() && BT_TelnetServer.getInstance().getPassword().equals(_password))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
writeOutFormatted("Invalid password.", true);
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
BT_Log.severe(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void sessionMainLoop()
|
||||
{
|
||||
if (this.hasTerminated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
writeOutFormatted("Logged in as " + this.userName + ".", true);
|
||||
BT_Log.info(this.clientAddress + " logged in as \"" + this.userName + "\".");
|
||||
|
||||
BT_Log.getLogger(true).addHandler(this.sessionLogHandler = new SessionLogHandler(this));
|
||||
|
||||
while (this.isConnected())
|
||||
{
|
||||
String command = null;
|
||||
try
|
||||
{
|
||||
command = this.reader.readLine();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
|
||||
writeOut(":");
|
||||
|
||||
if (command != null)
|
||||
{
|
||||
command = COMMAND_INPUT_FILTER.matcher(NONASCII_FILTER.matcher(command).replaceAll("")).replaceFirst("").trim();
|
||||
if (!command.isEmpty())
|
||||
{
|
||||
if (command.toLowerCase().startsWith("telnet"))
|
||||
{
|
||||
if (command.equalsIgnoreCase("telnet.help"))
|
||||
{
|
||||
writeOut("Telnet commands:\r\n");
|
||||
writeOut("telnet.help - See all of the telnet commands.\r\n");
|
||||
writeOut("telnet.stopserver - Shutdown the server.\r\n");
|
||||
writeOut("telnet.log - Change your logging settings.\r\n");
|
||||
writeOut("telnet.exit - Quit the telnet session.");
|
||||
}
|
||||
else if (command.equalsIgnoreCase("telnet.stopserver"))
|
||||
{
|
||||
writeOut("Shutting down the server...\r\n");
|
||||
BT_Log.warning(this.userName + " has shutdown the server.");
|
||||
System.exit(0);
|
||||
}
|
||||
else if (command.equalsIgnoreCase("telnet.log"))
|
||||
{
|
||||
if (filter_mode == FilterMode.CHAT_ONLY)
|
||||
{
|
||||
filter_mode = FilterMode.FULL;
|
||||
writeOut("Showing full console log.\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
filter_mode = FilterMode.CHAT_ONLY;
|
||||
writeOut("Showing chat log only.\r\n");
|
||||
}
|
||||
}
|
||||
else if (command.equalsIgnoreCase("telnet.exit"))
|
||||
{
|
||||
terminateSession();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sendBukkitCommand(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
BT_Log.severe(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean fuzzyIpMatch(String a, String b, int octets)
|
||||
{
|
||||
boolean match = true;
|
||||
|
||||
String[] aParts = a.split("\\.");
|
||||
String[] bParts = b.split("\\.");
|
||||
|
||||
if (aParts.length != 4 || bParts.length != 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (octets > 4)
|
||||
{
|
||||
octets = 4;
|
||||
}
|
||||
else if (octets < 1)
|
||||
{
|
||||
octets = 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < octets && i < 4; i++)
|
||||
{
|
||||
if (aParts[i].equals("*") || bParts[i].equals("*"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!aParts[i].equals(bParts[i]))
|
||||
{
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
private static class SessionLogHandler extends BT_Handler
|
||||
{
|
||||
private final BT_ClientSession session;
|
||||
|
||||
public SessionLogHandler(BT_ClientSession session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeOut(String string)
|
||||
{
|
||||
this.session.writeOut(string);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush()
|
||||
{
|
||||
this.session.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws SecurityException
|
||||
{
|
||||
this.session.terminateSession();
|
||||
}
|
||||
}
|
||||
|
||||
private static class SessionCommandSender extends BT_CommandSender
|
||||
{
|
||||
private final BT_ClientSession session;
|
||||
|
||||
public SessionCommandSender(BT_ClientSession session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message)
|
||||
{
|
||||
if (this.session.sessionLogHandler != null)
|
||||
{
|
||||
this.session.sessionLogHandler.writeOut(message + "\r\n:");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return this.session.getUserName();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package me.StevenLawson.BukkitTelnet;
|
||||
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
import me.StevenLawson.BukkitTelnet.BT_ClientSession.FilterMode;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
public abstract class BT_Handler extends Handler
|
||||
{
|
||||
private Formatter formatter;
|
||||
|
||||
public abstract void writeOut(String string);
|
||||
|
||||
@Override
|
||||
public final void publish(LogRecord record)
|
||||
{
|
||||
if (record == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String message = record.getMessage();
|
||||
|
||||
if (this.formatter == null)
|
||||
{
|
||||
this.formatter = getFormatter();
|
||||
}
|
||||
|
||||
if (this.formatter != null)
|
||||
{
|
||||
message = this.formatter.formatMessage(record);
|
||||
}
|
||||
|
||||
message = ChatColor.stripColor(message);
|
||||
|
||||
if (BT_ClientSession.filter_mode == FilterMode.CHAT_ONLY)
|
||||
{
|
||||
if (message.startsWith("<") || message.startsWith("[Server:") || message.startsWith("[CONSOLE]<") || message.startsWith("[TotalFreedomMod] [ADMIN]"))
|
||||
{
|
||||
writeOut(message + "\r\n:");
|
||||
}
|
||||
}
|
||||
else if (BT_ClientSession.filter_mode == FilterMode.NONCHAT_ONLY)
|
||||
{
|
||||
if (!(message.startsWith("<") || message.startsWith("[Server:") || message.startsWith("[CONSOLE]<") || message.startsWith("[TotalFreedomMod] [ADMIN]")))
|
||||
{
|
||||
writeOut(message + "\r\n:");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writeOut(message + "\r\n:");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Formatter getFormatter()
|
||||
{
|
||||
if (this.formatter == null)
|
||||
{
|
||||
this.formatter = super.getFormatter();
|
||||
|
||||
Handler[] handlers = org.bukkit.Bukkit.getLogger().getHandlers();
|
||||
for (Handler handler : handlers)
|
||||
{
|
||||
if (handler.getClass().getName().startsWith("org.bukkit.craftbukkit"))
|
||||
{
|
||||
Formatter _formatter = handler.getFormatter();
|
||||
if (_formatter != null)
|
||||
{
|
||||
this.formatter = _formatter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.formatter;
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
package me.StevenLawson.BukkitTelnet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class BT_TelnetServer
|
||||
{
|
||||
private String password;
|
||||
private ServerListener serverListener = null;
|
||||
|
||||
private BT_TelnetServer()
|
||||
{
|
||||
}
|
||||
|
||||
public void startServer()
|
||||
{
|
||||
stopServer();
|
||||
|
||||
final BT_Config.SimpleConfigEntries configEntries = BT_Config.getInstance().getConfigEntries();
|
||||
|
||||
final String address = configEntries.getAddress();
|
||||
final int port = configEntries.getPort();
|
||||
|
||||
this.password = configEntries.getPassword();
|
||||
|
||||
if (this.password == null)
|
||||
{
|
||||
BT_Log.warning("Telnet password is not defined in config file. Can't start server.");
|
||||
return;
|
||||
}
|
||||
|
||||
InetAddress hostAddress = null;
|
||||
|
||||
if (address != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
hostAddress = InetAddress.getByName(address);
|
||||
}
|
||||
catch (UnknownHostException ex)
|
||||
{
|
||||
BT_Log.severe(ex);
|
||||
}
|
||||
}
|
||||
|
||||
ServerSocket serverSocket = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (hostAddress == null)
|
||||
{
|
||||
serverSocket = new ServerSocket(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
serverSocket = new ServerSocket(port, 50, hostAddress);
|
||||
}
|
||||
|
||||
String hostIP = serverSocket.getInetAddress().getHostAddress();
|
||||
if (hostIP.equals("0.0.0.0"))
|
||||
{
|
||||
hostIP = "*";
|
||||
}
|
||||
|
||||
BT_Log.info("Server started on " + hostIP + ":" + serverSocket.getLocalPort());
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
BT_Log.severe("Cant bind to " + (hostAddress == null ? "*" : hostAddress) + ":" + port);
|
||||
BT_Log.severe(ex);
|
||||
}
|
||||
|
||||
if (serverSocket != null)
|
||||
{
|
||||
(this.serverListener = new ServerListener(serverSocket)).start();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopServer()
|
||||
{
|
||||
if (this.serverListener != null)
|
||||
{
|
||||
this.serverListener.stopServer();
|
||||
}
|
||||
}
|
||||
|
||||
public String getPassword()
|
||||
{
|
||||
return this.password;
|
||||
}
|
||||
|
||||
private static class ServerListener extends Thread
|
||||
{
|
||||
private final ServerSocket serverSocket;
|
||||
private final List<BT_ClientSession> clientSessions = Collections.synchronizedList(new ArrayList<BT_ClientSession>());
|
||||
|
||||
public ServerListener(ServerSocket serverSocket)
|
||||
{
|
||||
this.serverSocket = serverSocket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!this.serverSocket.isClosed())
|
||||
{
|
||||
synchronized (clientSessions)
|
||||
{
|
||||
final BT_ClientSession clientSession = new BT_ClientSession(this.serverSocket.accept());
|
||||
clientSessions.add(clientSession);
|
||||
clientSession.start();
|
||||
|
||||
final Iterator<BT_ClientSession> it = clientSessions.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
if (!it.next().isConnected())
|
||||
{
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void stopServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.serverSocket.close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
|
||||
synchronized (clientSessions)
|
||||
{
|
||||
final Iterator<BT_ClientSession> it = clientSessions.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
it.next().terminateSession();
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static BT_TelnetServer getInstance()
|
||||
{
|
||||
return BT_TelnetServerHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static class BT_TelnetServerHolder
|
||||
{
|
||||
private static final BT_TelnetServer INSTANCE = new BT_TelnetServer();
|
||||
}
|
||||
}
|
|
@ -14,26 +14,26 @@ public class BukkitTelnet extends JavaPlugin
|
|||
plugin = this;
|
||||
server = plugin.getServer();
|
||||
|
||||
BT_Log.setPluginLogger(plugin.getLogger());
|
||||
BT_Log.setServerLogger(server.getLogger());
|
||||
TelnetLogger.setPluginLogger(plugin.getLogger());
|
||||
TelnetLogger.setServerLogger(server.getLogger());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
BT_Config.getInstance().loadConfig();
|
||||
TelnetConfig.getInstance().loadConfig();
|
||||
|
||||
BT_TelnetServer.getInstance().startServer();
|
||||
TelnetServer.getInstance().startServer();
|
||||
|
||||
BT_Log.info(plugin.getName() + " v" + plugin.getDescription().getVersion() + " enabled");
|
||||
TelnetLogger.info(plugin.getName() + " v" + plugin.getDescription().getVersion() + " enabled");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable()
|
||||
{
|
||||
BT_TelnetServer.getInstance().stopServer();
|
||||
TelnetServer.getInstance().stopServer();
|
||||
|
||||
BT_Log.info("Plugin disabled");
|
||||
TelnetLogger.info("Plugin disabled.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
package me.StevenLawson.BukkitTelnet;
|
||||
|
||||
import me.StevenLawson.BukkitTelnet.session.ClientSession;
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class SocketListener extends Thread
|
||||
{
|
||||
private final ServerSocket serverSocket;
|
||||
private final List<ClientSession> clientSessions = new ArrayList<ClientSession>();
|
||||
|
||||
public SocketListener(ServerSocket serverSocket)
|
||||
{
|
||||
this.serverSocket = serverSocket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
while (!serverSocket.isClosed())
|
||||
{
|
||||
final Socket clientSocket;
|
||||
|
||||
try
|
||||
{
|
||||
clientSocket = serverSocket.accept();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final ClientSession clientSession = new ClientSession(clientSocket);
|
||||
clientSessions.add(clientSession);
|
||||
clientSession.start();
|
||||
|
||||
removeDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
private void removeDisconnected()
|
||||
{
|
||||
final Iterator<ClientSession> it = clientSessions.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
if (!it.next().syncIsConnected())
|
||||
{
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stopServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
serverSocket.close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
TelnetLogger.severe(ex);
|
||||
}
|
||||
|
||||
for (ClientSession session : clientSessions)
|
||||
{
|
||||
session.syncTerminateSession();
|
||||
}
|
||||
|
||||
clientSessions.clear();
|
||||
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
package me.StevenLawson.BukkitTelnet;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class TelnetCommandEvent extends Event implements Cancellable
|
||||
{
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private boolean cancelled = false;
|
||||
//
|
||||
private CommandSender sender;
|
||||
private String command;
|
||||
|
||||
public TelnetCommandEvent(CommandSender sender, String command)
|
||||
{
|
||||
this.sender = sender;
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers()
|
||||
{
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList()
|
||||
{
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled()
|
||||
{
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel)
|
||||
{
|
||||
cancelled = cancel;
|
||||
}
|
||||
|
||||
public CommandSender getSender()
|
||||
{
|
||||
return sender;
|
||||
}
|
||||
|
||||
public void setSender(CommandSender sender)
|
||||
{
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
public String getCommand()
|
||||
{
|
||||
return command;
|
||||
}
|
||||
|
||||
public void setCommand(String command)
|
||||
{
|
||||
this.command = command;
|
||||
}
|
||||
}
|
|
@ -1,33 +1,30 @@
|
|||
package me.StevenLawson.BukkitTelnet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.pravian.bukkitlib.YamlConfig;
|
||||
|
||||
public class BT_Config
|
||||
public class TelnetConfig
|
||||
{
|
||||
private YamlConfig config = null;
|
||||
private final YamlConfig config;
|
||||
private final SimpleConfigEntries configEntries;
|
||||
|
||||
private BT_Config()
|
||||
private TelnetConfig()
|
||||
{
|
||||
configEntries = new SimpleConfigEntries();
|
||||
config = new YamlConfig(BukkitTelnet.plugin, "config.yml", true);
|
||||
}
|
||||
|
||||
public void loadConfig()
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
config = new YamlConfig(BukkitTelnet.plugin, "config.yml", true);
|
||||
}
|
||||
|
||||
config.load();
|
||||
|
||||
configEntries.setAddress(config.getString("address"));
|
||||
configEntries.setPort(config.getInt("port"));
|
||||
configEntries.setPassword(config.getString("password"));
|
||||
configEntries.getAdmins().clear();
|
||||
configEntries.clearAdmins();
|
||||
|
||||
if (config.isConfigurationSection("admins"))
|
||||
{
|
||||
|
@ -39,15 +36,15 @@ public class BT_Config
|
|||
continue;
|
||||
}
|
||||
|
||||
configEntries.getAdmins().put(admin, config.getStringList("admins." + admin));
|
||||
configEntries.addAdmin(admin, config.getStringList("admins." + admin));
|
||||
}
|
||||
}
|
||||
|
||||
if (configEntries.getPassword().equals(""))
|
||||
if (configEntries.getPassword().isEmpty())
|
||||
{
|
||||
configEntries.setPassword(config.getDefaultConfig().getString("password"));
|
||||
BT_Log.warning("Password set to blank in config!");
|
||||
BT_Log.warning("Defaulting to " + configEntries.getPassword());
|
||||
TelnetLogger.warning("Password is undefined in config!");
|
||||
TelnetLogger.warning("Defaulting to " + configEntries.getPassword());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,17 +97,27 @@ public class BT_Config
|
|||
|
||||
public Map<String, List<String>> getAdmins()
|
||||
{
|
||||
return admins;
|
||||
return Collections.unmodifiableMap(admins);
|
||||
}
|
||||
|
||||
private void clearAdmins()
|
||||
{
|
||||
admins.clear();
|
||||
}
|
||||
|
||||
private void addAdmin(String name, List<String> ips)
|
||||
{
|
||||
admins.put(name, ips);
|
||||
}
|
||||
}
|
||||
|
||||
public static BT_Config getInstance()
|
||||
public static TelnetConfig getInstance()
|
||||
{
|
||||
return BT_ConfigHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static class BT_ConfigHolder
|
||||
{
|
||||
private static final BT_Config INSTANCE = new BT_Config();
|
||||
private static final TelnetConfig INSTANCE = new TelnetConfig();
|
||||
}
|
||||
}
|
|
@ -4,13 +4,13 @@ import java.util.logging.Level;
|
|||
import java.util.logging.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public final class BT_Log
|
||||
public final class TelnetLogger
|
||||
{
|
||||
private static final Logger FALLBACK_LOGGER = Bukkit.getLogger();
|
||||
private static Logger serverLogger = null;
|
||||
private static Logger pluginLogger = null;
|
||||
|
||||
private BT_Log()
|
||||
private TelnetLogger()
|
||||
{
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public final class BT_Log
|
|||
info(message, false);
|
||||
}
|
||||
|
||||
public static void info(String message, Boolean raw)
|
||||
public static void info(String message, boolean raw)
|
||||
{
|
||||
log(Level.INFO, message, raw);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public final class BT_Log
|
|||
info(message, false);
|
||||
}
|
||||
|
||||
public static void warning(String message, Boolean raw)
|
||||
public static void warning(String message, boolean raw)
|
||||
{
|
||||
log(Level.WARNING, message, raw);
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ public final class BT_Log
|
|||
info(message, false);
|
||||
}
|
||||
|
||||
public static void severe(String message, Boolean raw)
|
||||
public static void severe(String message, boolean raw)
|
||||
{
|
||||
log(Level.SEVERE, message, raw);
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
package me.StevenLawson.BukkitTelnet;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
public class TelnetPreLoginEvent extends Event implements Cancellable
|
||||
{
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private boolean cancelled = false;
|
||||
//
|
||||
private String name = null;
|
||||
private final String ip;
|
||||
private boolean bypassPassword;
|
||||
|
||||
public TelnetPreLoginEvent(String ip, String name, boolean bypassPassword)
|
||||
{
|
||||
this.ip = ip;
|
||||
this.name = name;
|
||||
this.bypassPassword = bypassPassword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers()
|
||||
{
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList()
|
||||
{
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled()
|
||||
{
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel)
|
||||
{
|
||||
cancelled = cancel;
|
||||
}
|
||||
|
||||
public String getIp()
|
||||
{
|
||||
return ip;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public boolean canBypassPassword()
|
||||
{
|
||||
return bypassPassword;
|
||||
}
|
||||
|
||||
public void setBypassPassword(boolean bypassPassword)
|
||||
{
|
||||
this.bypassPassword = bypassPassword;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package me.StevenLawson.BukkitTelnet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import me.StevenLawson.BukkitTelnet.TelnetConfig.SimpleConfigEntries;
|
||||
|
||||
public class TelnetServer
|
||||
{
|
||||
private SocketListener socketListener;
|
||||
|
||||
private TelnetServer()
|
||||
{
|
||||
}
|
||||
|
||||
public void startServer()
|
||||
{
|
||||
// If the server is running, stop it
|
||||
stopServer();
|
||||
|
||||
final SimpleConfigEntries config = TelnetConfig.getInstance().getConfigEntries();
|
||||
|
||||
// Server address, optional.
|
||||
final InetAddress hostAddress;
|
||||
|
||||
final String address = config.getAddress();
|
||||
if (address != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
hostAddress = InetAddress.getByName(address);
|
||||
}
|
||||
catch (UnknownHostException ex)
|
||||
{
|
||||
TelnetLogger.severe("Cannot start server - Invalid address: " + config.getAddress());
|
||||
TelnetLogger.severe(ex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hostAddress = null;
|
||||
}
|
||||
|
||||
// Server socket
|
||||
ServerSocket serversocket;
|
||||
|
||||
try
|
||||
{
|
||||
if (hostAddress == null)
|
||||
{
|
||||
serversocket = new ServerSocket(config.getPort());
|
||||
}
|
||||
else
|
||||
{
|
||||
serversocket = new ServerSocket(config.getPort(), 50, hostAddress);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
TelnetLogger.severe("Cannot start server - " + "Cant bind to " + (hostAddress == null ? "*" : hostAddress) + ":" + config.getPort());
|
||||
TelnetLogger.severe(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
socketListener = new SocketListener(serversocket);
|
||||
socketListener.start();
|
||||
|
||||
final String host = serversocket.getInetAddress().getHostAddress().replace("0.0.0.0", "*");
|
||||
TelnetLogger.info("Server started on " + host + ":" + serversocket.getLocalPort());
|
||||
}
|
||||
|
||||
public void stopServer()
|
||||
{
|
||||
if (socketListener == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
socketListener.stopServer();
|
||||
}
|
||||
|
||||
public static TelnetServer getInstance()
|
||||
{
|
||||
return BT_TelnetServerHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private static class BT_TelnetServerHolder
|
||||
{
|
||||
private static final TelnetServer INSTANCE = new TelnetServer();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package me.StevenLawson.BukkitTelnet;
|
||||
|
||||
public class Util
|
||||
{
|
||||
public static boolean fuzzyIpMatch(String a, String b, int octets)
|
||||
{
|
||||
boolean match = true;
|
||||
|
||||
String[] aParts = a.split("\\.");
|
||||
String[] bParts = b.split("\\.");
|
||||
|
||||
if (aParts.length != 4 || bParts.length != 4)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (octets > 4)
|
||||
{
|
||||
octets = 4;
|
||||
}
|
||||
else if (octets < 1)
|
||||
{
|
||||
octets = 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < octets && i < 4; i++)
|
||||
{
|
||||
if (aParts[i].equals("*") || bParts[i].equals("*"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!aParts[i].equals(bParts[i]))
|
||||
{
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
}
|
|
@ -25,11 +25,10 @@ public class TelnetCommandEvent extends Event implements Cancellable
|
|||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList()
|
||||
{
|
||||
return handlers;
|
||||
}
|
||||
|
||||
//public static HandlerList getHandlerList()
|
||||
//{
|
||||
// return handlers;
|
||||
//}
|
||||
@Override
|
||||
public boolean isCancelled()
|
||||
{
|
||||
|
@ -59,6 +58,11 @@ public class TelnetCommandEvent extends Event implements Cancellable
|
|||
|
||||
public void setCommand(String command)
|
||||
{
|
||||
if (command == null)
|
||||
{
|
||||
command = "";
|
||||
}
|
||||
|
||||
this.command = command;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,461 @@
|
|||
package me.StevenLawson.BukkitTelnet.session;
|
||||
|
||||
import me.StevenLawson.BukkitTelnet.api.TelnetPreLoginEvent;
|
||||
import me.StevenLawson.BukkitTelnet.api.TelnetCommandEvent;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import me.StevenLawson.BukkitTelnet.BukkitTelnet;
|
||||
import me.StevenLawson.BukkitTelnet.TelnetConfig;
|
||||
import me.StevenLawson.BukkitTelnet.TelnetLogger;
|
||||
import me.StevenLawson.BukkitTelnet.Util;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.apache.logging.log4j.core.Logger;
|
||||
|
||||
public final class ClientSession extends Thread
|
||||
{
|
||||
public static final Pattern NONASCII_FILTER = Pattern.compile("[^\\x20-\\x7E]");
|
||||
public static final Pattern AUTH_INPUT_FILTER = Pattern.compile("[^a-zA-Z0-9]");
|
||||
public static final Pattern COMMAND_INPUT_FILTER = Pattern.compile("^[^a-zA-Z0-9/\\?!\\.]+");
|
||||
//
|
||||
private final Socket clientSocket;
|
||||
private final String clientAddress;
|
||||
//
|
||||
private final SessionCommandSender commandSender;
|
||||
private final SessionLogAppender logAppender;
|
||||
private FilterMode filterMode = FilterMode.FULL;
|
||||
//
|
||||
private BufferedWriter writer;
|
||||
private BufferedReader reader;
|
||||
private String username;
|
||||
private boolean hasTerminated;
|
||||
|
||||
public ClientSession(Socket clientSocket)
|
||||
{
|
||||
this.clientSocket = clientSocket;
|
||||
this.clientAddress = clientSocket.getInetAddress().getHostAddress();
|
||||
this.username = "";
|
||||
this.commandSender = new SessionCommandSender(this);
|
||||
this.logAppender = new SessionLogAppender(this);
|
||||
this.hasTerminated = false;
|
||||
|
||||
TelnetLogger.info("Client connected: " + clientAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized (clientSocket)
|
||||
{
|
||||
reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
|
||||
writer = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
TelnetLogger.severe(ex);
|
||||
syncTerminateSession();
|
||||
return;
|
||||
}
|
||||
|
||||
printRaw(":");
|
||||
println("Session Started.");
|
||||
|
||||
if (!authenticate())
|
||||
{
|
||||
println("Authentication failed.");
|
||||
syncTerminateSession();
|
||||
}
|
||||
|
||||
mainLoop();
|
||||
syncTerminateSession();
|
||||
}
|
||||
|
||||
public boolean syncIsConnected()
|
||||
{
|
||||
synchronized (clientSocket)
|
||||
{
|
||||
return !clientSocket.isClosed();
|
||||
}
|
||||
}
|
||||
|
||||
private Logger getLogger()
|
||||
{
|
||||
return (Logger) LogManager.getRootLogger();
|
||||
}
|
||||
|
||||
public synchronized void syncTerminateSession()
|
||||
{
|
||||
if (hasTerminated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hasTerminated = true;
|
||||
|
||||
TelnetLogger.info("Closing connection: " + clientAddress + (username.isEmpty() ? "" : "(" + username + ")"));
|
||||
getLogger().removeAppender(logAppender);
|
||||
|
||||
synchronized (clientSocket)
|
||||
{
|
||||
if (clientSocket == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
println("Closing connection...");
|
||||
try
|
||||
{
|
||||
clientSocket.close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public String getUserName()
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
public SessionCommandSender getCommandSender()
|
||||
{
|
||||
return commandSender;
|
||||
}
|
||||
|
||||
public SessionLogAppender getAppender()
|
||||
{
|
||||
return logAppender;
|
||||
}
|
||||
|
||||
public FilterMode getFilterMode()
|
||||
{
|
||||
return filterMode;
|
||||
}
|
||||
|
||||
public void setFilterMode(FilterMode filterMode)
|
||||
{
|
||||
this.filterMode = filterMode;
|
||||
}
|
||||
|
||||
public void printRaw(String message)
|
||||
{
|
||||
if (writer == null || !syncIsConnected())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
writer.write(ChatColor.stripColor(message));
|
||||
writer.flush();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void printRawln(String message)
|
||||
{
|
||||
printRaw(message + "\r\n:");
|
||||
}
|
||||
|
||||
public void print(String message)
|
||||
{
|
||||
printRaw("[" + (username.isEmpty() ? "" : username + "@") + "BukkitTelnet]$ " + message);
|
||||
}
|
||||
|
||||
public void println(String message)
|
||||
{
|
||||
print(message + "\r\n:");
|
||||
}
|
||||
|
||||
public void flush()
|
||||
{
|
||||
if (writer == null || !syncIsConnected())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
writer.flush();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public void syncExecuteCommand(final String command)
|
||||
{
|
||||
new BukkitRunnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
final Server server = Bukkit.getServer();
|
||||
|
||||
final TelnetCommandEvent event = new TelnetCommandEvent(commandSender, command);
|
||||
server.getPluginManager().callEvent(event);
|
||||
|
||||
if (event.isCancelled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getCommand().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
server.dispatchCommand(event.getSender(), event.getCommand());
|
||||
}
|
||||
}.runTask(BukkitTelnet.plugin);
|
||||
}
|
||||
|
||||
private boolean authenticate()
|
||||
{
|
||||
if (hasTerminated)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean authenticated = false;
|
||||
|
||||
// Pre-authenticate IP addresses
|
||||
if (clientAddress != null)
|
||||
{
|
||||
final Map<String, List<String>> admins = TelnetConfig.getInstance().getConfigEntries().getAdmins();
|
||||
|
||||
// For every admin
|
||||
for (String name : admins.keySet())
|
||||
{
|
||||
|
||||
// For every IP of each admin
|
||||
for (String ip : admins.get(name))
|
||||
{
|
||||
if (Util.fuzzyIpMatch(ip, clientAddress, 3))
|
||||
{
|
||||
authenticated = true;
|
||||
this.username = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send TelnetPreLoginEvent
|
||||
final TelnetPreLoginEvent event = new TelnetPreLoginEvent(clientAddress, username, authenticated);
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
if (event.isCancelled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.canBypassPassword())
|
||||
{
|
||||
this.username = event.getName();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Username / password authentication
|
||||
boolean validUsername = false;
|
||||
|
||||
int tries = 0;
|
||||
while (tries++ < 3)
|
||||
{
|
||||
print("Username: ");
|
||||
|
||||
String input;
|
||||
try
|
||||
{
|
||||
input = reader.readLine();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
printRaw(":");
|
||||
|
||||
if (input == null || input.isEmpty()) // End of stream
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
input = AUTH_INPUT_FILTER.matcher(input).replaceAll("").trim();
|
||||
|
||||
if (input.isEmpty())
|
||||
{
|
||||
println("Invalid username.");
|
||||
continue;
|
||||
}
|
||||
|
||||
this.username = input;
|
||||
validUsername = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!validUsername)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
tries = 0;
|
||||
while (tries++ < 3)
|
||||
{
|
||||
print("Password: ");
|
||||
|
||||
String input;
|
||||
|
||||
try
|
||||
{
|
||||
input = reader.readLine();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
printRaw(":");
|
||||
|
||||
if (input == null || input.isEmpty()) // End of stream
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
input = AUTH_INPUT_FILTER.matcher(input).replaceAll("").trim();
|
||||
|
||||
if (TelnetConfig.getInstance().getConfigEntries().getPassword().equals(input))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
println("Invalid password.");
|
||||
try
|
||||
{
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
catch (InterruptedException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void mainLoop()
|
||||
{
|
||||
if (hasTerminated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
println("Logged in as " + username + ".");
|
||||
TelnetLogger.info(clientAddress + " logged in as \"" + username + "\".");
|
||||
|
||||
// Start feeding data to the client.
|
||||
getLogger().addAppender(logAppender);
|
||||
|
||||
while (syncIsConnected())
|
||||
{
|
||||
// Read a command
|
||||
String command;
|
||||
try
|
||||
{
|
||||
command = reader.readLine();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
printRaw(":");
|
||||
|
||||
if (command == null || command.isEmpty()) // End of stream
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
command = COMMAND_INPUT_FILTER.matcher(NONASCII_FILTER.matcher(command).replaceAll("")).replaceFirst("").trim();
|
||||
if (command.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command.toLowerCase().startsWith("telnet"))
|
||||
{
|
||||
executeTelnetCommand(command);
|
||||
continue;
|
||||
}
|
||||
|
||||
syncExecuteCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeTelnetCommand(String command)
|
||||
{
|
||||
if (command.equalsIgnoreCase("telnet.help"))
|
||||
{
|
||||
println("--- Telnet commands ---");
|
||||
println("telnet.help - See all of the telnet commands.");
|
||||
println("telnet.stop - Shut the server down.");
|
||||
println("telnet.log - Change your logging settings.");
|
||||
println("telnet.exit - Quit the telnet session.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (command.equalsIgnoreCase("telnet.stop"))
|
||||
{
|
||||
println("Shutting down the server...");
|
||||
TelnetLogger.warning(username + ": Shutting down the server...");
|
||||
System.exit(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (command.equalsIgnoreCase("telnet.log"))
|
||||
{
|
||||
if (filterMode == FilterMode.FULL)
|
||||
{
|
||||
filterMode = FilterMode.CHAT_ONLY;
|
||||
println("Showing only chat logs.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (filterMode == FilterMode.CHAT_ONLY)
|
||||
{
|
||||
filterMode = FilterMode.NONCHAT_ONLY;
|
||||
println("Showing only non-chat logs.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (filterMode == FilterMode.NONCHAT_ONLY)
|
||||
{
|
||||
filterMode = FilterMode.FULL;
|
||||
println("Showing all logs.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (command.equalsIgnoreCase("telnet.exit"))
|
||||
{
|
||||
syncTerminateSession();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package me.StevenLawson.BukkitTelnet.session;
|
||||
|
||||
public enum FilterMode
|
||||
{
|
||||
FULL, NONCHAT_ONLY, CHAT_ONLY
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package me.StevenLawson.BukkitTelnet;
|
||||
package me.StevenLawson.BukkitTelnet.session;
|
||||
|
||||
import java.util.Set;
|
||||
import org.bukkit.Bukkit;
|
||||
|
@ -9,8 +9,27 @@ import org.bukkit.permissions.PermissionAttachment;
|
|||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public abstract class BT_CommandSender implements CommandSender
|
||||
public class SessionCommandSender implements CommandSender
|
||||
{
|
||||
private final ClientSession session;
|
||||
|
||||
protected SessionCommandSender(ClientSession session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message)
|
||||
{
|
||||
session.printRaw(message + "\r\n:");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return this.session.getUserName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String[] messages)
|
||||
{
|
|
@ -0,0 +1,71 @@
|
|||
package me.StevenLawson.BukkitTelnet.session;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import org.apache.logging.log4j.core.LogEvent;
|
||||
import org.apache.logging.log4j.core.appender.AbstractAppender;
|
||||
|
||||
public class SessionLogAppender extends AbstractAppender
|
||||
{
|
||||
private final ClientSession session;
|
||||
private final SimpleDateFormat dateFormat;
|
||||
|
||||
public SessionLogAppender(ClientSession session)
|
||||
{
|
||||
super("BukkitTelnet", null, null);
|
||||
|
||||
this.session = session;
|
||||
this.dateFormat = new SimpleDateFormat("HH:mm:ss");
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void append(LogEvent event)
|
||||
{
|
||||
final String message = event.getMessage().getFormattedMessage();
|
||||
|
||||
if (session.getFilterMode() == FilterMode.CHAT_ONLY)
|
||||
{
|
||||
if (!(message.startsWith("<")
|
||||
|| message.startsWith("[Server")
|
||||
|| message.startsWith("[CONSOLE") || message.startsWith("[TotalFreedomMod] [ADMIN]")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (session.getFilterMode() == FilterMode.NONCHAT_ONLY)
|
||||
{
|
||||
if (message.startsWith("<") || message.startsWith("[Server") || message.startsWith("[CONSOLE") || message.startsWith("[TotalFreedomMod] [ADMIN]"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
session.printRawln(formatMessage(message, event));
|
||||
}
|
||||
|
||||
private String formatMessage(String message, LogEvent event)
|
||||
{
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final Throwable ex = event.getThrown();
|
||||
|
||||
builder.append("[");
|
||||
builder.append(dateFormat.format(event.getMillis()));
|
||||
builder.append(" ");
|
||||
builder.append(event.getLevel().name().toUpperCase());
|
||||
builder.append("]: ");
|
||||
builder.append(message);
|
||||
|
||||
if (ex != null)
|
||||
{
|
||||
StringWriter writer = new StringWriter();
|
||||
ex.printStackTrace(new PrintWriter(writer));
|
||||
builder.append(writer);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue