diff --git a/pom.xml b/pom.xml index 0214f42..17b397a 100644 --- a/pom.xml +++ b/pom.xml @@ -356,6 +356,11 @@ junit 4.12 + + org.hamcrest + hamcrest-library + 1.3 + diff --git a/sftp/pom.xml b/sftp/pom.xml index 7a7af74..be4b62d 100644 --- a/sftp/pom.xml +++ b/sftp/pom.xml @@ -28,6 +28,11 @@ junit test + + org.hamcrest + hamcrest-library + test + com.jcraft jsch diff --git a/sftp/src/main/java/no/maddin/niofs/sftp/SFTPFileSystemProvider.java b/sftp/src/main/java/no/maddin/niofs/sftp/SFTPFileSystemProvider.java index e8a4fed..a53dec8 100644 --- a/sftp/src/main/java/no/maddin/niofs/sftp/SFTPFileSystemProvider.java +++ b/sftp/src/main/java/no/maddin/niofs/sftp/SFTPFileSystemProvider.java @@ -121,12 +121,14 @@ public void createDirectory(Path dir, FileAttribute... attrs) throws IOExcept sftp.connect(); - SFTPPath sftpPath = (SFTPPath)dir; - String dirString = sftpPath.getPathString(); - try { - sftp.mkdir(dirString); - } catch(SftpException e) { - throw new IOException(dirString, e); + // Implementation might not support recursive creation of directories + for (String subPath : ((SFTPPath) dir).getParts()) { + try { + sftp.mkdir(subPath); + } catch(SftpException e) { + throw new IOException(subPath, e); + } + } sftp.quit(); diff --git a/sftp/src/main/java/no/maddin/niofs/sftp/SFTPPath.java b/sftp/src/main/java/no/maddin/niofs/sftp/SFTPPath.java index 3517dcc..8f0d7a8 100644 --- a/sftp/src/main/java/no/maddin/niofs/sftp/SFTPPath.java +++ b/sftp/src/main/java/no/maddin/niofs/sftp/SFTPPath.java @@ -1,5 +1,7 @@ package no.maddin.niofs.sftp; +import sun.nio.fs.UnixFileSystemProvider; + import java.io.File; import java.io.IOException; import java.net.URI; @@ -7,36 +9,38 @@ import java.nio.file.*; import java.nio.file.WatchEvent.Kind; import java.nio.file.WatchEvent.Modifier; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Queue; -import java.util.StringTokenizer; +import java.util.*; /** * A Path implementation for SFTP. */ public class SFTPPath implements Path { - private static final String HOME_PREFIX = "/~/"; - private static final int HOME_PREFIX_LEN = HOME_PREFIX.length(); - private static final String DEFAULT_ROOT_PATH = ""; private static final String PATH_SEP = "/"; private final String path; private final SFTPHost host; + private final java.util.List parts; SFTPPath(SFTPHost sftpHost, String path) { this.host = sftpHost; + this.path = path; + parts = splitParts(path); + } + + private List splitParts(String path) { + String[] parts = path.split(PATH_SEP, -1); + return Arrays.asList(parts); + } - // TODO split the path in ist components - if (path == null || path.trim().isEmpty()) { - this.path = DEFAULT_ROOT_PATH; - } else { - if (path.startsWith(HOME_PREFIX)) { - this.path = path.substring(HOME_PREFIX_LEN); - } else { - this.path = path; + private String combineParts(int startIdx, int endIdx) { + StringBuilder sb = new StringBuilder(); + for (String part : parts.subList(startIdx, endIdx)) { + if (sb.length() > 0) { + sb.append(PATH_SEP); } + sb.append(part); } + return sb.toString(); } @Override @@ -51,10 +55,10 @@ public boolean isAbsolute() { @Override public Path getRoot() { - if (path.equals(DEFAULT_ROOT_PATH)) { + if (path == null) { return this; } - return new SFTPPath(this.host, DEFAULT_ROOT_PATH); + return new SFTPPath(this.host, null); } @Override @@ -64,12 +68,17 @@ public Path getFileName() { @Override public Path getParent() { - throw new UnsupportedOperationException("Not Implemented"); + + if (path == null) { + return null; + } + return new SFTPPath(this.host, combineParts(0, getNameCount() - 1)); } @Override public int getNameCount() { - throw new UnsupportedOperationException("Not Implemented"); + + return parts.size(); } @Override @@ -79,7 +88,7 @@ public Path getName(int index) { @Override public Path subpath(int beginIndex, int endIndex) { - throw new UnsupportedOperationException("Not Implemented"); + return new SFTPPath(beginIndex == 0 ? host : null, combineParts(0, endIndex)); } @Override @@ -141,11 +150,14 @@ public Path relativize(Path other) { public URI toUri() { try { - String userInfo; + String userInfo = null; if (host.getUserName() != null) { - userInfo = host.getUserName() + ':' + host.getPassword(); - } else { - userInfo = null; + StringBuilder uinfoSb = new StringBuilder(); + uinfoSb.append(host.getUserName()); + if (host.getPassword() != null) { + uinfoSb.append(':').append(host.getPassword()); + } + userInfo = uinfoSb.toString(); } return new URI("sftp", userInfo, host.getHost(), host.getPort(), this.path, null, null); } catch (URISyntaxException e) { @@ -191,4 +203,8 @@ public int compareTo(Path other) { String getPathString() { return this.path; } + + List getParts() { + return Collections.unmodifiableList(parts); + } } \ No newline at end of file diff --git a/sftp/src/test/java/no/maddin/niofs/sftp/PartsTest.java b/sftp/src/test/java/no/maddin/niofs/sftp/PartsTest.java new file mode 100644 index 0000000..1f0e8a1 --- /dev/null +++ b/sftp/src/test/java/no/maddin/niofs/sftp/PartsTest.java @@ -0,0 +1,56 @@ +package no.maddin.niofs.sftp; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.assertThat; + +/** + * Tests splitting Path parts. + */ +@RunWith(Parameterized.class) +public class PartsTest { + + private final String input; + private final List result; + + @Parameterized.Parameters(name = "{index}: {0} {1}") + public static List data() { + + return Arrays.asList( + new Object[] {".", Arrays.asList(".")}, + new Object[] {"", Arrays.asList("")}, + new Object[] {"/", Arrays.asList("", "")}, + new Object[] {"./", Arrays.asList(".", "")}, + new Object[] {"/~", Arrays.asList("", "~")}, + new Object[] {"aa", Arrays.asList("aa")}, + new Object[] {"/aa/bb", Arrays.asList("", "aa", "bb")}, + new Object[] {"/aa/../bb", Arrays.asList("", "aa", "..", "bb")}, + new Object[] {"../", Arrays.asList("..", "")} + ); + } + + public PartsTest(String input, List result) { + this.input = input; + this.result = result; + } + + @Test + public void splitDot() { + SFTPPath path = new SFTPPath(null, input); + + List parts = path.getParts(); + + assertThat(parts, is(equalTo(this.result))); +// assertThat(parts, hasSize(1)); +// assertThat(parts, hasItem(equalTo("."))); + } + + +} diff --git a/sftp/src/test/java/no/maddin/niofs/sftp/SFTPServerTest.java b/sftp/src/test/java/no/maddin/niofs/sftp/SFTPServerTest.java index 9f03545..c9393a9 100644 --- a/sftp/src/test/java/no/maddin/niofs/sftp/SFTPServerTest.java +++ b/sftp/src/test/java/no/maddin/niofs/sftp/SFTPServerTest.java @@ -1,9 +1,17 @@ package no.maddin.niofs.sftp; +import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory; +import org.apache.sshd.server.Command; import org.apache.sshd.server.SshServer; +import org.apache.sshd.server.auth.password.PasswordAuthenticator; +import org.apache.sshd.server.auth.password.PasswordChangeRequiredException; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; import org.apache.sshd.server.scp.ScpCommandFactory; +import org.apache.sshd.server.session.ServerSession; import org.apache.sshd.server.shell.ProcessShellFactory; +import org.apache.sshd.server.subsystem.sftp.SftpSubsystem; +import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -14,6 +22,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; @@ -27,6 +38,8 @@ public class SFTPServerTest { private SshServer sshd; private int port; + private String sftpUserame = "username"; + private String sftpPassword = "password"; /** * https://mina.apache.org/sshd-project/embedding_ssh.html @@ -39,8 +52,17 @@ public void setupSftpServer() throws Exception { serverSocket.close(); sshd.setPort(this.port); sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(new File("target", "hostkey.ser"))); + sshd.setPasswordAuthenticator(new PasswordAuthenticator() { + @Override + public boolean authenticate(String username, String password, ServerSession session) throws PasswordChangeRequiredException { + return sftpUserame.equals(username) && sftpPassword.equals(password); + } + }); + + sshd.setShellFactory(new ProcessShellFactory("/bin/sh", "-i", "-l")); + sshd.setSubsystemFactories(Collections.>singletonList(new SftpSubsystemFactory())); + sshd.setFileSystemFactory(new VirtualFileSystemFactory(Paths.get(System.getProperty("user.dir"), "target"))); - sshd.setShellFactory(new ProcessShellFactory(new String[]{"/bin/sh", "-i", "-l"})); sshd.setCommandFactory(new ScpCommandFactory()); sshd.start(); } @@ -53,7 +75,7 @@ public void stopServer() throws Exception { @Test public void createDirectories() throws Exception { - URI uri = new URI("sftp", "test", "localhost", port, "/a/b/", null, null); + URI uri = new URI("sftp", sftpUserame + ':' + sftpPassword, "localhost", port, "/~/a/b/", null, null); Path path = Paths.get(uri); Path newPath = Files.createDirectories(path); assertThat(newPath, is(notNullValue())); diff --git a/sftp/src/test/java/no/maddin/niofs/sftp/Sftp.java b/sftp/src/test/java/no/maddin/niofs/sftp/Sftp.java deleted file mode 100644 index b6d4678..0000000 --- a/sftp/src/test/java/no/maddin/niofs/sftp/Sftp.java +++ /dev/null @@ -1,530 +0,0 @@ -/* - Copyright 2012-2013 University of Stavanger, Norway - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -package no.maddin.niofs.sftp; - -import com.jcraft.jsch.*; -import javax.swing.*; -import java.awt.*; -import java.util.List; -import java.util.ArrayList; - -/** - * This program will demonstrate the sftp protocol support. - * - * $ CLASSPATH=.:../build javac Sftp.java - * $ CLASSPATH=.:../build java Sftp - * - * You will be asked username, host and passwd. - * If everything works fine, you will get a prompt 'sftp<'. - * 'help' command will show available command. - * In current implementation, the destination path for 'get' and 'put' - * commands must be a file, not a directory. - */ -public class Sftp { - public static void main(String[] arg) { - - try { - JSch jsch = new JSch(); - - String host = null; - if (arg.length > 0) { - host = arg[0]; - } else { - host = JOptionPane.showInputDialog("Enter username@hostname", System.getProperty("user.name") + "@localhost"); - } - String user = host.substring(0, host.indexOf('@')); - host = host.substring(host.indexOf('@') + 1); - int port = 22; - - Session session = jsch.getSession(user, host, port); - - // username and password will be given via UserInfo interface. - UserInfo ui = new MyUserInfo(); - session.setUserInfo(ui); - - session.connect(); - - Channel channel = session.openChannel("sftp"); - channel.connect(); - ChannelSftp c = (ChannelSftp)channel; - - java.io.InputStream in = System.in; - java.io.PrintStream out = System.out; - - List cmds = new ArrayList<>(); - byte[] buf = new byte[1024]; - int i; - String str; - int level = 0; - - while (true) { - out.print("sftp> "); - cmds.clear(); - i = in.read(buf, 0, 1024); - if (i <= 0) - break; - - i--; - if (i > 0 && buf[i - 1] == 0x0d) - i--; - // str=new String(buf, 0, i); - // System.out.println("|"+str+"|"); - int s = 0; - for (int ii = 0; ii < i; ii++) { - if (buf[ii] == ' ') { - if (ii - s > 0) { - cmds.add(new String(buf, s, ii - s)); - } - while (ii < i) { - if (buf[ii] != ' ') - break; - ii++; - } - s = ii; - } - } - if (s < i) { - cmds.add(new String(buf, s, i - s)); - } - if (cmds.size() == 0) - continue; - - String cmd = cmds.get(0); - if (cmd.equals("quit")) { - c.quit(); - break; - } - if (cmd.equals("exit")) { - c.exit(); - break; - } - if (cmd.equals("rekey")) { - session.rekey(); - continue; - } - if (cmd.equals("compression")) { - if (cmds.size() < 2) { - out.println("compression level: " + level); - continue; - } - try { - level = Integer.parseInt(cmds.get(1)); - if (level == 0) { - session.setConfig("compression.s2c", "none"); - session.setConfig("compression.c2s", "none"); - } else { - session.setConfig("compression.s2c", "zlib@openssh.com,zlib,none"); - session.setConfig("compression.c2s", "zlib@openssh.com,zlib,none"); - } - } catch(Exception e) { - } - session.rekey(); - continue; - } - if (cmd.equals("cd") || cmd.equals("lcd")) { - if (cmds.size() < 2) - continue; - String path = cmds.get(1); - try { - if (cmd.equals("cd")) - c.cd(path); - else - c.lcd(path); - } catch(SftpException e) { - System.out.println(e.toString()); - } - continue; - } - if (cmd.equals("rm") || cmd.equals("rmdir") || cmd.equals("mkdir")) { - if (cmds.size() < 2) - continue; - String path = cmds.get(1); - try { - if (cmd.equals("rm")) - c.rm(path); - else if (cmd.equals("rmdir")) - c.rmdir(path); - else - c.mkdir(path); - } catch(SftpException e) { - System.out.println(e.toString()); - } - continue; - } - if (cmd.equals("chgrp") || cmd.equals("chown") || cmd.equals("chmod")) { - if (cmds.size() != 3) - continue; - String path = cmds.get(2); - int foo = 0; - if (cmd.equals("chmod")) { - byte[] bar = cmds.get(1).getBytes(); - int k; - for (byte aBar : bar) { - k = aBar; - if (k < '0' || k > '7') { - foo = -1; - break; - } - foo <<= 3; - foo |= (k - '0'); - } - if (foo == -1) - continue; - } else { - try { - foo = Integer.parseInt(cmds.get(1)); - } catch(Exception e) { - continue; - } - } - try { - switch (cmd) { - case "chgrp": - c.chgrp(foo, path); - break; - case "chown": - c.chown(foo, path); - break; - case "chmod": - c.chmod(foo, path); - break; - } - } catch(SftpException e) { - System.out.println(e.toString()); - } - continue; - } - if (cmd.equals("pwd") || cmd.equals("lpwd")) { - str = (cmd.equals("pwd") ? "Remote" : "Local"); - str += " working directory: "; - if (cmd.equals("pwd")) - str += c.pwd(); - else - str += c.lpwd(); - out.println(str); - continue; - } - if (cmd.equals("ls") || cmd.equals("dir")) { - String path = "."; - if (cmds.size() == 2) - path = cmds.get(1); - try { - List vv = c.ls(path); - if (vv != null) { - for (int ii = 0; ii < vv.size(); ii++) { - Object obj = vv.get(ii); - if (obj instanceof com.jcraft.jsch.ChannelSftp.LsEntry) { - out.println(((com.jcraft.jsch.ChannelSftp.LsEntry)obj).getLongname()); - } - } - } - } catch(SftpException e) { - System.out.println(e.toString()); - } - continue; - } - if (cmd.equals("lls") || cmd.equals("ldir")) { - String path = "."; - if (cmds.size() == 2) - path = cmds.get(1); - try { - java.io.File file = new java.io.File(path); - if (!file.exists()) { - out.println(path + ": No such file or directory"); - continue; - } - if (file.isDirectory()) { - String[] list = file.list(); - for (int ii = 0; ii < list.length; ii++) { - out.println(list[ii]); - } - continue; - } - out.println(path); - } catch(Exception e) { - System.out.println(e); - } - continue; - } - if (cmd.equals("get") || cmd.equals("get-resume") || cmd.equals("get-append") || cmd.equals("put") - || cmd.equals("put-resume") || cmd.equals("put-append")) - { - if (cmds.size() != 2 && cmds.size() != 3) { - continue; - } - String p1 = cmds.get(1); - // String p2=p1; - String p2 = "."; - if (cmds.size() == 3) - p2 = cmds.get(2); - try { - SftpProgressMonitor monitor = new MyProgressMonitor(); - if (cmd.startsWith("get")) { - int mode = ChannelSftp.OVERWRITE; - if (cmd.equals("get-resume")) { - mode = ChannelSftp.RESUME; - } else if (cmd.equals("get-append")) { - mode = ChannelSftp.APPEND; - } - c.get(p1, p2, monitor, mode); - } else { - int mode = ChannelSftp.OVERWRITE; - if (cmd.equals("put-resume")) { - mode = ChannelSftp.RESUME; - } else if (cmd.equals("put-append")) { - mode = ChannelSftp.APPEND; - } - c.put(p1, p2, monitor, mode); - } - } catch(SftpException e) { - System.out.println(e.toString()); - } - continue; - } - if (cmd.equals("ln") || cmd.equals("symlink") || cmd.equals("rename")) { - if (cmds.size() != 3) - continue; - String p1 = cmds.get(1); - String p2 = cmds.get(2); - try { - if (cmd.equals("rename")) - c.rename(p1, p2); - else - c.symlink(p1, p2); - } catch(SftpException e) { - System.out.println(e.toString()); - } - continue; - } - if (cmd.equals("stat") || cmd.equals("lstat")) { - if (cmds.size() != 2) - continue; - String p1 = cmds.get(1); - SftpATTRS attrs = null; - try { - if (cmd.equals("stat")) - attrs = c.stat(p1); - else - attrs = c.lstat(p1); - } catch(SftpException e) { - System.out.println(e.toString()); - } - if (attrs != null) { - out.println(attrs); - } - continue; - } - if (cmd.equals("readlink")) { - if (cmds.size() != 2) - continue; - String p1 = cmds.get(1); - try { - String filename = c.readlink(p1); - out.println(filename); - } catch(SftpException e) { - System.out.println(e.toString()); - } - continue; - } - if (cmd.equals("realpath")) { - if (cmds.size() != 2) - continue; - String p1 = cmds.get(1); - try { - String filename = c.realpath(p1); - out.println(filename); - } catch(SftpException e) { - System.out.println(e.toString()); - } - continue; - } - if (cmd.equals("version")) { - out.println("SFTP protocol version " + c.version()); - continue; - } - if (cmd.equals("help") || cmd.equals("?")) { - out.println(help); - continue; - } - out.println("unimplemented command: " + cmd); - } - session.disconnect(); - } catch(Exception e) { - System.out.println(e); - } - System.exit(0); - } - - public static class MyUserInfo implements UserInfo, UIKeyboardInteractive { - public String getPassword() { - return passwd; - } - - public boolean promptYesNo(String str) { - Object[] options = - { "yes", "no" }; - int foo = JOptionPane.showOptionDialog(null, str, "Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, - options, options[0]); - return foo == 0; - } - - private String passwd; - private JTextField passwordField = (JTextField)new JPasswordField(20); - - public String getPassphrase() { - return null; - } - - public boolean promptPassphrase(String message) { - return true; - } - - public boolean promptPassword(String message) { - Object[] ob = { passwordField }; - int result = JOptionPane.showConfirmDialog(null, ob, message, JOptionPane.OK_CANCEL_OPTION); - if (result == JOptionPane.OK_OPTION) { - passwd = passwordField.getText(); - return true; - } else { - return false; - } - } - - public void showMessage(String message) { - JOptionPane.showMessageDialog(null, message); - } - - final GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, - GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0); - private Container panel; - - public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt, boolean[] echo) - { - panel = new JPanel(); - panel.setLayout(new GridBagLayout()); - - gbc.weightx = 1.0; - gbc.gridwidth = GridBagConstraints.REMAINDER; - gbc.gridx = 0; - panel.add(new JLabel(instruction), gbc); - gbc.gridy++; - - gbc.gridwidth = GridBagConstraints.RELATIVE; - - JTextField[] texts = new JTextField[prompt.length]; - for (int i = 0; i < prompt.length; i++) { - gbc.fill = GridBagConstraints.NONE; - gbc.gridx = 0; - gbc.weightx = 1; - panel.add(new JLabel(prompt[i]), gbc); - - gbc.gridx = 1; - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.weighty = 1; - if (echo[i]) { - texts[i] = new JTextField(20); - } else { - texts[i] = new JPasswordField(20); - } - panel.add(texts[i], gbc); - gbc.gridy++; - } - - if (JOptionPane.showConfirmDialog(null, panel, destination + ": " + name, JOptionPane.OK_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION) - { - String[] response = new String[prompt.length]; - for (int i = 0; i < prompt.length; i++) { - response[i] = texts[i].getText(); - } - return response; - } else { - return null; // cancel - } - } - } - - /* - * public static class MyProgressMonitor implements com.jcraft.jsch.ProgressMonitor{ JProgressBar progressBar; JFrame frame; long count=0; long - * max=0; public void init(String info, long max){ this.max=max; if(frame==null){ frame=new JFrame(); frame.setSize(200, 20); progressBar = new - * JProgressBar(); } count=0; frame.setTitle(info); progressBar.setMaximum((int)max); progressBar.setMinimum((int)0); - * progressBar.setValue((int)count); progressBar.setStringPainted(true); JPanel p=new JPanel(); p.add(progressBar); - * frame.getContentPane().add(progressBar); frame.setVisible(true); System.out.println("!info:"+info+", max="+max+" "+progressBar); } public void - * count(long count){ this.count+=count; System.out.println("count: "+count); progressBar.setValue((int)this.count); } public void end(){ - * System.out.println("end"); progressBar.setValue((int)this.max); frame.setVisible(false); } } - */ - - public static class MyProgressMonitor implements SftpProgressMonitor { - ProgressMonitor monitor; - long count = 0; - long max = 0; - - public void init(int op, String src, String dest, long max) { - this.max = max; - monitor = new ProgressMonitor(null, ((op == SftpProgressMonitor.PUT) ? "put" : "get") + ": " + src, "", 0, (int)max); - count = 0; - percent = -1; - monitor.setProgress((int)this.count); - monitor.setMillisToDecideToPopup(1000); - } - - private long percent = -1; - - public boolean count(long count) { - this.count += count; - - if (percent >= this.count * 100 / max) { - return true; - } - percent = this.count * 100 / max; - - monitor.setNote("Completed " + this.count + "(" + percent + "%) out of " + max + "."); - monitor.setProgress((int)this.count); - - return !(monitor.isCanceled()); - } - - public void end() { - monitor.close(); - } - } - - private static String help = " Available commands:\n" + " * means unimplemented command.\n" - + "cd path Change remote directory to 'path'\n" - + "lcd path Change local directory to 'path'\n" - + "chgrp grp path Change group of file 'path' to 'grp'\n" - + "chmod mode path Change permissions of file 'path' to 'mode'\n" - + "chown own path Change owner of file 'path' to 'own'\n" - + "help Display this help text\n" + "get remote-path [local-path] Download file\n" - + "get-resume remote-path [local-path] Resume to download file.\n" - + "get-append remote-path [local-path] Append remote file to local file\n" - + "*lls [ls-options [path]] Display local directory listing\n" + "ln oldpath newpath Symlink remote file\n" - + "*lmkdir path Create local directory\n" + "lpwd Print local working directory\n" - + "ls [path] Display remote directory listing\n" - + "*lumask umask Set local umask to 'umask'\n" + "mkdir path Create remote directory\n" - + "put local-path [remote-path] Upload file\n" + "put-resume local-path [remote-path] Resume to upload file\n" - + "put-append local-path [remote-path] Append local file to remote file.\n" - + "pwd Display remote working directory\n" - + "stat path Display info about path\n" + "exit Quit sftp\n" - + "quit Quit sftp\n" + "rename oldpath newpath Rename remote file\n" - + "rmdir path Remove remote directory\n" + "rm path Delete remote file\n" - + "symlink oldpath newpath Symlink remote file\n" - + "readlink path Check the target of a symbolic link\n" - + "realpath path Canonicalize the path\n" + "rekey Key re-exchanging\n" - + "compression level Packet compression will be enabled\n" + "version Show SFTP version\n" - + "? Synonym for help"; -} diff --git a/sftp/src/test/resources/logback.xml b/sftp/src/test/resources/logback.xml new file mode 100644 index 0000000..a10feff --- /dev/null +++ b/sftp/src/test/resources/logback.xml @@ -0,0 +1,12 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + \ No newline at end of file