From 2380c420893b07f826b40bdaa7030c89ac90c403 Mon Sep 17 00:00:00 2001 From: Haarolean Date: Sat, 10 Feb 2018 19:13:21 +0300 Subject: [PATCH 1/2] Added RPC mode without preamble and annoying stuff. --- .../ryanmichela/sshd/ConsoleShellFactory.java | 33 +++++---- .../implementations/SSHDCommandSender.java | 69 +++++++++++++++++++ src/main/resources/config.yml | 3 + 3 files changed, 92 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java diff --git a/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java b/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java index 14533c2..ef9b3c6 100644 --- a/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java +++ b/src/main/java/com/ryanmichela/sshd/ConsoleShellFactory.java @@ -1,5 +1,6 @@ package com.ryanmichela.sshd; +import com.ryanmichela.sshd.implementations.SSHDCommandSender; import jline.console.ConsoleReader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Logger; @@ -12,9 +13,13 @@ import org.bukkit.Bukkit; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.logging.Level; import java.util.logging.StreamHandler; public class ConsoleShellFactory implements Factory { + + static SSHDCommandSender sshdCommandSender = new SSHDCommandSender(); + public Command get() { return this.create(); } @@ -24,7 +29,6 @@ public class ConsoleShellFactory implements Factory { } public static class ConsoleShell implements Command, Runnable { - private InputStream in; private OutputStream out; private OutputStream err; @@ -33,7 +37,7 @@ public class ConsoleShellFactory implements Factory { private Thread thread; StreamHandlerAppender streamHandlerAppender; - ConsoleReader consoleReader; + public static ConsoleReader consoleReader; public InputStream getIn() { return in; @@ -68,7 +72,6 @@ public class ConsoleShellFactory implements Factory { } public void start(Environment env) throws IOException { - try { consoleReader = new ConsoleReader(in, new FlushyOutputStream(out), new SshTerminal()); consoleReader.setExpandEvents(true); @@ -93,21 +96,25 @@ public class ConsoleShellFactory implements Factory { public void run() { try { - printPreamble(consoleReader); + if (!SshdPlugin.instance.getConfig().getString("mode").equals("RPC")) + printPreamble(consoleReader); while (true) { String command = consoleReader.readLine("\r>", null); - if (command != null) { - if (command.equals("exit")) { - break; - } - SshdPlugin.instance.getLogger().info("<" + environment.getEnv().get(Environment.ENV_USER) + "> " + command); - Bukkit.getScheduler().runTask(SshdPlugin.instance, () -> { + if (command == null) continue; + if (command.equals("exit")) break; + Bukkit.getScheduler().runTask(SshdPlugin.instance, () -> { + if (SshdPlugin.instance.getConfig().getString("mode").equals("RPC") && command.startsWith("rpc")) { + //NO ECHO NO PREAMBLE AND SHIT + String cmd = command.substring("rpc".length() + 1, command.length()); + Bukkit.dispatchCommand(sshdCommandSender, cmd); + } else { + SshdPlugin.instance.getLogger().info("<" + environment.getEnv().get(Environment.ENV_USER) + "> " + command); Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); - }); - } + } + }); } } catch (IOException e) { - SshdPlugin.instance.getLogger().severe("Error processing command from SSH"); + SshdPlugin.instance.getLogger().log(Level.SEVERE, "Error processing command from SSH", e); } finally { callback.onExit(0); } diff --git a/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java b/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java new file mode 100644 index 0000000..5f6a570 --- /dev/null +++ b/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java @@ -0,0 +1,69 @@ +package com.ryanmichela.sshd.implementations; + +import com.ryanmichela.sshd.ConsoleShellFactory; +import com.ryanmichela.sshd.SshdPlugin; +import org.bukkit.ChatColor; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.conversations.Conversation; +import org.bukkit.conversations.ConversationAbandonedEvent; +import org.bukkit.conversations.ManuallyAbandonedConversationCanceller; +import org.bukkit.craftbukkit.v1_12_R1.command.ServerCommandSender; +import org.bukkit.craftbukkit.v1_12_R1.conversations.ConversationTracker; + +import java.io.IOException; +import java.util.Arrays; +import java.util.logging.Level; + +public class SSHDCommandSender extends ServerCommandSender implements ConsoleCommandSender { + + private final ConversationTracker conversationTracker = new ConversationTracker(); + + public void sendMessage(String message) { + this.sendRawMessage(message); + } + + public void sendRawMessage(String message) { + try { + ConsoleShellFactory.ConsoleShell.consoleReader.println(ChatColor.stripColor(message) + "\r"); + } catch (IOException e) { + SshdPlugin.instance.getLogger().log(Level.SEVERE, "Error sending message to SSHDCommandSender", e); + } + } + + public void sendMessage(String[] messages) { + Arrays.asList(messages).forEach(this::sendMessage); + } + + public String getName() { + return "SSHD CONSOLE"; + } + + public boolean isOp() { + return true; + } + + public void setOp(boolean value) { + throw new UnsupportedOperationException("Cannot change operator status of server console"); + } + + public boolean beginConversation(Conversation conversation) { + return this.conversationTracker.beginConversation(conversation); + } + + public void abandonConversation(Conversation conversation) { + this.conversationTracker.abandonConversation(conversation, new ConversationAbandonedEvent(conversation, new ManuallyAbandonedConversationCanceller())); + } + + public void abandonConversation(Conversation conversation, ConversationAbandonedEvent details) { + this.conversationTracker.abandonConversation(conversation, details); + } + + public void acceptConversationInput(String input) { + this.conversationTracker.acceptConversationInput(input); + } + + public boolean isConversing() { + return this.conversationTracker.isConversing(); + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index bd09d50..6d9b05c 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -4,6 +4,9 @@ listenAddress: all # The port the SSH server will listen on. port: 22 +# Operational mode. Don't touch if you don't know what you're doing. Can be either DEFAULT or RPC +mode: DEFAULT + # By default, only public key authentication is enabled. This is the most secure mode. # To authorize a user to log in with public key authentication, install their public # PEM certificate in the authorized_users directory. Name the key file with user's user From dc8e49f6437df95454e465085e2a3cf75180b9e6 Mon Sep 17 00:00:00 2001 From: Haarolean Date: Mon, 12 Feb 2018 04:00:42 +0300 Subject: [PATCH 2/2] No need of NMS imports. --- .../implementations/SSHDCommandSender.java | 70 +++++++++++++++-- .../SSHDConversationTracker.java | 78 +++++++++++++++++++ 2 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/ryanmichela/sshd/implementations/SSHDConversationTracker.java diff --git a/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java b/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java index 5f6a570..cfceaaa 100644 --- a/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java +++ b/src/main/java/com/ryanmichela/sshd/implementations/SSHDCommandSender.java @@ -2,21 +2,29 @@ package com.ryanmichela.sshd.implementations; import com.ryanmichela.sshd.ConsoleShellFactory; import com.ryanmichela.sshd.SshdPlugin; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.Server; +import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.conversations.Conversation; import org.bukkit.conversations.ConversationAbandonedEvent; import org.bukkit.conversations.ManuallyAbandonedConversationCanceller; -import org.bukkit.craftbukkit.v1_12_R1.command.ServerCommandSender; -import org.bukkit.craftbukkit.v1_12_R1.conversations.ConversationTracker; +import org.bukkit.permissions.PermissibleBase; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionAttachment; +import org.bukkit.permissions.PermissionAttachmentInfo; +import org.bukkit.plugin.Plugin; import java.io.IOException; import java.util.Arrays; +import java.util.Set; import java.util.logging.Level; -public class SSHDCommandSender extends ServerCommandSender implements ConsoleCommandSender { +public class SSHDCommandSender implements ConsoleCommandSender, CommandSender { - private final ConversationTracker conversationTracker = new ConversationTracker(); + private final PermissibleBase perm = new PermissibleBase(this); + private final SSHDConversationTracker conversationTracker = new SSHDConversationTracker(); public void sendMessage(String message) { this.sendRawMessage(message); @@ -24,7 +32,7 @@ public class SSHDCommandSender extends ServerCommandSender implements ConsoleCom public void sendRawMessage(String message) { try { - ConsoleShellFactory.ConsoleShell.consoleReader.println(ChatColor.stripColor(message) + "\r"); + ConsoleShellFactory.ConsoleShell.consoleReader.println(ChatColor.stripColor(message)); } catch (IOException e) { SshdPlugin.instance.getLogger().log(Level.SEVERE, "Error sending message to SSHDCommandSender", e); } @@ -66,4 +74,56 @@ public class SSHDCommandSender extends ServerCommandSender implements ConsoleCom return this.conversationTracker.isConversing(); } + public boolean isPermissionSet(String name) { + return this.perm.isPermissionSet(name); + } + + public boolean isPermissionSet(Permission perm) { + return this.perm.isPermissionSet(perm); + } + + public boolean hasPermission(String name) { + return this.perm.hasPermission(name); + } + + public boolean hasPermission(Permission perm) { + return this.perm.hasPermission(perm); + } + + public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) { + return this.perm.addAttachment(plugin, name, value); + } + + public PermissionAttachment addAttachment(Plugin plugin) { + return this.perm.addAttachment(plugin); + } + + public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) { + return this.perm.addAttachment(plugin, name, value, ticks); + } + + public PermissionAttachment addAttachment(Plugin plugin, int ticks) { + return this.perm.addAttachment(plugin, ticks); + } + + public void removeAttachment(PermissionAttachment attachment) { + this.perm.removeAttachment(attachment); + } + + public void recalculatePermissions() { + this.perm.recalculatePermissions(); + } + + public Set getEffectivePermissions() { + return this.perm.getEffectivePermissions(); + } + + public boolean isPlayer() { + return false; + } + + public Server getServer() { + return Bukkit.getServer(); + } + } diff --git a/src/main/java/com/ryanmichela/sshd/implementations/SSHDConversationTracker.java b/src/main/java/com/ryanmichela/sshd/implementations/SSHDConversationTracker.java new file mode 100644 index 0000000..947ef2d --- /dev/null +++ b/src/main/java/com/ryanmichela/sshd/implementations/SSHDConversationTracker.java @@ -0,0 +1,78 @@ +package com.ryanmichela.sshd.implementations; + +import org.bukkit.Bukkit; +import org.bukkit.conversations.Conversation; +import org.bukkit.conversations.ConversationAbandonedEvent; +import org.bukkit.conversations.ManuallyAbandonedConversationCanceller; + +import java.util.LinkedList; +import java.util.logging.Level; + +public class SSHDConversationTracker { + private LinkedList conversationQueue = new LinkedList<>(); + + synchronized boolean beginConversation(Conversation conversation) { + if (!this.conversationQueue.contains(conversation)) { + this.conversationQueue.addLast(conversation); + if (this.conversationQueue.getFirst() == conversation) { + conversation.begin(); + conversation.outputNextPrompt(); + return true; + } + } + + return true; + } + + synchronized void abandonConversation(Conversation conversation, ConversationAbandonedEvent details) { + if (!this.conversationQueue.isEmpty()) { + if (this.conversationQueue.getFirst() == conversation) { + conversation.abandon(details); + } + + if (this.conversationQueue.contains(conversation)) { + this.conversationQueue.remove(conversation); + } + + if (!this.conversationQueue.isEmpty()) { + this.conversationQueue.getFirst().outputNextPrompt(); + } + } + + } + + public synchronized void abandonAllConversations() { + LinkedList oldQueue = this.conversationQueue; + this.conversationQueue = new LinkedList<>(); + + for (Conversation conversation : oldQueue) { + try { + conversation.abandon(new ConversationAbandonedEvent(conversation, new ManuallyAbandonedConversationCanceller())); + } catch (Throwable var5) { + Bukkit.getLogger().log(Level.SEVERE, "Unexpected exception while abandoning a conversation", var5); + } + } + + } + + synchronized void acceptConversationInput(String input) { + if (this.isConversing()) { + Conversation conversation = this.conversationQueue.getFirst(); + + try { + conversation.acceptInput(input); + } catch (Throwable var4) { + conversation.getContext().getPlugin().getLogger().log(Level.WARNING, String.format("Plugin %s generated an exception whilst handling conversation input", conversation.getContext().getPlugin().getDescription().getFullName()), var4); + } + } + + } + + synchronized boolean isConversing() { + return !this.conversationQueue.isEmpty(); + } + + public synchronized boolean isConversingModaly() { + return this.isConversing() && this.conversationQueue.getFirst().isModal(); + } +}