1 |
/* |
/* |
2 |
* $Id$ |
* FTPConnection.java |
3 |
* Copyright (C) 2003 The Free Software Foundation |
* Copyright (C) 2003 The Free Software Foundation |
4 |
* |
* |
5 |
* This file is part of GNU inetlib, a library. |
* This file is part of GNU inetlib, a library. |
73 |
* </ul> |
* </ul> |
74 |
* |
* |
75 |
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> |
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a> |
|
* @version $Revision$ $Date$ |
|
76 |
*/ |
*/ |
77 |
public class FTPConnection |
public class FTPConnection |
78 |
{ |
{ |
204 |
* Creates a new connection to the server using the default port. |
* Creates a new connection to the server using the default port. |
205 |
* @param hostname the hostname of the server to connect to |
* @param hostname the hostname of the server to connect to |
206 |
*/ |
*/ |
207 |
public FTPConnection (String hostname) |
public FTPConnection(String hostname) |
208 |
throws UnknownHostException, IOException |
throws UnknownHostException, IOException |
209 |
{ |
{ |
210 |
this (hostname, -1, 0, 0, false); |
this(hostname, -1, 0, 0, false); |
211 |
} |
} |
212 |
|
|
213 |
/** |
/** |
214 |
* Creates a new connection to the server. |
* Creates a new connection to the server. |
215 |
* @param hostname the hostname of the server to connect to |
* @param hostname the hostname of the server to connect to |
216 |
* @param port the port to connect to (if <=0, use default port) |
* @param port the port to connect to(if <=0, use default port) |
217 |
*/ |
*/ |
218 |
public FTPConnection (String hostname, int port) |
public FTPConnection(String hostname, int port) |
219 |
throws UnknownHostException, IOException |
throws UnknownHostException, IOException |
220 |
{ |
{ |
221 |
this (hostname, port, 0, 0, false); |
this(hostname, port, 0, 0, false); |
222 |
} |
} |
223 |
|
|
224 |
/** |
/** |
225 |
* Creates a new connection to the server. |
* Creates a new connection to the server. |
226 |
* @param hostname the hostname of the server to connect to |
* @param hostname the hostname of the server to connect to |
227 |
* @param port the port to connect to (if <=0, use default port) |
* @param port the port to connect to(if <=0, use default port) |
228 |
* @param connectionTimeout the connection timeout, in milliseconds |
* @param connectionTimeout the connection timeout, in milliseconds |
229 |
* @param timeout the I/O timeout, in milliseconds |
* @param timeout the I/O timeout, in milliseconds |
230 |
* @param debug print debugging information |
* @param debug print debugging information |
231 |
*/ |
*/ |
232 |
public FTPConnection (String hostname, int port, |
public FTPConnection(String hostname, int port, |
233 |
int connectionTimeout, int timeout, boolean debug) |
int connectionTimeout, int timeout, boolean debug) |
234 |
throws UnknownHostException, IOException |
throws UnknownHostException, IOException |
235 |
{ |
{ |
242 |
} |
} |
243 |
|
|
244 |
// Set up socket |
// Set up socket |
245 |
socket = new Socket (); |
socket = new Socket(); |
246 |
InetSocketAddress address = new InetSocketAddress (hostname, port); |
InetSocketAddress address = new InetSocketAddress(hostname, port); |
247 |
if (connectionTimeout > 0) |
if (connectionTimeout > 0) |
248 |
{ |
{ |
249 |
socket.connect (address, connectionTimeout); |
socket.connect(address, connectionTimeout); |
250 |
} |
} |
251 |
else |
else |
252 |
{ |
{ |
253 |
socket.connect (address); |
socket.connect(address); |
254 |
} |
} |
255 |
if (timeout > 0) |
if (timeout > 0) |
256 |
{ |
{ |
257 |
socket.setSoTimeout (timeout); |
socket.setSoTimeout(timeout); |
258 |
} |
} |
259 |
|
|
260 |
InputStream in = socket.getInputStream (); |
InputStream in = socket.getInputStream(); |
261 |
in = new BufferedInputStream (in); |
in = new BufferedInputStream(in); |
262 |
in = new CRLFInputStream (in); |
in = new CRLFInputStream(in); |
263 |
this.in = new LineInputStream (in); |
this.in = new LineInputStream(in); |
264 |
OutputStream out = socket.getOutputStream (); |
OutputStream out = socket.getOutputStream(); |
265 |
out = new BufferedOutputStream (out); |
out = new BufferedOutputStream(out); |
266 |
this.out = new CRLFOutputStream (out); |
this.out = new CRLFOutputStream(out); |
267 |
|
|
268 |
// Read greeting |
// Read greeting |
269 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
270 |
switch (response.getCode ()) |
switch (response.getCode()) |
271 |
{ |
{ |
272 |
case 220: // hello |
case 220: // hello |
273 |
break; |
break; |
274 |
default: |
default: |
275 |
throw new FTPException (response); |
throw new FTPException(response); |
276 |
} |
} |
277 |
} |
} |
278 |
|
|
284 |
* @param password the optional password |
* @param password the optional password |
285 |
* @return true on success, false otherwise |
* @return true on success, false otherwise |
286 |
*/ |
*/ |
287 |
public boolean authenticate (String username, String password) |
public boolean authenticate(String username, String password) |
288 |
throws IOException |
throws IOException |
289 |
{ |
{ |
290 |
String cmd = USER + ' ' + username; |
String cmd = USER + ' ' + username; |
291 |
send (cmd); |
send(cmd); |
292 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
293 |
switch (response.getCode ()) |
switch (response.getCode()) |
294 |
{ |
{ |
295 |
case 230: // User logged in |
case 230: // User logged in |
296 |
return true; |
return true; |
300 |
case 530: // No such user |
case 530: // No such user |
301 |
return false; |
return false; |
302 |
default: |
default: |
303 |
throw new FTPException (response); |
throw new FTPException(response); |
304 |
} |
} |
305 |
cmd = PASS + ' ' + password; |
cmd = PASS + ' ' + password; |
306 |
send (cmd); |
send(cmd); |
307 |
response = getResponse (); |
response = getResponse(); |
308 |
switch (response.getCode ()) |
switch (response.getCode()) |
309 |
{ |
{ |
310 |
case 230: // User logged in |
case 230: // User logged in |
311 |
case 202: // Superfluous |
case 202: // Superfluous |
314 |
case 530: // Bad password |
case 530: // Bad password |
315 |
return false; |
return false; |
316 |
default: |
default: |
317 |
throw new FTPException (response); |
throw new FTPException(response); |
318 |
} |
} |
319 |
} |
} |
320 |
|
|
324 |
* @param confidential whether to provide confidentiality for the |
* @param confidential whether to provide confidentiality for the |
325 |
* connection |
* connection |
326 |
*/ |
*/ |
327 |
public boolean starttls (boolean confidential) |
public boolean starttls(boolean confidential) |
328 |
throws IOException |
throws IOException |
329 |
{ |
{ |
330 |
return starttls (confidential, new EmptyX509TrustManager ()); |
return starttls(confidential, new EmptyX509TrustManager()); |
331 |
} |
} |
332 |
|
|
333 |
/** |
/** |
337 |
* connection |
* connection |
338 |
* @param tm the trust manager used to validate the server certificate. |
* @param tm the trust manager used to validate the server certificate. |
339 |
*/ |
*/ |
340 |
public boolean starttls (boolean confidential, TrustManager tm) |
public boolean starttls(boolean confidential, TrustManager tm) |
341 |
throws IOException |
throws IOException |
342 |
{ |
{ |
343 |
try |
try |
344 |
{ |
{ |
345 |
// Use SSLSocketFactory to negotiate a TLS session and wrap the |
// Use SSLSocketFactory to negotiate a TLS session and wrap the |
346 |
// current socket. |
// current socket. |
347 |
SSLContext context = SSLContext.getInstance ("TLS"); |
SSLContext context = SSLContext.getInstance("TLS"); |
348 |
// We don't require strong validation of the server certificate |
// We don't require strong validation of the server certificate |
349 |
TrustManager[] trust = new TrustManager[] { tm }; |
TrustManager[] trust = new TrustManager[] { tm }; |
350 |
context.init (null, trust, null); |
context.init(null, trust, null); |
351 |
SSLSocketFactory factory = context.getSocketFactory (); |
SSLSocketFactory factory = context.getSocketFactory(); |
352 |
|
|
353 |
send (AUTH + ' ' + TLS); |
send(AUTH + ' ' + TLS); |
354 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
355 |
switch (response.getCode ()) |
switch (response.getCode()) |
356 |
{ |
{ |
357 |
case 500: |
case 500: |
358 |
case 502: |
case 502: |
363 |
case 234: |
case 234: |
364 |
break; |
break; |
365 |
default: |
default: |
366 |
throw new FTPException (response); |
throw new FTPException(response); |
367 |
} |
} |
368 |
|
|
369 |
String hostname = socket.getInetAddress ().getHostName (); |
String hostname = socket.getInetAddress().getHostName(); |
370 |
int port = socket.getPort (); |
int port = socket.getPort(); |
371 |
SSLSocket ss = |
SSLSocket ss = |
372 |
(SSLSocket) factory.createSocket (socket, hostname, port, true); |
(SSLSocket) factory.createSocket(socket, hostname, port, true); |
373 |
String[] protocols = { "TLSv1", "SSLv3" }; |
String[] protocols = { "TLSv1", "SSLv3" }; |
374 |
ss.setEnabledProtocols (protocols); |
ss.setEnabledProtocols(protocols); |
375 |
ss.setUseClientMode (true); |
ss.setUseClientMode(true); |
376 |
ss.startHandshake (); |
ss.startHandshake(); |
377 |
|
|
378 |
// PBSZ:PROT sequence |
// PBSZ:PROT sequence |
379 |
send (PBSZ + ' ' + Integer.MAX_VALUE); |
send(PBSZ + ' ' + Integer.MAX_VALUE); |
380 |
response = getResponse (); |
response = getResponse(); |
381 |
switch (response.getCode ()) |
switch (response.getCode()) |
382 |
{ |
{ |
383 |
case 501: // syntax error |
case 501: // syntax error |
384 |
case 503: // not authenticated |
case 503: // not authenticated |
386 |
case 200: |
case 200: |
387 |
break; |
break; |
388 |
default: |
default: |
389 |
throw new FTPException (response); |
throw new FTPException(response); |
390 |
} |
} |
391 |
send (PROT + ' ' + (confidential ? 'P' : 'C')); |
send(PROT + ' ' +(confidential ? 'P' : 'C')); |
392 |
response = getResponse (); |
response = getResponse(); |
393 |
switch (response.getCode ()) |
switch (response.getCode()) |
394 |
{ |
{ |
395 |
case 503: // not authenticated |
case 503: // not authenticated |
396 |
case 504: // invalid level |
case 504: // invalid level |
399 |
case 200: |
case 200: |
400 |
break; |
break; |
401 |
default: |
default: |
402 |
throw new FTPException (response); |
throw new FTPException(response); |
403 |
} |
} |
404 |
|
|
405 |
if (confidential) |
if (confidential) |
406 |
{ |
{ |
407 |
// Set up streams |
// Set up streams |
408 |
InputStream in = ss.getInputStream (); |
InputStream in = ss.getInputStream(); |
409 |
in = new BufferedInputStream (in); |
in = new BufferedInputStream(in); |
410 |
in = new CRLFInputStream (in); |
in = new CRLFInputStream(in); |
411 |
this.in = new LineInputStream (in); |
this.in = new LineInputStream(in); |
412 |
OutputStream out = ss.getOutputStream (); |
OutputStream out = ss.getOutputStream(); |
413 |
out = new BufferedOutputStream (out); |
out = new BufferedOutputStream(out); |
414 |
this.out = new CRLFOutputStream (out); |
this.out = new CRLFOutputStream(out); |
415 |
} |
} |
416 |
return true; |
return true; |
417 |
} |
} |
426 |
* @param path an absolute or relative pathname |
* @param path an absolute or relative pathname |
427 |
* @return true on success, false if the specified path does not exist |
* @return true on success, false if the specified path does not exist |
428 |
*/ |
*/ |
429 |
public boolean changeWorkingDirectory (String path) |
public boolean changeWorkingDirectory(String path) |
430 |
throws IOException |
throws IOException |
431 |
{ |
{ |
432 |
String cmd = CWD + ' ' + path; |
String cmd = CWD + ' ' + path; |
433 |
send (cmd); |
send(cmd); |
434 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
435 |
switch (response.getCode ()) |
switch (response.getCode()) |
436 |
{ |
{ |
437 |
case 250: |
case 250: |
438 |
return true; |
return true; |
439 |
case 550: |
case 550: |
440 |
return false; |
return false; |
441 |
default: |
default: |
442 |
throw new FTPException (response); |
throw new FTPException(response); |
443 |
} |
} |
444 |
} |
} |
445 |
|
|
447 |
* Changes directory to the parent of the current working directory. |
* Changes directory to the parent of the current working directory. |
448 |
* @return true on success, false otherwise |
* @return true on success, false otherwise |
449 |
*/ |
*/ |
450 |
public boolean changeToParentDirectory () |
public boolean changeToParentDirectory() |
451 |
throws IOException |
throws IOException |
452 |
{ |
{ |
453 |
send (CDUP); |
send(CDUP); |
454 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
455 |
switch (response.getCode ()) |
switch (response.getCode()) |
456 |
{ |
{ |
457 |
case 250: |
case 250: |
458 |
return true; |
return true; |
459 |
case 550: |
case 550: |
460 |
return false; |
return false; |
461 |
default: |
default: |
462 |
throw new FTPException (response); |
throw new FTPException(response); |
463 |
} |
} |
464 |
} |
} |
465 |
|
|
468 |
* If file transfer is in progress, it remains active for result response |
* If file transfer is in progress, it remains active for result response |
469 |
* only. |
* only. |
470 |
*/ |
*/ |
471 |
public void reinitialize () |
public void reinitialize() |
472 |
throws IOException |
throws IOException |
473 |
{ |
{ |
474 |
send (REIN); |
send(REIN); |
475 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
476 |
switch (response.getCode ()) |
switch (response.getCode()) |
477 |
{ |
{ |
478 |
case 220: |
case 220: |
479 |
if (dtp != null) |
if (dtp != null) |
480 |
{ |
{ |
481 |
dtp.complete (); |
dtp.complete(); |
482 |
dtp = null; |
dtp = null; |
483 |
} |
} |
484 |
break; |
break; |
485 |
default: |
default: |
486 |
throw new FTPException (response); |
throw new FTPException(response); |
487 |
} |
} |
488 |
} |
} |
489 |
|
|
492 |
* The file transfer connection remains open for result response only. |
* The file transfer connection remains open for result response only. |
493 |
* This connection is invalid and no further commands may be issued. |
* This connection is invalid and no further commands may be issued. |
494 |
*/ |
*/ |
495 |
public void logout () |
public void logout() |
496 |
throws IOException |
throws IOException |
497 |
{ |
{ |
498 |
send (QUIT); |
send(QUIT); |
499 |
try |
try |
500 |
{ |
{ |
501 |
getResponse (); // not required |
getResponse(); // not required |
502 |
} |
} |
503 |
catch (IOException e) |
catch (IOException e) |
504 |
{ |
{ |
505 |
} |
} |
506 |
if (dtp != null) |
if (dtp != null) |
507 |
{ |
{ |
508 |
dtp.complete (); |
dtp.complete(); |
509 |
dtp = null; |
dtp = null; |
510 |
} |
} |
511 |
try |
try |
512 |
{ |
{ |
513 |
socket.close (); |
socket.close(); |
514 |
} |
} |
515 |
catch (IOException e) |
catch (IOException e) |
516 |
{ |
{ |
520 |
/** |
/** |
521 |
* Initialise the data transfer process. |
* Initialise the data transfer process. |
522 |
*/ |
*/ |
523 |
protected void initialiseDTP () |
protected void initialiseDTP() |
524 |
throws IOException |
throws IOException |
525 |
{ |
{ |
526 |
if (dtp != null) |
if (dtp != null) |
527 |
{ |
{ |
528 |
dtp.complete (); |
dtp.complete(); |
529 |
dtp = null; |
dtp = null; |
530 |
} |
} |
531 |
|
|
532 |
InetAddress localhost = socket.getLocalAddress (); |
InetAddress localhost = socket.getLocalAddress(); |
533 |
if (passive) |
if (passive) |
534 |
{ |
{ |
535 |
send (PASV); |
send(PASV); |
536 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
537 |
switch (response.getCode ()) |
switch (response.getCode()) |
538 |
{ |
{ |
539 |
case 227: |
case 227: |
540 |
String message = response.getMessage (); |
String message = response.getMessage(); |
541 |
try |
try |
542 |
{ |
{ |
543 |
int start = message.indexOf (','); |
int start = message.indexOf(','); |
544 |
char c = message.charAt (start - 1); |
char c = message.charAt(start - 1); |
545 |
while (c >= 0x30 && c <= 0x39) |
while (c >= 0x30 && c <= 0x39) |
546 |
{ |
{ |
547 |
c = message.charAt ((--start) - 1); |
c = message.charAt((--start) - 1); |
548 |
} |
} |
549 |
int mid1 = start; |
int mid1 = start; |
550 |
for (int i = 0; i < 4; i++) |
for (int i = 0; i < 4; i++) |
551 |
{ |
{ |
552 |
mid1 = message.indexOf (',', mid1 + 1); |
mid1 = message.indexOf(',', mid1 + 1); |
553 |
} |
} |
554 |
int mid2 = message.indexOf (',', mid1 + 1); |
int mid2 = message.indexOf(',', mid1 + 1); |
555 |
if (mid1 == -1 || mid2 < mid1) |
if (mid1 == -1 || mid2 < mid1) |
556 |
{ |
{ |
557 |
throw new ProtocolException ("Malformed 227: " + |
throw new ProtocolException("Malformed 227: " + |
558 |
message); |
message); |
559 |
} |
} |
560 |
int end = mid2; |
int end = mid2; |
561 |
c = message.charAt (end + 1); |
c = message.charAt(end + 1); |
562 |
while (c >= 0x30 && c <= 0x39) |
while (c >= 0x30 && c <= 0x39) |
563 |
{ |
{ |
564 |
c = message.charAt((++end) + 1); |
c = message.charAt((++end) + 1); |
565 |
} |
} |
566 |
|
|
567 |
String address = |
String address = |
568 |
message.substring (start, mid1).replace (',', '.'); |
message.substring(start, mid1).replace(',', '.'); |
569 |
int port_hi = |
int port_hi = |
570 |
Integer.parseInt (message.substring (mid1 + 1, mid2)); |
Integer.parseInt(message.substring(mid1 + 1, mid2)); |
571 |
int port_lo = |
int port_lo = |
572 |
Integer.parseInt (message.substring (mid2 + 1, end + 1)); |
Integer.parseInt(message.substring(mid2 + 1, end + 1)); |
573 |
int port = (port_hi << 8) | port_lo; |
int port = (port_hi << 8) | port_lo; |
574 |
|
|
575 |
/*System.out.println ("Entering passive mode: " + address + |
/*System.out.println("Entering passive mode: " + address + |
576 |
":" + port);*/ |
":" + port);*/ |
577 |
dtp = new PassiveModeDTP (address, port, localhost, |
dtp = new PassiveModeDTP(address, port, localhost, |
578 |
connectionTimeout, timeout); |
connectionTimeout, timeout); |
579 |
break; |
break; |
580 |
} |
} |
581 |
catch (ArrayIndexOutOfBoundsException e) |
catch (ArrayIndexOutOfBoundsException e) |
582 |
{ |
{ |
583 |
throw new ProtocolException (e.getMessage () + ": " + |
throw new ProtocolException(e.getMessage() + ": " + |
584 |
message); |
message); |
585 |
} |
} |
586 |
catch (NumberFormatException e) |
catch (NumberFormatException e) |
587 |
{ |
{ |
588 |
throw new ProtocolException (e.getMessage () + ": " + |
throw new ProtocolException(e.getMessage() + ": " + |
589 |
message); |
message); |
590 |
} |
} |
591 |
default: |
default: |
592 |
throw new FTPException (response); |
throw new FTPException(response); |
593 |
} |
} |
594 |
} |
} |
595 |
else |
else |
596 |
{ |
{ |
597 |
// Get the local port |
// Get the local port |
598 |
int port = socket.getLocalPort () + 1; |
int port = socket.getLocalPort() + 1; |
599 |
int tries = 0; |
int tries = 0; |
600 |
// Bind the active mode DTP |
// Bind the active mode DTP |
601 |
while (dtp == null) |
while (dtp == null) |
602 |
{ |
{ |
603 |
try |
try |
604 |
{ |
{ |
605 |
dtp = new ActiveModeDTP (localhost, port, |
dtp = new ActiveModeDTP(localhost, port, |
606 |
connectionTimeout, timeout); |
connectionTimeout, timeout); |
607 |
/*System.out.println ("Listening on: " + port);*/ |
/*System.out.println("Listening on: " + port);*/ |
608 |
} |
} |
609 |
catch (BindException e) |
catch (BindException e) |
610 |
{ |
{ |
618 |
} |
} |
619 |
|
|
620 |
// Send PORT command |
// Send PORT command |
621 |
StringBuffer buf = new StringBuffer (PORT); |
StringBuffer buf = new StringBuffer(PORT); |
622 |
buf.append (' '); |
buf.append(' '); |
623 |
// Construct the address/port string form |
// Construct the address/port string form |
624 |
byte[] address = localhost.getAddress (); |
byte[] address = localhost.getAddress(); |
625 |
for (int i = 0; i < address.length; i++) |
for (int i = 0; i < address.length; i++) |
626 |
{ |
{ |
627 |
int a = (int) address[i]; |
int a =(int) address[i]; |
628 |
if (a < 0) |
if (a < 0) |
629 |
{ |
{ |
630 |
a += 0x100; |
a += 0x100; |
631 |
} |
} |
632 |
buf.append (a); |
buf.append(a); |
633 |
buf.append (','); |
buf.append(','); |
634 |
} |
} |
635 |
int port_hi = (port & 0xff00) >> 8; |
int port_hi =(port & 0xff00) >> 8; |
636 |
int port_lo = (port & 0x00ff); |
int port_lo =(port & 0x00ff); |
637 |
buf.append (port_hi); |
buf.append(port_hi); |
638 |
buf.append (','); |
buf.append(','); |
639 |
buf.append (port_lo); |
buf.append(port_lo); |
640 |
send (buf.toString ()); |
send(buf.toString()); |
641 |
// Get response |
// Get response |
642 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
643 |
switch (response.getCode ()) |
switch (response.getCode()) |
644 |
{ |
{ |
645 |
case 200: // OK |
case 200: // OK |
646 |
break; |
break; |
647 |
default: |
default: |
648 |
dtp.abort (); |
dtp.abort(); |
649 |
dtp = null; |
dtp = null; |
650 |
throw new FTPException (response); |
throw new FTPException(response); |
651 |
} |
} |
652 |
} |
} |
653 |
dtp.setTransferMode (transferMode); |
dtp.setTransferMode(transferMode); |
654 |
} |
} |
655 |
|
|
656 |
/** |
/** |
657 |
* Set passive mode. |
* Set passive mode. |
658 |
* @param flag true if we should use passive mode, false otherwise |
* @param flag true if we should use passive mode, false otherwise |
659 |
*/ |
*/ |
660 |
public void setPassive (boolean flag) |
public void setPassive(boolean flag) |
661 |
throws IOException |
throws IOException |
662 |
{ |
{ |
663 |
if (passive != flag) |
if (passive != flag) |
664 |
{ |
{ |
665 |
passive = flag; |
passive = flag; |
666 |
initialiseDTP (); |
initialiseDTP(); |
667 |
} |
} |
668 |
} |
} |
669 |
|
|
671 |
* Returns the current representation type of the transfer data. |
* Returns the current representation type of the transfer data. |
672 |
* @return TYPE_ASCII, TYPE_EBCDIC, or TYPE_BINARY |
* @return TYPE_ASCII, TYPE_EBCDIC, or TYPE_BINARY |
673 |
*/ |
*/ |
674 |
public int getRepresentationType () |
public int getRepresentationType() |
675 |
{ |
{ |
676 |
return representationType; |
return representationType; |
677 |
} |
} |
680 |
* Sets the desired representation type of the transfer data. |
* Sets the desired representation type of the transfer data. |
681 |
* @param type TYPE_ASCII, TYPE_EBCDIC, or TYPE_BINARY |
* @param type TYPE_ASCII, TYPE_EBCDIC, or TYPE_BINARY |
682 |
*/ |
*/ |
683 |
public void setRepresentationType (int type) |
public void setRepresentationType(int type) |
684 |
throws IOException |
throws IOException |
685 |
{ |
{ |
686 |
StringBuffer buf = new StringBuffer (TYPE); |
StringBuffer buf = new StringBuffer(TYPE); |
687 |
buf.append(' '); |
buf.append(' '); |
688 |
switch (type) |
switch (type) |
689 |
{ |
{ |
690 |
case TYPE_ASCII: |
case TYPE_ASCII: |
691 |
buf.append ('A'); |
buf.append('A'); |
692 |
break; |
break; |
693 |
case TYPE_EBCDIC: |
case TYPE_EBCDIC: |
694 |
buf.append ('E'); |
buf.append('E'); |
695 |
break; |
break; |
696 |
case TYPE_BINARY: |
case TYPE_BINARY: |
697 |
buf.append ('I'); |
buf.append('I'); |
698 |
break; |
break; |
699 |
default: |
default: |
700 |
throw new IllegalArgumentException (Integer.toString (type)); |
throw new IllegalArgumentException(Integer.toString(type)); |
701 |
} |
} |
702 |
//buf.append (' '); |
//buf.append(' '); |
703 |
//buf.append ('N'); |
//buf.append('N'); |
704 |
send (buf.toString ()); |
send(buf.toString()); |
705 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
706 |
switch (response.getCode ()) |
switch (response.getCode()) |
707 |
{ |
{ |
708 |
case 200: |
case 200: |
709 |
representationType = type; |
representationType = type; |
710 |
break; |
break; |
711 |
default: |
default: |
712 |
throw new FTPException (response); |
throw new FTPException(response); |
713 |
} |
} |
714 |
} |
} |
715 |
|
|
717 |
* Returns the current file structure type. |
* Returns the current file structure type. |
718 |
* @return STRUCTURE_FILE, STRUCTURE_RECORD, or STRUCTURE_PAGE |
* @return STRUCTURE_FILE, STRUCTURE_RECORD, or STRUCTURE_PAGE |
719 |
*/ |
*/ |
720 |
public int getFileStructure () |
public int getFileStructure() |
721 |
{ |
{ |
722 |
return fileStructure; |
return fileStructure; |
723 |
} |
} |
726 |
* Sets the desired file structure type. |
* Sets the desired file structure type. |
727 |
* @param structure STRUCTURE_FILE, STRUCTURE_RECORD, or STRUCTURE_PAGE |
* @param structure STRUCTURE_FILE, STRUCTURE_RECORD, or STRUCTURE_PAGE |
728 |
*/ |
*/ |
729 |
public void setFileStructure (int structure) |
public void setFileStructure(int structure) |
730 |
throws IOException |
throws IOException |
731 |
{ |
{ |
732 |
StringBuffer buf = new StringBuffer (STRU); |
StringBuffer buf = new StringBuffer(STRU); |
733 |
buf.append (' '); |
buf.append(' '); |
734 |
switch (structure) |
switch (structure) |
735 |
{ |
{ |
736 |
case STRUCTURE_FILE: |
case STRUCTURE_FILE: |
737 |
buf.append ('F'); |
buf.append('F'); |
738 |
break; |
break; |
739 |
case STRUCTURE_RECORD: |
case STRUCTURE_RECORD: |
740 |
buf.append ('R'); |
buf.append('R'); |
741 |
break; |
break; |
742 |
case STRUCTURE_PAGE: |
case STRUCTURE_PAGE: |
743 |
buf.append ('P'); |
buf.append('P'); |
744 |
break; |
break; |
745 |
default: |
default: |
746 |
throw new IllegalArgumentException (Integer.toString (structure)); |
throw new IllegalArgumentException(Integer.toString(structure)); |
747 |
} |
} |
748 |
send (buf.toString ()); |
send(buf.toString()); |
749 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
750 |
switch (response.getCode ()) |
switch (response.getCode()) |
751 |
{ |
{ |
752 |
case 200: |
case 200: |
753 |
fileStructure = structure; |
fileStructure = structure; |
754 |
break; |
break; |
755 |
default: |
default: |
756 |
throw new FTPException (response); |
throw new FTPException(response); |
757 |
} |
} |
758 |
} |
} |
759 |
|
|
761 |
* Returns the current transfer mode. |
* Returns the current transfer mode. |
762 |
* @return MODE_STREAM, MODE_BLOCK, or MODE_COMPRESSED |
* @return MODE_STREAM, MODE_BLOCK, or MODE_COMPRESSED |
763 |
*/ |
*/ |
764 |
public int getTransferMode () |
public int getTransferMode() |
765 |
{ |
{ |
766 |
return transferMode; |
return transferMode; |
767 |
} |
} |
770 |
* Sets the desired transfer mode. |
* Sets the desired transfer mode. |
771 |
* @param mode MODE_STREAM, MODE_BLOCK, or MODE_COMPRESSED |
* @param mode MODE_STREAM, MODE_BLOCK, or MODE_COMPRESSED |
772 |
*/ |
*/ |
773 |
public void setTransferMode (int mode) |
public void setTransferMode(int mode) |
774 |
throws IOException |
throws IOException |
775 |
{ |
{ |
776 |
StringBuffer buf = new StringBuffer (MODE); |
StringBuffer buf = new StringBuffer(MODE); |
777 |
buf.append (' '); |
buf.append(' '); |
778 |
switch (mode) |
switch (mode) |
779 |
{ |
{ |
780 |
case MODE_STREAM: |
case MODE_STREAM: |
781 |
buf.append ('S'); |
buf.append('S'); |
782 |
break; |
break; |
783 |
case MODE_BLOCK: |
case MODE_BLOCK: |
784 |
buf.append ('B'); |
buf.append('B'); |
785 |
break; |
break; |
786 |
case MODE_COMPRESSED: |
case MODE_COMPRESSED: |
787 |
buf.append ('C'); |
buf.append('C'); |
788 |
break; |
break; |
789 |
default: |
default: |
790 |
throw new IllegalArgumentException (Integer.toString (mode)); |
throw new IllegalArgumentException(Integer.toString(mode)); |
791 |
} |
} |
792 |
send (buf.toString ()); |
send(buf.toString()); |
793 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
794 |
switch (response.getCode ()) |
switch (response.getCode()) |
795 |
{ |
{ |
796 |
case 200: |
case 200: |
797 |
transferMode = mode; |
transferMode = mode; |
798 |
if (dtp != null) |
if (dtp != null) |
799 |
{ |
{ |
800 |
dtp.setTransferMode (mode); |
dtp.setTransferMode(mode); |
801 |
} |
} |
802 |
break; |
break; |
803 |
default: |
default: |
804 |
throw new FTPException (response); |
throw new FTPException(response); |
805 |
} |
} |
806 |
} |
} |
807 |
|
|
810 |
* @param filename the filename of the file to retrieve |
* @param filename the filename of the file to retrieve |
811 |
* @return an InputStream containing the file content |
* @return an InputStream containing the file content |
812 |
*/ |
*/ |
813 |
public InputStream retrieve (String filename) |
public InputStream retrieve(String filename) |
814 |
throws IOException |
throws IOException |
815 |
{ |
{ |
816 |
if (dtp == null || transferMode == MODE_STREAM) |
if (dtp == null || transferMode == MODE_STREAM) |
817 |
{ |
{ |
818 |
initialiseDTP (); |
initialiseDTP(); |
819 |
} |
} |
820 |
/* |
/* |
821 |
int size = -1; |
int size = -1; |
822 |
String cmd = SIZE + ' ' + filename; |
String cmd = SIZE + ' ' + filename; |
823 |
send (cmd); |
send(cmd); |
824 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
825 |
switch (response.getCode ()) |
switch (response.getCode()) |
826 |
{ |
{ |
827 |
case 213: |
case 213: |
828 |
size = Integer.parseInt (response.getMessage ()); |
size = Integer.parseInt(response.getMessage()); |
829 |
break; |
break; |
830 |
case 550: // File not found |
case 550: // File not found |
831 |
default: |
default: |
832 |
throw new FTPException (response); |
throw new FTPException(response); |
833 |
} |
} |
834 |
*/ |
*/ |
835 |
String cmd = RETR + ' ' + filename; |
String cmd = RETR + ' ' + filename; |
836 |
send (cmd); |
send(cmd); |
837 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
838 |
switch (response.getCode ()) |
switch (response.getCode()) |
839 |
{ |
{ |
840 |
case 125: // Data connection already open; transfer starting |
case 125: // Data connection already open; transfer starting |
841 |
case 150: // File status okay; about to open data connection |
case 150: // File status okay; about to open data connection |
842 |
return dtp.getInputStream (); |
return dtp.getInputStream(); |
843 |
default: |
default: |
844 |
throw new FTPException (response); |
throw new FTPException(response); |
845 |
} |
} |
846 |
} |
} |
847 |
|
|
852 |
* @param filename the name of the file to save the content as |
* @param filename the name of the file to save the content as |
853 |
* @return an OutputStream to write the file data to |
* @return an OutputStream to write the file data to |
854 |
*/ |
*/ |
855 |
public OutputStream store (String filename) |
public OutputStream store(String filename) |
856 |
throws IOException |
throws IOException |
857 |
{ |
{ |
858 |
if (dtp == null || transferMode == MODE_STREAM) |
if (dtp == null || transferMode == MODE_STREAM) |
859 |
{ |
{ |
860 |
initialiseDTP (); |
initialiseDTP(); |
861 |
} |
} |
862 |
String cmd = STOR + ' ' + filename; |
String cmd = STOR + ' ' + filename; |
863 |
send (cmd); |
send(cmd); |
864 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
865 |
switch (response.getCode ()) |
switch (response.getCode()) |
866 |
{ |
{ |
867 |
case 125: // Data connection already open; transfer starting |
case 125: // Data connection already open; transfer starting |
868 |
case 150: // File status okay; about to open data connection |
case 150: // File status okay; about to open data connection |
869 |
return dtp.getOutputStream (); |
return dtp.getOutputStream(); |
870 |
default: |
default: |
871 |
throw new FTPException (response); |
throw new FTPException(response); |
872 |
} |
} |
873 |
} |
} |
874 |
|
|
879 |
* @param filename the name of the file to save the content as |
* @param filename the name of the file to save the content as |
880 |
* @return an OutputStream to write the file data to |
* @return an OutputStream to write the file data to |
881 |
*/ |
*/ |
882 |
public OutputStream append (String filename) |
public OutputStream append(String filename) |
883 |
throws IOException |
throws IOException |
884 |
{ |
{ |
885 |
if (dtp == null || transferMode == MODE_STREAM) |
if (dtp == null || transferMode == MODE_STREAM) |
886 |
{ |
{ |
887 |
initialiseDTP (); |
initialiseDTP(); |
888 |
} |
} |
889 |
String cmd = APPE + ' ' + filename; |
String cmd = APPE + ' ' + filename; |
890 |
send (cmd); |
send(cmd); |
891 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
892 |
switch (response.getCode ()) |
switch (response.getCode()) |
893 |
{ |
{ |
894 |
case 125: // Data connection already open; transfer starting |
case 125: // Data connection already open; transfer starting |
895 |
case 150: // File status okay; about to open data connection |
case 150: // File status okay; about to open data connection |
896 |
return dtp.getOutputStream (); |
return dtp.getOutputStream(); |
897 |
default: |
default: |
898 |
throw new FTPException (response); |
throw new FTPException(response); |
899 |
} |
} |
900 |
} |
} |
901 |
|
|
906 |
* <code>append</code>. |
* <code>append</code>. |
907 |
* @param size the number of bytes of storage to allocate |
* @param size the number of bytes of storage to allocate |
908 |
*/ |
*/ |
909 |
public void allocate (long size) |
public void allocate(long size) |
910 |
throws IOException |
throws IOException |
911 |
{ |
{ |
912 |
String cmd = ALLO + ' ' + size; |
String cmd = ALLO + ' ' + size; |
913 |
send (cmd); |
send(cmd); |
914 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
915 |
switch (response.getCode ()) |
switch (response.getCode()) |
916 |
{ |
{ |
917 |
case 200: // OK |
case 200: // OK |
918 |
case 202: // Superfluous |
case 202: // Superfluous |
919 |
break; |
break; |
920 |
default: |
default: |
921 |
throw new FTPException (response); |
throw new FTPException(response); |
922 |
} |
} |
923 |
} |
} |
924 |
|
|
928 |
* @param newName the new name |
* @param newName the new name |
929 |
* @return true if successful, false otherwise |
* @return true if successful, false otherwise |
930 |
*/ |
*/ |
931 |
public boolean rename (String oldName, String newName) |
public boolean rename(String oldName, String newName) |
932 |
throws IOException |
throws IOException |
933 |
{ |
{ |
934 |
String cmd = RNFR + ' ' + oldName; |
String cmd = RNFR + ' ' + oldName; |
935 |
send (cmd); |
send(cmd); |
936 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
937 |
switch (response.getCode ()) |
switch (response.getCode()) |
938 |
{ |
{ |
939 |
case 450: // File unavailable |
case 450: // File unavailable |
940 |
case 550: // File not found |
case 550: // File not found |
942 |
case 350: // Pending |
case 350: // Pending |
943 |
break; |
break; |
944 |
default: |
default: |
945 |
throw new FTPException (response); |
throw new FTPException(response); |
946 |
} |
} |
947 |
cmd = RNTO + ' ' + newName; |
cmd = RNTO + ' ' + newName; |
948 |
send (cmd); |
send(cmd); |
949 |
response = getResponse (); |
response = getResponse(); |
950 |
switch (response.getCode ()) |
switch (response.getCode()) |
951 |
{ |
{ |
952 |
case 250: // OK |
case 250: // OK |
953 |
return true; |
return true; |
955 |
case 550: |
case 550: |
956 |
return false; |
return false; |
957 |
default: |
default: |
958 |
throw new FTPException (response); |
throw new FTPException(response); |
959 |
} |
} |
960 |
} |
} |
961 |
|
|
963 |
* Aborts the transfer in progress. |
* Aborts the transfer in progress. |
964 |
* @return true if a transfer was in progress, false otherwise |
* @return true if a transfer was in progress, false otherwise |
965 |
*/ |
*/ |
966 |
public boolean abort () |
public boolean abort() |
967 |
throws IOException |
throws IOException |
968 |
{ |
{ |
969 |
send (ABOR); |
send(ABOR); |
970 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
971 |
// Abort client DTP |
// Abort client DTP |
972 |
if (dtp != null) |
if (dtp != null) |
973 |
{ |
{ |
974 |
dtp.abort (); |
dtp.abort(); |
975 |
} |
} |
976 |
switch (response.getCode ()) |
switch (response.getCode()) |
977 |
{ |
{ |
978 |
case 226: // successful abort |
case 226: // successful abort |
979 |
return false; |
return false; |
980 |
case 426: // interrupted |
case 426: // interrupted |
981 |
response = getResponse (); |
response = getResponse(); |
982 |
if (response.getCode () == 226) |
if (response.getCode() == 226) |
983 |
{ |
{ |
984 |
return true; |
return true; |
985 |
} |
} |
986 |
// Otherwise fall through to throw exception |
// Otherwise fall through to throw exception |
987 |
default: |
default: |
988 |
throw new FTPException (response); |
throw new FTPException(response); |
989 |
} |
} |
990 |
} |
} |
991 |
|
|
993 |
* Causes the file specified to be deleted at the server site. |
* Causes the file specified to be deleted at the server site. |
994 |
* @param filename the file to delete |
* @param filename the file to delete |
995 |
*/ |
*/ |
996 |
public boolean delete (String filename) |
public boolean delete(String filename) |
997 |
throws IOException |
throws IOException |
998 |
{ |
{ |
999 |
String cmd = DELE + ' ' + filename; |
String cmd = DELE + ' ' + filename; |
1000 |
send (cmd); |
send(cmd); |
1001 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
1002 |
switch (response.getCode ()) |
switch (response.getCode()) |
1003 |
{ |
{ |
1004 |
case 250: // OK |
case 250: // OK |
1005 |
return true; |
return true; |
1007 |
case 550: // File not found |
case 550: // File not found |
1008 |
return false; |
return false; |
1009 |
default: |
default: |
1010 |
throw new FTPException (response); |
throw new FTPException(response); |
1011 |
} |
} |
1012 |
} |
} |
1013 |
|
|
1016 |
* This may be an absolute or relative pathname. |
* This may be an absolute or relative pathname. |
1017 |
* @param pathname the directory to delete |
* @param pathname the directory to delete |
1018 |
*/ |
*/ |
1019 |
public boolean removeDirectory (String pathname) |
public boolean removeDirectory(String pathname) |
1020 |
throws IOException |
throws IOException |
1021 |
{ |
{ |
1022 |
String cmd = RMD + ' ' + pathname; |
String cmd = RMD + ' ' + pathname; |
1023 |
send (cmd); |
send(cmd); |
1024 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
1025 |
switch (response.getCode ()) |
switch (response.getCode()) |
1026 |
{ |
{ |
1027 |
case 250: // OK |
case 250: // OK |
1028 |
return true; |
return true; |
1029 |
case 550: // File not found |
case 550: // File not found |
1030 |
return false; |
return false; |
1031 |
default: |
default: |
1032 |
throw new FTPException (response); |
throw new FTPException(response); |
1033 |
} |
} |
1034 |
} |
} |
1035 |
|
|
1038 |
* This may be an absolute or relative pathname. |
* This may be an absolute or relative pathname. |
1039 |
* @param pathname the directory to create |
* @param pathname the directory to create |
1040 |
*/ |
*/ |
1041 |
public boolean makeDirectory (String pathname) |
public boolean makeDirectory(String pathname) |
1042 |
throws IOException |
throws IOException |
1043 |
{ |
{ |
1044 |
String cmd = MKD + ' ' + pathname; |
String cmd = MKD + ' ' + pathname; |
1045 |
send (cmd); |
send(cmd); |
1046 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
1047 |
switch (response.getCode ()) |
switch (response.getCode()) |
1048 |
{ |
{ |
1049 |
case 257: // Directory created |
case 257: // Directory created |
1050 |
return true; |
return true; |
1051 |
case 550: // File not found |
case 550: // File not found |
1052 |
return false; |
return false; |
1053 |
default: |
default: |
1054 |
throw new FTPException (response); |
throw new FTPException(response); |
1055 |
} |
} |
1056 |
} |
} |
1057 |
|
|
1058 |
/** |
/** |
1059 |
* Returns the current working directory. |
* Returns the current working directory. |
1060 |
*/ |
*/ |
1061 |
public String getWorkingDirectory () |
public String getWorkingDirectory() |
1062 |
throws IOException |
throws IOException |
1063 |
{ |
{ |
1064 |
send (PWD); |
send(PWD); |
1065 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
1066 |
switch (response.getCode ()) |
switch (response.getCode()) |
1067 |
{ |
{ |
1068 |
case 257: |
case 257: |
1069 |
String message = response.getMessage (); |
String message = response.getMessage(); |
1070 |
if (message.charAt (0) == '"') |
if (message.charAt(0) == '"') |
1071 |
{ |
{ |
1072 |
int end = message.indexOf ('"', 1); |
int end = message.indexOf('"', 1); |
1073 |
if (end == -1) |
if (end == -1) |
1074 |
{ |
{ |
1075 |
throw new ProtocolException (message); |
throw new ProtocolException(message); |
1076 |
} |
} |
1077 |
return message.substring (1, end); |
return message.substring(1, end); |
1078 |
} |
} |
1079 |
else |
else |
1080 |
{ |
{ |
1081 |
int end = message.indexOf (' '); |
int end = message.indexOf(' '); |
1082 |
if (end == -1) |
if (end == -1) |
1083 |
{ |
{ |
1084 |
return message; |
return message; |
1085 |
} |
} |
1086 |
else |
else |
1087 |
{ |
{ |
1088 |
return message.substring (0, end); |
return message.substring(0, end); |
1089 |
} |
} |
1090 |
} |
} |
1091 |
default: |
default: |
1092 |
throw new FTPException (response); |
throw new FTPException(response); |
1093 |
} |
} |
1094 |
} |
} |
1095 |
|
|
1102 |
* current working or default directory. |
* current working or default directory. |
1103 |
* @param pathname the context pathname, or null |
* @param pathname the context pathname, or null |
1104 |
*/ |
*/ |
1105 |
public InputStream list (String pathname) |
public InputStream list(String pathname) |
1106 |
throws IOException |
throws IOException |
1107 |
{ |
{ |
1108 |
if (dtp == null || transferMode == MODE_STREAM) |
if (dtp == null || transferMode == MODE_STREAM) |
1109 |
{ |
{ |
1110 |
initialiseDTP (); |
initialiseDTP(); |
1111 |
} |
} |
1112 |
if (pathname == null) |
if (pathname == null) |
1113 |
{ |
{ |
1114 |
send (LIST); |
send(LIST); |
1115 |
} |
} |
1116 |
else |
else |
1117 |
{ |
{ |
1118 |
String cmd = LIST + ' ' + pathname; |
String cmd = LIST + ' ' + pathname; |
1119 |
send (cmd); |
send(cmd); |
1120 |
} |
} |
1121 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
1122 |
switch (response.getCode ()) |
switch (response.getCode()) |
1123 |
{ |
{ |
1124 |
case 125: // Data connection already open; transfer starting |
case 125: // Data connection already open; transfer starting |
1125 |
case 150: // File status okay; about to open data connection |
case 150: // File status okay; about to open data connection |
1126 |
return dtp.getInputStream (); |
return dtp.getInputStream(); |
1127 |
default: |
default: |
1128 |
throw new FTPException (response); |
throw new FTPException(response); |
1129 |
} |
} |
1130 |
} |
} |
1131 |
|
|
1134 |
* directory or other system-specific file group descriptor; a null |
* directory or other system-specific file group descriptor; a null |
1135 |
* argument implies the user's current working or default directory. |
* argument implies the user's current working or default directory. |
1136 |
* @param pathname the directory pathname, or null |
* @param pathname the directory pathname, or null |
1137 |
* @return a list of filenames (strings) |
* @return a list of filenames(strings) |
1138 |
*/ |
*/ |
1139 |
public List nameList (String pathname) |
public List nameList(String pathname) |
1140 |
throws IOException |
throws IOException |
1141 |
{ |
{ |
1142 |
if (dtp == null || transferMode == MODE_STREAM) |
if (dtp == null || transferMode == MODE_STREAM) |
1143 |
{ |
{ |
1144 |
initialiseDTP (); |
initialiseDTP(); |
1145 |
} |
} |
1146 |
if (pathname == null) |
if (pathname == null) |
1147 |
{ |
{ |
1148 |
send (NLST); |
send(NLST); |
1149 |
} |
} |
1150 |
else |
else |
1151 |
{ |
{ |
1152 |
String cmd = NLST + ' ' + pathname; |
String cmd = NLST + ' ' + pathname; |
1153 |
send (cmd); |
send(cmd); |
1154 |
} |
} |
1155 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
1156 |
switch (response.getCode ()) |
switch (response.getCode()) |
1157 |
{ |
{ |
1158 |
case 125: // Data connection already open; transfer starting |
case 125: // Data connection already open; transfer starting |
1159 |
case 150: // File status okay; about to open data connection |
case 150: // File status okay; about to open data connection |
1160 |
InputStream in = dtp.getInputStream (); |
InputStream in = dtp.getInputStream(); |
1161 |
in = new BufferedInputStream (in); |
in = new BufferedInputStream(in); |
1162 |
in = new CRLFInputStream (in); // TODO ensure that TYPE is correct |
in = new CRLFInputStream(in); // TODO ensure that TYPE is correct |
1163 |
LineInputStream li = new LineInputStream (in); |
LineInputStream li = new LineInputStream(in); |
1164 |
List ret = new ArrayList (); |
List ret = new ArrayList(); |
1165 |
for (String line = li.readLine (); |
for (String line = li.readLine(); |
1166 |
line != null; |
line != null; |
1167 |
line = li.readLine ()) |
line = li.readLine()) |
1168 |
{ |
{ |
1169 |
ret.add (line); |
ret.add(line); |
1170 |
} |
} |
1171 |
li.close (); |
li.close(); |
1172 |
return ret; |
return ret; |
1173 |
default: |
default: |
1174 |
throw new FTPException (response); |
throw new FTPException(response); |
1175 |
} |
} |
1176 |
} |
} |
1177 |
|
|
1178 |
/** |
/** |
1179 |
* Returns the type of operating system at the server. |
* Returns the type of operating system at the server. |
1180 |
*/ |
*/ |
1181 |
public String system () |
public String system() |
1182 |
throws IOException |
throws IOException |
1183 |
{ |
{ |
1184 |
send (SYST); |
send(SYST); |
1185 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
1186 |
switch (response.getCode ()) |
switch (response.getCode()) |
1187 |
{ |
{ |
1188 |
case 215: |
case 215: |
1189 |
String message = response.getMessage (); |
String message = response.getMessage(); |
1190 |
int end = message.indexOf (' '); |
int end = message.indexOf(' '); |
1191 |
if (end == -1) |
if (end == -1) |
1192 |
{ |
{ |
1193 |
return message; |
return message; |
1194 |
} |
} |
1195 |
else |
else |
1196 |
{ |
{ |
1197 |
return message.substring (0, end); |
return message.substring(0, end); |
1198 |
} |
} |
1199 |
default: |
default: |
1200 |
throw new FTPException (response); |
throw new FTPException(response); |
1201 |
} |
} |
1202 |
} |
} |
1203 |
|
|
1206 |
* This method can be used to ensure that the connection does not time |
* This method can be used to ensure that the connection does not time |
1207 |
* out. |
* out. |
1208 |
*/ |
*/ |
1209 |
public void noop () |
public void noop() |
1210 |
throws IOException |
throws IOException |
1211 |
{ |
{ |
1212 |
send (NOOP); |
send(NOOP); |
1213 |
FTPResponse response = getResponse (); |
FTPResponse response = getResponse(); |
1214 |
switch (response.getCode ()) |
switch (response.getCode()) |
1215 |
{ |
{ |
1216 |
case 200: |
case 200: |
1217 |
break; |
break; |
1218 |
default: |
default: |
1219 |
throw new FTPException (response); |
throw new FTPException(response); |
1220 |
} |
} |
1221 |
} |
} |
1222 |
|
|
1227 |
* The CRLF sequence is automatically appended. |
* The CRLF sequence is automatically appended. |
1228 |
* @param cmd the command line to send |
* @param cmd the command line to send |
1229 |
*/ |
*/ |
1230 |
protected void send (String cmd) |
protected void send(String cmd) |
1231 |
throws IOException |
throws IOException |
1232 |
{ |
{ |
1233 |
byte[] data = cmd.getBytes (US_ASCII); |
byte[] data = cmd.getBytes(US_ASCII); |
1234 |
out.write (data); |
out.write(data); |
1235 |
out.writeln (); |
out.writeln(); |
1236 |
out.flush (); |
out.flush(); |
1237 |
} |
} |
1238 |
|
|
1239 |
/** |
/** |
1241 |
* If the server sends the "transfer complete" code, this is handled here, |
* If the server sends the "transfer complete" code, this is handled here, |
1242 |
* and the next response is passed to the caller. |
* and the next response is passed to the caller. |
1243 |
*/ |
*/ |
1244 |
protected FTPResponse getResponse () |
protected FTPResponse getResponse() |
1245 |
throws IOException |
throws IOException |
1246 |
{ |
{ |
1247 |
FTPResponse response = readResponse (); |
FTPResponse response = readResponse(); |
1248 |
if (response.getCode () == 226) |
if (response.getCode() == 226) |
1249 |
{ |
{ |
1250 |
if (dtp != null) |
if (dtp != null) |
1251 |
{ |
{ |
1252 |
dtp.transferComplete (); |
dtp.transferComplete(); |
1253 |
} |
} |
1254 |
response = readResponse (); |
response = readResponse(); |
1255 |
} |
} |
1256 |
return response; |
return response; |
1257 |
} |
} |
1259 |
/** |
/** |
1260 |
* Reads and parses the next response from the server. |
* Reads and parses the next response from the server. |
1261 |
*/ |
*/ |
1262 |
protected FTPResponse readResponse () |
protected FTPResponse readResponse() |
1263 |
throws IOException |
throws IOException |
1264 |
{ |
{ |
1265 |
String line = in.readLine (); |
String line = in.readLine(); |
1266 |
if (line == null) |
if (line == null) |
1267 |
{ |
{ |
1268 |
throw new ProtocolException( "EOF"); |
throw new ProtocolException( "EOF"); |
1269 |
} |
} |
1270 |
if (line.length () < 4) |
if (line.length() < 4) |
1271 |
{ |
{ |
1272 |
throw new ProtocolException (line); |
throw new ProtocolException(line); |
1273 |
} |
} |
1274 |
int code = parseCode (line); |
int code = parseCode(line); |
1275 |
if (code == -1) |
if (code == -1) |
1276 |
{ |
{ |
1277 |
throw new ProtocolException (line); |
throw new ProtocolException(line); |
1278 |
} |
} |
1279 |
char c = line.charAt (3); |
char c = line.charAt(3); |
1280 |
if (c == ' ') |
if (c == ' ') |
1281 |
{ |
{ |
1282 |
return new FTPResponse (code, line.substring (4)); |
return new FTPResponse(code, line.substring(4)); |
1283 |
} |
} |
1284 |
else if (c == '-') |
else if (c == '-') |
1285 |
{ |
{ |
1286 |
StringBuffer buf = new StringBuffer (line.substring (4)); |
StringBuffer buf = new StringBuffer(line.substring(4)); |
1287 |
buf.append ('\n'); |
buf.append('\n'); |
1288 |
while (true) |
while(true) |
1289 |
{ |
{ |
1290 |
line = in.readLine (); |
line = in.readLine(); |
1291 |
if (line == null) |
if (line == null) |
1292 |
{ |
{ |
1293 |
throw new ProtocolException ("EOF"); |
throw new ProtocolException("EOF"); |
1294 |
} |
} |
1295 |
if (line.length () >= 4 && |
if (line.length() >= 4 && |
1296 |
line.charAt (3) == ' ' && |
line.charAt(3) == ' ' && |
1297 |
parseCode (line) == code) |
parseCode(line) == code) |
1298 |
{ |
{ |
1299 |
return new FTPResponse (code, line.substring (4), |
return new FTPResponse(code, line.substring(4), |
1300 |
buf.toString ()); |
buf.toString()); |
1301 |
} |
} |
1302 |
else |
else |
1303 |
{ |
{ |
1304 |
buf.append (line); |
buf.append(line); |
1305 |
buf.append ('\n'); |
buf.append('\n'); |
1306 |
} |
} |
1307 |
} |
} |
1308 |
} |
} |
1309 |
else |
else |
1310 |
{ |
{ |
1311 |
throw new ProtocolException (line); |
throw new ProtocolException(line); |
1312 |
} |
} |
1313 |
} |
} |
1314 |
|
|
1316 |
* Parses the 3-digit numeric code at the beginning of the given line. |
* Parses the 3-digit numeric code at the beginning of the given line. |
1317 |
* Returns -1 on failure. |
* Returns -1 on failure. |
1318 |
*/ |
*/ |
1319 |
static final int parseCode (String line) |
static final int parseCode(String line) |
1320 |
{ |
{ |
1321 |
char[] c = { line.charAt (0), line.charAt (1), line.charAt (2) }; |
char[] c = { line.charAt(0), line.charAt(1), line.charAt(2) }; |
1322 |
int ret = 0; |
int ret = 0; |
1323 |
for (int i = 0; i < 3; i++) |
for (int i = 0; i < 3; i++) |
1324 |
{ |
{ |
1325 |
int digit = ((int) c[i]) - 0x30; |
int digit =((int) c[i]) - 0x30; |
1326 |
if (digit < 0 || digit > 9) |
if (digit < 0 || digit > 9) |
1327 |
{ |
{ |
1328 |
return -1; |
return -1; |
1331 |
switch (i) |
switch (i) |
1332 |
{ |
{ |
1333 |
case 0: |
case 0: |
1334 |
ret += (100 * digit); |
ret +=(100 * digit); |
1335 |
break; |
break; |
1336 |
case 1: |
case 1: |
1337 |
ret += (10 * digit); |
ret +=(10 * digit); |
1338 |
break; |
break; |
1339 |
case 2: |
case 2: |
1340 |
ret += digit; |
ret += digit; |
1345 |
} |
} |
1346 |
|
|
1347 |
} |
} |
1348 |
|
|