Source code: com/enterprisedt/net/ftp/FTPClient.java
1 /**
2 *
3 * Java FTP client library.
4 *
5 * Copyright (C) 2000 Enterprise Distributed Technologies Ltd
6 *
7 * www.enterprisedt.com
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 * Bug fixes, suggestions and comments should be sent to:
24 *
25 * bruceb@cryptsoft.com
26 *
27 * or by snail mail to:
28 *
29 * Bruce P. Blackshaw
30 * 53 Wakehurst Road
31 * London SW11 6DB
32 * United Kingdom
33 *
34 * Change Log:
35 *
36 *
37 * 2002/07/04 7:32:46 PM Michael Kandelaars
38 * Added get method that returns an
39 * InputStream
40 *
41 * $Log: FTPClient.java,v $
42 * Revision 1.3 2001/10/09 20:53:46 bruceb
43 * Active mode changes
44 *
45 * Revision 1.1 2001/10/05 14:42:03 bruceb
46 * moved from old project
47 *
48 *
49 */
50
51
52 package com.enterprisedt.net.ftp;
53
54 import java.io.IOException;
55 import java.io.LineNumberReader;
56 import java.io.InputStreamReader;
57 import java.io.OutputStreamWriter;
58 import java.io.BufferedWriter;
59 import java.io.FileWriter;
60 import java.io.FileReader;
61 import java.io.InputStream;
62 import java.io.DataInputStream;
63 import java.io.DataOutputStream;
64 import java.io.BufferedInputStream;
65 import java.io.BufferedOutputStream;
66 import java.io.FileOutputStream;
67 import java.io.FileInputStream;
68 import java.io.File;
69
70 import java.net.InetAddress;
71 import java.net.Socket;
72
73 import java.util.Vector;
74 import java.util.Properties;
75
76 /**
77 * Supports client-side FTP. Most common
78 * FTP operations are present in this class.
79 *
80 * @author Bruce Blackshaw
81 * @version $Revision: 1.3 $
82 *
83 */
84 public class FTPClient {
85
86 /**
87 * Revision control id
88 */
89 private static String cvsId = "$Id: FTPClient.java,v 1.3 2001/10/09 20:53:46 bruceb Exp $";
90
91 /**
92 * Socket responsible for controlling
93 * the connection
94 */
95 private FTPControlSocket control = null;
96
97 /**
98 * Socket responsible for transferring
99 * the data
100 */
101 private FTPDataSocket data = null;
102
103
104 /**
105 * Socket timeout for both data and control. In
106 * milliseconds
107 */
108 private int timeout = 0;
109
110
111 /**
112 * Record of the transfer type - make the default ASCII
113 */
114 private FTPTransferType transferType = FTPTransferType.ASCII;
115
116 /**
117 * Record of the connect mode - make the default PASV (as this was
118 * the original mode supported)
119 */
120 private FTPConnectMode connectMode = FTPConnectMode.PASV;
121
122 /**
123 * Constructor. Creates the control
124 * socket
125 *
126 * @param remoteHost the remote hostname
127 */
128 public FTPClient(String remoteHost)
129 throws IOException, FTPException {
130
131 control = new FTPControlSocket(remoteHost);
132 }
133
134 /**
135 * Constructor. Creates the control
136 * socket
137 *
138 * @param remoteHost the remote hostname
139 * @param controlPort port for control stream
140 */
141 public FTPClient(String remoteHost, int controlPort)
142 throws IOException, FTPException {
143
144 control = new FTPControlSocket(remoteHost, controlPort);
145 }
146
147 /**
148 * Constructor. Creates the control
149 * socket
150 *
151 * @param remoteAddr the address of the
152 * remote host
153 */
154 public FTPClient(InetAddress remoteAddr)
155 throws IOException, FTPException {
156
157 control = new FTPControlSocket(remoteAddr);
158 }
159
160
161 /**
162 * Constructor. Creates the control
163 * socket. Allows setting of control port (normally
164 * set by default to 21).
165 *
166 * @param remoteAddr the address of the
167 * remote host
168 * @param controlPort port for control stream
169 */
170 public FTPClient(InetAddress remoteAddr, int controlPort)
171 throws IOException, FTPException {
172
173 control = new FTPControlSocket(remoteAddr, controlPort);
174 }
175
176
177 /**
178 * Set the TCP timeout on the underlying socket.
179 *
180 * If a timeout is set, then any operation which
181 * takes longer than the timeout value will be
182 * killed with a java.io.InterruptedException. We
183 * set both the control and data connections
184 *
185 * @param millis The length of the timeout, in milliseconds
186 */
187 public void setTimeout(int millis)
188 throws IOException {
189
190 this.timeout = millis;
191 control.setTimeout(millis);
192 }
193
194
195 /**
196 * Set the connect mode
197 *
198 * @param mode ACTIVE or PASV mode
199 */
200 public void setConnectMode(FTPConnectMode mode) {
201
202 connectMode = mode;
203 }
204
205
206 /**
207 * Login into an account on the FTP server. This
208 * call completes the entire login process
209 *
210 * @param user user name
211 * @param password user's password
212 */
213 public void login(String user, String password)
214 throws IOException, FTPException {
215
216 String response = control.sendCommand("USER " + user);
217 control.validateReply(response, "331");
218 response = control.sendCommand("PASS " + password);
219 control.validateReply(response, "230");
220 }
221
222
223 /**
224 * Supply the user name to log into an account
225 * on the FTP server. Must be followed by the
226 * password() method - but we allow for
227 *
228 * @param user user name
229 * @param password user's password
230 */
231 public void user(String user)
232 throws IOException, FTPException {
233
234 String reply = control.sendCommand("USER " + user);
235
236 // we allow for a site with no password - 230 response
237 String[] validCodes = {"230", "331"};
238 control.validateReply(reply, validCodes);
239 }
240
241
242 /**
243 * Supplies the password for a previously supplied
244 * username to log into the FTP server. Must be
245 * preceeded by the user() method
246 *
247 * @param user user name
248 * @param password user's password
249 */
250 public void password(String password)
251 throws IOException, FTPException {
252
253 String reply = control.sendCommand("PASS " + password);
254
255 // we allow for a site with no passwords (202)
256 String[] validCodes = {"230", "202"};
257 control.validateReply(reply, validCodes);
258 }
259
260 /**
261 * Set up SOCKS v4 proxy settings. This can be used if there
262 * is a SOCKS proxy server in place that must be connected thru.
263 *
264 * @param port SOCKS proxy port
265 * @param host SOCKS proxy hostname
266 */
267 public void initSOCKS(String port, String host) {
268
269 Properties props = System.getProperties();
270 props.put("socksProxyPort", port);
271 props.put("socksProxyHost", host);
272 System.setProperties(props);
273 }
274
275
276 /**
277 * Get the name of the remote host
278 *
279 * @return remote host name
280 */
281 String getRemoteHostName() {
282 return control.getRemoteHostName();
283 }
284
285
286 /**
287 * Issue arbitrary ftp commands to the FTP server.
288 *
289 * @param command ftp command to be sent to server
290 * @param validCodes valid return codes for this command
291 */
292 public void quote(String command, String[] validCodes)
293 throws IOException, FTPException {
294
295 String reply = control.sendCommand(command);
296
297 // allow for no validation to be supplied
298 if (validCodes != null && validCodes.length > 0)
299 control.validateReply(reply, validCodes);
300 }
301
302
303 /**
304 * Put a local file onto the FTP server. It
305 * is placed in the current directory.
306 *
307 * @param localPath path of the local file
308 * @param remoteFile name of remote file in
309 * current directory
310 */
311 public void put(String localPath, String remoteFile)
312 throws IOException, FTPException {
313
314 put(localPath, remoteFile, false);
315 }
316
317
318 /**
319 * Put a local file onto the FTP server. It
320 * is placed in the current directory. Allows appending
321 * if current file exists
322 *
323 * @param localPath path of the local file
324 * @param remoteFile name of remote file in
325 * current directory
326 * @param append true if appending, false otherwise
327 */
328 public void put(String localPath, String remoteFile, boolean append)
329 throws IOException, FTPException {
330
331 // get according to set type
332 if (getType() == FTPTransferType.ASCII) {
333 putASCII(localPath, remoteFile, append);
334 }
335 else {
336 putBinary(localPath, remoteFile, append);
337 }
338
339 // check the control response
340 String[] validCodes2 = {"226", "250"};
341 String reply = control.readReply();
342 control.validateReply(reply, validCodes2);
343 }
344
345
346 /**
347 * Request the server to set up the put
348 *
349 * @param remoteFile name of remote file in
350 * current directory
351 * @param append true if appending, false otherwise
352 */
353 private void initPut(String remoteFile, boolean append)
354 throws IOException, FTPException {
355
356 // set up data channel
357 data = control.createDataSocket(connectMode);
358 data.setTimeout(timeout);
359
360 // send the command to store
361 String cmd = append ? "APPE " : "STOR ";
362 String reply = control.sendCommand(cmd + remoteFile);
363
364 // Can get a 125 or a 150
365 String[] validCodes1 = {"125", "150"};
366 control.validateReply(reply, validCodes1);
367 }
368
369
370 /**
371 * Put as ASCII, i.e. read a line at a time and write
372 * inserting the correct FTP separator
373 *
374 * @param localPath full path of local file to read from
375 * @param remoteFile name of remote file we are writing to
376 * @param append true if appending, false otherwise
377 */
378 private void putASCII(String localPath, String remoteFile, boolean append)
379 throws IOException, FTPException {
380
381 // create the buffered stream for reading
382 LineNumberReader in
383 = new LineNumberReader(
384 new FileReader(localPath));
385
386 initPut(remoteFile, append);
387
388 // get an character output stream to write to ... AFTER we
389 // have the ok to go ahead AND AFTER we've successfully opened a
390 // stream for the local file
391 BufferedWriter out =
392 new BufferedWriter(
393 new OutputStreamWriter(data.getOutputStream()));
394
395 // write line by line, writing \r\n as required by RFC959 after
396 // each line
397 String line = null;
398 while ((line = in.readLine()) != null) {
399 out.write(line, 0, line.length());
400 out.write(FTPControlSocket.EOL, 0, FTPControlSocket.EOL.length());
401 }
402 in.close();
403 out.flush();
404 out.close();
405
406 // and close the data socket
407 try {
408 data.close();
409 }
410 catch (IOException ignore) {}
411 }
412
413
414 /**
415 * Put as binary, i.e. read and write raw bytes
416 *
417 * @param localPath full path of local file to read from
418 * @param remoteFile name of remote file we are writing to
419 * @param append true if appending, false otherwise
420 */
421 private void putBinary(String localPath, String remoteFile, boolean append)
422 throws IOException, FTPException {
423
424 // open input stream to read source file ... do this
425 // BEFORE opening output stream to server, so if file not
426 // found, an exception is thrown
427 BufferedInputStream in =
428 new BufferedInputStream(
429 new FileInputStream(localPath));
430
431 initPut(remoteFile, append);
432
433 // get an output stream
434 BufferedOutputStream out =
435 new BufferedOutputStream(
436 new DataOutputStream(data.getOutputStream()));
437
438 byte[] buf = new byte[512];
439
440 // read a chunk at a time and write to the data socket
441 int count = 0;
442 while ((count = in.read(buf)) > 0) {
443 out.write(buf, 0, count);
444 }
445 in.close();
446
447 // flush and clean up
448 out.flush();
449 out.close();
450
451 // and close the data socket
452 try {
453 data.close();
454 }
455 catch (IOException ignore) {}
456 }
457
458
459 /**
460 * Put data onto the FTP server. It
461 * is placed in the current directory.
462 *
463 * @param data array of bytes
464 * @param remoteFile name of remote file in
465 * current directory
466 */
467 public void put(byte[] bytes, String remoteFile)
468 throws IOException, FTPException {
469
470 put(bytes, remoteFile, false);
471 }
472
473 /**
474 * Put data onto the FTP server. It
475 * is placed in the current directory. Allows
476 * appending if current file exists
477 *
478 * @param data array of bytes
479 * @param remoteFile name of remote file in
480 * current directory
481 * @param append true if appending, false otherwise
482 */
483 public void put(byte[] bytes, String remoteFile, boolean append)
484 throws IOException, FTPException {
485
486 initPut(remoteFile, append);
487
488 // get an output stream
489 BufferedOutputStream out =
490 new BufferedOutputStream(
491 new DataOutputStream(data.getOutputStream()));
492
493 // write array
494 out.write(bytes, 0, bytes.length);
495
496 // flush and clean up
497 out.flush();
498 out.close();
499
500 // and close the data socket
501 try {
502 data.close();
503 }
504 catch (IOException ignore) {}
505
506 // check the control response
507 String[] validCodes2 = {"226", "250"};
508 String reply = control.readReply();
509 control.validateReply(reply, validCodes2);
510 }
511
512
513 /**
514 * Get data from the FTP server. Uses the currently
515 * set transfer mode.
516 *
517 * @param localPath local file to put data in
518 * @param remoteFile name of remote file in
519 * current directory
520 */
521 public void get(String localPath, String remoteFile)
522 throws IOException, FTPException {
523
524 // get according to set type
525 if (getType() == FTPTransferType.ASCII) {
526 getASCII(localPath, remoteFile);
527 }
528 else {
529 getBinary(localPath, remoteFile);
530 }
531
532 // check the control response
533 String[] validCodes2 = {"226", "250"};
534 String reply = control.readReply();
535 control.validateReply(reply, validCodes2);
536 }
537
538
539 /**
540 * Request to the server that the get is set up
541 *
542 * @param remoteFile name of remote file
543 */
544 private void initGet(String remoteFile)
545 throws IOException, FTPException {
546
547 // set up data channel
548 data = control.createDataSocket(connectMode);
549 data.setTimeout(timeout);
550
551 // send the retrieve command
552 String reply = control.sendCommand("RETR " + remoteFile);
553
554 // Can get a 125 or a 150
555 String[] validCodes1 = {"125", "150"};
556 control.validateReply(reply, validCodes1);
557 }
558
559
560 /**
561 * Get as ASCII, i.e. read a line at a time and write
562 * using the correct newline separator for the OS
563 *
564 * @param localPath full path of local file to write to
565 * @param remoteFile name of remote file
566 */
567 private void getASCII(String localPath, String remoteFile)
568 throws IOException, FTPException {
569
570 // create the buffered stream for writing
571 BufferedWriter out =
572 new BufferedWriter(
573 new FileWriter(localPath));
574
575 initGet(remoteFile);
576
577 // get an character input stream to read data from ... AFTER we
578 // have the ok to go ahead AND AFTER we've successfully opened a
579 // stream for the local file
580 LineNumberReader in =
581 new LineNumberReader(
582 new InputStreamReader(data.getInputStream()));
583
584 // read/write a line at a time
585 String line = null;
586 while ((line = in.readLine()) != null) {
587 out.write(line, 0, line.length());
588 out.newLine();
589 }
590 out.close();
591
592 try {
593 in.close();
594 data.close();
595 }
596 catch (IOException ignore) {}
597 }
598
599
600 /**
601 * Get as binary file, i.e. straight transfer of data
602 *
603 * @param localPath full path of local file to write to
604 * @param remoteFile name of remote file
605 */
606 private void getBinary(String localPath, String remoteFile)
607 throws IOException, FTPException {
608
609 // create the buffered output stream for writing the file
610 BufferedOutputStream out =
611 new BufferedOutputStream(
612 new FileOutputStream(localPath, false));
613
614 initGet(remoteFile);
615
616 // get an input stream to read data from ... AFTER we have
617 // the ok to go ahead AND AFTER we've successfully opened a
618 // stream for the local file
619 BufferedInputStream in =
620 new BufferedInputStream(
621 new DataInputStream(data.getInputStream()));
622
623 // do the retrieving
624 int chunksize = 4096;
625 byte [] chunk = new byte[chunksize];
626 int count;
627
628 // read from socket & write to file in chunks
629 while ((count = in.read(chunk, 0, chunksize)) >= 0) {
630
631 out.write(chunk, 0, count);
632 }
633 out.close();
634
635 // close streams
636 try {
637 in.close();
638 data.close();
639 }
640 catch (IOException ignore) {}
641 }
642
643
644 /**
645 * Get data from the FTP server. Transfers in
646 * whatever mode we are in. Returns the
647 * InputStream for the FTP connection.
648 *
649 * @param remoteFile name of remote file in
650 * current directory
651 * @return InputStream handle to the FTP
652 * connection
653 * @author Michael Kandelaars
654 * @date Thursday, 4 July 2002 7:32:46 PM
655 */
656 public InputStream get(String remoteFile, long byteSkip)
657 throws IOException, FTPException {
658
659 String reply = "";
660
661 // set up data channel
662 data = control.createDataSocket(connectMode);
663 data.setTimeout(timeout);
664
665 if(byteSkip > 0) {
666 // send the rest command
667 reply = control.sendCommand("REST " + byteSkip);
668
669 // Can get a 350
670 String validCodes1 = "350";
671 control.validateReply(reply, validCodes1);
672 }
673
674 // send the retrieve command
675 reply = control.sendCommand("RETR " + remoteFile);
676
677 // Can get a 125 or a 150
678 String[] validCodes2 = {"125", "150"};
679 control.validateReply(reply, validCodes2);
680
681 return data.getInputStream();
682 }
683
684
685 public int getFileSize(String remoteFile)
686 throws IOException, FTPException {
687
688 String reply = "";
689
690 reply = control.sendCommand("SIZE " + remoteFile);
691
692 // Can get a 213
693 String validCodes = "213";
694 control.validateReply(reply, validCodes);
695
696 return Integer.parseInt(reply.substring(4));
697 }
698
699
700 /**
701 * Get data from the FTP server. Transfers in
702 * whatever mode we are in. Retrieve as a byte array. Note
703 * that we may experience memory limitations as the
704 * entire file must be held in memory at one time.
705 *
706 * @param remoteFile name of remote file in
707 * current directory
708 */
709 public byte[] get(String remoteFile)
710 throws IOException, FTPException {
711
712 // set up data channel
713 data = control.createDataSocket(connectMode);
714 data.setTimeout(timeout);
715
716 // send the retrieve command
717 String reply = control.sendCommand("RETR " + remoteFile);
718
719 // Can get a 125 or a 150
720 String[] validCodes1 = {"125", "150"};
721 control.validateReply(reply, validCodes1);
722
723 // get an input stream to read data from
724 BufferedInputStream in =
725 new BufferedInputStream(
726 new DataInputStream(data.getInputStream()));
727
728 // do the retrieving
729 int chunksize = 4096;
730 byte [] chunk = new byte[chunksize]; // read chunks into
731 byte [] resultBuf = new byte[chunksize]; // where we place chunks
732 byte [] temp = null; // temp swap buffer
733 int count; // size of chunk read
734 int bufsize = 0; // size of resultBuf
735
736 // read from socket & write to file
737 while ((count = in.read(chunk, 0, chunksize)) >= 0) {
738
739 // new buffer to hold current buf + new chunk
740 temp = new byte[bufsize+count];
741
742 // copy current buf to temp
743 System.arraycopy(resultBuf, 0, temp, 0, bufsize);
744
745 // copy new chunk onto end of temp
746 System.arraycopy(chunk, 0, temp, bufsize, count);
747
748 // re-assign temp buffer to buf
749 resultBuf = temp;
750
751 // update size of buffer
752 bufsize += count;
753 }
754
755 // close streams
756 try {
757 in.close();
758 data.close();
759 }
760 catch (IOException ignore) {}
761
762 // check the control response
763 String[] validCodes2 = {"226", "250"};
764 reply = control.readReply();
765 control.validateReply(reply, validCodes2);
766
767 return resultBuf;
768 }
769
770
771 /**
772 * Run a site-specific command on the
773 * server. Support for commands is dependent
774 * on the server
775 *
776 * @param command the site command to run
777 * @return true if command ok, false if
778 * command not implemented
779 */
780 public boolean site(String command)
781 throws IOException, FTPException {
782
783 // send the retrieve command
784 String reply = control.sendCommand("SITE " + command);
785
786 // Can get a 200 (ok) or 202 (not impl). Some
787 // FTP servers return 502 (not impl)
788 String[] validCodes = {"200", "202", "502"};
789 control.validateReply(reply, validCodes);
790
791 // return true or false? 200 is ok, 202/502 not
792 // implemented
793 if (reply.substring(0, 3).equals("200"))
794 return true;
795 else
796 return false;
797 }
798
799
800 /**
801 * List a directory's contents
802 *
803 * @param mask the file mask to use
804 * @return a string containing the line separated
805 * directory listing
806 * @deprecated As of FTP 1.1, replaced by {@link #dir(String)}
807 */
808 public String list(String mask)
809 throws IOException, FTPException {
810
811 return list(mask, false);
812 }
813
814
815 /**
816 * List a directory's contents as one string. A detailed
817 * listing is available, otherwise just filenames are provided.
818 * The detailed listing varies in details depending on OS and
819 * FTP server.
820 *
821 * @param mask the file mask to use
822 * @param full true if detailed listing required
823 * false otherwise
824 * @return a string containing the line separated
825 * directory listing
826 * @deprecated As of FTP 1.1, replaced by {@link #dir(String,boolean)}
827 */
828 public String list(String mask, boolean full)
829 throws IOException, FTPException {
830
831 String[] list = dir(mask, full);
832
833 StringBuffer result = new StringBuffer();
834 String sep = System.getProperty("line.separator");
835
836 // loop thru results and make into one string
837 for (int i = 0; i < list.length; i++) {
838 result.append(list[i]);
839 result.append(sep);
840 }
841
842 return result.toString();
843 }
844
845
846 /**
847 * List a directory's contents as an array of strings of filenames.
848 *
849 * @param mask the file mask to use
850 * @return an array of directory listing strings
851 */
852 public String[] dir(String mask)
853 throws IOException, FTPException {
854
855 return dir(mask, false);
856 }
857
858
859 /**
860 * List a directory's contents as an array of strings. A detailed
861 * listing is available, otherwise just filenames are provided.
862 * The detailed listing varies in details depending on OS and
863 * FTP server.
864 *
865 * @param mask the file mask to use
866 * @param full true if detailed listing required
867 * false otherwise
868 * @return an array of directory listing strings
869 */
870 public String[] dir(String mask, boolean full)
871 throws IOException, FTPException {
872
873 // set up data channel
874 data = control.createDataSocket(connectMode);
875 data.setTimeout(timeout);
876
877 // send the retrieve command
878 String command = full ? "LIST ":"NLST ";
879 command += mask;
880
881 // some FTP servers bomb out if NLST has whitespace appended
882 command = command.trim();
883 String reply = control.sendCommand(command);
884
885 // Can get a 125 or a 150
886 String[] validCodes1 = {"125", "150"};
887 control.validateReply(reply, validCodes1);
888
889 // get an character input stream to read data from ... AFTER we
890 // have the ok to go ahead
891 LineNumberReader in =
892 new LineNumberReader(
893 new InputStreamReader(data.getInputStream()));
894
895 // read a line at a time
896 Vector lines = new Vector();
897 String line = null;
898 while ((line = in.readLine()) != null) {
899 lines.add(line);
900 }
901
902 try {
903 in.close();
904 data.close();
905 }
906 catch (IOException ignore) {}
907
908 // check the control response
909 String[] validCodes2 = {"226", "250"};
910 reply = control.readReply();
911 control.validateReply(reply, validCodes2);
912
913 return (String[])lines.toArray(new String[0]);
914 }
915
916
917
918 /**
919 * Switch debug of responses on or off
920 *
921 * @param on true if you wish to have responses to
922 * stdout, false otherwise
923 */
924 public void debugResponses(boolean on) {
925
926 control.debugResponses(on);
927 }
928
929
930 /**
931 * Get the current transfer type
932 *
933 * @return the current type of the transfer,
934 * i.e. BINARY or ASCII
935 */
936 public FTPTransferType getType() {
937
938 return transferType;
939 }
940
941
942 /**
943 * Set the transfer type
944 *
945 * @param type the transfer type to
946 * set the server to
947 */
948 public void setType(FTPTransferType type)
949 throws IOException, FTPException {
950
951 // determine the character to send
952 String typeStr = FTPTransferType.ASCII_CHAR;
953 if (type.equals(FTPTransferType.BINARY))
954 typeStr = FTPTransferType.BINARY_CHAR;
955
956 // send the command
957 String reply = control.sendCommand("TYPE " + typeStr);
958 control.validateReply(reply, "200");
959
960 // record the type
961 transferType = type;
962 }
963
964
965 /**
966 * Delete the specified remote file
967 *
968 * @param remoteFile name of remote file to
969 * delete
970 */
971 public void delete(String remoteFile)
972 throws IOException, FTPException {
973
974 String reply = control.sendCommand("DELE " + remoteFile);
975 control.validateReply(reply, "250");
976 }
977
978
979 /**
980 * Rename a file or directory
981 *
982 * @param from name of file or directory to rename
983 * @param to intended name
984 */
985 public void rename(String from, String to)
986 throws IOException, FTPException {
987
988 String reply = control.sendCommand("RNFR " + from);
989 control.validateReply(reply, "350");
990
991 reply = control.sendCommand("RNTO " + to);
992 control.validateReply(reply, "250");
993 }
994
995
996 /**
997 * Delete the specified remote working directory
998 *
999 * @param dir name of remote directory to
1000 * delete
1001 */
1002 public void rmdir(String dir)
1003 throws IOException, FTPException {
1004
1005 String reply = control.sendCommand("RMD " + dir);
1006 control.validateReply(reply, "250");
1007 }
1008
1009
1010 /**
1011 * Create the specified remote working directory
1012 *
1013 * @param dir name of remote directory to
1014 * create
1015 */
1016 public void mkdir(String dir)
1017 throws IOException, FTPException {
1018
1019 String reply = control.sendCommand("MKD " + dir);
1020 control.validateReply(reply, "257");
1021 }
1022
1023
1024 /**
1025 * Change the remote working directory to
1026 * that supplied
1027 *
1028 * @param dir name of remote directory to
1029 * change to
1030 */
1031 public void chdir(String dir)
1032 throws IOException, FTPException {
1033
1034 String reply = control.sendCommand("CWD " + dir);
1035 control.validateReply(reply, "250");
1036 }
1037
1038
1039 /**
1040 * Get the current remote working directory
1041 *
1042 * @return the current working directory
1043 */
1044 public String pwd()
1045 throws IOException, FTPException {
1046
1047 String reply = control.sendCommand("PWD");
1048 control.validateReply(reply, "257");
1049 return reply.substring(4);
1050 }
1051
1052
1053 /**
1054 * Get the type of the OS at the server
1055 *
1056 * @return the type of server OS
1057 */
1058 public String system()
1059 throws IOException, FTPException {
1060
1061 String reply = control.sendCommand("SYST");
1062 control.validateReply(reply, "215");
1063 return reply.substring(4);
1064 }
1065
1066
1067 /**
1068 * Quit the FTP session
1069 *
1070 */
1071 public void quit()
1072 throws IOException, FTPException {
1073
1074 String reply = control.sendCommand("QUIT" + FTPControlSocket.EOL);
1075 control.validateReply(reply, "221");
1076
1077 control.logout();
1078 control = null;
1079 }
1080
1081}
1082
1083
1084