/[classpath]/inetlib/source/gnu/inet/ftp/FTPConnection.java
ViewVC logotype

Diff of /inetlib/source/gnu/inet/ftp/FTPConnection.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.10 by dog, Thu Oct 21 15:21:54 2004 UTC revision 1.11 by dog, Thu Nov 25 22:15:05 2004 UTC
# Line 1  Line 1 
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.
# Line 73  import gnu.inet.util.LineInputStream; Line 73  import gnu.inet.util.LineInputStream;
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  {  {
# Line 205  public class FTPConnection Line 204  public class FTPConnection
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 &lt;=0, use default port)     * @param port the port to connect to(if &lt;=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 &lt;=0, use default port)     * @param port the port to connect to(if &lt;=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    {    {
# Line 243  public class FTPConnection Line 242  public class FTPConnection
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        
# Line 285  public class FTPConnection Line 284  public class FTPConnection
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;
# Line 301  public class FTPConnection Line 300  public class FTPConnection
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
# Line 315  public class FTPConnection Line 314  public class FTPConnection
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    
# Line 325  public class FTPConnection Line 324  public class FTPConnection
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    /**    /**
# Line 338  public class FTPConnection Line 337  public class FTPConnection
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:
# Line 364  public class FTPConnection Line 363  public class FTPConnection
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
# Line 387  public class FTPConnection Line 386  public class FTPConnection
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
# Line 400  public class FTPConnection Line 399  public class FTPConnection
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        }        }
# Line 427  public class FTPConnection Line 426  public class FTPConnection
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        
# Line 448  public class FTPConnection Line 447  public class FTPConnection
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    
# Line 469  public class FTPConnection Line 468  public class FTPConnection
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    
# Line 493  public class FTPConnection Line 492  public class FTPConnection
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        {        {
# Line 521  public class FTPConnection Line 520  public class FTPConnection
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                {                {
# Line 619  public class FTPConnection Line 618  public class FTPConnection
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        
# Line 672  public class FTPConnection Line 671  public class FTPConnection
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    }    }
# Line 681  public class FTPConnection Line 680  public class FTPConnection
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    
# Line 718  public class FTPConnection Line 717  public class FTPConnection
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    }    }
# Line 727  public class FTPConnection Line 726  public class FTPConnection
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    
# Line 762  public class FTPConnection Line 761  public class FTPConnection
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    }    }
# Line 771  public class FTPConnection Line 770  public class FTPConnection
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        
# Line 811  public class FTPConnection Line 810  public class FTPConnection
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        
# Line 853  public class FTPConnection Line 852  public class FTPConnection
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    
# Line 880  public class FTPConnection Line 879  public class FTPConnection
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        
# Line 907  public class FTPConnection Line 906  public class FTPConnection
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        
# Line 929  public class FTPConnection Line 928  public class FTPConnection
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
# Line 943  public class FTPConnection Line 942  public class FTPConnection
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;
# Line 956  public class FTPConnection Line 955  public class FTPConnection
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        
# Line 964  public class FTPConnection Line 963  public class FTPConnection
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        
# Line 994  public class FTPConnection Line 993  public class FTPConnection
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;
# Line 1008  public class FTPConnection Line 1007  public class FTPConnection
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        
# Line 1017  public class FTPConnection Line 1016  public class FTPConnection
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    
# Line 1039  public class FTPConnection Line 1038  public class FTPConnection
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        
# Line 1103  public class FTPConnection Line 1102  public class FTPConnection
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        
# Line 1135  public class FTPConnection Line 1134  public class FTPConnection
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        
# Line 1207  public class FTPConnection Line 1206  public class FTPConnection
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    
# Line 1228  public class FTPConnection Line 1227  public class FTPConnection
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    /**    /**
# Line 1242  public class FTPConnection Line 1241  public class FTPConnection
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    }    }
# Line 1260  public class FTPConnection Line 1259  public class FTPConnection
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        
# Line 1317  public class FTPConnection Line 1316  public class FTPConnection
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;
# Line 1332  public class FTPConnection Line 1331  public class FTPConnection
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;
# Line 1346  public class FTPConnection Line 1345  public class FTPConnection
1345    }    }
1346    
1347  }  }
1348    

Legend:
Removed from v.1.10  
changed lines
  Added in v.1.11

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26