Support incomplete input
[xylftp.git] / client / src / XylFTPConnection.java
blobb26a1a2d44d938a46429ee8ae30a398d2fc34763
1 //////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Zhou Xiao-wei, Apr. 2007.
3 // Copyright (C) Wang Cong, Apr. 2007.
4 // See AUTHORS and CREDITS to learn more.
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License version 2 as
7 // published by the Free Software Foundation.
8 // See COPYING to learn more.
9 //////////////////////////////////////////////////////////////////////////
11 import java.net.*;
12 import java.io.*;
14 /**
15 * This class is for FTP connection.
16 * Extends XylTelnetConnection.
17 * @author WANG Cong, Zhou Xiao-Wei
18 * @version 1.14
20 public class XylFTPConnection extends XylTelnetConnection{
22 /**
23 *The size of reader's buffer.
25 private final int RDBUF_SIZE = 1024;
27 /**
28 *The size of writer's buffer.
30 private final int WRBUF_SIZE = 1024;
32 /**
33 *The status of FTP connection.
35 private int Status;
36 // 0 for not connected
37 // 1 for connected but not login
38 // 2 for login and no data transfer
39 // 3 for login and getting data down
40 // 4 for login and putting data up
42 /**
43 *Presents the mode (active or passive) of FTP connection.
45 private int Mode;
46 //1 for passive, 0 for active, defaults to 1. ;)
48 /**
49 *Gets the line separator used by local system.
51 private byte[] LineSeparator = System.getProperty("line.separator").getBytes();
53 /**
54 *Presents the mode (ascii or binary) of transfer files.
56 private int TransferMode;
57 //1 for ascii, 0 for binary, defaults to 0. ;)
59 /**
60 *Constructs a LocalFile for data storage.
62 private String LocalFile;
63 // Empty string for this means stdout. ;)
65 /**
66 *The data connection socket.
68 private Socket DataSocket;
70 /**
71 *The sever data socket, used by active mode.
73 private ServerSocket DataServerSocket;
75 /**
76 *The input stream.
78 private BufferedInputStream FTPInStream;
80 /**
81 *The output stream.
83 private BufferedOutputStream FTPOutStream;
85 /**
86 *Initializes some values.
88 XylFTPConnection(){
89 super();
90 Status = 0;
91 Mode = 1;
92 TransferMode = 0;
93 LocalFile = null;
94 DataSocket = null;
95 DataServerSocket = null;
98 /**
99 *Gets status of current FTP connection.
100 *@return the status of connection
102 public int GetStatus(){
103 return Status;
107 *Sets status of the connection.
108 *@param NewStatus
110 public void SetStatus(int NewStatus){
111 Status = NewStatus;
115 *Get Mode of tranfer files.
116 *@return the mode of transfer files
118 public int GetTransferMode(){
119 return TransferMode;
123 *Sets TransferMode of transfer files.
124 *@param NewTransferMode New Transfer Mode
126 public void SetTransferMode(int NewTransferMode){
127 TransferMode = NewTransferMode;
131 *Sets the LocalFile name.
132 *@param FileName
134 public void SetLocalFile(String FileName){
135 LocalFile = FileName;
139 *Tests whether the mode is passive
141 public boolean IsPassive(){
142 if (Mode==1)
143 return true;
144 else
145 return false;
148 *Sets the passive mode.
150 public void SetPassive(){
151 Mode = 1;
155 *Sets the active mode.
157 public void SetActive(){
158 Mode = 0;
162 *Prepares for active data connection.
164 public void ReadyForActive() throws Exception{
165 try {
166 if(-1 == ReturnSelfPort())
167 throw new XylFTPException("Port is unavailable.");
168 DataServerSocket = new ServerSocket(ReturnSelfPort());
169 DataServerSocket.setSoTimeout(Timeout/2);//Hmm, short is better.
170 } catch(Exception e) {
171 SetStatus(2);
172 throw e;
176 *Opens the data connection in active mode.
177 *@see Exception
178 *@throws Exception on opening dataconnection error
180 public void OpenDataConnection() throws Exception{
181 try {
182 DataSocket = DataServerSocket.accept();
183 } catch(Exception e) {
184 SetStatus(2);
185 throw e;
190 *Opens the data connection in passive mode.
191 *@param Port the port of server
192 *@param Host the IP of server
193 *@see Exception
194 *@throws Exception on opening DataConnection error
196 public void OpenDataConnection(String Host, int Port) throws Exception{
197 try {
198 DataSocket = new Socket(Host, Port);
199 DataSocket.setSoTimeout(Timeout);
200 } catch (Exception e) {
201 SetStatus(2);
202 throw e;
207 *Closes the data connection.
208 *@see XylFTPException
209 *@throws XylFTPException on closing DataConnection error
211 public void CloseDataConnection() throws Exception{
212 DataSocket.close();
213 if(DataServerSocket != null) {
214 DataServerSocket.close();
219 *Uploads a file in active mode.
220 *@throws XylFTPException on sending file error
221 *@see XylFTPException
223 public void SendFileActive() throws Exception{
224 int bytesRead;
225 byte [] buf = new byte[WRBUF_SIZE];
226 if (Mode!=0) {
227 SetStatus(2);
228 throw new XylFTPException("You are not in active mode!");
230 if (LocalFile.equals("")) {
231 SetStatus(2);
232 throw new XylFTPException("Can't send unnamed file!");
233 } else {
234 FTPInStream = new BufferedInputStream(new FileInputStream(LocalFile));
236 FTPOutStream = new BufferedOutputStream(DataSocket.getOutputStream());
238 if (TransferMode==1) {
239 int separatorPos = 0;
240 while ((bytesRead = FTPInStream.read(buf, 0, WRBUF_SIZE)) > 0) {
241 for (int i = 0; i< bytesRead; i++) {
242 boolean found = true;
243 int skip = 0;
244 for (; separatorPos < LineSeparator.length
245 && i+separatorPos < bytesRead;
246 skip++, separatorPos++) {
247 if (buf[i+separatorPos] != LineSeparator[separatorPos]) {
248 found = false;
249 break;
250 }//if
251 }//for
252 if (found) { // either found match or run out of buffer
253 if (separatorPos == LineSeparator.length) {
254 // found line separator
255 FTPOutStream.write('\r');
256 FTPOutStream.write('\n');
257 separatorPos = 0;
258 //skip over bytes that match
259 i += (skip-1);
260 } else {
261 // reached end of buffer && matching so far
262 // Do nothing. ;)
263 }//else
264 } else{
265 FTPOutStream.write(buf[i]);
267 }//for
268 }//while
269 } else if (TransferMode==0) {
270 while ((bytesRead = FTPInStream.read(buf, 0, WRBUF_SIZE)) > 0) {
271 FTPOutStream.write(buf, 0, bytesRead);
273 } else {
274 throw new XylFTPException("panic", 0, "No such mode!");
276 FTPOutStream.flush();
277 FTPOutStream.close();
278 FTPInStream.close();
281 *Uploads a file in passive mode.
282 *@throws XylFTPException on sending file error
283 *@see XylFTPException
285 public void SendFilePassive() throws Exception{
286 int bytesRead;
287 byte [] buf = new byte[WRBUF_SIZE];
288 if (Mode!=1) {
289 SetStatus(2);
290 throw new XylFTPException("You are not in passive mode!");
292 if (LocalFile.equals("")) {
293 SetStatus(2);
294 throw new XylFTPException("Can't send unnamed file!");
295 } else {
296 FTPInStream = new BufferedInputStream(new FileInputStream(LocalFile));
298 FTPOutStream = new BufferedOutputStream(DataSocket.getOutputStream());
299 if (TransferMode==1) {
300 int separatorPos = 0;
301 while ((bytesRead = FTPInStream.read(buf, 0, WRBUF_SIZE)) > 0) {
302 for (int i = 0; i< bytesRead; i++) {
303 boolean found = true;
304 int skip = 0;
305 for (; separatorPos < LineSeparator.length
306 && i+separatorPos < bytesRead;
307 skip++, separatorPos++) {
308 if (buf[i+separatorPos] != LineSeparator[separatorPos]) {
309 found = false;
310 break;
311 }//if
312 }//for
313 if (found) { // either found match or run out of buffer
314 if (separatorPos == LineSeparator.length) {
315 // found line separator
316 FTPOutStream.write('\r');
317 FTPOutStream.write('\n');
318 separatorPos = 0;
319 //skip over bytes that match
320 i += (skip-1);
321 } else {
322 // reached end of buffer && matching so far
323 // Do nothing. ;)
324 }//else
325 } else{
326 FTPOutStream.write(buf[i]);
328 }//for
329 }//while
330 } else if (TransferMode==0) {
331 while ((bytesRead = FTPInStream.read(buf, 0, WRBUF_SIZE)) > 0) {
332 FTPOutStream.write(buf, 0, bytesRead);
334 } else {
335 throw new XylFTPException("panic", 0, "No such mode!");
337 FTPOutStream.flush();
338 FTPOutStream.close();
339 FTPInStream.close();
343 *Downloads a file in active mode.
344 *@throws XylFTPException on getting file error
345 *@see XylFTPException
347 public void GetFileActive() throws Exception{
348 int bytesRead;
349 byte [] buf = new byte[RDBUF_SIZE];
350 if (Mode!=0) {
351 SetStatus(2);
352 throw new XylFTPException("You are not in active mode!");
354 if (LocalFile.equals("")) {
355 FTPOutStream = new BufferedOutputStream((OutputStream)System.out);
356 } else {
357 FTPOutStream = new BufferedOutputStream(new FileOutputStream(LocalFile));
359 FTPInStream = new BufferedInputStream(DataSocket.getInputStream());
361 if (TransferMode==1) {
362 boolean crFound = false;
363 while ((bytesRead = FTPInStream.read(buf, 0, RDBUF_SIZE)) > 0) {
364 boolean lfFound = false;
365 for (int i = 0; i < bytesRead; i++) {
366 lfFound = buf[i] == '\n';
367 if (crFound) {
368 if (lfFound) {
369 FTPOutStream.write(LineSeparator, 0,
370 LineSeparator.length);
371 } else {
372 FTPOutStream.write('\r');
375 crFound = buf[i] == '\r';
376 if (!lfFound && !crFound) {
377 FTPOutStream.write(buf[i]);
378 }//if
379 }//for
380 }//while
381 } else if (TransferMode==0) {
382 while ((bytesRead = FTPInStream.read(buf, 0, RDBUF_SIZE)) > 0) {
383 FTPOutStream.write(buf, 0, bytesRead);
385 } else {
386 throw new XylFTPException("panic", 0, "No such mode!");
388 FTPOutStream.flush();
389 if (!LocalFile.equals("")) //We can NOT close the stdout.
390 FTPOutStream.close();
391 FTPInStream.close();
395 *Downloads a file in passive mode.
396 *@throws XylFTPException on getting file error
397 *@see XylFTPException
399 public void GetFilePassive() throws Exception{
400 int bytesRead;
401 byte [] buf = new byte[RDBUF_SIZE];
402 if (Mode!=1) {
403 SetStatus(2);
404 throw new XylFTPException("You are not in passive mode!");
406 if (LocalFile.equals("")) {
407 FTPOutStream = new BufferedOutputStream((OutputStream)System.out);
408 } else {
409 FTPOutStream = new BufferedOutputStream(new FileOutputStream(LocalFile));
411 FTPInStream = new BufferedInputStream(DataSocket.getInputStream());
412 if (TransferMode==1) {
413 boolean crFound = false;
414 while ((bytesRead = FTPInStream.read(buf, 0, RDBUF_SIZE)) > 0) {
415 boolean lfFound = false;
416 for (int i = 0; i < bytesRead; i++) {
417 lfFound = buf[i] == '\n';
418 if (crFound) {
419 if (lfFound) {
420 FTPOutStream.write(LineSeparator, 0,
421 LineSeparator.length);
422 } else {
423 FTPOutStream.write('\r');
426 crFound = buf[i] == '\r';
427 if (!lfFound && !crFound) {
428 FTPOutStream.write(buf[i]);
429 }//if
430 }//for
431 }//while
432 } else if (TransferMode==0) {
433 while ((bytesRead = FTPInStream.read(buf, 0, RDBUF_SIZE)) > 0) {
434 FTPOutStream.write(buf, 0, bytesRead);
436 } else {
437 throw new XylFTPException("panic", 0, "No such mode!");
439 FTPOutStream.flush();
440 if (!LocalFile.equals("")) //We can NOT close the stdout.
441 FTPOutStream.close();
442 FTPInStream.close();