Author: gnodet
Date: Wed Oct 28 09:27:36 2009
New Revision: 830479
URL:
http://svn.apache.org/viewvc?rev=830479&view=revLog:
SSHD-44: NPE in ScpCommand and improvements to ScpCommandFactory.createCommand
Modified:
mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/CommandFactory.java
mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java
mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommandFactory.java
mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ScpTest.java
Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/CommandFactory.java
URL:
http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/CommandFactory.java?rev=830479&r1=830478&r2=830479&view=diff==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/CommandFactory.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/CommandFactory.java Wed Oct 28 09:27:36 2009
@@ -101,12 +101,19 @@
public interface ExitCallback {
/**
- * Informs the SSH server that the shell has exited
+ * Informs the SSH client/server that the shell has exited
*
* @param exitValue the exit value
*/
void onExit(int exitValue);
+ /**
+ * Informs the SSH client/server that the shell has exited
+ *
+ * @param exitValue the exit value
+ * @param exitMessage exit value description
+ */
+ void onExit(int exitValue, String exitMessage);
}
}
Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
URL:
http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java?rev=830479&r1=830478&r2=830479&view=diff==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java Wed Oct 28 09:27:36 2009
@@ -474,6 +474,7 @@
}
protected boolean handleExec(Buffer buffer) throws IOException {
+ CommandFactory.Command command;
boolean wantReply = buffer.getBoolean();
String commandLine = buffer.getString();
@@ -481,7 +482,12 @@
return false;
}
- CommandFactory.Command command = ((ServerSession) session).getServerFactoryManager().getCommandFactory().createCommand(commandLine);
+ try {
+ command = ((ServerSession) session).getServerFactoryManager().getCommandFactory().createCommand(commandLine);
+ } catch (IllegalArgumentException iae) {
+ // TODO: Shouldn't we log errors on the server side?
+ return false;
+ }
// If the command wants to be aware of the session, let's do that
if (command instanceof CommandFactory.SessionAware) {
((CommandFactory.SessionAware) command).setSession((ServerSession) session);
@@ -505,6 +511,9 @@
log.info("Error closing shell", e);
}
}
+ public void onExit(int exitValue, String exitMessage) {
+ onExit(exitValue);
+ }
});
if (wantReply) {
Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java
URL:
http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java?rev=830479&r1=830478&r2=830479&view=diff==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java Wed Oct 28 09:27:36 2009
@@ -41,6 +41,8 @@
public class ScpCommand implements CommandFactory.Command, Runnable {
private static final Logger log = LoggerFactory.getLogger(ScpCommand.class);
+ private static final int OK = 0;
+ private static final int ERROR = 2;
private boolean optR;
private boolean optT;
@@ -116,6 +118,9 @@
}
public void run() {
+ int exitValue = OK;
+ String exitMessage = null;
+
try {
if (optT && !optR) {
ack();
@@ -143,8 +148,10 @@
}
} catch (IOException e) {
try {
- out.write(2);
- out.write(e.getMessage().getBytes());
+ exitValue = ERROR;
+ exitMessage = e.getMessage();
+ out.write(exitValue);
+ out.write(exitMessage.getBytes());
out.write('\n');
out.flush();
} catch (IOException e2) {
@@ -152,7 +159,9 @@
}
log.info("Error in scp command", e);
} finally {
- callback.onExit(0);
+ if (callback != null) {
+ callback.onExit(exitValue, exitMessage);
+ }
}
}
Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommandFactory.java
URL:
http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommandFactory.java?rev=830479&r1=830478&r2=830479&view=diff==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommandFactory.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommandFactory.java Wed Oct 28 09:27:36 2009
@@ -18,6 +18,9 @@
*/
package org.apache.sshd.server.command;
+import java.util.ArrayList;
+import java.util.List;
+
import org.apache.sshd.server.CommandFactory;
/**
@@ -40,15 +43,51 @@
this.delegate = delegate;
}
- public Command createCommand(String command){
- String[] args = command.split(" ");
- if (args.length > 0 && "scp".equals(args[0])) {
- return new ScpCommand(args);
+ /**
+ * Parses a command string and verifies that the basic syntax is
+ * correct. If parsing fails the responsibility is delegated to
+ * the configured {@link CommandFactory} instance; if one exist.
+ *
+ * @param command command to parse
+ * @return configured {@link CommandFactory.Command} instance
+ * @throws IllegalArgumentException
+ */
+ public Command createCommand(String command) {
+ try {
+ return new ScpCommand(splitCommandString(command));
+ } catch (IllegalArgumentException iae) {
+ if (delegate != null) {
+ return delegate.createCommand(command);
+ }
+ throw iae;
+ }
+ }
+
+ private String[] splitCommandString(String command) {
+ if (!command.trim().startsWith("scp")) {
+ throw new IllegalArgumentException("Unknown command, does not begin with 'scp'");
}
- if (delegate != null) {
- return delegate.createCommand(command);
+
+ String[] args = command.split(" ");
+ List<String> parts = new ArrayList<String>();
+ parts.add(args[0]);
+ for (int i = 1; i < args.length; i++) {
+ if (!args[i].trim().startsWith("-")) {
+ parts.add(concatenateWithSpace(args, i));
+ break;
+ } else {
+ parts.add(args[i]);
+ }
}
- return new UnknownCommand(command);
+ return parts.toArray(new String[parts.size()]);
}
+ private String concatenateWithSpace(String[] args, int from) {
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = from; i < args.length; i++) {
+ sb.append(args[i] + " ");
+ }
+ return sb.toString().trim();
+ }
}
Modified: mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ScpTest.java
URL:
http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ScpTest.java?rev=830479&r1=830478&r2=830479&view=diff==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ScpTest.java (original)
+++ mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/ScpTest.java Wed Oct 28 09:27:36 2009
@@ -109,32 +109,32 @@
String data = "0123456789\n";
File root = new File("target/scp");
- File target = new File("target/scp/out.txt");
+ File target = new File("target/scp/o ut.txt");
root.mkdirs();
assertTrue(root.exists());
target.delete();
assertFalse(target.exists());
- sendFile("target/scp/out.txt", "out.txt", data);
+ sendFile("target/scp/o ut.txt", "out.txt", data);
assertFileLength(target, data.length(), 5000);
target.delete();
assertFalse(target.exists());
- sendFile("target/scp", "out.txt", data);
+ sendFile("target/scp", "o ut.txt", data);
assertFileLength(target, data.length(), 5000);
sendFileError("target", "scp", "0123456789\n");
readFileError("target/scp");
- assertEquals(data, readFile("target/scp/out.txt"));
+ assertEquals(data, readFile("target/scp/o ut.txt"));
assertEquals(data, readDir("target/scp"));
target.delete();
root.delete();
- sendDir("target", "scp", "out.txt", data);
+ sendDir("target", "scp", "o ut.txt", data);
assertFileLength(target, data.length(), 5000);
}
@@ -164,7 +164,7 @@
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
String header = readLine(is);
- assertEquals("C0644 11 out.txt", header);
+ assertEquals("C0644 11 o ut.txt", header);
int length = Integer.parseInt(header.substring(6, header.indexOf(' ', 6)));
os.write(0);
os.flush();
@@ -191,7 +191,7 @@
os.write(0);
os.flush();
header = readLine(is);
- assertEquals("C0644 11 out.txt", header);
+ assertEquals("C0644 11 o ut.txt", header);
int length = Integer.parseInt(header.substring(6, header.indexOf(' ', 6)));
os.write(0);
os.flush();