KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ftpserver > CommandHandler


1 /*
2  * This file is part of the QuickServer library
3  * Copyright (C) 2003-2005 QuickServer.org
4  *
5  * Use, modification, copying and distribution of this software is subject to
6  * the terms and conditions of the GNU Lesser General Public License.
7  * You should have received a copy of the GNU LGP License along with this
8  * library; if not, you can download a copy from <http://www.quickserver.org/>.
9  *
10  * For questions, suggestions, bug-reports, enhancement-requests etc.
11  * visit http://www.quickserver.org
12  *
13  */

14
15 package ftpserver;
16
17 import org.quickserver.net.server.ClientCommandHandler;
18 import org.quickserver.net.server.ClientHandler;
19
20 import java.net.*;
21 import java.io.*;
22 import java.util.StringTokenizer JavaDoc;
23 import org.quickserver.util.*;
24 import java.text.*;
25 import java.util.Date JavaDoc;
26 import java.util.logging.*;
27
28 /**
29  * IMPORTANT NOTE: This example just demonstrates how to use some
30  * of the QuickServer features. This example not built keeping
31  * security in mind.
32  */

33 public class CommandHandler implements ClientCommandHandler {
34     private static Logger logger =
35         Logger.getLogger(CommandHandler.class.getName());
36
37     public void gotConnected(ClientHandler handler)
38         throws SocketTimeoutException, IOException {
39         handler.sendSystemMsg("Connection opened : "+
40             handler.getSocket().getInetAddress(), Level.FINE);
41
42         handler.sendClientMsg("220- QuickFTPServer v 0.1 ");
43         handler.sendClientMsg("220- Developed using QuickServer");
44         handler.sendClientMsg("220 ");
45         //send feature supported msg
46
//handler.sendClientMsg("220 Features: a p .");
47
}
48
49     public void lostConnection(ClientHandler handler) throws IOException {
50         logger.fine("Connection lost : "+
51             handler.getSocket().getInetAddress());
52     }
53     public void closingConnection(ClientHandler handler) throws IOException {
54         logger.fine("Connection closed: " +
55             handler.getSocket().getInetAddress());
56     }
57
58     public void handleCommand(ClientHandler handler, String JavaDoc command)
59             throws SocketTimeoutException, IOException {
60         Data data = (Data)handler.getClientData();
61         command = command.trim();
62         String JavaDoc ucCommand = command.toUpperCase();
63         String JavaDoc args = null;
64         String JavaDoc temp = null;
65         
66         logger.fine("Got command : " + command);
67
68         if(ucCommand.equals("QUIT")) {
69             //LOGOUT
70
data.wasQuit = true;
71             handler.sendClientMsg("221 Logged out.");
72             handler.closeConnection();
73             return;
74         } else if(ucCommand.endsWith("ABOR")) {
75             //ABORT
76
data.isStop = true;
77             //close data connection
78
//handler.sendClientMsg("502 Command not implemented.");
79
handler.sendClientMsg("220 OK");
80             return;
81         } else if(ucCommand.startsWith("STAT")) {
82             //STATUS
83
handler.sendClientMsg("211- QuickFTPServer");
84             handler.sendClientMsg(" Version 0.1 ");
85             handler.sendClientMsg(" Connected to " +
86                 handler.getSocket().getInetAddress());
87             handler.sendClientMsg(" Logged in as "+data.username);
88             handler.sendClientMsg(" Cur Dir : "+data.wDir);
89             handler.sendClientMsg(" Data connection : "+
90                 data.isTransferring);
91             handler.sendClientMsg("211 End of status");
92             return;
93         }
94         
95         ///////////// now check if only not processing ///////
96
if(data.isProcessing==true) {
97             handler.sendClientMsg("503 Bad sequence of commands; another command is being processed.");
98             return;
99         }
100         /////////// ACCESS CONTROL COMMANDS /////////
101
if(ucCommand.equals("REIN")) {
102             //REINITIALIZE
103
handler.sendClientMsg("502 Command not implemented.");
104         } else if(ucCommand.startsWith("ACCT")) {
105             //ACCOUNT
106
args = command.substring("ACCT".length()).trim();
107             data.account = args;
108             handler.sendClientMsg("230 Account OK.");
109         } else if(ucCommand.equals("CDUP")) {
110             //CHANGE TO PARENT DIRECTORY
111
int i = data.wDir.lastIndexOf("/");
112             String JavaDoc temp_wDir = null;
113             if(i!=-1) {
114                 temp_wDir = data.wDir.substring(0,i);
115                 if(temp_wDir.equals(""))
116                     temp_wDir = "/";
117                 else
118                     temp_wDir += "/"; //end
119
temp = MyString.replaceAll(data.root+temp_wDir,"/","\\");
120                 temp = MyString.replaceAll(temp,"\\\\","\\");
121                 File file = new File(temp);
122                 if( file.canRead() ){
123                     data.wDir = temp_wDir;
124                     handler.sendClientMsg("250 Okay");
125                 } else {
126                     handler.sendClientMsg("550 No parent dir");
127                 }
128             } else {
129                 handler.sendClientMsg("550 No parent dir");
130             }
131         } else if(ucCommand.startsWith("SMNT")) {
132             //STRUCTURE MOUNT
133
handler.sendClientMsg("502 Command not implemented.");
134         }
135         ///////// TRANSFER PARAMETER COMMANDS ////////
136
else if(ucCommand.startsWith("PORT")) {
137             /*
138             PORT h1,h2,h3,h4,p1,p2
139             */

140             args = command.substring("PORT".length()).trim();
141             String JavaDoc ipAddr = "";
142             int port = 0;
143             StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(args,",");
144             int p1 = 0;
145             int p2 = 0;
146             try {
147                 ipAddr+=st.nextToken()+".";
148                 ipAddr+=st.nextToken()+".";
149                 ipAddr+=st.nextToken()+".";
150                 ipAddr+=st.nextToken();
151                 p1 = Integer.parseInt(st.nextToken());
152                 p2 = Integer.parseInt(st.nextToken());
153                 port = p1*256+p2;
154                 data.ip = ipAddr;
155                 data.socketPort = port;
156                 handler.sendClientMsg("200 Command okay.");
157             } catch (Exception JavaDoc e) {
158                 handler.sendClientMsg("501 Syntax error in parameters or arguments. : PORT "+e);
159             }
160         } else if(ucCommand.startsWith("PASV")) {
161             /*
162             PASSIVE
163             This command requests the server-DTP to "listen" on a data
164             port (which is not its default data port) and to wait for a
165             connection rather than initiate one upon receipt of a
166             transfer command. The response to this command includes the
167             host and port address this server is listening on.
168             PORT = p1*256+p2
169             p1 = PORT / 256
170             p2 = PORT - p1*256
171             */

172             //227 =127,0,0,1,10,5
173

174             //reset for PORT
175
data.ip = null;
176
177             try {
178                 InetAddress ipAddr = handler.getSocket().getLocalAddress();
179                 String JavaDoc ip_port ="";
180                 StringTokenizer JavaDoc st =
181                     new StringTokenizer JavaDoc(ipAddr.getHostAddress(),".");
182                 while (st.hasMoreTokens()) {
183                     ip_port+=st.nextToken()+",";
184                 }
185                 data.server = new ServerSocket(0,1,ipAddr);
186                 data.serverPort = data.server.getLocalPort();
187                 int p1 = data.serverPort / 256;
188                 int p2 = data.serverPort - p1*256;
189                 ip_port += p1+","+p2;
190                 data.startDataServer(data.server,data); //start server
191
handler.sendClientMsg("227 ="+ip_port);
192             } catch(Exception JavaDoc e){
193                 handler.sendClientMsg("425 Can't open data port; Error : "+e);
194             }
195         } else if(ucCommand.startsWith("TYPE")) {
196             /*
197             REPRESENTATION TYPE
198                          \ /
199                A - ASCII | | N - Non-print
200                          |-><-| T - Telnet format effectors
201                E - EBCDIC| | C - Carriage Control (ASA)
202                          / \
203                I - Image
204                
205                L <byte size> - Local byte Byte size
206             */

207             args = command.substring("TYPE".length()).trim();
208             if(args.equals("A")) {
209                 data.binary = false;
210                 data.type = 'A';
211                 data.typeSub = 'Z';
212             } else if(args.equals("A N")) {
213                 data.binary = false;
214                 data.type = 'A';
215                 data.typeSub = 'N';
216             } else if(args.equals("I")) {
217                 data.binary = true;
218                 data.type = 'I';
219                 data.typeSub = 'Z';
220             } else if(args.equals("L 8")) {
221                 data.binary = true;
222                 //data.type = 'A';
223
//data.typeSub = 'N';
224
} else {
225                 handler.sendClientMsg("501 Syntax error in parameters.");
226                 return;
227             }
228             handler.sendClientMsg("200 Command OK.");
229         } else if(ucCommand.startsWith("STRU")) {
230             /*
231             FILE STRUCTURE
232                F - File (no record structure) - default
233                R - Record structure
234                P - Page structure
235             */

236             if(ucCommand.equals("STRU F")) {
237                 handler.sendClientMsg("200 Command OK.");
238             } else {
239                 //obsolete
240
handler.sendClientMsg("504 Command not implemented for that parameter.");
241             }
242         } else if(ucCommand.startsWith("MODE")) {
243             /*
244             TRANSFER MODE
245                S - Stream - Default
246                B - Block
247                C - Compressed
248             */

249             if(ucCommand.equals("MODE S")) {
250                 handler.sendClientMsg("200 Command OK.");
251             } else {
252                 //obsolete
253
handler.sendClientMsg("504 Command not implemented for that parameter.");
254             }
255         }
256         /////// FTP SERVICE COMMANDS ///////
257
else if(ucCommand.startsWith("RETR")) {
258             data.isTransferring = true;
259             //RETRIEVE
260
args = command.substring("RETR".length()).trim();
261             String JavaDoc sfile = "";
262             //check if NOT PASSIVE, i.e PORT was set
263
if(data.ip!=null) {
264                 try {
265                     data.socket = new Socket(
266                         InetAddress.getByName(data.ip), data.socketPort);
267                 } catch (Exception JavaDoc e) {
268                     handler.sendClientMsg("425 Can't open data connection.");
269                     data.isTransferring = false;
270                     return;
271                 }
272             }
273             if(data.socket != null) {
274                 if(args.charAt(0)=='/') {
275                     sfile = data.root + args;
276                 } else {
277                     sfile = data.root + data.wDir + "/" + args;
278                 }
279                 temp = MyString.replaceAll(sfile,"/","\\");
280                 temp = MyString.replaceAll(temp,"\\\\","\\");
281                 File file = new File(temp);
282                 if(file.canRead() && file.isFile()) {
283                     handler.sendClientMsg("150 I see that file.");
284                     //send file
285
try {
286                         data.sendFile(temp);
287                         //close data connection when done
288
if(data.ip!=null)
289                             data.socket.close();
290                         data.closeDataServer = true;
291                         if(data.isStop==false)
292                             handler.sendClientMsg("226 File transferred successfully.");
293                         else
294                             handler.sendClientMsg("551 Error sending file : User Aborted");
295                     } catch (Exception JavaDoc e) {
296                         data.closeDataServer = true;
297                         handler.sendClientMsg("551 Error sending file : "+e);
298                     }
299                 } else {
300                     handler.sendClientMsg("451 Sorry, that isn't a data file");
301                 }
302             } else {
303                 handler.sendClientMsg("425 Sorry no TCP connection was established.");
304             }
305             data.isTransferring = false;
306         } else if(ucCommand.startsWith("STOR")) {
307             //STORE
308
args = command.substring("STOR".length()).trim();
309             handler.sendClientMsg("502 Command not implemented.");
310         } else if(ucCommand.startsWith("STOU")) {
311             //STORE UNIQUE - The 250 Transfer Started response
312
//must include the name generated.
313
args = command.substring("STOU".length()).trim();
314             handler.sendClientMsg("502 Command not implemented.");
315         } else if(ucCommand.startsWith("APPE")) {
316             //APPEND (with create)
317
handler.sendClientMsg("502 Command not implemented.");
318         } else if(ucCommand.startsWith("ALLO")) {
319             //ALLOCATE - obsolete
320
handler.sendClientMsg("502 Command not implemented - obsolete.");
321         } else if(ucCommand.startsWith("REST")) {
322             //RESTART transfer
323
//350 ok
324
handler.sendClientMsg("502 Command not implemented.");
325         } else if(ucCommand.startsWith("RNFR")) {
326             //RENAME FROM
327
data.isRenameFrom = true;
328             handler.sendClientMsg("502 Command not implemented.");
329         } else if(ucCommand.startsWith("RNTO")) {
330             //RENAME TO
331
if(!data.isRenameFrom) {
332                 //error should not happen
333
}
334             data.isRenameFrom = false;
335             handler.sendClientMsg("502 Command not implemented.");
336         } else if(ucCommand.startsWith("DELE")) {
337             //DELETE
338
handler.sendClientMsg("502 Command not implemented.");
339         } else if(ucCommand.startsWith("RMD")) {
340             //REMOVE DIRECTORY
341
handler.sendClientMsg("502 Command not implemented.");
342         } else if(ucCommand.startsWith("MKD")) {
343             //MAKE DIRECTORY
344
args = command.substring("MKD".length()).trim();
345             temp = MyString.replaceAll(data.root+data.wDir+args,"/","\\");
346             temp = MyString.replaceAll(temp,"\\\\","\\");
347             File file = new File(temp);
348             try {
349                 file.mkdir();
350                 file.canRead();
351                 temp = file.getAbsolutePath();
352                 temp = "/"+MyString.replaceAll(temp,data.root,"");
353                 temp = MyString.replaceAll(temp,"\\","/");
354                 temp = MyString.replaceAll(temp,"//","/");
355                 handler.sendClientMsg("257 \""+temp+"\" directory created");
356             } catch(Exception JavaDoc e) {
357                 handler.sendClientMsg("521-Could not create dir \""+args+"\"");
358                 handler.sendClientMsg("521 Error : "+e);
359             }
360         } else if(ucCommand.startsWith("CWD")) {
361             //CHANGE DIRECTORY
362
temp = data.wDir;
363             args = command.substring("CWD".length()).trim();
364             if(data.wDir.charAt(data.wDir.length()-1)!='/')
365                 data.wDir += "/";
366             if(args.charAt(args.length()-1)!='/')
367                 args += "/";
368
369             if(args.charAt(0)!='/')
370                 data.wDir += args;
371             else
372                 data.wDir = args;
373
374             temp = MyString.replaceAll(data.root+data.wDir,"/","\\");
375             temp = MyString.replaceAll(temp,"\\\\","\\");
376             File file = new File(temp);
377             if(file.canRead() && file.isDirectory()) {
378                 handler.sendClientMsg("250 Directory changed to "+data.wDir);
379             } else {
380                 if(file.canRead())
381                     handler.sendClientMsg("550 "+data.wDir+": The directory name is invalid.");
382                 else
383                     handler.sendClientMsg("550 "+data.wDir+": The system cannot find the file specified .");
384                 data.wDir = temp;
385                 logger.logp(Level.FINER, "CommandHandler", "handleCommand",
386                     "Command=CWD; ERROR : 550 No such directory "+file);
387             }
388         } else if(ucCommand.startsWith("PWD")) {
389             //PRINT WORKING DIRECTORY
390
temp = MyString.replaceAll(data.wDir,"\"","\"\"");
391             handler.sendClientMsg("257 \""+data.wDir+"\"");
392         } else if(ucCommand.startsWith("LIST")) {
393             data.isTransferring = true;
394             if(ucCommand.equals("LIST")) {
395                 args = "";
396             } else {
397                 args = command.substring("LIST".length()).trim();
398                 if(args.equals("-latr")) //not known
399
args="";
400             }
401             temp = MyString.replaceAll(data.root+data.wDir+args,"/","\\");
402             temp = MyString.replaceAll(temp,"\\\\","\\");
403             File file = new File(temp);
404             
405             if( file.canRead() ) {
406                 handler.sendClientMsg("150 Opening data connection for LIST "+data.wDir+args);
407                 if(data.ip!=null) {
408                     try {
409                         data.socket = new Socket(
410                             InetAddress.getByName(data.ip),
411                             data.socketPort);
412                     } catch (Exception JavaDoc e) {
413                         handler.sendClientMsg("425 Can't open data connection.");
414                         data.isTransferring = false;
415                         return;
416                     }
417                 }
418                 String JavaDoc result = winDirList(temp);
419                 try {
420                     data.sendData(result);
421                     //close data connection when done
422
if(data.ip!=null) {
423                         data.socket.close();
424                     }
425                     data.closeDataServer = true;
426                     if(data.isStop==false)
427                         handler.sendClientMsg("226 File transferred successfully.");
428                     else
429                         handler.sendClientMsg("551 Error sending file : User Aborted");
430                 } catch (Exception JavaDoc e) {
431                     if(data.ip!=null && data.socket!=null)
432                         data.socket.close();
433                     data.closeDataServer = true;
434                     handler.sendClientMsg("551 Error sending LIST : "+e);
435                 }
436             } else {
437                 handler.sendClientMsg("550 No such directory : "+data.wDir+args);
438                 logger.logp(Level.FINER, "CommandHandler", "handleCommand",
439                     "Command=LIST; ERROR : 550 No such directory "+file);
440             }
441             data.isTransferring = false;
442         } else if(ucCommand.startsWith("NLST")) {
443             //NAME LIST of directory only
444
data.isTransferring = true;
445             if(ucCommand.equals("NLST")) {
446                 args = "";
447             } else {
448                 args = command.substring("NLST".length()).trim();
449             }
450             temp = MyString.replaceAll(data.root+data.wDir+args,"/","\\");
451             temp = MyString.replaceAll(temp,"\\\\","\\");
452             File file = new File(temp);
453             String JavaDoc result = "";
454             if( file.canRead() && file.isDirectory() ) {
455                 handler.sendClientMsg("150 Opening data connection for LIST "+data.wDir+args);
456                 if(data.ip!=null) {
457                     try {
458                         data.socket = new Socket(
459                             InetAddress.getByName(data.ip),
460                             data.socketPort);
461                     } catch (Exception JavaDoc e) {
462                         handler.sendClientMsg("425 Can't open data connection.");
463                         data.isTransferring = false;
464                         return;
465                     }
466                 }
467                 String JavaDoc list[] = file.list();
468                 for(int i=0;i<list.length;i++) {
469                     if(!list[i].equals(".") && !list[i].equals("..") )
470                         result +=list[i]+"\r\n";
471                 }
472                 try {
473                     data.sendData(result);
474                     //close data connection when done
475
if(data.ip!=null)
476                         data.socket.close();
477                     data.closeDataServer = true;
478                     if(data.isStop==false)
479                         handler.sendClientMsg("226 File transferred successfully.");
480                     else
481                         handler.sendClientMsg("551 Error sending file : User Aborted");
482                 } catch (Exception JavaDoc e) {
483                     if(data.ip!=null && data.socket!=null)
484                         data.socket.close();
485                     data.closeDataServer = true;
486                     handler.sendClientMsg("551 Error sending NLST : "+e);
487                 }
488             } else {
489                 handler.sendClientMsg("550 No such directory : "+data.wDir+args);
490                 logger.logp(Level.FINER, "CommandHandler", "handleCommand",
491                     "Command=NLST; ERROR : 550 No such directory "+file);
492             }
493             data.isTransferring = false;
494         } else if(ucCommand.startsWith("SITE")) {
495             //SITE PARAMETERS
496
handler.sendClientMsg("502 Command not implemented.");
497         } else if(ucCommand.startsWith("SYST")) {
498             //SYSTEM - Assigned Numbers document [4]
499
// UNIX Type: L8
500
handler.sendClientMsg("215 "+"Windows_NT version 5.0");
501         } else if(ucCommand.startsWith("HELP")) {
502             //HELP
503
//The reply is type 211 or 214.
504
handler.sendClientMsg("502 Command not implemented.");
505         } else if(ucCommand.startsWith("NOOP")) {
506             //NOOP - OK reply
507
handler.sendClientMsg("200 OK");
508         } else if(ucCommand.startsWith("SIZE")) {
509             //SIZE OF FILE
510
args = command.substring("SIZE".length()).trim();
511             temp = MyString.replaceAll(data.root+data.wDir+args,"/","\\");
512             temp = MyString.replaceAll(temp,"\\\\","\\");
513             File file = new File(temp);
514             if( file.canRead() ) {
515                 handler.sendClientMsg("213 "+file.length());
516             } else {
517                 handler.sendClientMsg("550 No such file.");
518             }
519         } else {
520             //ERROR
521
handler.sendClientMsg("500 Syntax error, command unrecognized.");
522         }
523     }
524
525     // helper meethods
526
private String JavaDoc dirList(String JavaDoc dir) {
527         //+FACTS1,FACTS@..,FACTN\tfile_name\r\n
528
/*
529             FACE = xy
530            >X<
531             r -> File
532             / -> Dir
533             s ->Size, y=size in bytes
534             m ->Modified since 1970
535             i ->This file has identifier y.
536             up->Chmode is allowed
537         */

538         File file = new File(dir);
539         File subFile = null;
540         String JavaDoc result = "";
541         if( file.canRead() ) {
542             String JavaDoc list[] = file.list();
543             for(int i=0;i<list.length;i++) {
544                 //if(list[i].equals(".") || list[i].equals("..") )
545
// continue;
546
subFile = new File(dir+File.separator+list[i]);
547                 result += "+";
548                 result +="i"+subFile.hashCode()+",";
549                 result +="s"+subFile.length()+",";
550                 result +="m"+subFile.lastModified()+",";
551                 if(subFile.isFile()) {
552                     result +="r,";
553                 } else {
554                     result +="/,";
555                 }
556                 result +="\t"+list[i]+"\r\n";
557             }
558         }
559         return result;
560     }
561
562     private String JavaDoc winDirList(String JavaDoc dir) {
563         File file = new File(dir);
564         File subFile = null;
565         String JavaDoc result = "";
566         if( file.canRead() ) {
567             String JavaDoc list[] = file.list();
568             for(int i=0;i<list.length;i++) {
569                 subFile = new File(dir+File.separator+list[i]);
570                 SimpleDateFormat dformat =
571                     new SimpleDateFormat("MM-dd-yy HH:mm:a ");
572                 result += dformat.format(new Date JavaDoc(subFile.lastModified()));
573                 if(subFile.isFile()) {
574                     //20 field length
575
StringBuffer JavaDoc size = new StringBuffer JavaDoc(20);
576                     size.append(subFile.length());
577                     while(size.length()<20) {
578                         size.insert(0," ");
579                     }
580                     result += size.toString();
581                 } else {
582                     result +=" <DIR> ";
583                 }
584                 result +=" "+list[i]+"\r\n";
585             }
586         }
587         return result;
588     }
589 }
590
Popular Tags