📄 ftpconnection.java
字号:
}
}
/**
* <code>MODE <SP> <mode-code> <CRLF></code><br>
*
* The argument is a single Telnet character code specifying
* the data transfer modes described in the Section on
* Transmission Modes.
*/
public void doMODE(FtpRequest request, FtpWriter out) throws IOException {
// reset state variables
resetState();
// argument check
if(!request.hasArgument()) {
out.write(mFtpStatus.getResponse(501, request, mUser, null));
return;
}
if (mUser.setMode(request.getArgument().charAt(0))) {
out.write(mFtpStatus.getResponse(200, request, mUser, null));
}
else {
out.write(mFtpStatus.getResponse(504, request, mUser, null));
}
}
/**
* <code>NLST [<SP> <pathname>] <CRLF></code><br>
*
* This command causes a directory listing to be sent from
* server to user site. The pathname should specify a
* directory or other system-specific file group descriptor; a
* null argument implies the current directory. The server
* will return a stream of names of files and no other
* information.
*/
public void doNLST(FtpRequest request, FtpWriter out) throws IOException {
// reset state variables
resetState();
out.write(mFtpStatus.getResponse(150, request, mUser, null));
Writer os = null;
try {
Socket dataSoc = mDataConnection.getDataSocket();
if (dataSoc == null) {
out.write(mFtpStatus.getResponse(550, request, mUser, null));
return;
}
os = new OutputStreamWriter(dataSoc.getOutputStream());
if (!mUser.getVirtualDirectory().printNList(request.getArgument(), os)) {
out.write(mFtpStatus.getResponse(501, request, mUser, null));
}
else {
os.flush();
out.write(mFtpStatus.getResponse(226, request, mUser, null));
}
}
catch(IOException ex) {
out.write(mFtpStatus.getResponse(425, request, mUser, null));
}
finally {
IoUtils.close(os);
mDataConnection.reset();
}
}
/**
* <code>NOOP <CRLF></code><br>
*
* This command does not affect any parameters or previously
* entered commands. It specifies no action other than that the
* server send an OK reply.
*/
public void doNOOP(FtpRequest request, FtpWriter out) throws IOException {
// reset state variables
resetState();
out.write(mFtpStatus.getResponse(200, request, mUser, null));
}
/**
* <code>PASS <SP> <password> <CRLF></code><br>
*
* The argument field is a Telnet string specifying the user's
* password. This command must be immediately preceded by the
* user name command.
*/
public void doPASS(FtpRequest request, FtpWriter out) throws IOException {
// set state variables
if(!mbUser) {
out.write(mFtpStatus.getResponse(500, request, mUser, null));
resetState();
return;
}
resetState();
mbPass = true;
// set user password and login
String pass = request.hasArgument() ? request.getArgument() : "";
mUser.setPassword(pass);
// login failure - close connection
String args[] = {mUser.getName()};
if (mConfig.getConnectionService().login(mUser)) {
out.write(mFtpStatus.getResponse(230, request, mUser, args));
}
else {
out.write(mFtpStatus.getResponse(530, request, mUser, args));
ConnectionService conService = mConfig.getConnectionService();
if (conService != null) {
conService.closeConnection(mUser.getSessionId());
}
}
}
/**
* <code>PASV <CRLF></code><br>
*
* This command requests the server-DTP to "listen" on a data
* port (which is not its default data port) and to wait for a
* connection rather than initiate one upon receipt of a
* transfer command. The response to this command includes the
* host and port address this server is listening on.
*/
public void doPASV(FtpRequest request, FtpWriter out) throws IOException {
if (!mDataConnection.setPasvCommand()) {
out.write(mFtpStatus.getResponse(550, request, mUser, null));
return;
}
InetAddress servAddr = mDataConnection.getInetAddress();
if(servAddr == null) {
servAddr = mConfig.getSelfAddress();
}
int servPort = mDataConnection.getPort();
String addrStr = servAddr.getHostAddress().replace( '.', ',' ) + ',' + (servPort>>8) + ',' + (servPort&0xFF);
String[] args = {addrStr};
out.write(mFtpStatus.getResponse(227, request, mUser, args));
if (!mDataConnection.listenPasvConnection()) {
out.write(mFtpStatus.getResponse(425, request, mUser, args));
}
}
/**
* <code>PORT <SP> <host-port> <CRLF></code><br>
*
* The argument is a HOST-PORT specification for the data port
* to be used in data connection. There are defaults for both
* the user and server data ports, and under normal
* circumstances this command and its reply are not needed. If
* this command is used, the argument is the concatenation of a
* 32-bit internet host address and a 16-bit TCP port address.
* This address information is broken into 8-bit fields and the
* value of each field is transmitted as a decimal number (in
* character string representation). The fields are separated
* by commas. A port command would be:
*
* PORT h1,h2,h3,h4,p1,p2
*
* where h1 is the high order 8 bits of the internet host address.
*/
public void doPORT(FtpRequest request, FtpWriter out) throws IOException {
// reset state variables
resetState();
InetAddress clientAddr = null;
int clientPort = 0;
// argument check
if(!request.hasArgument()) {
out.write(mFtpStatus.getResponse(501, request, mUser, null));
return;
}
StringTokenizer st = new StringTokenizer(request.getArgument(), ",");
if(st.countTokens() != 6) {
out.write(mFtpStatus.getResponse(510, request, mUser, null));
return;
}
// get data server
String dataSrvName = st.nextToken() + '.' + st.nextToken() + '.' +
st.nextToken() + '.' + st.nextToken();
try {
clientAddr = InetAddress.getByName(dataSrvName);
}
catch(UnknownHostException ex) {
out.write(mFtpStatus.getResponse(553, request, mUser, null));
return;
}
// get data server port
try {
int hi = Integer.parseInt(st.nextToken());
int lo = Integer.parseInt(st.nextToken());
clientPort = (hi << 8) | lo;
}
catch(NumberFormatException ex) {
out.write(mFtpStatus.getResponse(552, request, mUser, null));
return;
}
mDataConnection.setPortCommand(clientAddr, clientPort);
out.write(mFtpStatus.getResponse(200, request, mUser, null));
}
/**
* <code>PWD <CRLF></code><br>
*
* This command causes the name of the current working
* directory to be returned in the reply.
*/
public void doPWD(FtpRequest request, FtpWriter out) throws IOException {
// reset state variables
resetState();
String args[] = {mUser.getVirtualDirectory().getCurrentDirectory()};
out.write(mFtpStatus.getResponse(257, request, mUser, args));
}
/**
* <code>QUIT <CRLF></code><br>
*
* This command terminates a USER and if file transfer is not
* in progress, the server closes the control connection.
*/
public void doQUIT(FtpRequest request, FtpWriter out) throws IOException {
// reset state variables
resetState();
// and exit
out.write(mFtpStatus.getResponse(221, request, mUser, null));
ConnectionService conService = mConfig.getConnectionService();
if (conService != null) {
conService.closeConnection(mUser.getSessionId());
}
}
/**
* <code>REST <SP> <marker> <CRLF></code><br>
*
* The argument field represents the server marker at which
* file transfer is to be restarted. This command does not
* cause file transfer but skips over the file to the specified
* data checkpoint. This command shall be immediately followed
* by the appropriate FTP service command which shall cause
* file transfer to resume.
*/
public void doREST(FtpRequest request, FtpWriter out) throws IOException {
// argument check
if(!request.hasArgument()) {
out.write(mFtpStatus.getResponse(501, request, mUser, null));
return;
}
// set state variables
resetState();
mlSkipLen = 0;
String skipNum = request.getArgument();
try {
mlSkipLen = Long.parseLong(skipNum);
}
catch(NumberFormatException ex) {
out.write(mFtpStatus.getResponse(501, request, mUser, null));
return;
}
if(mlSkipLen < 0) {
mlSkipLen = 0;
out.write(mFtpStatus.getResponse(501, request, mUser, null));
return;
}
mbReset = true;
out.write(mFtpStatus.getResponse(350, request, mUser, null));
}
/**
* <code>RETR <SP> <pathname> <CRLF></code><br>
*
* This command causes the server-DTP to transfer a copy of the
* file, specified in the pathname, to the server- or user-DTP
* at the other end of the data connection. The status and
* contents of the file at the server site shall be unaffected.
*/
public void doRETR(FtpRequest request, FtpWriter out) throws IOException {
// set state variables
long skipLen = (mbReset) ? mlSkipLen : 0;
resetState();
// argument check
if(!request.hasArgument()) {
out.write(mFtpStatus.getResponse(501, request, mUser, null));
return;
}
// get filenames
String fileName = request.getArgument();
fileName = mUser.getVirtualDirectory().getAbsoluteName(fileName);
String physicalName = mUser.getVirtualDirectory().getPhysicalName(fileName);
File requestedFile = new File(physicalName);
String args[] = {fileName};
// check permission
if(!mUser.getVirtualDirectory().hasReadPermission(physicalName, true)) {
out.write(mFtpStatus.getResponse(550, request, mUser, args));
return;
}
// now transfer file data
out.write(mFtpStatus.getResponse(150, request, mUser, null));
InputStream is = null;
OutputStream os = null;
try {
Socket dataSoc = mDataConnection.getDataSocket();
if (dataSoc == null) {
out.write(mFtpStatus.getResponse(550, request, mUser, args));
return;
}
os = mUser.getOutputStream(dataSoc.getOutputStream());
RandomAccessFile raf = new RandomAccessFile(requestedFile, "r");
raf.seek(skipLen);
is = new FileInputStream(raf.getFD());
StreamConnector msc = new StreamConnector(is, os);
msc.setMaxTransferRate(mUser.getMaxDownloadRate());
msc.setObserver(this);
msc.connect();
if(msc.hasException()) {
out.write(mFtpStatus.getResponse(451, request, mUser, args));
return;
}
else {
mConfig.getStatistics().setDownload(requestedFile, mUser, msc.getTransferredSize());
}
out.write(mFtpStatus.getResponse(226, request, mUser, null));
}
catch(IOException ex) {
out.write(mFtpStatus.getResponse(425, request, mUser, null));
}
finally {
IoUtils.close(is);
IoUtils.close(os);
mDataConnection.reset();
}
}
/**
* <code>RMD <SP> <pathname> <CRLF></code><br>
*
* This command causes the directory specified in the pathname
* to be removed as a directory (if the pathname is absolute)
* or as a subdirectory of the current working directory (if
* the pathname is relative).
*/
public void doRMD(FtpRequest request, FtpWriter out) throws IOException {
// reset state variables
resetState();
// argument check
if(!request.hasArgument()) {
out.write(mFtpStatus.getResponse(501, request, mUser, null));
return;
}
// get file names
String fileName = request.getArgument();
fileName = mUser.getVirtualDirectory().getAbsoluteName(fileName);
String physicalName = mUser.getVirtualDirectory().getPhysicalName(fileName);
File requestedFile = new File(physicalName);
String args[] = {fileName};
// check permission
if(!mUser.getVirtualDirectory().hasWritePermission(physicalName, true)) {
out.write(mFtpStatus.getResponse(450, request, mUser, args));
return;
}
// now delete
if(requestedFile.delete()) {
out.write(mFtpStatus.getResponse(250, request, mUser, args));
}
else {
out.write(mFtpStatus.getResponse(450, request, mUser, args));
}
}
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -