Skip to content

Commit

Permalink
Improve path handling for up and downloads
Browse files Browse the repository at this point in the history
Cross OS up and downloads in Java are always difficult as path
normalization is always done relative to the currently executing
system. This commit implements some hacks to make conflicts more
unlikely, but they are probably still possible. #34
  • Loading branch information
qtc-de committed Jan 23, 2025
1 parent 9b4e4ae commit 3413d52
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,22 @@ public class Dispatcher extends eu.tneitzel.beanshooter.mbean.Dispatcher
private String cwd;
private Map<String,String> env;
private TonkaBeanMBean tonkaBean;
private String separator = File.separator;

/**
* Creates the dispatcher that operates on the Tonka MBean.
*/
public Dispatcher()
{
super(MBean.TONKA);

cwd = ".";
env = new HashMap<String,String>();

if(BeanshooterOption.TARGET_HOST.isNull())
{
return;
}

MBeanInvocationHandler invo = new MBeanInvocationHandler(bean.getObjectName(), getMBeanServerConnection());
tonkaBean = (TonkaBeanMBean) Proxy.newProxyInstance(Dispatcher.class.getClassLoader(),
Expand All @@ -60,10 +64,13 @@ public Dispatcher()
*/
public void version()
{
try {
try
{
Logger.printlnBlue(tonkaBean.version());
}

} catch (MBeanException e) {
catch (MBeanException e)
{
ExceptionHandler.unexpectedException(e, "obtaining", "version", true);
}
}
Expand Down Expand Up @@ -117,8 +124,10 @@ public void executeCommand(List<String> command)
Map<String,String> env = Utils.parseEnvironmentString(TonkaBeanOption.EXEC_ENV.<String>getValue(""));
String[] envArray = envToString(env);

if( TonkaBeanOption.EXEC_RAW.getBool() )
if (TonkaBeanOption.EXEC_RAW.getBool())
{
Logger.disableStdout();
}

Logger.printMixedYellow("Invoking the", "executeCommand", "method with arguments: ");
Logger.printlnPlainBlue(Arrays.toString(command.toArray(new String[0])));
Expand All @@ -133,13 +142,13 @@ public void executeCommand(List<String> command)
Logger.printlnBlue("The call was successful");
Logger.lineBreak();

if( TonkaBeanOption.EXEC_HEX.getBool() )
if (TonkaBeanOption.EXEC_HEX.getBool())
{
Logger.printlnYellow("Server response:");
System.out.println(Utils.bytesToHex(result));
}

else if( TonkaBeanOption.EXEC_FILE.notNull() )
else if (TonkaBeanOption.EXEC_FILE.notNull())
{
try (FileOutputStream stream = new FileOutputStream(TonkaBeanOption.EXEC_FILE.<String>getValue()))
{
Expand All @@ -162,7 +171,7 @@ else if( TonkaBeanOption.EXEC_FILE.notNull() )
ExceptionHandler.handleExecException(e, command);
}

catch( IOException e )
catch (IOException e)
{
ExceptionHandler.handleFileWrite(e, TonkaBeanOption.EXEC_FILE.<String>getValue(), true);
}
Expand All @@ -180,7 +189,9 @@ public void upload()
String uploadSrc = uploadFile.toPath().normalize().toAbsolutePath().toString();

if (uploadDest == null)
{
uploadDest = ".";
}

Logger.printMixedYellow("Uploading local file", uploadSrc, "to path ");
Logger.printlnPlainMixedBlueFirst(uploadDest, "on the MBeanSerer.");
Expand All @@ -192,7 +203,7 @@ public void upload()
Logger.printlnMixedYellowFirst(content.length + " bytes", "were written to", finalPath);
}

catch ( MBeanException e)
catch (MBeanException e)
{
ExceptionHandler.handleMBeanGeneric(e);
ExceptionHandler.handleFileWrite(e, uploadDest, true);
Expand All @@ -214,12 +225,16 @@ public void download()
File downloadSrc = new File(ArgumentHandler.<String>require(TonkaBeanOption.DOWNLOAD_SOURCE));

if (downloadDest == null)
downloadDest = downloadSrc.getName();
{
downloadDest = Utils.getFilename(downloadSrc);
}

File localFile = new File(downloadDest);

if(localFile.isDirectory())
{
localFile = Paths.get(downloadDest, downloadSrc.getName()).normalize().toFile();
}

Logger.printMixedYellow("Saving remote file", downloadSrc.getPath(), "to local path ");
Logger.printlnPlainBlue(localFile.getAbsolutePath());
Expand Down Expand Up @@ -262,20 +277,22 @@ public void shell()
String[] shellVars = shellInit();
String username = shellVars[0];
String hostname = shellVars[1];
String separator = shellVars[2];
separator = shellVars[2];

List<String> shell = getShell(separator);

if (hostname == null)
{
hostname = targetHost;
}

do {
do
{
Logger.printPlainYellow(String.format("[%s@%s", username, hostname));
Logger.printPlainMixedBlue("", cwd);
Logger.printPlainYellow("]");
Logger.printPlain("$ ");
command = console.readLine();

} while (handleShellCommand(command, shell));
}

Expand All @@ -288,8 +305,10 @@ public void shell()
*/
private boolean handleShellCommand(String command, List<String> shellCmd)
{
if( command == null )
if (command == null)
{
return false;
}

String[] commandArray = command.trim().split(" ", 2);
List<String> shell = new ArrayList<String>(shellCmd);
Expand Down Expand Up @@ -359,9 +378,12 @@ private void shellChangeDirectory(String change)
Throwable t = ExceptionHandler.getCause(e);

if (t instanceof IOException || t instanceof InvalidPathException)
{
System.out.println(e.getMessage());
}

else {
else
{
Logger.printlnMixedYellow("Caught unexpected", t.getClass().getName(), "while changing directory.");
ExceptionHandler.stackTrace(e);
}
Expand Down Expand Up @@ -420,13 +442,21 @@ private void shellUpload(String argument)
File destination = new File(".");

if (arguments.length > 1)
{
destination = new File(arguments[1]);
}

if (!destination.isAbsolute())
destination = Paths.get(cwd, destination.getPath()).toAbsolutePath().normalize().toFile();
String destStr = destination.getPath();

if (!destStr.startsWith(separator) && (destStr.charAt(1) != ':' || separator.equals("/")))
{
destination = new File(cwd + separator + destStr);
}

if (!source.isAbsolute())
{
source = Paths.get(".", source.getPath()).toAbsolutePath().normalize().toFile();
}

try
{
Expand Down Expand Up @@ -458,19 +488,29 @@ private void shellDownload(String argument)
String[] arguments = Utils.splitSpaces(argument, 1);

File source = new File(arguments[0]);
File destination = new File(source.getName());
String sourceStr = source.getPath();

File destination = new File(Utils.getFilename(source));

if (arguments.length > 1)
{
destination = new File(Utils.expandPath(arguments[1]));
}

if (!source.isAbsolute())
source = Paths.get(cwd, source.getPath()).toAbsolutePath().normalize().toFile();
if (!sourceStr.startsWith(separator) && (sourceStr.charAt(1) != ':' || separator.equals("/")))
{
source = new File(cwd + separator + sourceStr);
}

if (!destination.isAbsolute())
{
destination = Paths.get(".", destination.getPath()).toAbsolutePath().normalize().toFile();
}

if (destination.isDirectory())
{
destination = Paths.get(destination.toPath().toString(), source.getName()).toFile();
}

try
{
Expand Down Expand Up @@ -520,10 +560,12 @@ private String[] shellInit()
*/
private void initCwd()
{
try {
try
{
cwd = tonkaBean.toServerDir(cwd, ".");
}

} catch( MBeanException e ){}
catch (MBeanException e){}
}

/**
Expand Down Expand Up @@ -582,11 +624,15 @@ else if (separator.equals("\\"))
}

else
{
ExceptionHandler.internalError("Dispatcher.getShell", "Unhandeled path separator: " + separator);
}
}

else
{
ExceptionHandler.internalError("Dispatcher.getShell", "Called without a separator");
}

return shell;
}
Expand All @@ -601,7 +647,9 @@ else if (separator.equals("\\"))
private void addShellArgument(List<String> command)
{
if (command.size() > 1)
{
return;
}

String shellCommand = command.get(0);

Expand Down Expand Up @@ -653,5 +701,4 @@ private String[] envToString(Map<String,String> env)

return envArray;
}

}
32 changes: 30 additions & 2 deletions beanshooter/src/eu/tneitzel/beanshooter/utils/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -488,15 +488,43 @@ public static <T> List<Set<T>> splitSet(Set<T> original, int count)
*/
public static void disableWarning()
{
try {
try
{
Field theUnsafe = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
sun.misc.Unsafe u = (sun.misc.Unsafe) theUnsafe.get(null);

Class<?> cls = Class.forName("jdk.internal.module.IllegalAccessLogger");
Field logger = cls.getDeclaredField("logger");
u.putObjectVolatile(cls, u.staticFieldOffset(logger), null);
} catch (Exception e) {}
}

catch (Exception e) {}
}

/**
* Returns the name of a file by cutting of all characters after the last /
* or \. This means that filenames that contain a \ are incorrectly handled
* on Linux.
*
* @param file the file to get the name for
* @return filename of the specified file
*/
public static String getFilename(File file)
{
String filename = file.getName();

if (filename.contains("/"))
{
filename = filename.substring(filename.lastIndexOf('/'));
}

if (filename.contains("\\"))
{
filename = filename.substring(filename.lastIndexOf('\\'));
}

return filename;
}

/**
Expand Down
24 changes: 21 additions & 3 deletions tonka-bean/src/eu/tneitzel/beanshooter/tonkabean/TonkaBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@ public String[] shellInit()
returnValue[0] = System.getProperty("user.name");

if (File.separator == "/")
{
returnValue[1] = System.getenv("HOSTNAME");
}

else
{
returnValue[1] = System.getenv("COMPUTERNAME");
}

returnValue[2] = File.separator;

return returnValue;
}

Expand All @@ -77,13 +81,19 @@ public String toServerDir(String path, String change) throws IOException, Invali
File changeFile = new File(change);

if (changeFile.isAbsolute())
{
changeFile = Paths.get(change).normalize().toAbsolutePath().toFile();
}

else
{
changeFile = Paths.get(path, change).normalize().toAbsolutePath().toFile();
}

if( !changeFile.isDirectory() )
if (!changeFile.isDirectory())
{
throw new IOException("Specified path " + changeFile.getAbsolutePath() + " is not a valid directory.");
}

return changeFile.getAbsolutePath();
}
Expand All @@ -110,7 +120,9 @@ public byte[] executeCommand(String[] command, String cwd, String[] env, boolean
Process proc = builder.start();

if (background)
{
return null;
}

proc.waitFor();
return readInputStream(proc.getInputStream());
Expand Down Expand Up @@ -141,7 +153,9 @@ public String uploadFile(String destination, String filename, byte[] content) th
Path path = Paths.get(destination);

if (path.toFile().isDirectory())
{
path = Paths.get(destination, filename);
}

FileOutputStream stream = new FileOutputStream(path.toString());

Expand All @@ -166,7 +180,7 @@ private byte[] readInputStream(InputStream stream) throws IOException

while(( readCount = stream.read(buffer, 0, buffer.length)) != -1)
{
bos.write(buffer, 0, readCount);
bos.write(buffer, 0, readCount);
}

return bos.toByteArray();
Expand All @@ -187,10 +201,14 @@ private Map<String, String> parseEnvironment(String[] input)
Map<String, String> env = new HashMap<String, String>();

if (input.length % 2 != 0)
{
return env;
}

for (int ctr = 0; ctr < input.length; ctr+=2)
{
env.put(input[ctr], input[ctr+1]);
}

return env;
}
Expand Down

0 comments on commit 3413d52

Please sign in to comment.