Finish the port to Sponge. Things seem to work well.
This commit is contained in:
parent
41b561a88c
commit
a7918c68aa
106
pom.xml
106
pom.xml
@ -5,7 +5,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>com.ryanmichela</groupId>
|
<groupId>com.ryanmichela</groupId>
|
||||||
<artifactId>Sponge-SSHD</artifactId>
|
<artifactId>sshd</artifactId>
|
||||||
<version>1.3.7</version>
|
<version>1.3.7</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>Sponge-SSHD</name>
|
<name>Sponge-SSHD</name>
|
||||||
@ -56,24 +56,6 @@
|
|||||||
<version>0.3.0</version>
|
<version>0.3.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.mina</groupId>
|
|
||||||
<artifactId>mina-core</artifactId>
|
|
||||||
<version>2.1.3</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-api</artifactId>
|
|
||||||
<version>1.7.28</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-jdk14</artifactId>
|
|
||||||
<version>1.7.28</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jline</groupId>
|
<groupId>jline</groupId>
|
||||||
<artifactId>jline</artifactId>
|
<artifactId>jline</artifactId>
|
||||||
@ -83,7 +65,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.logging.log4j</groupId>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<artifactId>log4j-core</artifactId>
|
<artifactId>log4j-core</artifactId>
|
||||||
<version>2.0</version>
|
<version>2.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -91,25 +73,6 @@
|
|||||||
<artifactId>log4j-api</artifactId>
|
<artifactId>log4j-api</artifactId>
|
||||||
<version>2.1</version>
|
<version>2.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-codec</groupId>
|
|
||||||
<artifactId>commons-codec</artifactId>
|
|
||||||
<version>1.10</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-lang</groupId>
|
|
||||||
<artifactId>commons-lang</artifactId>
|
|
||||||
<version>2.6</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<version>1.18.4</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- include Sponge API -->
|
<!-- include Sponge API -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.spongepowered</groupId>
|
<groupId>org.spongepowered</groupId>
|
||||||
@ -123,7 +86,7 @@
|
|||||||
<!-- Set our default goal to be clean and build a package -->
|
<!-- Set our default goal to be clean and build a package -->
|
||||||
<defaultGoal>clean package</defaultGoal>
|
<defaultGoal>clean package</defaultGoal>
|
||||||
<!-- Include our git hash in the final name -->
|
<!-- Include our git hash in the final name -->
|
||||||
<finalName>${project.name}-${project.version}</finalName>
|
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<resource>
|
<resource>
|
||||||
@ -138,59 +101,36 @@
|
|||||||
|
|
||||||
<!-- Plugins -->
|
<!-- Plugins -->
|
||||||
<plugins>
|
<plugins>
|
||||||
<!-- Run the get git info stuff so we have revisions and whatnot -->
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>pl.project13.maven</groupId>
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
<artifactId>git-commit-id-plugin</artifactId>
|
<version>3.1.1</version>
|
||||||
<version>2.2.5</version>
|
|
||||||
|
|
||||||
<configuration>
|
|
||||||
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<!-- Shade plugin (resolves Jar dependencies) -->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>3.2.1</version>
|
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<phase>package</phase>
|
<phase>package</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>shade</goal>
|
<goal>single</goal>
|
||||||
</goals>
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
<configuration>
|
<configuration>
|
||||||
<minimizeJar>true</minimizeJar>
|
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||||
<!-- Remove jar signing from other jars -->
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
<filters>
|
<descriptorRefs>
|
||||||
<filter>
|
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||||
<artifact>*:*:*:*</artifact>
|
</descriptorRefs>
|
||||||
<excludes>
|
|
||||||
<exclude>META-INF/*.RSA</exclude>
|
|
||||||
<exclude>META-INF/*.SF</exclude>
|
|
||||||
<exclude>META-INF/*.DSA</exclude>
|
|
||||||
</excludes>
|
|
||||||
</filter>
|
|
||||||
</filters>
|
|
||||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
|
||||||
<dependencyReducedPomLocation>${java.io.tmpdir}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
<!-- Maven templates for our PomData file -->
|
|
||||||
|
<!-- Compile plugin -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>templating-maven-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>1.0-alpha-3</version>
|
<version>3.7.0</version>
|
||||||
<executions>
|
<configuration>
|
||||||
<execution>
|
<source>1.8</source>
|
||||||
<id>filter-src</id>
|
<target>1.8</target>
|
||||||
<goals>
|
<showDeprecation>true</showDeprecation>
|
||||||
<goal>filter-sources</goal>
|
</configuration>
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
222
src/main/java/com/ryanmichela/sshd/ChatColor.java
Normal file
222
src/main/java/com/ryanmichela/sshd/ChatColor.java
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
package com.ryanmichela.sshd;
|
||||||
|
// The below code was taken from md_5's BungeeCord project - Justin
|
||||||
|
/*
|
||||||
|
Copyright (c) 2012, md_5. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
The name of the author may not be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
You may not use the software for commercial software hosting services without
|
||||||
|
written permission from the author.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simplistic enumeration of all supported color values for chat.
|
||||||
|
*/
|
||||||
|
public enum ChatColor
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Represents black.
|
||||||
|
*/
|
||||||
|
BLACK( '0', "black" ),
|
||||||
|
/**
|
||||||
|
* Represents dark blue.
|
||||||
|
*/
|
||||||
|
DARK_BLUE( '1', "dark_blue" ),
|
||||||
|
/**
|
||||||
|
* Represents dark green.
|
||||||
|
*/
|
||||||
|
DARK_GREEN( '2', "dark_green" ),
|
||||||
|
/**
|
||||||
|
* Represents dark blue (aqua).
|
||||||
|
*/
|
||||||
|
DARK_AQUA( '3', "dark_aqua" ),
|
||||||
|
/**
|
||||||
|
* Represents dark red.
|
||||||
|
*/
|
||||||
|
DARK_RED( '4', "dark_red" ),
|
||||||
|
/**
|
||||||
|
* Represents dark purple.
|
||||||
|
*/
|
||||||
|
DARK_PURPLE( '5', "dark_purple" ),
|
||||||
|
/**
|
||||||
|
* Represents gold.
|
||||||
|
*/
|
||||||
|
GOLD( '6', "gold" ),
|
||||||
|
/**
|
||||||
|
* Represents gray.
|
||||||
|
*/
|
||||||
|
GRAY( '7', "gray" ),
|
||||||
|
/**
|
||||||
|
* Represents dark gray.
|
||||||
|
*/
|
||||||
|
DARK_GRAY( '8', "dark_gray" ),
|
||||||
|
/**
|
||||||
|
* Represents blue.
|
||||||
|
*/
|
||||||
|
BLUE( '9', "blue" ),
|
||||||
|
/**
|
||||||
|
* Represents green.
|
||||||
|
*/
|
||||||
|
GREEN( 'a', "green" ),
|
||||||
|
/**
|
||||||
|
* Represents aqua.
|
||||||
|
*/
|
||||||
|
AQUA( 'b', "aqua" ),
|
||||||
|
/**
|
||||||
|
* Represents red.
|
||||||
|
*/
|
||||||
|
RED( 'c', "red" ),
|
||||||
|
/**
|
||||||
|
* Represents light purple.
|
||||||
|
*/
|
||||||
|
LIGHT_PURPLE( 'd', "light_purple" ),
|
||||||
|
/**
|
||||||
|
* Represents yellow.
|
||||||
|
*/
|
||||||
|
YELLOW( 'e', "yellow" ),
|
||||||
|
/**
|
||||||
|
* Represents white.
|
||||||
|
*/
|
||||||
|
WHITE( 'f', "white" ),
|
||||||
|
/**
|
||||||
|
* Represents magical characters that change around randomly.
|
||||||
|
*/
|
||||||
|
MAGIC( 'k', "obfuscated" ),
|
||||||
|
/**
|
||||||
|
* Makes the text bold.
|
||||||
|
*/
|
||||||
|
BOLD( 'l', "bold" ),
|
||||||
|
/**
|
||||||
|
* Makes a line appear through the text.
|
||||||
|
*/
|
||||||
|
STRIKETHROUGH( 'm', "strikethrough" ),
|
||||||
|
/**
|
||||||
|
* Makes the text appear underlined.
|
||||||
|
*/
|
||||||
|
UNDERLINE( 'n', "underline" ),
|
||||||
|
/**
|
||||||
|
* Makes the text italic.
|
||||||
|
*/
|
||||||
|
ITALIC( 'o', "italic" ),
|
||||||
|
/**
|
||||||
|
* Resets all previous chat colors or formats.
|
||||||
|
*/
|
||||||
|
RESET( 'r', "reset" );
|
||||||
|
/**
|
||||||
|
* The special character which prefixes all chat colour codes. Use this if
|
||||||
|
* you need to dynamically convert colour codes from your custom format.
|
||||||
|
*/
|
||||||
|
public static final char COLOR_CHAR = '\u00A7';
|
||||||
|
public static final String ALL_CODES = "0123456789AaBbCcDdEeFfKkLlMmNnOoRr";
|
||||||
|
/**
|
||||||
|
* Pattern to remove all colour codes.
|
||||||
|
*/
|
||||||
|
public static final Pattern STRIP_COLOR_PATTERN = Pattern.compile( "(?i)" + String.valueOf( COLOR_CHAR ) + "[0-9A-FK-OR]" );
|
||||||
|
/**
|
||||||
|
* Colour instances keyed by their active character.
|
||||||
|
*/
|
||||||
|
private static final Map<Character, ChatColor> BY_CHAR = new HashMap<Character, ChatColor>();
|
||||||
|
/**
|
||||||
|
* The code appended to {@link #COLOR_CHAR} to make usable colour.
|
||||||
|
*/
|
||||||
|
private final char code;
|
||||||
|
/**
|
||||||
|
* This colour's colour char prefixed by the {@link #COLOR_CHAR}.
|
||||||
|
*/
|
||||||
|
private final String toString;
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public String getName() { return this.name; }
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
for ( ChatColor colour : values() )
|
||||||
|
{
|
||||||
|
BY_CHAR.put( colour.code, colour );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ChatColor(char code, String name)
|
||||||
|
{
|
||||||
|
this.code = code;
|
||||||
|
this.name = name;
|
||||||
|
this.toString = new String( new char[]
|
||||||
|
{
|
||||||
|
COLOR_CHAR, code
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return toString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strips the given message of all color codes
|
||||||
|
*
|
||||||
|
* @param input String to strip of color
|
||||||
|
* @return A copy of the input string, without any coloring
|
||||||
|
*/
|
||||||
|
public static String stripColor(final String input)
|
||||||
|
{
|
||||||
|
if ( input == null )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STRIP_COLOR_PATTERN.matcher( input ).replaceAll( "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String translateAlternateColorCodes(char altColorChar, String textToTranslate)
|
||||||
|
{
|
||||||
|
char[] b = textToTranslate.toCharArray();
|
||||||
|
for ( int i = 0; i < b.length - 1; i++ )
|
||||||
|
{
|
||||||
|
if ( b[i] == altColorChar && ALL_CODES.indexOf( b[i + 1] ) > -1 )
|
||||||
|
{
|
||||||
|
b[i] = ChatColor.COLOR_CHAR;
|
||||||
|
b[i + 1] = Character.toLowerCase( b[i + 1] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new String( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the colour represented by the specified code.
|
||||||
|
*
|
||||||
|
* @param code the code to search for
|
||||||
|
* @return the mapped colour, or null if non exists
|
||||||
|
*/
|
||||||
|
public static ChatColor getByChar(char code)
|
||||||
|
{
|
||||||
|
return BY_CHAR.get( code );
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@ public class ConfigPasswordAuthenticator implements PasswordAuthenticator {
|
|||||||
String ConfigHash = SshdPlugin.GetInstance().config.configNode.getNode("Credentials", username.trim(), "password").getString();
|
String ConfigHash = SshdPlugin.GetInstance().config.configNode.getNode("Credentials", username.trim(), "password").getString();
|
||||||
|
|
||||||
if (ConfigHash == null)
|
if (ConfigHash == null)
|
||||||
SshdPlugin.GetLogger().warn("Config has no such user: " + username);
|
SshdPlugin.GetInstance().logger.warn("Config has no such user: " + username);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -69,7 +69,7 @@ public class ConfigPasswordAuthenticator implements PasswordAuthenticator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SshdPlugin.GetLogger().info("Failed login for " + username + " using " + HashType + "-based password authentication.");
|
SshdPlugin.GetInstance().logger.info("Failed login for " + username + " using " + HashType + "-based password authentication.");
|
||||||
Integer tries = SshdPlugin.GetInstance().LoginRetries;
|
Integer tries = SshdPlugin.GetInstance().LoginRetries;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -83,7 +83,7 @@ public class ConfigPasswordAuthenticator implements PasswordAuthenticator {
|
|||||||
if (this.FailCounts.get(username) >= tries)
|
if (this.FailCounts.get(username) >= tries)
|
||||||
{
|
{
|
||||||
this.FailCounts.put(username, 0);
|
this.FailCounts.put(username, 0);
|
||||||
SshdPlugin.GetLogger().info("Too many failures for " + username + ", disconnecting.");
|
SshdPlugin.GetInstance().logger.info("Too many failures for " + username + ", disconnecting.");
|
||||||
ss.close(true);
|
ss.close(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,23 @@ package com.ryanmichela.sshd;
|
|||||||
|
|
||||||
import jline.console.completer.Completer;
|
import jline.console.completer.Completer;
|
||||||
|
|
||||||
|
import org.spongepowered.api.Sponge;
|
||||||
|
import org.spongepowered.api.scheduler.SpongeExecutorService;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class ConsoleCommandCompleter //implements Completer
|
public class ConsoleCommandCompleter implements Completer
|
||||||
{
|
{
|
||||||
/*
|
private SpongeExecutorService MinecraftExecutor;
|
||||||
|
|
||||||
|
public ConsoleCommandCompleter()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this.MinecraftExecutor = Sponge.getScheduler().createSyncExecutor(SshdPlugin.GetInstance());
|
||||||
|
}
|
||||||
|
|
||||||
public int complete(final String buffer, final int cursor, final List<CharSequence> candidates)
|
public int complete(final String buffer, final int cursor, final List<CharSequence> candidates)
|
||||||
{
|
{
|
||||||
Waitable<List<String>> waitable = new Waitable<List<String>>()
|
Waitable<List<String>> waitable = new Waitable<List<String>>()
|
||||||
@ -20,12 +30,11 @@ public class ConsoleCommandCompleter //implements Completer
|
|||||||
@Override
|
@Override
|
||||||
protected List<String> evaluate()
|
protected List<String> evaluate()
|
||||||
{
|
{
|
||||||
CommandMap commandMap = ReflectionUtil.getProtectedValue(Bukkit.getServer(), "commandMap");
|
return Sponge.getCommandManager().getSuggestions(Sponge.getServer().getConsole(), buffer, null);
|
||||||
return commandMap.tabComplete(Bukkit.getServer().getConsoleSender(), buffer);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Bukkit.getScheduler().runTask(SshdPlugin.instance, waitable);
|
this.MinecraftExecutor.execute(waitable);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<String> offers = waitable.get();
|
List<String> offers = waitable.get();
|
||||||
@ -47,7 +56,7 @@ public class ConsoleCommandCompleter //implements Completer
|
|||||||
}
|
}
|
||||||
catch (ExecutionException e)
|
catch (ExecutionException e)
|
||||||
{
|
{
|
||||||
SshdPlugin.instance.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e);
|
SshdPlugin.GetInstance().logger.warn("Unhandled exception when tab completing", e);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e)
|
catch (InterruptedException e)
|
||||||
{
|
{
|
||||||
@ -55,6 +64,5 @@ public class ConsoleCommandCompleter //implements Completer
|
|||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,14 +55,14 @@ public class ConsoleCommandFactory implements CommandFactory {
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SshdPlugin.GetLogger()
|
SshdPlugin.GetInstance().logger
|
||||||
.info("[U: " + environment.getEnv().get(Environment.ENV_USER) + "] " + command);
|
.info("[U: " + environment.getEnv().get(Environment.ENV_USER) + "] " + command);
|
||||||
|
|
||||||
Sponge.getCommandManager().process(Sponge.getServer().getConsole(), command);
|
Sponge.getCommandManager().process(Sponge.getServer().getConsole(), command);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
SshdPlugin.GetLogger().error("Error processing command from SSH -" + e.getMessage());
|
SshdPlugin.GetInstance().logger.error("Error processing command from SSH -" + e.getMessage());
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -9,21 +9,13 @@ import org.fusesource.jansi.Ansi;
|
|||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Formatter;
|
|
||||||
import java.util.logging.LogRecord;
|
|
||||||
|
|
||||||
public class ConsoleLogFormatter extends Formatter {
|
public class ConsoleLogFormatter
|
||||||
|
{
|
||||||
private SimpleDateFormat dateFormat;
|
|
||||||
private static final Map<ChatColor, String> replacements = new EnumMap<ChatColor, String>(ChatColor.class);
|
private static final Map<ChatColor, String> replacements = new EnumMap<ChatColor, String>(ChatColor.class);
|
||||||
|
|
||||||
public ConsoleLogFormatter() {
|
|
||||||
this.dateFormat = new SimpleDateFormat("HH:mm:ss");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String ColorizeString(String str)
|
public static String ColorizeString(String str)
|
||||||
{
|
{
|
||||||
// ORIGINAL CODE FROM org.bukkit.craftbukkit.command.ColouredConsoleSender
|
// ORIGINAL CODE FROM org.bukkit.craftbukkit.command.ColouredConsoleSender
|
||||||
@ -66,43 +58,5 @@ public class ConsoleLogFormatter extends Formatter {
|
|||||||
result += Ansi.ansi().reset().toString();
|
result += Ansi.ansi().reset().toString();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String format(LogRecord logrecord)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Class.forName("org.bukkit.craftbukkit.command.ColouredConsoleSender");
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException ignored)
|
|
||||||
{
|
|
||||||
// MEANS WE'RE ON PAPER/TACO/OTHER SHIT
|
|
||||||
colorize(logrecord);
|
|
||||||
}
|
|
||||||
StringBuilder stringbuilder = new StringBuilder();
|
|
||||||
|
|
||||||
stringbuilder.append(" [");
|
|
||||||
stringbuilder.append(this.dateFormat.format(logrecord.getMillis())).append(" ");
|
|
||||||
|
|
||||||
stringbuilder.append(logrecord.getLevel().getName()).append("]: ");
|
|
||||||
stringbuilder.append(this.formatMessage(logrecord));
|
|
||||||
stringbuilder.append('\n');
|
|
||||||
Throwable throwable = logrecord.getThrown();
|
|
||||||
|
|
||||||
if (throwable != null)
|
|
||||||
{
|
|
||||||
StringWriter stringwriter = new StringWriter();
|
|
||||||
|
|
||||||
throwable.printStackTrace(new PrintWriter(stringwriter));
|
|
||||||
stringbuilder.append(stringwriter.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringbuilder.toString().replace("\n", "\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void colorize(LogRecord logrecord)
|
|
||||||
{
|
|
||||||
String result = ColorizeString(logrecord.getMessage());
|
|
||||||
logrecord.setMessage(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ package com.ryanmichela.sshd;
|
|||||||
import com.ryanmichela.sshd.ConsoleCommandCompleter;
|
import com.ryanmichela.sshd.ConsoleCommandCompleter;
|
||||||
import com.ryanmichela.sshd.ConsoleLogFormatter;
|
import com.ryanmichela.sshd.ConsoleLogFormatter;
|
||||||
import com.ryanmichela.sshd.FlushyOutputStream;
|
import com.ryanmichela.sshd.FlushyOutputStream;
|
||||||
import com.ryanmichela.sshd.FlushyStreamHandler;
|
|
||||||
import com.ryanmichela.sshd.SshTerminal;
|
import com.ryanmichela.sshd.SshTerminal;
|
||||||
import com.ryanmichela.sshd.SshdPlugin;
|
import com.ryanmichela.sshd.SshdPlugin;
|
||||||
import com.ryanmichela.sshd.StreamHandlerAppender;
|
import com.ryanmichela.sshd.StreamHandlerAppender;
|
||||||
@ -34,7 +33,6 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.StreamHandler;
|
import java.util.logging.StreamHandler;
|
||||||
|
|
||||||
@ -97,10 +95,9 @@ public class ConsoleShellFactory implements ShellFactory {
|
|||||||
{
|
{
|
||||||
this.ConsoleReader = new ConsoleReader(in, new FlushyOutputStream(out), new SshTerminal());
|
this.ConsoleReader = new ConsoleReader(in, new FlushyOutputStream(out), new SshTerminal());
|
||||||
this.ConsoleReader.setExpandEvents(true);
|
this.ConsoleReader.setExpandEvents(true);
|
||||||
//this.ConsoleReader.addCompleter(new ConsoleCommandCompleter());
|
this.ConsoleReader.addCompleter(new ConsoleCommandCompleter());
|
||||||
|
|
||||||
StreamHandler streamHandler = new FlushyStreamHandler(out, new ConsoleLogFormatter(), this.ConsoleReader);
|
this.streamHandlerAppender = new StreamHandlerAppender(this.ConsoleReader);
|
||||||
this.streamHandlerAppender = new StreamHandlerAppender(streamHandler);
|
|
||||||
|
|
||||||
((Logger)LogManager.getRootLogger()).addAppender(this.streamHandlerAppender);
|
((Logger)LogManager.getRootLogger()).addAppender(this.streamHandlerAppender);
|
||||||
|
|
||||||
@ -153,7 +150,7 @@ public class ConsoleShellFactory implements ShellFactory {
|
|||||||
// Hide the mkpasswd command input from other users.
|
// Hide the mkpasswd command input from other users.
|
||||||
Boolean mkpasswd = command.split(" ")[0].equals("mkpasswd");
|
Boolean mkpasswd = command.split(" ")[0].equals("mkpasswd");
|
||||||
|
|
||||||
MinecraftExecutor.schedule(() ->
|
MinecraftExecutor.submit(() ->
|
||||||
{
|
{
|
||||||
if (SshdPlugin.GetInstance().Mode.equals("RPC") && command.startsWith("rpc"))
|
if (SshdPlugin.GetInstance().Mode.equals("RPC") && command.startsWith("rpc"))
|
||||||
{
|
{
|
||||||
@ -168,7 +165,7 @@ public class ConsoleShellFactory implements ShellFactory {
|
|||||||
// our plugin and the connected client.
|
// our plugin and the connected client.
|
||||||
if (!mkpasswd)
|
if (!mkpasswd)
|
||||||
{
|
{
|
||||||
SshdPlugin.GetLogger().info("<" + this.Username + "> " + command);
|
SshdPlugin.GetInstance().logger.info("<" + this.Username + "> " + command);
|
||||||
CmdManager.process(Sponge.getServer().getConsole(), command);
|
CmdManager.process(Sponge.getServer().getConsole(), command);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -176,16 +173,16 @@ public class ConsoleShellFactory implements ShellFactory {
|
|||||||
CmdManager.process(this.SshdCommandSender, command);
|
CmdManager.process(this.SshdCommandSender, command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 0, TimeUnit.SECONDS);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
SshdPlugin.GetLogger().error("Error processing command from SSH", e);
|
SshdPlugin.GetInstance().logger.error("Error processing command from SSH", e);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
SshdPlugin.GetLogger().info(this.Username + " disconnected from SSH.");
|
SshdPlugin.GetInstance().logger.info(this.Username + " disconnected from SSH.");
|
||||||
callback.onExit(0);
|
callback.onExit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,7 +200,7 @@ public class ConsoleShellFactory implements ShellFactory {
|
|||||||
}
|
}
|
||||||
catch (FileNotFoundException e)
|
catch (FileNotFoundException e)
|
||||||
{
|
{
|
||||||
SshdPlugin.GetLogger().warn("Could not open " + f + ": File does not exist.");
|
SshdPlugin.GetInstance().logger.warn("Could not open " + f + ": File does not exist.");
|
||||||
// Not showing the SSH motd is not a fatal failure, let the session continue.
|
// Not showing the SSH motd is not a fatal failure, let the session continue.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +219,7 @@ public class ConsoleShellFactory implements ShellFactory {
|
|||||||
cr.println(str + "\r");
|
cr.println(str + "\r");
|
||||||
cr.println(ConsoleLogFormatter.ColorizeString(Sponge.getServer().getMotd().toPlain()).replaceAll("\n", "\r\n"));
|
cr.println(ConsoleLogFormatter.ColorizeString(Sponge.getServer().getMotd().toPlain()).replaceAll("\n", "\r\n"));
|
||||||
cr.println("\r");
|
cr.println("\r");
|
||||||
cr.println("Type 'exit' to exit the shell." + "\r");
|
cr.println("Type 'exit' or CTRL+D to exit the shell." + "\r");
|
||||||
cr.println("===============================================" + "\r");
|
cr.println("===============================================" + "\r");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
package com.ryanmichela.sshd;
|
|
||||||
|
|
||||||
import jline.console.ConsoleReader;
|
|
||||||
import org.apache.sshd.common.SshException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.logging.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright 2013 Ryan Michela
|
|
||||||
*/
|
|
||||||
public class FlushyStreamHandler extends StreamHandler {
|
|
||||||
|
|
||||||
private ConsoleReader reader;
|
|
||||||
|
|
||||||
public FlushyStreamHandler(OutputStream out, Formatter formatter, ConsoleReader reader) {
|
|
||||||
super(out, formatter);
|
|
||||||
this.reader = reader;
|
|
||||||
setLevel(Level.INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void publish(LogRecord record) {
|
|
||||||
record.setMessage(record.getMessage().replace("\n", "\n\r"));
|
|
||||||
super.publish(record);
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public synchronized void flush() {
|
|
||||||
try {
|
|
||||||
reader.print(ConsoleReader.RESET_LINE + "");
|
|
||||||
reader.flush();
|
|
||||||
super.flush();
|
|
||||||
try {
|
|
||||||
reader.drawLine();
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
reader.getCursorBuffer().clear();
|
|
||||||
}
|
|
||||||
reader.flush();
|
|
||||||
super.flush();
|
|
||||||
} catch (SshException ex) {
|
|
||||||
// do nothing
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(FlushyStreamHandler.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -35,7 +35,7 @@ public class MkpasswdCommand implements CommandExecutor
|
|||||||
.executor((CommandSource source, CommandContext args) -> {
|
.executor((CommandSource source, CommandContext args) -> {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
source.sendMessage(Text.of("\u00A79Your Hash: " + Cryptography.PBKDF2_HashPassword(args.<String>getOne("message").get())));
|
source.sendMessage(Text.of("\u00A79Your Hash: " + Cryptography.PBKDF2_HashPassword(args.<String>getOne("password").get())));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -53,7 +53,7 @@ public class MkpasswdCommand implements CommandExecutor
|
|||||||
.executor((CommandSource source, CommandContext args) -> {
|
.executor((CommandSource source, CommandContext args) -> {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
source.sendMessage(Text.of("\u00A79Your Hash: " + Cryptography.BCrypt_HashPassword(args.<String>getOne("message").get())));
|
source.sendMessage(Text.of("\u00A79Your Hash: " + Cryptography.BCrypt_HashPassword(args.<String>getOne("password").get())));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -71,7 +71,7 @@ public class MkpasswdCommand implements CommandExecutor
|
|||||||
.executor((CommandSource source, CommandContext args) -> {
|
.executor((CommandSource source, CommandContext args) -> {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
source.sendMessage(Text.of("\u00A79Your Hash: " + Cryptography.SHA256_HashPassword(args.<String>getOne("message").get())));
|
source.sendMessage(Text.of("\u00A79Your Hash: " + Cryptography.SHA256_HashPassword(args.<String>getOne("password").get())));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -82,33 +82,22 @@ public class MkpasswdCommand implements CommandExecutor
|
|||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// The plain text encryption method
|
// The plain text "encryption" method
|
||||||
CommandSpec plain = CommandSpec.builder()
|
CommandSpec plain = CommandSpec.builder()
|
||||||
.description(Text.of("Plain text password (insecure)"))
|
.description(Text.of("Plain text password (insecure)"))
|
||||||
.permission("sshd.mkpasswd.plain")
|
.permission("sshd.mkpasswd.plain")
|
||||||
|
.arguments(GenericArguments.remainingJoinedStrings(Text.of("password")))
|
||||||
.executor((CommandSource source, CommandContext args) -> {
|
.executor((CommandSource source, CommandContext args) -> {
|
||||||
source.sendMessage(Text.of("Bro... It's literally your unhashed password."));
|
source.sendMessage(Text.of("Bro... It's literally your unhashed password."));
|
||||||
return CommandResult.success();
|
return CommandResult.success();
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// The "help" command to show syntax usage
|
|
||||||
CommandSpec helpcmd = CommandSpec.builder()
|
|
||||||
.description(Text.of("Display's mkpasswd help"))
|
|
||||||
.permission("sshd.mkpasswd.help")
|
|
||||||
.executor((CommandSource source, CommandContext args) -> {
|
|
||||||
source.sendMessage(Text.of("\u00A7a/mkpasswd <help|hash> <password>\u00A7r"));
|
|
||||||
source.sendMessage(Text.of("\u00A79Supported Hashes: SHA256, PBKDF2, BCRYPT, PLAIN\u00A7r"));
|
|
||||||
return CommandResult.success();
|
|
||||||
})
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// the root "mkpasswd" command
|
// the root "mkpasswd" command
|
||||||
cmdspec = CommandSpec.builder()
|
cmdspec = CommandSpec.builder()
|
||||||
.description(Text.of("Create an SSHd password using hashes"))
|
.description(Text.of("Create an SSHd password using hashes"))
|
||||||
.extendedDescription(Text.of("Supported Hashes: SHA256, PBKDF2, BCRYPT, PLAIN"))
|
.extendedDescription(Text.of("Supported Hashes: SHA256, PBKDF2, BCRYPT, PLAIN"))
|
||||||
.permission("sshd.mkpasswd")
|
.permission("sshd.mkpasswd")
|
||||||
.child(helpcmd, "help", "h")
|
|
||||||
.child(plain, "plain")
|
.child(plain, "plain")
|
||||||
.child(sha256, "sha256")
|
.child(sha256, "sha256")
|
||||||
.child(bcrypt, "bcrypt")
|
.child(bcrypt, "bcrypt")
|
||||||
@ -125,7 +114,7 @@ public class MkpasswdCommand implements CommandExecutor
|
|||||||
public CommandResult execute(CommandSource src, CommandContext args) throws CommandException
|
public CommandResult execute(CommandSource src, CommandContext args) throws CommandException
|
||||||
{
|
{
|
||||||
// This command doesn't do anything.
|
// This command doesn't do anything.
|
||||||
src.sendMessage(Text.of("\u00A7a/mkpasswd <help|hash> <password>\u00A7r"));
|
src.sendMessage(Text.of("\u00A7a/mkpasswd <hash> <password...>\u00A7r"));
|
||||||
src.sendMessage(Text.of("\u00A79Supported Hashes: SHA256, PBKDF2, BCRYPT, PLAIN\u00A7r"));
|
src.sendMessage(Text.of("\u00A79Supported Hashes: SHA256, PBKDF2, BCRYPT, PLAIN\u00A7r"));
|
||||||
return CommandResult.success();
|
return CommandResult.success();
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ public class PublicKeyAuthenticator implements PublickeyAuthenticator
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SshdPlugin.GetLogger().info(
|
SshdPlugin.GetInstance().logger.info(
|
||||||
username + " failed authentication via SSH session using key file " + keyFile.getAbsolutePath());
|
username + " failed authentication via SSH session using key file " + keyFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ public class PublicKeyAuthenticator implements PublickeyAuthenticator
|
|||||||
if (this.FailCounts.get(username) >= tries)
|
if (this.FailCounts.get(username) >= tries)
|
||||||
{
|
{
|
||||||
this.FailCounts.put(username, 0);
|
this.FailCounts.put(username, 0);
|
||||||
SshdPlugin.GetLogger().info("Too many failures for " + username + ", disconnecting.");
|
SshdPlugin.GetInstance().logger.info("Too many failures for " + username + ", disconnecting.");
|
||||||
session.close(true);
|
session.close(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,12 +67,12 @@ public class PublicKeyAuthenticator implements PublickeyAuthenticator
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
SshdPlugin.GetLogger().error("Failed to process public key " + keyFile.getAbsolutePath() + " " + e.getMessage());
|
SshdPlugin.GetInstance().logger.error("Failed to process public key " + keyFile.getAbsolutePath() + " " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SshdPlugin.GetLogger().error("Could not locate public key for " + username
|
SshdPlugin.GetInstance().logger.error("Could not locate public key for " + username
|
||||||
+ ". Make sure the user's key is named the same as their user name "
|
+ ". Make sure the user's key is named the same as their user name "
|
||||||
+ "without a file extension.");
|
+ "without a file extension.");
|
||||||
}
|
}
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
package com.ryanmichela.sshd;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright 2013 Ryan Michela
|
|
||||||
*/
|
|
||||||
public class ReflectionUtil {
|
|
||||||
|
|
||||||
public static void setProtectedValue(Object o, String field, Object newValue) {
|
|
||||||
setProtectedValue(o.getClass(), o, field, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setProtectedValue(Class c, String field, Object newValue) {
|
|
||||||
setProtectedValue(c, null, field, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setProtectedValue(Class c, Object o, String field, Object newValue) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
Field f = c.getDeclaredField(field);
|
|
||||||
|
|
||||||
f.setAccessible(true);
|
|
||||||
|
|
||||||
Field modifiersField = Field.class.getDeclaredField("modifiers");
|
|
||||||
modifiersField.setAccessible(true);
|
|
||||||
modifiersField.setInt(f, f.getModifiers() & ~Modifier.FINAL);
|
|
||||||
|
|
||||||
f.set(o, newValue);
|
|
||||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
|
||||||
System.out.println("*** " + c.getName() + ":" + ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T getProtectedValue(Object obj, String fieldName) {
|
|
||||||
try {
|
|
||||||
Class c = obj.getClass();
|
|
||||||
while (c != Object.class) {
|
|
||||||
Field[] fields = c.getDeclaredFields();
|
|
||||||
for (Field f : fields) {
|
|
||||||
if (f.getName() == fieldName) {
|
|
||||||
f.setAccessible(true);
|
|
||||||
return (T) f.get(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c = c.getSuperclass();
|
|
||||||
}
|
|
||||||
System.out.println("*** " + obj.getClass().getName() + ":No such field");
|
|
||||||
return null;
|
|
||||||
} catch (Exception ex) {
|
|
||||||
System.out.println("*** " + obj.getClass().getName() + ":" + ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T getProtectedValue(Class c, String field) {
|
|
||||||
try {
|
|
||||||
Field f = c.getDeclaredField(field);
|
|
||||||
f.setAccessible(true);
|
|
||||||
return (T) f.get(c);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
System.out.println("*** " + c.getName() + ":" + ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Object invokeProtectedMethod(Class c, String method, Object... args) {
|
|
||||||
return invokeProtectedMethod(c, null, method, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Object invokeProtectedMethod(Object o, String method, Object... args) {
|
|
||||||
return invokeProtectedMethod(o.getClass(), o, method, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Object invokeProtectedMethod(Class c, Object o, String method, Object... args) {
|
|
||||||
try {
|
|
||||||
Class[] pTypes = new Class[args.length];
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
if (args[i] instanceof Integer) {
|
|
||||||
pTypes[i] = int.class;
|
|
||||||
} else {
|
|
||||||
pTypes[i] = args[i].getClass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Method m = c.getDeclaredMethod(method, pTypes);
|
|
||||||
m.setAccessible(true);
|
|
||||||
return m.invoke(o, args);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
System.out.println("*** " + c.getName() + "." + method + "(): " + ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -51,7 +51,7 @@ public class SshdPlugin
|
|||||||
private static SshdPlugin instance;
|
private static SshdPlugin instance;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public static Logger logger;
|
public Logger logger;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@DefaultConfig(sharedRoot = false)
|
@DefaultConfig(sharedRoot = false)
|
||||||
@ -71,6 +71,11 @@ public class SshdPlugin
|
|||||||
config = new Config();
|
config = new Config();
|
||||||
config.setup();
|
config.setup();
|
||||||
|
|
||||||
|
// Make sure our authorized_keys folder exists
|
||||||
|
File authorizedKeys = new File(this.ConfigDir.toFile(), "authorized_keys");
|
||||||
|
if (!authorizedKeys.exists())
|
||||||
|
authorizedKeys.mkdirs();
|
||||||
|
|
||||||
// Now include it in our dealio here
|
// Now include it in our dealio here
|
||||||
this.Mode = config.configNode.getNode("Mode").getString();
|
this.Mode = config.configNode.getNode("Mode").getString();
|
||||||
this.PasswordType = config.configNode.getNode("PasswordType").getString();
|
this.PasswordType = config.configNode.getNode("PasswordType").getString();
|
||||||
@ -99,7 +104,6 @@ public class SshdPlugin
|
|||||||
sshd.setHost(this.ListenAddress.equals("all") ? null : this.ListenAddress);
|
sshd.setHost(this.ListenAddress.equals("all") ? null : this.ListenAddress);
|
||||||
|
|
||||||
File hostKey = new File(this.ConfigDir.toFile(), "hostkey");
|
File hostKey = new File(this.ConfigDir.toFile(), "hostkey");
|
||||||
File authorizedKeys = new File(this.ConfigDir.toFile(), "authorized_keys");
|
|
||||||
|
|
||||||
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(hostKey.toPath()));
|
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(hostKey.toPath()));
|
||||||
sshd.setShellFactory(new ConsoleShellFactory());
|
sshd.setShellFactory(new ConsoleShellFactory());
|
||||||
@ -109,8 +113,7 @@ public class SshdPlugin
|
|||||||
if (this.EnableSFTP)
|
if (this.EnableSFTP)
|
||||||
{
|
{
|
||||||
sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory()));
|
sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory()));
|
||||||
sshd.setFileSystemFactory(
|
sshd.setFileSystemFactory(new VirtualFileSystemFactory(this.ConfigDir.getParent().getParent()));
|
||||||
new VirtualFileSystemFactory(this.ConfigDir.getParent().getParent()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MkpasswdCommand.BuildCommand();
|
MkpasswdCommand.BuildCommand();
|
||||||
@ -133,8 +136,8 @@ public class SshdPlugin
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Logger GetLogger()
|
public Logger GetLogger()
|
||||||
{
|
{
|
||||||
return logger;
|
return this.logger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,48 +1,75 @@
|
|||||||
package com.ryanmichela.sshd;
|
package com.ryanmichela.sshd;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.Level;
|
||||||
import org.apache.logging.log4j.core.Appender;
|
import org.apache.logging.log4j.core.Appender;
|
||||||
import org.apache.logging.log4j.core.ErrorHandler;
|
import org.apache.logging.log4j.core.ErrorHandler;
|
||||||
import org.apache.logging.log4j.core.Layout;
|
import org.apache.logging.log4j.core.Layout;
|
||||||
import org.apache.logging.log4j.core.LogEvent;
|
import org.apache.logging.log4j.core.LogEvent;
|
||||||
|
import org.apache.logging.log4j.core.layout.PatternLayout;
|
||||||
|
|
||||||
|
import jline.console.ConsoleReader;
|
||||||
|
import org.apache.sshd.common.SshException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.logging.LogRecord;
|
import java.nio.charset.Charset;
|
||||||
import java.util.logging.StreamHandler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copyright 2014 Ryan Michela
|
* Copyright 2014 Ryan Michela
|
||||||
*/
|
*/
|
||||||
public class StreamHandlerAppender implements Appender {
|
public class StreamHandlerAppender implements Appender
|
||||||
|
{
|
||||||
private StreamHandler streamHandler;
|
private ConsoleReader console;
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
|
private PatternLayout MinecraftLayout = PatternLayout.newBuilder().withPattern("%highlightError{[%d{HH:mm:ss} %level] [%logger]: %minecraftFormatting{%msg}%xEx}").build();
|
||||||
|
private PatternLayout MojangLayout = PatternLayout.newBuilder().withPattern("%highlightError{[%d{HH:mm:ss} %level]: %minecraftFormatting{%msg}%xEx}").build();
|
||||||
|
|
||||||
public StreamHandlerAppender(StreamHandler streamHandler) {
|
public StreamHandlerAppender(ConsoleReader console)
|
||||||
this.streamHandler = streamHandler;
|
{
|
||||||
|
this.console = console;
|
||||||
uuid = UUID.randomUUID();
|
uuid = UUID.randomUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void append(LogEvent logEvent) {
|
public void append(LogEvent logEvent)
|
||||||
java.util.logging.Level level;
|
{
|
||||||
|
if(true) return;
|
||||||
|
|
||||||
if (logEvent.getLevel().equals(org.apache.logging.log4j.Level.DEBUG)) {
|
if (logEvent.getLevel() == Level.DEBUG || logEvent.getLevel() == Level.TRACE)
|
||||||
level = java.util.logging.Level.FINE;
|
return;
|
||||||
} else if (logEvent.getLevel().equals(org.apache.logging.log4j.Level.INFO)) {
|
|
||||||
level = java.util.logging.Level.INFO;
|
try
|
||||||
} else if (logEvent.getLevel().equals(org.apache.logging.log4j.Level.WARN)) {
|
{
|
||||||
level = java.util.logging.Level.WARNING;
|
// Delete the jline's `> ` character
|
||||||
} else if (logEvent.getLevel().equals(org.apache.logging.log4j.Level.ERROR)) {
|
this.console.print(ConsoleReader.BACKSPACE + "" + ConsoleReader.BACKSPACE);
|
||||||
level = java.util.logging.Level.SEVERE;
|
// Print our message
|
||||||
} else {
|
if (logEvent.getLoggerName().matches("net\\.minecraft\\..*|com\\.mojang\\..*"))
|
||||||
level = java.util.logging.Level.INFO;
|
this.console.println(ConsoleLogFormatter.ColorizeString(this.MojangLayout.toSerializable(logEvent)).replaceAll("\n", "\r\n") + "\r");
|
||||||
|
else
|
||||||
|
this.console.println(ConsoleLogFormatter.ColorizeString(this.MinecraftLayout.toSerializable(logEvent)).replaceAll("\n", "\r\n") + "\r");
|
||||||
|
// Reset the console (colors, formatting, etc)
|
||||||
|
this.console.print(ConsoleReader.RESET_LINE + "");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Attempt to draw new console line
|
||||||
|
this.console.drawLine();
|
||||||
|
}
|
||||||
|
catch (Throwable ex)
|
||||||
|
{
|
||||||
|
this.console.getCursorBuffer().clear();
|
||||||
|
}
|
||||||
|
// Push it to the end user.
|
||||||
|
this.console.flush();
|
||||||
|
}
|
||||||
|
catch (SshException ex)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
String message = logEvent.getMessage().getFormattedMessage();
|
|
||||||
|
|
||||||
|
|
||||||
LogRecord logRecord = new LogRecord(level, message);
|
|
||||||
streamHandler.publish(logRecord);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,6 +4,7 @@ import com.ryanmichela.sshd.SshdPlugin;
|
|||||||
import com.ryanmichela.sshd.ConsoleShellFactory;
|
import com.ryanmichela.sshd.ConsoleShellFactory;
|
||||||
import com.ryanmichela.sshd.ConsoleLogFormatter;
|
import com.ryanmichela.sshd.ConsoleLogFormatter;
|
||||||
import org.spongepowered.api.command.source.ConsoleSource;
|
import org.spongepowered.api.command.source.ConsoleSource;
|
||||||
|
import org.checkerframework.checker.nullness.Opt;
|
||||||
import org.spongepowered.api.command.CommandSource;
|
import org.spongepowered.api.command.CommandSource;
|
||||||
import org.spongepowered.api.text.Text;
|
import org.spongepowered.api.text.Text;
|
||||||
import org.spongepowered.api.text.channel.MessageChannel;
|
import org.spongepowered.api.text.channel.MessageChannel;
|
||||||
@ -13,10 +14,13 @@ import org.spongepowered.api.service.permission.SubjectData;
|
|||||||
import org.spongepowered.api.service.permission.SubjectReference;
|
import org.spongepowered.api.service.permission.SubjectReference;
|
||||||
import org.spongepowered.api.service.context.Context;
|
import org.spongepowered.api.service.context.Context;
|
||||||
import org.spongepowered.api.util.Tristate;
|
import org.spongepowered.api.util.Tristate;
|
||||||
|
import jline.console.ConsoleReader;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -28,17 +32,19 @@ public class SSHDCommandSender implements ConsoleSource
|
|||||||
private Subject subjectDelegate;
|
private Subject subjectDelegate;
|
||||||
// Set by the upstream allocating function
|
// Set by the upstream allocating function
|
||||||
public ConsoleShellFactory.ConsoleShell console;
|
public ConsoleShellFactory.ConsoleShell console;
|
||||||
|
private UUID uuid = UUID.randomUUID();
|
||||||
|
|
||||||
// This is an override for Sponge to work with the SSH consoles.
|
// This is an override for Sponge to work with the SSH consoles.
|
||||||
|
@Override
|
||||||
public void sendMessage(Text message)
|
public void sendMessage(Text message)
|
||||||
{
|
{
|
||||||
this.sendRawMessage(message.toPlain() + "\r");
|
this.sendRawMessage(message.toPlain());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Back port from Spigot/BungeeCord-style API calls.
|
// Back port from Spigot/BungeeCord-style API calls.
|
||||||
public void sendMessage(String message)
|
public void sendMessage(String message)
|
||||||
{
|
{
|
||||||
this.sendRawMessage(message + "\r");
|
this.sendRawMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendRawMessage(String message)
|
public void sendRawMessage(String message)
|
||||||
@ -48,8 +54,9 @@ public class SSHDCommandSender implements ConsoleSource
|
|||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.console.ConsoleReader.println(ConsoleLogFormatter.ColorizeString(message).replace("\n", "\n\r"));
|
this.console.ConsoleReader.print(ConsoleReader.BACKSPACE + "" + ConsoleReader.BACKSPACE);
|
||||||
this.console.ConsoleReader.print(this.console.ConsoleReader.RESET_LINE + "");
|
this.console.ConsoleReader.println(ConsoleLogFormatter.ColorizeString(message).replaceAll("\n", "\n\r") + "\r");
|
||||||
|
this.console.ConsoleReader.print(ConsoleReader.RESET_LINE + "");
|
||||||
this.console.ConsoleReader.flush();
|
this.console.ConsoleReader.flush();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -63,7 +70,7 @@ public class SSHDCommandSender implements ConsoleSource
|
|||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
SshdPlugin.GetLogger().error("Error sending message to SSHDCommandSender", e);
|
SshdPlugin.GetInstance().logger.error("Error sending message to SSHDCommandSender", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,72 +95,83 @@ public class SSHDCommandSender implements ConsoleSource
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIdentifier() {
|
public String getIdentifier() {
|
||||||
// TODO Auto-generated method stub
|
return uuid.toString();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Context> getActiveContexts() {
|
public Set<Context> getActiveContexts()
|
||||||
// TODO Auto-generated method stub
|
{
|
||||||
return null;
|
// No clue what any of this does but sponge needs it to work with this class. - Justin
|
||||||
|
Set<Context> set = new HashSet<Context>();
|
||||||
|
set.add(new Context(Context.USER_KEY, "SSHD"));
|
||||||
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSubjectDataPersisted() {
|
public boolean isSubjectDataPersisted()
|
||||||
|
{
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isChildOf(Set<Context> contexts, SubjectReference parent) {
|
public boolean isChildOf(Set<Context> contexts, SubjectReference parent)
|
||||||
|
{
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubjectData getTransientSubjectData() {
|
public SubjectData getTransientSubjectData()
|
||||||
|
{
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubjectData getSubjectData() {
|
public SubjectData getSubjectData()
|
||||||
|
{
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Tristate getPermissionValue(Set<Context> contexts, String permission) {
|
public Tristate getPermissionValue(Set<Context> contexts, String permission)
|
||||||
|
{
|
||||||
|
// We're allowed to view all permissions.
|
||||||
|
return Tristate.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SubjectReference> getParents(Set<Context> contexts)
|
||||||
|
{
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SubjectReference> getParents(Set<Context> contexts) {
|
public Optional<String> getOption(Set<Context> contexts, String key)
|
||||||
|
{
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubjectCollection getContainingCollection()
|
||||||
|
{
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<String> getOption(Set<Context> contexts, String key) {
|
public Optional<CommandSource> getCommandSource()
|
||||||
|
{
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return null;
|
return Optional.of(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubjectCollection getContainingCollection() {
|
public SubjectReference asSubjectReference()
|
||||||
// TODO Auto-generated method stub
|
{
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<CommandSource> getCommandSource() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SubjectReference asSubjectReference() {
|
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -74,54 +74,36 @@ public class Config
|
|||||||
("The IP addresses(s) the SSH server will listen on. Use a comma separated list for multiple addresses.\n" +
|
("The IP addresses(s) the SSH server will listen on. Use a comma separated list for multiple addresses.\n" +
|
||||||
"Leave as \"all\" for all addresses.");
|
"Leave as \"all\" for all addresses.");
|
||||||
this.configNode.getNode("Port").setValue("1025").setComment(
|
this.configNode.getNode("Port").setValue("1025").setComment(
|
||||||
"# The port the SSH server will listen on. Note that anything above 1024 will require you to run\n" +
|
"The port the SSH server will listen on. Note that anything above 1024 will require you to run\n" +
|
||||||
"# the whole minecraft server with elevated privileges, this is not recommended and you should\n" +
|
"the whole minecraft server with elevated privileges, this is not recommended and you should\n" +
|
||||||
"# use iptables to route packets from a lower port.");
|
"use iptables to route packets from a lower port.");
|
||||||
this.configNode.getNode("Mode").setValue("DEFAULT").setComment("Operational mode. Don't touch if you don't know what you're doing. Can be either DEFAULT or RPC");
|
this.configNode.getNode("Mode").setValue("DEFAULT").setComment("Operational mode. Don't touch if you don't know what you're doing. Can be either DEFAULT or RPC");
|
||||||
this.configNode.getNode("EnableSFTP").setValue("true").setComment(
|
this.configNode.getNode("EnableSFTP").setValue("true").setComment(
|
||||||
"# Enable built-in SFTP server or not. You'll be able to connect and upload/download files via SFTP protocol.\n" +
|
"Enable built-in SFTP server or not. You'll be able to connect and upload/download files via SFTP protocol.\n" +
|
||||||
"# Might be useful for testing purposes as well , i. e. docker containers.");
|
"Might be useful for testing purposes as well , i. e. docker containers.");
|
||||||
this.configNode.getNode("LoginRetries").setValue("3").setComment(
|
this.configNode.getNode("LoginRetries").setValue("3").setComment(
|
||||||
"# Number of times a person can fail to use an SSH key or enter a password\n" +
|
"Number of times a person can fail to use an SSH key or enter a password\n" +
|
||||||
"# before it terminates the connection.");
|
"before it terminates the connection.");
|
||||||
|
|
||||||
this.configNode.getNode("PasswordType").setValue("bcrypt").setComment
|
this.configNode.getNode("PasswordType").setValue("bcrypt").setComment
|
||||||
("########################################################################################\n" +
|
("########################################################################################\n" +
|
||||||
"# By default, only public key authentication is enabled. This is the most secure mode.\n" +
|
"By default, only public key authentication is enabled. This is the most secure mode.\n" +
|
||||||
"# To authorize a user to login with their public key, install their key using the\n" +
|
"To authorize a user to login with their public key, install their key using the\n" +
|
||||||
"# OpenSSH authorized_keys file format in the authorized_users directory. Name the key\n" +
|
"OpenSSH authorized_keys file format in the authorized_users directory. Name the key\n" +
|
||||||
"# file with the user's username and no extension. Note: If you want to let a user have\n" +
|
"file with the user's username and no extension. Note: If you want to let a user have\n" +
|
||||||
"# many keys, you can append the keys to their file in authorized_users.\n" +
|
"many keys, you can append the keys to their file in authorized_users.\n" +
|
||||||
"########################################################################################\n" +
|
"########################################################################################\n" +
|
||||||
"For less secure username and password based authentication, complete the sections below.\n" +
|
"For less secure username and password based authentication, complete the sections below.\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"# Type of hashing to use for the passwords below.\n" +
|
"Type of hashing to use for the passwords below.\n" +
|
||||||
"# Options are: PLAIN (insecure), bcrypt, pbkdf2, sha256\n" +
|
"Options are: PLAIN (insecure), bcrypt, pbkdf2, sha256\n" +
|
||||||
"#\n" +
|
"\n" +
|
||||||
"# You can use the console/in-game command `/mkpasswd [hash] PASSWORD` to\n" +
|
"You can use the console/in-game command `/mkpasswd [hash] PASSWORD` to\n" +
|
||||||
"# generate a password hash string then copy it for your passwords below.\n" +
|
"generate a password hash string then copy it for your passwords below.\n" +
|
||||||
"# You can also use `/mkpasswd help` to see what algorithms are supported.");
|
"You can also use `/mkpasswd help` to see what algorithms are supported.");
|
||||||
|
|
||||||
this.configNode.getNode("Credentials").setComment("# Associate each username with a password hash (or the password if the PasswordType is set to PLAIN)");
|
this.configNode.getNode("Credentials").setComment("Associate each username with a password hash (or the password if the PasswordType is set to PLAIN)");
|
||||||
this.configNode.getNode("Credentials", "user1", "password").setValue("MySecretPassword");
|
this.configNode.getNode("Credentials", "user1", "password").setValue("MySecretPassword");
|
||||||
this.configNode.getNode("Credentials", "user2", "password").setValue("MyBestFriendsPassword");
|
this.configNode.getNode("Credentials", "user2", "password").setValue("MyBestFriendsPassword");
|
||||||
//this.configNode.getNode("").setValue("").setComment("");
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
this.Mode = config.configNode.getNode("Mode").getString();
|
|
||||||
this.PasswordType = config.configNode.getNode("PasswordType").getString();
|
|
||||||
this.ListenAddress = config.configNode.getNode("ListenAddress").getString();
|
|
||||||
this.Port = config.configNode.getNode("Port").getInt();
|
|
||||||
this.LoginRetries = config.configNode.getNode("LoginRetries").getInt();
|
|
||||||
this.EnableSFTP = config.configNode.getNode("EnableSFTP").getBoolean();
|
|
||||||
|
|
||||||
this.configNode.getNode("mysql").setComment("MySQL database for Whitelisting");
|
|
||||||
this.configNode.getNode("mysql", "port").setValue(3306).setComment("MySQL server port");
|
|
||||||
this.configNode.getNode("mysql", "host").setValue("localhost").setComment("MySQL server to connect to");
|
|
||||||
this.configNode.getNode("mysql", "database").setValue("WhitelistSync").setComment("MySQL database for Whitelisting");
|
|
||||||
this.configNode.getNode("mysql", "username").setValue("Whitelist").setComment("MySQL username for the database");
|
|
||||||
this.configNode.getNode("mysql", "password").setValue("letmein").setComment("MySQL password for the database");
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user