Support incomplete input
[xylftp.git] / client / src / XylFTPCLI.java
blobdc9544b5def931bf85d6ad57391fcdf8bc07d63f
1 //////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Kong Jian-jun, Apr. 2007.
3 // Implemented XylFTPCLI.ShowHelp(), XylFTPCLI.ProcessEcho(), etc.
4 // Copyright (C) Wang Cong, Apr. 2007.
5 // Implemented XylFTPCLI.ParseInput().
6 // Hacked by Zhou Xiao-wei, May. 2007.
7 // See AUTHORS and CREDITS to learn more.
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License version 2 as
10 // published by the Free Software Foundation.
11 // See COPYING to learn more.
12 //////////////////////////////////////////////////////////////////////////
14 import java.net.*;
15 import java.io.*;
17 /**
18 *This is class Command-line interface.
19 *Extends XylFTPConnection.
20 *Implements XylFTPInterface.
21 *@see XylFTPConnection
22 *@see XylFTPInterface
23 *@author WANG Cong, KONG Jian-Jun
24 *@version 1.14
26 public class XylFTPCLI extends XylFTPConnection implements XylFTPInterface{
27 /**
28 *The username.
30 private String UserName;
32 /**
33 *The password.
35 private String PassWord;
37 /**
38 *Presents the input of user.
40 private String UserInput;
42 /**
43 *The current working directory on local host.
45 private File CurrentDir;
47 /**
48 *Sets the default password.
50 private final String DefaultPass = "xylftpuser@xylftp";
52 /**
53 *Commands list.
55 private String[] commands = {"help", "?", "ls", "lls",
56 "dir", "get", "put", "cwd", "cd", "lcwd", "lcd", "pwd",
57 "lpwd", "passive", "cdup", "lcdup", "quit", "bye",
58 "open", "close", "user", "!!", "delete", "rmdir",
59 "mkdir", "chmod", "size", "rename", "type", "status",
60 "quote", "verbose", "debug"};
62 /**
63 *Initializes some values.
65 XylFTPCLI(){
66 super();
67 UserName = "anonymous";
68 PassWord = DefaultPass;
69 File f = new File(".");
70 try {
71 CurrentDir = new File(f.getCanonicalPath());
72 } catch (Exception e) {
73 System.out.println("Fatal: Can't get current directory!");
74 System.exit(-1);
78 /**
79 *Sets the username.
80 *@param NewName the new user name.
82 public void SetUserName(String NewName){
83 UserName = NewName;
86 /**
87 *Returns the username.
88 *@return username
90 public String GetUserName(){
91 return UserName;
94 /**
95 *Sets the password.
96 *@param NewPass the new password.
98 public void SetPassWord(String NewPass){
99 PassWord = NewPass;
103 *Gets the password.
104 *@return password
106 public String GetPassWord(){
107 return PassWord;
111 *Splits the command string into commands list.
112 *@param Command
113 *@return the string of command
115 public String[] MakeCommands(String Command){
116 if(Command == null)
117 return null;
118 String[] nstr;
119 nstr = Command.split("\r\n");
120 return nstr;
124 *Counts the number of arguments.
125 *@param Str the input
126 *@return the number of arguments in Str
128 private int CountArgs(String Str){
129 String[] nstr;
130 nstr = Str.split("[\t ]+");
131 return nstr.length;
135 *Look up the commands list, recognize which command matches.
136 *@return the index of the command, -1 on failure.
138 private int LookupCommands(String input) throws Exception{
139 int i = 0;
140 for (; i< commands.length; i++) {
141 if (StartsOnlyWith(input, commands[i]))
142 return i;
144 //If not found, try again for incomplete input.
145 boolean found_one = false;
146 int tmp = -1;
147 for (i = 0; i< commands.length; i++) {
148 if (commands[i].startsWith(input.toLowerCase())) {
149 if (found_one) {
150 return -1;
151 } else {
152 found_one = true;
153 tmp = i;
157 if (found_one)
158 return tmp;
159 else
160 return -1;
163 *Judges the command.
164 *@param CmdString the command of the user input
165 *@param Cmd the handled command
166 *@throws XylFTPException on dealing with command error
167 *@return true while right,false while wrong
169 private boolean StartsOnlyWith(String CmdString, String Cmd) throws Exception{
170 switch(CountArgs(CmdString)){
171 case 1:
172 if (CmdString.equalsIgnoreCase(Cmd))
173 return true;
174 else
175 return false;
176 default:
177 String []cmds = CmdString.split("[\t ]+");
178 if(cmds[0].equalsIgnoreCase(Cmd))
179 return true;
180 else
181 return false;
186 *Translates the command for FTP protocol.
187 *@param Input the input of the user
188 *@return ehco for input
189 *@see Exception
190 *@see XylFTPException
191 *@throws XylFTPException on parsing input error
193 private String ParseInput(String Input) throws Exception{
194 String tmp = Input.trim();
195 if (tmp.equals(""))
196 return null;
197 switch (LookupCommands(tmp)) {
198 case 0:
199 case 1:
201 switch (CountArgs(tmp)){
202 case 1:
203 ShowHelp("");
204 break;
205 case 2:
206 String []cmds = tmp.split("[\t ]+");
207 ShowHelp(cmds[1]);
208 break;
209 default:
210 throw new XylFTPException("help", "Too many arguments.");
212 return null;
214 case 2:
216 if (GetStatus()!=2)
217 throw new XylFTPException("ls", "Can't execute it now. Try again later.");
218 switch (CountArgs(tmp)){
219 case 1:
220 SetLocalFile("");
221 if (IsPassive())
222 return "PASV\r\nLIST\r\n";
223 else
224 return "PORT "+GetSelfIP()+GetSelfPort()+"\r\nLIST\r\n";
225 default:
226 String []cmds = tmp.split("[\t ]+");
227 String substr = "";
228 for(int i=1; i< cmds.length; i++)
229 substr = substr + cmds[i] + " ";
230 SetLocalFile("");
231 substr = substr.trim();
232 if (IsPassive())
233 return "PASV\r\nLIST "+substr+"\r\n";
234 else
235 return "PORT "+GetSelfIP()+GetSelfPort()+"\r\nLIST "+substr+"\r\n";
238 case 3:
240 switch (CountArgs(tmp)){
241 case 1:
242 String[] list = CurrentDir.list();
243 for (int i=0; i < list.length; i++) {
244 System.out.println(list[i]);
246 break;
247 default:
248 String []cmds = tmp.split("[\t ]+");
249 File f2;
250 for (int i=1; i< cmds.length; i++) {
251 f2 = new File(CurrentDir.getCanonicalPath()+File.separator+cmds[i]);
252 if (!f2.exists()) {
253 System.out.println(cmds[i]+" doesn't exist.");
254 break;
255 } else {
256 if (f2.isFile())
257 System.out.println(cmds[i]);
258 if (f2.isDirectory()){
259 System.out.println(cmds[i]+":");
260 String[] lst = f2.list();
261 for(int j=0; j < lst.length; j++)
262 System.out.println("\t"+lst[j]);
267 return null;
269 case 4:
271 if (GetStatus()!=2)
272 throw new XylFTPException("dir", "Can't execute it now. Try again later.");
273 switch (CountArgs(tmp)){
274 case 1:
275 SetLocalFile("");
276 if (IsPassive())
277 return "PASV\r\nNLST\r\n";
278 else
279 return "PORT "+GetSelfIP()+GetSelfPort()+"\r\nNLST\r\n";
280 default:
281 String []cmds = tmp.split("[\t ]+");
282 String substr = "";
283 for(int i=1; i< cmds.length; i++)
284 substr = substr + cmds[i] + " ";
285 SetLocalFile("");
286 substr = substr.trim();
287 if (IsPassive())
288 return "PASV\r\nNLST "+substr+"\r\n";
289 else
290 return "PORT "+GetSelfIP()+GetSelfPort()+"\r\nNLST "+substr+"\r\n";
293 case 5:
295 if (GetStatus()!=2)
296 throw new XylFTPException("get", "You can't excute it now. Try again later.");
297 switch (CountArgs(tmp)){
298 case 1:
299 throw new XylFTPException("get", "Missed arguments.");
300 case 2:
301 String []cmds = tmp.split("[\t ]+");
302 String tmp3 = cmds[1];
303 if (cmds[1].charAt(0)!='/')
304 tmp3 = CurrentDir.getCanonicalPath()+File.separator+cmds[1];
305 int p = tmp3.lastIndexOf("/");
306 if (p!=-1) {
307 File d = new File(tmp3.substring(0, p));
308 if (!d.exists())
309 throw new XylFTPException("get", "Directory doesn't exist.");
311 SetLocalFile(tmp3);
312 File f = new File(tmp3);
313 if (f.isDirectory())
314 throw new XylFTPException("get", "can't gets to a directory.");
315 if (IsPassive())
316 return "PASV\r\nRETR "+cmds[1]+"\r\n";
317 else
318 return "PORT "+GetSelfIP()+GetSelfPort()+"\r\nRETR "+cmds[1]+"\r\n";
319 case 3:
320 String []cmds2 = tmp.split("[\t ]+");
321 String tmp4 = cmds2[2];
322 if (cmds2[2].charAt(0)!='/')
323 tmp4 = CurrentDir.getCanonicalPath()+File.separator+cmds2[2];
324 int q = tmp4.lastIndexOf("/");
325 if (q!=-1) {
326 File d2 = new File(tmp4.substring(0, q));
327 if (!d2.exists())
328 throw new XylFTPException("get", "Directory doesn't exist.");
330 SetLocalFile(tmp4);
331 File f2 = new File(tmp4);
332 if (f2.isDirectory())
333 throw new XylFTPException("get", "can't gets to a directory.");
334 if (IsPassive())
335 return "PASV\r\nRETR "+cmds2[1]+"\r\n";
336 else
337 return "PORT "+GetSelfIP()+GetSelfPort()+"\r\nRETR "+cmds2[1]+"\r\n";
338 default:
339 throw new XylFTPException("get", "Too many arguments.");
342 case 6:
344 if (GetStatus()!=2)
345 throw new XylFTPException("put", "You can't excute it now. Try again later.");
346 switch (CountArgs(tmp)){
347 case 1:
348 throw new XylFTPException("put", "Missed arguments.");
349 case 2:
350 String []cmds = tmp.split("[\t ]+");
351 String tmp1 = cmds[1];
352 if (cmds[1].charAt(0)!='/')
353 tmp1 = CurrentDir.getCanonicalPath()+File.separator+cmds[1];
354 SetLocalFile(tmp1);
355 File f = new File(tmp1);
356 if (!f.exists())
357 throw new XylFTPException("put", "file doesn't exist.");
358 if (f.isDirectory())
359 throw new XylFTPException("put", "can't puts from a directory.");
360 if (IsPassive())
361 return "PASV\r\nSTOR "+cmds[1]+"\r\n";
362 else
363 return "PORT "+GetSelfIP()+GetSelfPort()+"\r\nSTOR "+cmds[1]+"\r\n";
364 case 3:
365 String []cmds2 = tmp.split("[\t ]+");
366 String tmp2 = cmds2[1];
367 if (cmds2[1].charAt(0)!='/')
368 tmp2 = CurrentDir.getCanonicalPath()+File.separator+cmds2[1];
369 SetLocalFile(tmp2);
370 File f2 = new File(tmp2);
371 if (!f2.exists())
372 throw new XylFTPException("put", "file doesn't exist.");
373 if (f2.isDirectory())
374 throw new XylFTPException("put", "can't puts from a directory.");
375 if (IsPassive())
376 return "PASV\r\nSTOR "+cmds2[2]+"\r\n";
377 else
378 return "PORT "+GetSelfIP()+GetSelfPort()+"\r\nSTOR "+cmds2[2]+"\r\n";
379 default:
380 throw new XylFTPException("put", "Too many arguments.");
383 case 7:
384 case 8:
386 if (GetStatus()!=2)
387 throw new XylFTPException("cd", "You can't execute it now. Try again later.");
388 switch (CountArgs(tmp)){
389 case 1:
390 return null;
391 case 2:
392 String []cmds = tmp.split("[\t ]+");
393 return "CWD "+cmds[1]+"\r\n";
394 default:
395 throw new XylFTPException("cd", "Too many arguments.");
398 case 9:
399 case 10:
401 switch (CountArgs(tmp)){
402 case 1:
403 break;
404 case 2:
405 String []cmds = tmp.split("[\t ]+");
406 if (cmds[1].equals("."))
407 break;
408 else if (cmds[1].equals("..")) {
409 String parent = CurrentDir.getAbsoluteFile().getParent();
410 if (parent==null) {
411 break;
412 } else {
413 System.out.println("cd into: "+parent);
414 CurrentDir = new File(parent);
416 } else if (cmds[1].charAt(0)=='/') {
417 File ff = new File(cmds[1]);
418 if(!ff.exists() || !ff.isDirectory())
419 System.out.println(cmds[1]+": No such dir.");
420 else {
421 CurrentDir = ff;
422 System.out.println("cd into: "+CurrentDir.getCanonicalPath());
425 } else{
426 File fl = new File(CurrentDir.getCanonicalPath()+File.separator+cmds[1]);
427 if(!fl.exists() || !fl.isDirectory())
428 System.out.println(cmds[1]+": No such dir.");
429 else {
430 CurrentDir = fl;
431 System.out.println("cd into: "+CurrentDir.getCanonicalPath());
434 break;
435 default:
436 throw new XylFTPException("cd", "Too many arguments.");
438 return null;
440 case 11:
442 if (GetStatus()!=2)
443 throw new XylFTPException("pwd", "You can't execute it now. Try again later.");
444 switch (CountArgs(tmp)){
445 case 1:
446 return "PWD\r\n";
447 default:
448 throw new XylFTPException("pwd", "It doesn't accept any arguments.");
451 case 12:
453 switch (CountArgs(tmp)){
454 case 1:
455 System.out.println(CurrentDir.getCanonicalPath());
456 break;
457 default:
458 throw new XylFTPException("lpwd", "It doesn't accept any arguments.");
460 return null;
462 case 13:
464 switch (CountArgs(tmp)){
465 case 2:
466 String []cmds = tmp.split("[\t ]+");
467 if (!cmds[1].equals("on") && !cmds[1].equals("off"))
468 throw new XylFTPException("passive", "Wrong arugment.");
469 else {
470 if (cmds[1].equals("on")) {
471 System.out.println("Passive mode on.");
472 SetPassive();
473 } else {
474 System.out.println("Passive mode off.");
475 SetActive();
478 break;
479 case 1:
480 throw new XylFTPException("passive", "It must have an argument.");
481 default:
482 throw new XylFTPException("passive", "Too many arguments.");
484 return null;
486 case 14:
488 if (GetStatus()!=2)
489 throw new XylFTPException("cdup",
490 "Can't execute it now. Try again later.");
491 switch (CountArgs(tmp)){
492 case 1:
493 return "CDUP\r\n";
494 default:
495 throw new XylFTPException("cdup",
496 "It doesn't accept any arguments.");
499 case 15:
501 switch (CountArgs(tmp)){
502 case 1:
503 String parent = CurrentDir.getAbsoluteFile().getParent();
504 if (parent==null) {
505 break;
506 } else {
507 System.out.println("cd into: "+parent);
508 CurrentDir = new File(parent);
510 break;
511 default:
512 throw new XylFTPException("lcdup",
513 "It doesn't accept any arguments.");
515 return null;
517 case 16:
518 case 17:
520 if (CountArgs(tmp) > 1) {
521 throw new XylFTPException("quit",
522 "It doesn't accept any arguments.");
524 switch (GetStatus()){
525 case 0:
526 System.exit(0);
527 case 1:
528 case 2:
529 return "QUIT\r\nQUIT\r\n"; //Note! It is used to differ 'quit' from 'close'.
530 case 3:
531 case 4:
532 return "ABOR\r\nQUIT\r\nQUIT\r\n";
533 default:
534 throw new XylFTPException("Unknown status!");
537 case 18:
539 int n = CountArgs(tmp);
540 if (n < 2){
541 throw new XylFTPException("open",
542 "It must be followed by at least one argument.");
544 if (n > 3){
545 throw new XylFTPException("open", "Too many arguments.");
547 switch (GetStatus()){
548 case 0:
549 case 1:
550 int portNum;
551 String []cmds = tmp.split("[\t ]+");
552 if(cmds.length==2) {
553 portNum = 21;
554 } else {
555 try {
556 portNum = Integer.parseInt(cmds[2]);
557 } catch (NumberFormatException e) {
558 ShowHelp("open");
559 return null;
562 SetHost(cmds[1]);
563 SetPort(portNum);
564 OpenConnection();
565 String s = GetEcho();
566 if (s==null)
567 throw new XylFTPException("xylftp", 0,
568 "Cann't get an echo.");
569 else
570 System.out.println(s);
571 while (s.charAt(3) == '-'){
572 s = GetEcho();
573 if (s==null)
574 throw new XylFTPException("xylftp", 0,
575 "Can't get an echo.");
576 if (XylFTPMain.GetEnableDebug())
577 System.out.println("<---"+s);
578 System.out.println(s);
580 SetStatus(1);
581 return "USER "+UserName+"\r\n"+"PASS "+PassWord+"\r\n";
582 case 2:
583 case 3:
584 case 4:
585 throw new XylFTPException("Connection already existed.");
586 default:
587 throw new XylFTPException("panic", "Unknown status!");
590 case 19:
592 if (CountArgs(tmp) > 1){
593 throw new XylFTPException("close", "Too many arguments.");
595 switch (GetStatus()){
596 case 0:
597 throw new XylFTPException("Not connected yet.");
598 case 1:
599 case 2:
600 return "QUIT\r\n";
601 case 3:
602 case 4:
603 return "ABOR\r\nQUIT\r\n";
604 default:
605 throw new XylFTPException("Unknown status!");
608 case 20:
610 switch (GetStatus()){
611 case 0:
612 String [] cmds = tmp.split("[\t ]+");
613 if (cmds.length == 2) {
614 UserName = cmds[1];
616 else if (cmds.length == 3) {
617 UserName = cmds[1];
618 PassWord = cmds[2];
620 else if (cmds.length == 1) {
621 throw new XylFTPException("user",
622 "It must be followed by at least one argument.");
624 else {
625 throw new XylFTPException("user", "Too many arguments.");
627 SetUserName(UserName);
628 SetPassWord(PassWord);
629 return null;
630 case 1:
631 case 2:
632 String [] cmds2 = tmp.split("[\t ]+");
633 if (cmds2.length == 2) {
634 UserName = cmds2[1];
636 else if (cmds2.length == 3) {
637 UserName = cmds2[1];
638 PassWord = cmds2[2];
640 else if (cmds2.length == 1) {
641 throw new XylFTPException("user",
642 "It must be followed by at least one argument.");
644 else{
645 throw new XylFTPException("user", "Too many arguments.");
647 return "USER "+UserName+"\r\n"+"PASS "+PassWord+"\r\n";
648 case 3:
649 case 4:
650 throw new XylFTPException("user",
651 "Can't execute it now. Try again later.");
652 default:
653 throw new XylFTPException("panic", "Unknown status!");
656 case 21:
658 if (CountArgs(tmp) > 1) {
659 throw new XylFTPException("!!", "It doesn't accept any arguments.");
660 } else {
661 System.out.println("=====Enter shell mode=====");
662 String cmd = GetInput();
663 System.out.println("cmd :"+cmd);
664 while(!cmd.equals("exit")){
665 Runtime run = Runtime.getRuntime();
666 Process pp=run.exec(cmd);
667 pp.waitFor();
668 BufferedReader in = new BufferedReader(new InputStreamReader(pp.getInputStream()));
669 String line;
670 while ((line = in.readLine()) != null) {
671 System.out.println(line);
673 cmd = GetInput();
675 System.out.println("=====Exit shell mode=====");
676 return null;
679 case 22:
681 if (GetStatus()!=2)
682 throw new XylFTPException("delete",
683 "Can't execute it now. Try again later.");
684 switch (CountArgs(tmp)){
685 case 1:
686 throw new XylFTPException("delete", "Missed arguments.");
687 case 2:
688 String []cmds = tmp.split("[\t ]+");
689 return "DELE "+cmds[1]+"\r\n";
690 default:
691 throw new XylFTPException("delete", "Too many arguments.");
694 case 23:
696 if (GetStatus()!=2)
697 throw new XylFTPException("rmdir",
698 "Can't execute it now. Try again later.");
699 switch (CountArgs(tmp)){
700 case 1:
701 throw new XylFTPException("rmdir", "Missed arguments.");
702 case 2:
703 String []cmds = tmp.split("[\t ]+");
704 return "RMD "+cmds[1]+"\r\n";
705 default:
706 throw new XylFTPException("rmdir", "Too many arguments.");
709 case 24:
711 if (GetStatus()!=2)
712 throw new XylFTPException("mkdir",
713 "Can't execute it now. Try again later.");
714 switch (CountArgs(tmp)){
715 case 1:
716 throw new XylFTPException("mkdir", "Missed arguments.");
717 case 2:
718 String []cmds = tmp.split("[\t ]+");
719 return "MKD "+cmds[1]+"\r\n";
720 default:
721 throw new XylFTPException("mkdir", "Too many arguments.");
724 case 25:
726 if (GetStatus()!=2)
727 throw new XylFTPException("chmod",
728 "Can't execute it now. Try again later.");
729 switch (CountArgs(tmp)){
730 case 1:
731 case 2:
732 throw new XylFTPException("chmod", "Missed arguments.");
733 case 3:
734 String []cmds = tmp.split("[\t ]+");
735 return "SITE CHMOD "+cmds[1]+" "+cmds[2]+"\r\n";
736 default:
737 throw new XylFTPException("chmod", "Too many arguments.");
740 case 26:
742 if (GetStatus()!=2)
743 throw new XylFTPException("size",
744 "Can't execute it now. Try again later.");
745 switch (CountArgs(tmp)){
746 case 1:
747 throw new XylFTPException("size", "Missed arguments.");
748 case 2:
749 String []cmds = tmp.split("[\t ]+");
750 return "SIZE "+cmds[1]+"\r\n";
751 default:
752 throw new XylFTPException("size", "Too many arguments.");
755 case 27:
757 if (GetStatus()!=2)
758 throw new XylFTPException("rename",
759 "Can't execute it now. Try again later.");
760 switch (CountArgs(tmp)){
761 case 1:
762 case 2:
763 throw new XylFTPException("rename", "Missed arguments.");
764 case 3:
765 String []cmds = tmp.split("[\t ]+");
766 return "RNFR "+cmds[1]+"\r\nRNTO "+cmds[2]+"\r\n";
767 default:
768 throw new XylFTPException("rename", "Too many arguments.");
772 case 28:
774 switch (CountArgs(tmp)){
775 case 1:
776 if(GetTransferMode()==0)
777 System.out.println("Using binary mode to transfer files.");
778 else
779 System.out.println("Using ascii mode to transfer files.");
780 return null;
781 case 2:
782 String []cmds = tmp.split("[\t ]+");
783 if(cmds[1].equalsIgnoreCase("ascii"))
784 return "TYPE A\r\n";
785 else if(cmds[1].equalsIgnoreCase("binary"))
786 return "TYPE I\r\n";
787 else
788 throw new XylFTPException("type", "Wrong arguments.");
789 default:
790 throw new XylFTPException("type", "Too many arguments.");
794 case 29:
796 switch (GetStatus()){
797 case 0:
798 System.out.println("Not connected.");
799 break;
800 case 1:
801 System.out.println("Connected to "+GetHost()+",but not login.");
802 break;
803 case 2:
804 System.out.println("Login ("+GetHost()+") and no data transfer.");
805 break;
806 case 3:
807 System.out.println("Login ("+GetHost()+") and getting data down.");
808 break;
809 case 4:
810 System.out.println("Login ("+GetHost()+") and putting data up.");
811 break;
812 default:
813 throw new XylFTPException("status", "Wrong status.");
816 if (IsPassive()){
817 System.out.println("Passive: on");
819 else
820 System.out.println("Passive: off");
822 if (GetTransferMode()==0)
823 System.out.println("Type: binary");
824 else
825 System.out.println("Type: ascii");
828 if (XylFTPMain.GetEnableVerbose()){
829 System.out.println("Verbose: on");
831 else
832 System.out.println("Verbose: off");
834 if (XylFTPMain.GetEnableDebug()){
835 System.out.println("Debug: on");
837 else
838 System.out.println("Debug: off");
840 return null;
842 case 30:
844 String in, echo;
845 int ret;
846 if (GetStatus()==0)
847 throw new XylFTPException("quote", "Not connection.");
848 switch(CountArgs(tmp)){
849 case 1:
850 System.out.print("Enter the command to send:");
851 in = GetInput();
852 break;
853 default:
854 in = tmp.substring(5, tmp.length()).trim();
856 SendCommand(in);
857 if (XylFTPMain.GetEnableDebug())
858 System.out.println("--->" + in);
859 do {
860 echo = GetEcho();
861 if(echo == null || !IsValidEcho(echo))
862 throw new XylFTPException("Can't get an echo.");
863 if (XylFTPMain.GetEnableDebug())
864 System.out.println("<---" + echo);
865 ret = ProcessEcho(echo);
866 } while(ret == 6);
867 return null;
869 case 31:
871 switch(CountArgs(tmp)){
872 case 1:
873 if (XylFTPMain.GetEnableVerbose()){
874 XylFTPMain.SetEnableVerbose(false);
875 System.out.println("Verbose off.");
877 else {
878 XylFTPMain.SetEnableVerbose(true);
879 System.out.println("Verbose on.");
881 break;
882 default:
883 throw new XylFTPException("verbose", "Too many arguments.");
885 return null;
887 case 32:
889 switch(CountArgs(tmp)){
890 case 1:
891 if (XylFTPMain.GetEnableDebug()){
892 XylFTPMain.SetEnableDebug(false);
893 System.out.println("Debugging off.");
895 else {
896 XylFTPMain.SetEnableDebug(true);
897 System.out.println("Debugging on.");
899 break;
900 default:
901 throw new XylFTPException("debug", "Too many arguments.");
903 return null;
905 default:
906 throw new XylFTPException("xylftp", GetStatus(), "Unknown command!");
911 *Reads the input.
912 *@return In the readline from buffer
913 *@see Exception
914 *@throws Exception
916 public String GetInput() throws Exception{
917 //Why System.in.skip(System.in.available()); cann't help us?
918 BufferedReader Buf = new BufferedReader(new InputStreamReader(System.in));
919 String In = Buf.readLine();
920 return In;
924 *Shows the echo from server.
925 *@param Echo
927 private void ShowEcho(String Echo){
928 System.out.println(Echo);
932 *Determines whether the echo is valid
933 *@param OEcho
935 public boolean IsValidEcho(String OEcho){
936 String Echo = OEcho.trim();
937 if (Echo.length() < 4)
938 return false;
939 if (Echo.charAt(0)<'0' || Echo.charAt(0)>'9')
940 return false;
941 if (Echo.charAt(1)<'0' || Echo.charAt(1)>'9')
942 return false;
943 if (Echo.charAt(2)<'0' || Echo.charAt(2)>'9')
944 return false;
945 if (Echo.charAt(3)!=' ' && Echo.charAt(3)!='-')
946 return false;
947 return true;
951 *Process the echo from the server.
952 *@param OEcho a number returns from the server
953 *@return a number that shows the echo as a logo
955 public int ProcessEcho(String OEcho){
956 String Echo = OEcho.trim();
957 ShowEcho(Echo);
958 if (Echo.charAt(3) == '-')
959 return 6; //This means multi-line echo.
960 if(Echo.substring(0,1).equals("1"))
961 return 1; //We need data connection.
962 if(Echo.substring(0,1).equals("2")){
963 if(Echo.substring(0,3).equals("227"))
964 return 3;
965 else if(Echo.substring(0,3).equals("200"))
966 return 3;
967 else
968 return 2; //Don't to be continued.
970 if(Echo.substring(0,1).equals("3"))
971 return 3; //Continue.
972 if(Echo.substring (0,1).equals("4")){
973 if(Echo.substring(0,3).equals("421")){
974 SetStatus(0);
975 return 2;
977 if(Echo.substring(0,3).equals("450"))
978 return 2;
979 return 4; //Send again.
981 if(Echo.substring(0,1).equals("5"))
982 return 5; //Stop resending.
983 if(Echo.substring(1,2).equals("0"))
984 return 0; //Invalid format.
985 else
986 return -1; //Unknow mistake
990 *Gets the commands that user inputs.
991 *@throws XylFTPException on getting commands error
992 *@see XylFTPException
993 *@return the handled command as a string
995 public String[] GetCommands() throws Exception{
996 String CmdString = ParseInput(GetInput());
997 String[] cmds;
998 cmds = MakeCommands(CmdString);
999 return cmds;
1003 *Show the usage.
1005 public void ShowUsage(){
1006 System.out.println("xylftp [-h|--help][-V | -version]");
1007 System.out.println("xylftp [-v|--verbose][-u $USERNAME|--user=$USERNAME][-p $PASSWORD | --password=$PASSWORD][-d|--debug] [$HOST]");
1008 System.out.println("");
1009 System.out.println("-u $username | -user=$username \n\tTry $username as username to connect to the host, if this is not specified, use anonymous as default.");
1010 System.out.println("-h | --help \n\tShow this help screen.");
1011 System.out.println("-V | -version \n\tShow version information.");
1012 System.out.println("-v | -verbose \n\tShow verbose information.");
1013 System.out.println("-p $PASSWORD | --password=$PASSWORD \n\tUse $PASSWORD as your password. If this is unspecified, use empty password as default.");
1014 System.out.println("-d | --debug \n\tShow more information for developers and system admins.");
1018 *Show help information.
1020 public void ShowHelp(String Command){
1021 String help[] = new String[31];
1022 int i = 0;
1024 help[0]="?\tprint local help information";
1025 help[1]="bye\tterminate ftp session and exit";
1026 help[2]="cd\tchange remote working directory";
1027 help[3]="cdup\tchange remote working directory to parent directory";
1028 help[4]="chmod\tchange file permissions of remote file";
1029 help[5]="close\tterminate ftp session";
1030 help[6]="debug\toggle/set debugging mode";
1031 help[7]="delete\tdelete remote file";
1032 help[8]="dir\tlist contents of remote directory";
1033 help[9]="get\tget a file";
1034 help[10]="help\tprint local help information";
1035 help[11]="lcd\tchange local working directory";
1036 help[12]="lcdup\tget to local parent directory";
1037 help[13]="lcwd\tchange local working directory";
1038 help[14]="lls\tlist contents of local directory";
1039 help[15]="lpwd\tprint working directory on local machine";
1040 help[16]="ls\tlist contents of remote directory";
1041 help[17]="mkdir\tmake directory on the remote machine";
1042 help[18]="open\tconnect to remote ftp";
1043 help[19]="passive\tturn passive transfer mode on/off";
1044 help[20]="put\tsend one file";
1045 help[21]="pwd\tprint working directory on remote machine";
1046 help[22]="quit\tterminate ftp session and exit";
1047 help[23]="quote\tsend arbitrary ftp command";
1048 help[24]="rename\trename a file";
1049 help[25]="rmdir\tremove directory on the remote machine";
1050 help[26]="size\tshow size of remote file";
1051 help[27]="status\tshow current status";
1052 help[28]="type\tset file transfer type";
1053 help[29]="user\tsend new user information";
1054 help[30]="verbose\ttoggle verbose mode";
1056 if (Command.equals("")){
1057 System.out.println("Help of xylftp commands:\n");
1058 while(i < help.length){
1059 System.out.println(help[i]);
1060 i++;
1062 } else {
1063 while(i < help.length){
1064 if(help[i].startsWith(Command+"\t")){
1065 System.out.println(help[i]);
1066 return ;
1068 i++;
1070 System.out.println("There is no information about "+Command);
1075 *Show the version.
1077 public void ShowVersion(){
1078 System.out.println("xylftp: version 1.1.");