Support incomplete input
[xylftp.git] / client / src / XylFTPMain.java
bloba8e07245719e067ba3c89db82aef838ee1db4027
1 //////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Zhou Xiao-wei, Apr. 2007.
3 // Implemented XylFTPMain.main().
4 // Hacked by Wang Cong, May. 2007.
5 // See AUTHORS and CREDITS to learn more.
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License version 2 as
8 // published by the Free Software Foundation.
9 // See COPYING to learn more.
10 //////////////////////////////////////////////////////////////////////////
11 import java.net.*;
12 import java.io.*;
15 /**
16 *The main class.
17 *@author ZHOU Xiao-Wei
18 *@author WANG Cong
19 *@version 1.11
20 *@see XylFTPException
22 public final class XylFTPMain{
24 /**
25 *Builds an object.
27 private static XylFTPCLI MyFTP;
29 /**
30 *Enable verbose output.
32 private static boolean EnableVerbose = false;
34 /**
35 *Enable debugging output.
37 private static boolean EnableDebug = false;
39 /**
40 *Tests whether it is enable debug.
42 public static boolean GetEnableDebug(){
43 return EnableDebug;
46 /**
47 *Tests whether it is enable verbose.
49 public static boolean GetEnableVerbose(){
50 return EnableVerbose;
53 /**
54 *Sets the value of Enabledebug.
55 *@param Value the new value of Enabledebug.
57 public static void SetEnableDebug(boolean Value){
58 EnableDebug = Value;
61 /**
62 *Sets the value of Enableverbose.
63 *@param Value the new value of Enableverbose.
65 public static void SetEnableVerbose(boolean Value){
66 EnableVerbose = Value;
69 /**
70 *Logo used by this program.
72 private final static String LOGO = "xylftp>";
74 /**
75 *Parse the port number from echo.
76 *@param From the echo to be parsed
77 *@exception XylFTPException on parsing port error
78 *@see XylFTPException
79 *@return the number of the port
81 private static int ParsePort(String From) throws XylFTPException{
82 int i, j;
83 int port1, port2;
84 String t;
85 String [] nums;
86 i = From.indexOf("(");
87 if (i==-1)
88 throw new XylFTPException("", 1, "Invalid echo!");
89 j = From.indexOf(")");
90 if (j==-1)
91 throw new XylFTPException("", 1, "Invalid echo!");
92 t = From.substring(i+1, j);
93 nums = t.split(",");
94 port1 = Integer.parseInt(nums[4]);
95 port2 = Integer.parseInt(nums[5]);
96 return port1*256 + port2;
99 /**
100 *Parse the IP address from the echo.
101 *@param From the echo to be parsed
102 *@exception XylFTPException on parsing IP error
103 *@see XylFTPException
104 *@return all the numbers of the IP as a string
106 private static String ParseIP(String From) throws XylFTPException{
107 int i, j;
108 String t;
109 String [] nums;
110 i = From.indexOf("(");
111 if (i==-1)
112 throw new XylFTPException("PASV", 1, "Invalid echo!");
113 j = From.indexOf(")");
114 if (j==-1)
115 throw new XylFTPException("PASV", 1, "Invalid echo!");
116 t = From.substring(i+1, j);
117 nums = t.split(",");
118 if (nums.length < 4)
119 throw new XylFTPException("PASV", 1, "Invalid echo!");
120 return (nums[0]+"."+nums[1]+"."+nums[2]+"."+nums[3]);
125 *The main function.
127 public static void main(String args[]) {
128 int flag = 0;
129 // 0 for standard read
130 // 1 for read username
131 // 2 for read password
132 // 3 for read help parameter
133 char ch;
134 boolean toConnectAtStart = false;
135 MyFTP = new XylFTPCLI();
137 for (int i = 0; i < args.length; i++) {
138 if (flag == 0) { // standard read
139 if (args[i].charAt(0) == '-' && args[i].charAt(1) == '-') { // long argument
140 if (args[i].equals("--user")) {
141 if (i < args.length - 1) {
142 flag = 1; // Read username next time
143 } else { // Nothing after --user indicates an error
144 MyFTP.ShowUsage();
145 System.exit(1);
147 } else if (args[i].equals("--help")) {
148 if (i < args.length - 1
149 && args[i + 1].charAt(0) != '-') { // Need to read help parameter
150 flag = 3;
151 } else {
152 MyFTP.ShowUsage();
153 System.exit(0);
155 } else if (args[i].equals("--password")) {
156 if (i < args.length - 1) {
157 flag = 2; // Read password next time
158 } else { // Nothing after --password indicates an error
159 MyFTP.ShowUsage();
160 System.exit(1);
162 } else if (args[i].equals("--version")) {
163 MyFTP.ShowVersion();
164 System.exit(0);
165 } else if (args[i].equals("--verbose")) {
166 EnableVerbose = true;
167 } else if (args[i].equals("--debug")) {
168 EnableDebug = true;
169 } else { // illegal long argument
170 MyFTP.ShowUsage();
171 System.exit(1);
174 } else if (args[i].charAt(0) == '-') { // short argument
175 if (args[i].length() > 2 || args[i].length() <= 1) { // Short argument too long or too short
176 MyFTP.ShowUsage();
177 System.exit(1);
178 } else {
179 ch = args[i].charAt(1); // argument char
180 switch (ch) {
181 case 'u':
182 if (i < args.length - 1) {
183 flag = 1; // Read username next time
184 } else { // Nothing after -u indicates an error
185 MyFTP.ShowUsage();
186 System.exit(1);
188 break;
189 case 'h':
190 if (i < args.length - 1
191 && args[i + 1].charAt(0) != '-') { // Need to read help parameter
192 flag = 3;
193 } else {
194 MyFTP.ShowUsage();
195 System.exit(0);
197 break;
198 case 'p':
199 if (i < args.length - 1) {
200 flag = 2; // Read password next time
201 } else { // Nothing after -p indicates an error
202 MyFTP.ShowUsage();
203 System.exit(1);
205 break;
206 case 'V':
207 MyFTP.ShowVersion();
208 System.exit(0);
209 break;
210 case 'v':
211 EnableVerbose = true;
212 break;
213 case 'd':
214 EnableDebug = true;
215 break;
216 default: // illegal short argument
217 MyFTP.ShowUsage();
218 System.exit(1);
221 } else {
222 if (toConnectAtStart) { // illegal argument
223 MyFTP.ShowUsage();
224 System.exit(1);
225 } else { // Command line contains host name
226 toConnectAtStart = true;
227 MyFTP.SetHost(args[i]);
230 } else if (flag == 1) { // Read Username
231 MyFTP.SetUserName(args[i]);
232 flag = 0;
233 } else if (flag == 2) { // Read password
234 MyFTP.SetPassWord(args[i]);
235 flag = 0;
236 } else if (flag == 3) { // Read help parameter
237 MyFTP.ShowHelp(args[i]);
238 System.exit(0);
242 String echo;
243 String cmds[];
244 int echoMeaning;
245 int HostPort = 0;
246 String HostIP = null;
247 while (true) {
248 try {
249 if (toConnectAtStart) {
250 try {
251 MyFTP.OpenConnection();
252 String s = MyFTP.GetEcho();
253 if (s==null)
254 throw new XylFTPException("xylftp", 0,
255 "Cann't get an echo.");
256 else
257 System.out.println(s);
258 while (s.charAt(3) == '-'){
259 s = MyFTP.GetEcho();
260 if (s==null)
261 throw new XylFTPException("xylftp",
262 0, "Can't get an echo.");
263 if (EnableDebug)
264 System.out.println("<---"+s);
265 System.out.println(s);
267 MyFTP.SetStatus(1);
268 cmds = MyFTP.MakeCommands("USER "
269 +MyFTP.GetUserName()+"\r\n"
270 +"PASS "+MyFTP.GetPassWord()
271 +"\r\n");
272 } finally {
273 toConnectAtStart = false;
275 } else {
276 System.out.print(LOGO);
277 cmds = MyFTP.GetCommands();
279 if (cmds == null)
280 continue;
281 FOR:
282 for (int j = 0; j < cmds.length; j++) {
283 if (EnableDebug)
284 if (cmds[j].startsWith("PASS"))
285 System.out.println("--->PASS ******");
286 else
287 System.out.println("--->"+cmds[j]);
288 int restore = MyFTP.GetStatus();
289 try{
290 MyFTP.SendCommand(cmds[j]);
291 } catch (IOException e) {
292 throw new XylFTPException("xylftp", restore,
293 e.getMessage());
295 if (cmds[j].startsWith("RETR")
296 || cmds[j].startsWith("LIST")
297 || cmds[j].startsWith("NLST")){
298 MyFTP.SetStatus(3);
299 try {
300 if (MyFTP.IsPassive())
301 MyFTP.OpenDataConnection(HostIP,
302 HostPort);
303 else
304 MyFTP.OpenDataConnection();
305 } catch (Exception e) {
306 if (MyFTP.HasEcho()){
307 String ec = MyFTP.GetEcho();
308 if (EnableDebug)
309 System.out.println("<---"+ec);
310 MyFTP.ProcessEcho(ec);
312 throw new XylFTPException("xylftp", 2,
313 e.getMessage());
316 if (cmds[j].startsWith("STOR")){
317 MyFTP.SetStatus(4);
318 try {
319 if (MyFTP.IsPassive())
320 MyFTP.OpenDataConnection(HostIP, HostPort);
321 else
322 MyFTP.OpenDataConnection();
323 } catch (Exception e) {
324 throw new XylFTPException("", 2, e.getMessage());
327 if (cmds[j].startsWith("PORT")){
328 MyFTP.ReadyForActive();
331 boolean toGetEchoAgain;
332 do {
333 toGetEchoAgain = false;
334 try {
335 echo = MyFTP.GetEcho();
336 if (echo==null)
337 throw new XylFTPException("xylftp",
338 0, "Can't get an echo.");
339 } catch (IOException e) {
340 throw new XylFTPException("xylftp", 0,
341 e.getMessage());
343 if (!MyFTP.IsValidEcho(echo))
344 throw new XylFTPException("xylftp", 0,
345 "Invaild echo.");
346 if (EnableDebug)
347 System.out.println("<---"+echo);
348 echoMeaning = MyFTP.ProcessEcho(echo);
349 while (echoMeaning == 6) {
350 echo = MyFTP.GetEcho();
351 if (echo==null)
352 throw new XylFTPException("xylftp",
353 0, "Can't get an echo.");
354 if (EnableDebug)
355 System.out.println("<---"+echo);
356 echoMeaning = MyFTP.ProcessEcho(echo);
358 switch (echoMeaning) {
359 case -1:
360 throw new XylFTPException("panic", 0,
361 "Unknown mistake!");
362 case 0:
363 throw new XylFTPException("xylftp", 0,
364 "Invalid format!");
365 case 1: // Need data connection
366 if (cmds[j].startsWith("RETR")
367 || cmds[j].startsWith("LIST")
368 || cmds[j].startsWith("NLST")){
369 try {
370 if (MyFTP.IsPassive())
371 MyFTP.GetFilePassive();
372 else
373 MyFTP.GetFileActive();
374 MyFTP.CloseDataConnection();
375 } catch (Exception e) {
376 throw new XylFTPException("", e.getMessage());
377 } finally {
378 MyFTP.SetStatus(2);
380 toGetEchoAgain = true;
382 if (cmds[j].startsWith("STOR")){
383 try {
384 if (MyFTP.IsPassive())
385 MyFTP.SendFilePassive();
386 else
387 MyFTP.SendFileActive();
388 MyFTP.CloseDataConnection();
389 } finally {
390 MyFTP.SetStatus(2);
392 toGetEchoAgain = true;
394 break;
395 case 2:
396 if (cmds[j].startsWith("PASS")){
397 MyFTP.SetStatus(2);
398 if (EnableDebug)
399 System.out.println(
400 "--->TYPE I");
401 MyFTP.SendCommand("TYPE I");
402 String s = MyFTP.GetEcho();
403 if (s!=null &&
404 MyFTP.IsValidEcho(s) &&
405 s.substring(0,3).equals("200")){
406 if (EnableDebug)
407 System.out.println(
408 "<---"+s);
409 MyFTP.ProcessEcho(s);
410 MyFTP.SetTransferMode(0);
413 if (cmds[j].startsWith("QUIT")){
414 MyFTP.SetStatus(0);
415 MyFTP.CloseConnection();
416 if (j+1 < cmds.length &&
417 cmds[j+1].startsWith("QUIT"))
418 System.exit(0);
420 if (cmds[j].startsWith("NLST") //For 450
421 || cmds[j].startsWith("LIST")){
422 MyFTP.SetStatus(2);
424 break FOR;
425 case 3:
426 if (cmds[j].startsWith("TYPE")){
427 String []cmd = cmds[j].split("[\t ]+");
428 if(cmd[1].equals("A"))
429 MyFTP.SetTransferMode(1);
430 if(cmd[1].equals("I"))
431 MyFTP.SetTransferMode(0);
432 break FOR;
434 if (cmds[j].startsWith("PASV")){
435 MyFTP.SetPassive();
436 HostIP = ParseIP(echo);
437 HostPort = ParsePort(echo);
438 if (EnableVerbose)
439 System.out.println("Connect to "+HostIP+": "+HostPort);
441 if (cmds[j].startsWith("PORT")){
442 MyFTP.SetActive();
444 break;
445 case 4:
446 j=0;
447 break;
448 case 5:
449 if (cmds[j].startsWith("RETR")
450 || cmds[j].startsWith("STOR")) {
451 MyFTP.SetStatus(2);
453 break FOR;
454 } // switch
455 } while (toGetEchoAgain); // do
456 } // for
457 } catch (XylFTPException e) {
458 System.out.println(e.GetMessage());
459 if (e.GetStatus()!=-1) {
460 if (MyFTP.GetStatus()!=0 && e.GetStatus()==0)
461 try {
462 System.out.println("Connection closed!");
463 MyFTP.CloseConnection();
464 } catch (Exception ee) {
465 System.out.println(ee.getMessage());
467 MyFTP.SetStatus(e.GetStatus());
469 } catch (Exception e) {
470 System.out.println(e.getMessage());
473 } // while(true)