/[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.1 by dog, Sun Oct 19 08:51:37 2003 UTC revision 1.2 by dog, Sun Oct 19 16:16:49 2003 UTC
# Line 63  public class FTPConnection Line 63  public class FTPConnection
63     */     */
64    public static final int FTP_PORT = 21;    public static final int FTP_PORT = 21;
65    
66          /**          /**
67           * The FTP data port.           * The FTP data port.
68           */           */
69          public static final int FTP_DATA_PORT = 20;    public static final int FTP_DATA_PORT = 20;
70    
71          // -- FTP vocabulary --    // -- FTP vocabulary --
72          protected static final String USER = "USER";    protected static final String USER = "USER";
73          protected static final String PASS = "PASS";    protected static final String PASS = "PASS";
74          protected static final String ACCT = "ACCT";    protected static final String ACCT = "ACCT";
75          protected static final String CWD = "CWD";    protected static final String CWD = "CWD";
76          protected static final String CDUP = "CDUP";    protected static final String CDUP = "CDUP";
77          protected static final String SMNT = "SMNT";    protected static final String SMNT = "SMNT";
78          protected static final String REIN = "REIN";    protected static final String REIN = "REIN";
79          protected static final String QUIT = "QUIT";    protected static final String QUIT = "QUIT";
80            
81          protected static final String PORT = "PORT";    protected static final String PORT = "PORT";
82          protected static final String PASV = "PASV";    protected static final String PASV = "PASV";
83          protected static final String TYPE = "TYPE";    protected static final String TYPE = "TYPE";
84          protected static final String STRU = "STRU";    protected static final String STRU = "STRU";
85          protected static final String MODE = "MODE";    protected static final String MODE = "MODE";
86    
87          protected static final String RETR = "RETR";    protected static final String RETR = "RETR";
88          protected static final String STOR = "STOR";    protected static final String STOR = "STOR";
89          protected static final String STOU = "STOU";    protected static final String STOU = "STOU";
90          protected static final String APPE = "APPE";    protected static final String APPE = "APPE";
91          protected static final String ALLO = "ALLO";    protected static final String ALLO = "ALLO";
92          protected static final String REST = "REST";    protected static final String REST = "REST";
93          protected static final String RNFR = "RNFR";    protected static final String RNFR = "RNFR";
94          protected static final String RNTO = "RNTO";    protected static final String RNTO = "RNTO";
95          protected static final String ABOR = "ABOR";    protected static final String ABOR = "ABOR";
96          protected static final String DELE = "DELE";    protected static final String DELE = "DELE";
97          protected static final String RMD = "RMD";    protected static final String RMD = "RMD";
98          protected static final String MKD = "MKD";    protected static final String MKD = "MKD";
99          protected static final String PWD = "PWD";    protected static final String PWD = "PWD";
100          protected static final String LIST = "LIST";    protected static final String LIST = "LIST";
101          protected static final String NLST = "NLST";    protected static final String NLST = "NLST";
102          protected static final String SITE = "SITE";    protected static final String SITE = "SITE";
103          protected static final String SYST = "SYST";    protected static final String SYST = "SYST";
104          protected static final String STAT = "STAT";    protected static final String STAT = "STAT";
105          protected static final String HELP = "HELP";    protected static final String HELP = "HELP";
106          protected static final String NOOP = "NOOP";    protected static final String NOOP = "NOOP";
107    
108          public static final int TYPE_ASCII = 1;    public static final int TYPE_ASCII = 1;
109          public static final int TYPE_EBCDIC = 2;    public static final int TYPE_EBCDIC = 2;
110          public static final int TYPE_BINARY = 3;    public static final int TYPE_BINARY = 3;
111            
112          public static final int STRUCTURE_FILE = 1;    public static final int STRUCTURE_FILE = 1;
113          public static final int STRUCTURE_RECORD = 2;    public static final int STRUCTURE_RECORD = 2;
114          public static final int STRUCTURE_PAGE = 3;    public static final int STRUCTURE_PAGE = 3;
115            
116          public static final int MODE_STREAM = 1;    public static final int MODE_STREAM = 1;
117          public static final int MODE_BLOCK = 2;    public static final int MODE_BLOCK = 2;
118          public static final int MODE_COMPRESSED = 3;    public static final int MODE_COMPRESSED = 3;
119    
120          // -- Telnet constants --    // -- Telnet constants --
121          private static final String US_ASCII = "US-ASCII";    private static final String US_ASCII = "US-ASCII";
122          private static final byte[] CRLF = { 0x0d, 0x0a };    private static final byte[] CRLF = { 0x0d, 0x0a };
123    
124          /**          /**
125           * The socket used to communicate with the server.           * The socket used to communicate with the server.
126           */           */
127    protected Socket socket;    protected Socket socket;
128    
129          /**          /**
130           * The socket input stream.           * The socket input stream.
131           */           */
132    protected LineInputStream in;    protected LineInputStream in;
133    
134          /**          /**
135           * The socket output stream.           * The socket output stream.
136           */           */
137    protected OutputStream out;    protected OutputStream out;
138      
139          /**          /**
140           * If true, print debugging information.           * If true, print debugging information.
141           */           */
142          protected boolean debug;    protected boolean debug;
143    
144          /**          /**
145           * The current data transfer process in use by this connection.           * The current data transfer process in use by this connection.
146           */           */
147          protected DTP dtp;    protected DTP dtp;
148    
149          /**          /**
150           * The current representation type.           * The current representation type.
151           */           */
152          protected int representationType = TYPE_ASCII;    protected int representationType = TYPE_ASCII;
153    
154          /**          /**
155           * The current file structure type.           * The current file structure type.
156           */           */
157          protected int fileStructure = STRUCTURE_FILE;    protected int fileStructure = STRUCTURE_FILE;
158    
159          /**          /**
160           * The current transfer mode.           * The current transfer mode.
161           */           */
162          protected int transferMode = MODE_STREAM;    protected int transferMode = MODE_STREAM;
163    
164          /**          /**
165           * If true, use passive mode.           * If true, use passive mode.
166           */           */
167          protected boolean passive = false;    protected boolean passive = false;
168    
169    /**    /**
170     * Creates a new connection to the server using the default port.     * Creates a new connection to the server using the default port.
171           * @param hostname the hostname of the server to connect to           * @param hostname the hostname of the server to connect to
172     */     */
173    public FTPConnection(String hostname)    public FTPConnection(String hostname)
174                  throws UnknownHostException, IOException      throws UnknownHostException, IOException
175          {    {
176                  this(hostname, -1, -1, -1, false);      this(hostname, -1, -1, -1, false);
177          }    }
178            
179    /**    /**
180     * Creates a new connection to the server.     * Creates a new connection to the server.
181           * @param hostname the hostname of the server to connect to           * @param hostname the hostname of the server to connect to
182           * @param port the port to connect to (if <=0, use default port)           * @param port the port to connect to (if <=0, use default port)
183     */     */
184    public FTPConnection(String hostname, int port)    public FTPConnection(String hostname, int port)
185                  throws UnknownHostException, IOException      throws UnknownHostException, IOException
186          {    {
187                  this(hostname, port, -1, -1, false);      this(hostname, port, -1, -1, false);
188          }    }
189            
190    /**    /**
191     * Creates a new connection to the server.     * Creates a new connection to the server.
192           * @param hostname the hostname of the server to connect to           * @param hostname the hostname of the server to connect to
# Line 196  public class FTPConnection Line 196  public class FTPConnection
196           * @param debug print debugging information           * @param debug print debugging information
197     */     */
198    public FTPConnection(String hostname, int port,    public FTPConnection(String hostname, int port,
199                          int connectionTimeout, int timeout, boolean debug)                         int connectionTimeout, int timeout, boolean debug)
200                  throws UnknownHostException, IOException      throws UnknownHostException, IOException
201    {    {
202                  this.debug = debug;      this.debug = debug;
203      if (port<=0)      if (port <= 0)
204        port = FTP_PORT;        port = FTP_PORT;
205    
206                  // Set up socket      // Set up socket
207                  // TODO connection timeout      // TODO connection timeout
208                  socket = new Socket(hostname, port);      socket = new Socket(hostname, port);
209                  if (timeout>0)      if (timeout > 0)
210                          socket.setSoTimeout(timeout);        socket.setSoTimeout(timeout);
211                    
212                  InputStream in = socket.getInputStream();      InputStream in = socket.getInputStream();
213                  in = new BufferedInputStream(in);        in = new BufferedInputStream(in);
214                  in = new CRLFInputStream(in);        in = new CRLFInputStream(in);
215                  this.in = new LineInputStream(in);        this.in = new LineInputStream(in);
216                  OutputStream out = socket.getOutputStream();      OutputStream out = socket.getOutputStream();
217                  this.out = new BufferedOutputStream(out);        this.out = new BufferedOutputStream(out);
218    
219                  // Read greeting      // Read greeting
220                  FTPResponse response = getResponse();      FTPResponse response = getResponse();
221                  switch (response.getCode())      switch (response.getCode())
222                  {      {
223                          case 220: // hello      case 220:                  // hello
224                                  break;        break;
225                          default:        default:throw new FTPException(response);
226                                  throw new FTPException(response);      }
227                  }    }
         }  
228    
229          /**          /**
230           * Authenticate using the specified username and password.           * Authenticate using the specified username and password.
231           * If the username suffices for the server, the password will not be used           * If the username suffices for the server, the password will not be used
232           * and may be null.           * and may be null.
# Line 235  public class FTPConnection Line 234  public class FTPConnection
234           * @param password the optional password           * @param password the optional password
235           * @return true on success, false otherwise           * @return true on success, false otherwise
236           */           */
237          public boolean authenticate(String username, String password)    public boolean authenticate(String username, String password)
238                  throws IOException      throws IOException
239          {    {
240                  String cmd = new StringBuffer(USER)      String cmd =
241                          .append(' ')        new StringBuffer(USER).append(' ').append(username).toString();
242                          .append(username)        send(cmd);
243                          .toString();      FTPResponse response = getResponse();
244                  send(cmd);      switch (response.getCode())
245                  FTPResponse response = getResponse();      {
246                  switch (response.getCode())      case 230:                  // User logged in
247                  {        return true;
248                          case 230: // User logged in        case 331:                 // User name okay, need password
249                                  return true;        break;
250                          case 331: // User name okay, need password        case 332:                 // Need account for login
251                                  break;        case 530:                 // No such user
252                          case 332: // Need account for login        return false;
253                          case 530: // No such user        default:throw new FTPException(response);
254                                  return false;      }
255                          default:      cmd = new StringBuffer(PASS).append(' ').append(password).toString();
256                                  throw new FTPException(response);      send(cmd);
257                  }      response = getResponse();
258                  cmd = new StringBuffer(PASS)      switch (response.getCode())
259                          .append(' ')      {
260                          .append(password)      case 230:                  // User logged in
261                          .toString();      case 202:                  // Superfluous
262                  send(cmd);        return true;
263                  response = getResponse();      case 332:                  // Need account for login
264                  switch (response.getCode())      case 530:                  // Bad password
265                  {        return false;
266                          case 230: // User logged in      default:
267                          case 202: // Superfluous        throw new FTPException(response);
268                                  return true;      }
269                          case 332: // Need account for login    }
                         case 530: // Bad password  
                                 return false;  
                         default:  
                                 throw new FTPException(response);  
                 }  
         }  
270    
271          /**          /**
272           * Changes directory to the specified path.           * Changes directory to the specified path.
273           * @param path an absolute or relative pathname           * @param path an absolute or relative pathname
274           * @return true on success, false if the specified path does not exist           * @return true on success, false if the specified path does not exist
275           */           */
276          public boolean changeWorkingDirectory(String path)    public boolean changeWorkingDirectory(String path) throws IOException
277                  throws IOException    {
278          {      String cmd = new StringBuffer(CWD).append(' ').append(path).toString();
279                  String cmd = new StringBuffer(CWD)        send(cmd);
280                          .append(' ')      FTPResponse response = getResponse();
281                          .append(path)      switch (response.getCode())
282                          .toString();      {
283                  send(cmd);      case 250:
284                  FTPResponse response = getResponse();        return true;
285                  switch (response.getCode())        case 550:return false;
286                  {        default:throw new FTPException(response);
287                          case 250:      }
288                                  return true;    }
                         case 550:  
                                 return false;  
                         default:  
                                 throw new FTPException(response);  
                 }  
         }  
289    
290          /**          /**
291           * Changes directory to the parent of the current working directory.           * Changes directory to the parent of the current working directory.
292           * @return true on success, false otherwise           * @return true on success, false otherwise
293           */           */
294          public boolean changeToParentDirectory()    public boolean changeToParentDirectory() throws IOException
295                  throws IOException    {
296          {      send(CDUP);
297                  send(CDUP);      FTPResponse response = getResponse();
298                  FTPResponse response = getResponse();      switch (response.getCode())
299                  switch (response.getCode())      {
300                  {      case 250:
301                          case 250:        return true;
302                                  return true;        case 550:return false;
303                          case 550:        default:throw new FTPException(response);
304                                  return false;      }
305                          default:    }
                                 throw new FTPException(response);  
                 }  
         }  
306    
307          /**          /**
308           * Terminates an authenticated login.           * Terminates an authenticated login.
309           * If file transfer is in progress, it remains active for result response           * If file transfer is in progress, it remains active for result response
310           * only.           * only.
311           */           */
312          public void reinitialize()    public void reinitialize() throws IOException
313                  throws IOException    {
314          {      send(REIN);
315                  send(REIN);      FTPResponse response = getResponse();
316                  FTPResponse response = getResponse();      switch (response.getCode())
317                  switch (response.getCode())      {
318                  {      case 220:
319                          case 220:        if (dtp != null)
320                                  if (dtp!=null)        {
321                                  {          dtp.complete();
322                                          dtp.complete();          dtp = null;
323                                          dtp = null;        }
324                                  }        break;
325                                  break;      default:
326                          default:        throw new FTPException(response);
327                                  throw new FTPException(response);      }
328                  }    }
         }  
329    
330          /**          /**
331           * Terminates the control connection.           * Terminates the control connection.
332           * The file transfer connection remains open for result response only.           * The file transfer connection remains open for result response only.
333           * This connection is invalid and no further commands may be issued.           * This connection is invalid and no further commands may be issued.
334           */           */
335          public void logout()    public void logout() throws IOException
336                  throws IOException    {
337          {      send(QUIT);
338                  send(QUIT);      try
339                  try      {
340                  {        getResponse();            // not required
341                          getResponse(); // not required      }
342                  }      catch(IOException e)
343                  catch (IOException e)      {
344                  {      }
345                  }      if (dtp != null)
346                  if (dtp!=null)      {
347                  {        dtp.complete();
348                          dtp.complete();        dtp = null;
349                          dtp = null;      }
350                  }      try
351                  try      {
352                  {        socket.close();
353                          socket.close();      }
354                  }      catch(IOException e)
355                  catch (IOException e)      {
356                  {      }
357                  }    }
         }  
358    
359          /**          /**
360           * Initialise the data transfer process.           * Initialise the data transfer process.
361           */           */
362          protected void initialiseDTP()    protected void initialiseDTP() throws IOException
363                  throws IOException    {
364          {      if (dtp != null)
365                  if (dtp!=null)      {
366                  {        dtp.complete();
367                          dtp.complete();        dtp = null;
368                          dtp = null;      }
369                  }  
370                        InetAddress localhost = socket.getLocalAddress();
371                  InetAddress localhost = socket.getLocalAddress();      if (passive)
372                  if (passive)      {
373                  {        send(PASV);
374                          send(PASV);        FTPResponse response = getResponse();
375                          FTPResponse response = getResponse();        switch (response.getCode())
376                          switch (response.getCode())        {
377                          {        case 227:
378                                  case 227:          String message = response.getMessage();
379                                          String message = response.getMessage();          try
380                                          try          {
381                                          {            int start = message.indexOf(',');
382                                                  int start = message.indexOf(',');            char c = message.charAt(start - 1);
383                                                  char c = message.charAt(start-1);            while (c > 0x30 && c < 0x39)
384                                                  while (c>0x30 && c<0x39)              c = message.charAt((--start) - 1);
385                                                          c = message.charAt((--start)-1);            int mid1 = start;
386                                                  int mid1 = start;            for (int i = 0; i < 4; i++)
387                                                  for (int i=0; i<4; i++)              mid1 = message.indexOf(',', mid1 + 1);
388                                                          mid1 = message.indexOf(',', mid1+1);            int mid2 = message.indexOf(',', mid1 + 1);
389                                                  int mid2 = message.indexOf(',', mid1+1);            int end = mid2;
390                                                  int end = mid2;            c = message.charAt(end + 1);
391                                                  c = message.charAt(end+1);            while (c > 0x30 && c < 0x39)
392                                                  while (c>0x30 && c<0x39)              c = message.charAt((++end) + 1);
393                                                          c = message.charAt((++end)+1);  
394                                                              String address = message.substring(start, mid1).replace(',', '.');
395                                                  String address = message.substring(start, mid1).replace(',', '.');            int port_hi = Integer.parseInt(message.substring(mid1 + 1, mid2));
396                                                  int port_hi = Integer.parseInt(message.substring(mid1+1, mid2));            int port_lo =
397                                                  int port_lo = Integer.parseInt(message.substring(mid2+1, end+1));              Integer.parseInt(message.substring(mid2 + 1, end + 1));
398                                                  int port = (port_hi<<8) | port_lo;            int port = (port_hi << 8) | port_lo;
399                                                    
400                                                  System.out.println("Entering passive mode: "+address+":"+port);            System.out.println("Entering passive mode: " + address + ":" +
401                                                  dtp = new PassiveModeDTP(address, port, localhost);                               port);
402                                                  break;            dtp = new PassiveModeDTP(address, port, localhost);
403                                          }            break;
404                                          catch (ArrayIndexOutOfBoundsException e)          }
405                                          {          catch(ArrayIndexOutOfBoundsException e)
406                                                  throw new ProtocolException(e.getMessage()+": "+message);          {
407                                          }            throw new ProtocolException(e.getMessage() + ": " + message);
408                                          catch (NumberFormatException e)          }
409                                          {          catch(NumberFormatException e)
410                                                  throw new ProtocolException(e.getMessage()+": "+message);          {
411                                          }            throw new ProtocolException(e.getMessage() + ": " + message);
412                                  default:          }
413                                          throw new FTPException(response);        default:
414                          }          throw new FTPException(response);
415                  }        }
416                  else      }
417                  {      else
418                          // Get the local port      {
419                          int port = socket.getLocalPort()+1;        // Get the local port
420                          int tries = 0;        int port = socket.getLocalPort() + 1;
421                          // Bind the active mode DTP        int tries = 0;
422                          while (dtp==null)        // Bind the active mode DTP
423                          {        while (dtp == null)
424                                  try        {
425                                  {          try
426                                          dtp = new ActiveModeDTP(localhost, port);          {
427                                          System.out.println("Listening on: "+port);            dtp = new ActiveModeDTP(localhost, port);
428                                  }            System.out.println("Listening on: " + port);
429                                  catch (BindException e)          }
430                                  {          catch(BindException e)
431                                          port++;          {
432                                          tries++;            port++;
433                                          if (tries>9)            tries++;
434                                                  throw e;            if (tries > 9)
435                                  }              throw e;
436                          }          }
437                                  }
438                          // Send PORT command  
439                          StringBuffer buf = new StringBuffer(PORT);        // Send PORT command
440                          buf.append(' ');        StringBuffer buf = new StringBuffer(PORT);
441                          // Construct the address/port string form        buf.append(' ');
442                          byte[] address = localhost.getAddress();        // Construct the address/port string form
443                          for (int i=0; i<address.length; i++)        byte[]address = localhost.getAddress();
444                          {        for (int i = 0; i < address.length; i++)
445                                  int a = (int)address[i];        {
446                                  if (a<0)          int a = (int) address[i];
447                                          a += 0x100;          if (a < 0)
448                                  buf.append(a);            a += 0x100;
449                                  buf.append(',');          buf.append(a);
450                          }          buf.append(',');
451                          int port_hi = (port & 0xff00) >> 8;        }
452                          int port_lo = (port & 0x00ff);        int port_hi = (port & 0xff00) >> 8;
453                          buf.append(port_hi);        int port_lo = (port & 0x00ff);
454                          buf.append(',');        buf.append(port_hi);
455                          buf.append(port_lo);        buf.append(',');
456                          send(buf.toString());        buf.append(port_lo);
457                          // Get response        send(buf.toString());
458                          FTPResponse response = getResponse();        // Get response
459                          switch (response.getCode())        FTPResponse response = getResponse();
460                          {        switch (response.getCode())
461                                  case 200: // OK        {
462                                          break;        case 200:                // OK
463                                  default:          break;
464                                          dtp.abort();        default:
465                                          dtp = null;          dtp.abort();
466                                          throw new FTPException(response);          dtp = null;
467                          }          throw new FTPException(response);
468                  }        }
469                  dtp.setTransferMode(transferMode);      }
470          }      dtp.setTransferMode(transferMode);
471              }
472          /**  
473            /**
474           * Set passive mode.           * Set passive mode.
475           * @param flag true if we should use passive mode, false otherwise           * @param flag true if we should use passive mode, false otherwise
476           */           */
477          public void setPassive(boolean flag)    public void setPassive(boolean flag) throws IOException
478                  throws IOException    {
479          {      if (passive != flag)
480                  if (passive!=flag)      {
481                  {        passive = flag;
482                          passive = flag;        initialiseDTP();
483                          initialiseDTP();      }
484                  }    }
         }  
485    
486          /**          /**
487           * Returns the current representation type of the transfer data.           * Returns the current representation type of the transfer data.
488           * @return TYPE_ASCII, TYPE_EBCDIC, or TYPE_BINARY           * @return TYPE_ASCII, TYPE_EBCDIC, or TYPE_BINARY
489           */           */
490          public int getRepresentationType()    public int getRepresentationType()
491          {    {
492                  return representationType;      return representationType;
493          }    }
494    
495          /**          /**
496           * Sets the desired representation type of the transfer data.           * Sets the desired representation type of the transfer data.
497           * @param type TYPE_ASCII, TYPE_EBCDIC, or TYPE_BINARY           * @param type TYPE_ASCII, TYPE_EBCDIC, or TYPE_BINARY
498           */           */
499          public void setRepresentationType(int type)    public void setRepresentationType(int type) throws IOException
500                  throws IOException    {
501          {      StringBuffer buf = new StringBuffer(TYPE);
502                  StringBuffer buf = new StringBuffer(TYPE);        buf.append(' ');
503                  buf.append(' ');      switch (type)
504                  switch (type)      {
505                  {      case TYPE_ASCII:
506                          case TYPE_ASCII:        buf.append('A');
507                                  buf.append('A');        break;
508                                  break;        case TYPE_EBCDIC:buf.append('E');
509                          case TYPE_EBCDIC:        break;
510                                  buf.append('E');        case TYPE_BINARY:buf.append('I');
511                                  break;        break;
512                          case TYPE_BINARY:        default:throw new IllegalArgumentException(Integer.toString(type));
513                                  buf.append('I');      }
514                                  break;      //buf.append(' ');
515                          default:      //buf.append('N');
516                                  throw new IllegalArgumentException(Integer.toString(type));      send(buf.toString());
517                  }      FTPResponse response = getResponse();
518                  //buf.append(' ');      switch (response.getCode())
519                  //buf.append('N');      {
520                  send(buf.toString());      case 200:
521                  FTPResponse response = getResponse();        representationType = type;
522                  switch (response.getCode())        break;
523                  {      default:
524                          case 200:        throw new FTPException(response);
525                                  representationType = type;      }
526                                  break;    }
                         default:  
                                 throw new FTPException(response);  
                 }  
         }  
527    
528          /**          /**
529           * Returns the current file structure type.           * Returns the current file structure type.
530           * @return STRUCTURE_FILE, STRUCTURE_RECORD, or STRUCTURE_PAGE           * @return STRUCTURE_FILE, STRUCTURE_RECORD, or STRUCTURE_PAGE
531           */           */
532          public int getFileStructure()    public int getFileStructure()
533          {    {
534                  return fileStructure;      return fileStructure;
535          }    }
536            
537          /**          /**
538           * Sets the desired file structure type.           * Sets the desired file structure type.
539           * @param structure STRUCTURE_FILE, STRUCTURE_RECORD, or STRUCTURE_PAGE           * @param structure STRUCTURE_FILE, STRUCTURE_RECORD, or STRUCTURE_PAGE
540           */           */
541          public void setFileStructure(int structure)    public void setFileStructure(int structure) throws IOException
542                  throws IOException    {
543          {      StringBuffer buf = new StringBuffer(STRU);
544                  StringBuffer buf = new StringBuffer(STRU);        buf.append(' ');
545                  buf.append(' ');      switch (structure)
546                  switch (structure)      {
547                  {      case STRUCTURE_FILE:
548                          case STRUCTURE_FILE:        buf.append('F');
549                                  buf.append('F');        break;
550                                  break;        case STRUCTURE_RECORD:buf.append('R');
551                          case STRUCTURE_RECORD:        break;
552                                  buf.append('R');        case STRUCTURE_PAGE:buf.append('P');
553                                  break;        break;
554                          case STRUCTURE_PAGE:        default:throw new IllegalArgumentException(Integer.toString(structure));
555                                  buf.append('P');      }
556                                  break;      send(buf.toString());
557                          default:      FTPResponse response = getResponse();
558                                  throw new IllegalArgumentException(Integer.toString(structure));      switch (response.getCode())
559                  }      {
560                  send(buf.toString());      case 200:
561                  FTPResponse response = getResponse();        fileStructure = structure;
562                  switch (response.getCode())        break;
563                  {      default:
564                          case 200:        throw new FTPException(response);
565                                  fileStructure = structure;      }
566                                  break;    }
                         default:  
                                 throw new FTPException(response);  
                 }  
         }  
567    
568          /**          /**
569           * Returns the current transfer mode.           * Returns the current transfer mode.
570           * @return MODE_STREAM, MODE_BLOCK, or MODE_COMPRESSED           * @return MODE_STREAM, MODE_BLOCK, or MODE_COMPRESSED
571           */           */
572          public int getTransferMode()    public int getTransferMode()
573          {    {
574                  return transferMode;      return transferMode;
575          }    }
576            
577          /**          /**
578           * Sets the desired transfer mode.           * Sets the desired transfer mode.
579           * @param mode MODE_STREAM, MODE_BLOCK, or MODE_COMPRESSED           * @param mode MODE_STREAM, MODE_BLOCK, or MODE_COMPRESSED
580           */           */
581          public void setTransferMode(int mode)    public void setTransferMode(int mode) throws IOException
582                  throws IOException    {
583          {      StringBuffer buf = new StringBuffer(MODE);
584                  StringBuffer buf = new StringBuffer(MODE);        buf.append(' ');
585                  buf.append(' ');      switch (mode)
586                  switch (mode)      {
587                  {      case MODE_STREAM:
588                          case MODE_STREAM:        buf.append('S');
589                                  buf.append('S');        break;
590                                  break;        case MODE_BLOCK:buf.append('B');
591                          case MODE_BLOCK:        break;
592                                  buf.append('B');        case MODE_COMPRESSED:buf.append('C');
593                                  break;        break;
594                          case MODE_COMPRESSED:        default:throw new IllegalArgumentException(Integer.toString(mode));
595                                  buf.append('C');      }
596                                  break;      send(buf.toString());
597                          default:      FTPResponse response = getResponse();
598                                  throw new IllegalArgumentException(Integer.toString(mode));      switch (response.getCode())
599                  }      {
600                  send(buf.toString());      case 200:
601                  FTPResponse response = getResponse();        transferMode = mode;
602                  switch (response.getCode())        if (dtp != null)
603                  {          dtp.setTransferMode(mode);
604                          case 200:        break;
605                                  transferMode = mode;      default:
606                                  if (dtp!=null)        throw new FTPException(response);
607                                          dtp.setTransferMode(mode);      }
608                                  break;    }
                         default:  
                                 throw new FTPException(response);  
                 }  
         }  
609    
610          /**          /**
611           * Retrieves the specified file.           * Retrieves the specified file.
612           * @param filename the filename of the file to retrieve           * @param filename the filename of the file to retrieve
613           * @return an InputStream containing the file content           * @return an InputStream containing the file content
614           */           */
615          public InputStream retrieve(String filename)    public InputStream retrieve(String filename) throws IOException
616                  throws IOException    {
617          {      if (dtp == null || transferMode == MODE_STREAM)
618                  if (dtp==null || transferMode==MODE_STREAM)        initialiseDTP();
619                          initialiseDTP();      /*
620                  /*         int size = -1;
621                  int size = -1;         String cmd = new StringBuffer(SIZE)
622                  String cmd = new StringBuffer(SIZE)         .append(' ')
623                          .append(' ')         .append(filename)
624                          .append(filename)         .toString();
625                          .toString();         send(cmd);
626                  send(cmd);         FTPResponse response = getResponse();
627                  FTPResponse response = getResponse();         switch (response.getCode())
628                  switch (response.getCode())         {
629                  {         case 213:
630                          case 213:         size = Integer.parseInt(response.getMessage());
631                                  size = Integer.parseInt(response.getMessage());         break;
632                                  break;         case 550: // File not found
633                          case 550: // File not found         default:
634                          default:         throw new FTPException(response);
635                                  throw new FTPException(response);         }
636                  }       */
637                  */      String cmd =
638                  String cmd = new StringBuffer(RETR)        new StringBuffer(RETR).append(' ').append(filename).toString();
639                          .append(' ')        send(cmd);
640                          .append(filename)      FTPResponse response = getResponse();
641                          .toString();      switch (response.getCode())
642                  send(cmd);      {
643                  FTPResponse response = getResponse();      case 125:                  // Data connection already open; transfer starting
644                  switch (response.getCode())      case 150:                  // File status okay; about to open data connection
645                  {        return dtp.getInputStream();
646                          case 125: // Data connection already open; transfer starting        default:throw new FTPException(response);
647                          case 150: // File status okay; about to open data connection      }
648                                  return dtp.getInputStream();    }
                         default:  
                                 throw new FTPException(response);  
                 }  
         }  
649    
650          /**          /**
651           * Returns a stream for uploading a file.           * Returns a stream for uploading a file.
652           * If a file with the same filename already exists on the server, it will           * If a file with the same filename already exists on the server, it will
653           * be overwritten.           * be overwritten.
654           * @param filename the name of the file to save the content as           * @param filename the name of the file to save the content as
655           * @return an OutputStream to write the file data to           * @return an OutputStream to write the file data to
656           */           */
657          public OutputStream store(String filename)    public OutputStream store(String filename) throws IOException
658                  throws IOException    {
659          {      if (dtp == null || transferMode == MODE_STREAM)
660                  if (dtp==null || transferMode==MODE_STREAM)        initialiseDTP();
661                          initialiseDTP();      String cmd =
662                  String cmd = new StringBuffer(STOR)        new StringBuffer(STOR).append(' ').append(filename).toString();
663                          .append(' ')        send(cmd);
664                          .append(filename)      FTPResponse response = getResponse();
665                          .toString();      switch (response.getCode())
666                  send(cmd);      {
667                  FTPResponse response = getResponse();      case 125:                  // Data connection already open; transfer starting
668                  switch (response.getCode())      case 150:                  // File status okay; about to open data connection
669                  {        return dtp.getOutputStream();
670                          case 125: // Data connection already open; transfer starting        default:throw new FTPException(response);
671                          case 150: // File status okay; about to open data connection      }
672                                  return dtp.getOutputStream();    }
                         default:  
                                 throw new FTPException(response);  
                 }  
         }  
673    
674          /**          /**
675           * Returns a stream for uploading a file.           * Returns a stream for uploading a file.
676           * If a file with the same filename already exists on the server, the           * If a file with the same filename already exists on the server, the
677           * content specified will be appended to the existing file.           * content specified will be appended to the existing file.
678           * @param filename the name of the file to save the content as           * @param filename the name of the file to save the content as
679           * @return an OutputStream to write the file data to           * @return an OutputStream to write the file data to
680           */           */
681          public OutputStream append(String filename)    public OutputStream append(String filename) throws IOException
682                  throws IOException    {
683          {      if (dtp == null || transferMode == MODE_STREAM)
684                  if (dtp==null || transferMode==MODE_STREAM)        initialiseDTP();
685                          initialiseDTP();      String cmd =
686                  String cmd = new StringBuffer(APPE)        new StringBuffer(APPE).append(' ').append(filename).toString();
687                          .append(' ')        send(cmd);
688                          .append(filename)      FTPResponse response = getResponse();
689                          .toString();      switch (response.getCode())
690                  send(cmd);      {
691                  FTPResponse response = getResponse();      case 125:                  // Data connection already open; transfer starting
692                  switch (response.getCode())      case 150:                  // File status okay; about to open data connection
693                  {        return dtp.getOutputStream();
694                          case 125: // Data connection already open; transfer starting        default:throw new FTPException(response);
695                          case 150: // File status okay; about to open data connection      }
696                                  return dtp.getOutputStream();    }
                         default:  
                                 throw new FTPException(response);  
                 }  
         }  
697    
698          /**          /**
699           * This command may be required by some servers to reserve sufficient           * This command may be required by some servers to reserve sufficient
700           * storage to accommodate the new file to be transferred.           * storage to accommodate the new file to be transferred.
701           * It should be immediately followed by a <code>store</code> or           * It should be immediately followed by a <code>store</code> or
702           * <code>append</code>.           * <code>append</code>.
703           * @param size the number of bytes of storage to allocate           * @param size the number of bytes of storage to allocate
704           */           */
705          public void allocate(long size)    public void allocate(long size) throws IOException
706                  throws IOException    {
707          {      String cmd = new StringBuffer(ALLO).append(' ').append(size).toString();
708                  String cmd = new StringBuffer(ALLO)        send(cmd);
709                          .append(' ')      FTPResponse response = getResponse();
710                          .append(size)      switch (response.getCode())
711                          .toString();      {
712                  send(cmd);      case 200:                  // OK
713                  FTPResponse response = getResponse();      case 202:                  // Superfluous
714                  switch (response.getCode())        break;
715                  {        default:throw new FTPException(response);
716                          case 200: // OK      }
717                          case 202: // Superfluous    }
                                 break;  
                         default:  
                                 throw new FTPException(response);  
                 }  
         }  
718    
719          /**          /**
720           * Renames a file.           * Renames a file.
721           * @param oldName the current name of the file           * @param oldName the current name of the file
722           * @param newName the new name           * @param newName the new name
723           * @return true if successful, false otherwise           * @return true if successful, false otherwise
724           */           */
725          public boolean rename(String oldName, String newName)    public boolean rename(String oldName, String newName) throws IOException
726                  throws IOException    {
727          {      String cmd =
728                  String cmd = new StringBuffer(RNFR)        new StringBuffer(RNFR).append(' ').append(oldName).toString();
729                          .append(' ')        send(cmd);
730                          .append(oldName)      FTPResponse response = getResponse();
731                          .toString();      switch (response.getCode())
732                  send(cmd);      {
733                  FTPResponse response = getResponse();      case 450:                  // File unavailable
734                  switch (response.getCode())      case 550:                  // File not found
735                  {        return false;
736                          case 450: // File unavailable        case 350:                 // Pending
737                          case 550: // File not found        break;
738                                  return false;        default:throw new FTPException(response);
739                          case 350: // Pending      }
740                                  break;      cmd = new StringBuffer(RNTO).append(' ').append(newName).toString();
741                          default:      send(cmd);
742                                  throw new FTPException(response);      response = getResponse();
743                  }      switch (response.getCode())
744                  cmd = new StringBuffer(RNTO)      {
745                          .append(' ')      case 250:                  // OK
746                          .append(newName)        return true;
747                          .toString();      case 450:
748                  send(cmd);      case 550:
749                  response = getResponse();        return false;
750                  switch (response.getCode())      default:
751                  {        throw new FTPException(response);
752                          case 250: // OK      }
753                                  return true;    }
                         case 450:  
                         case 550:  
                                 return false;  
                         default:  
                                 throw new FTPException(response);  
                 }  
         }  
754    
755          /**          /**
756           * Aborts the transfer in progress.           * Aborts the transfer in progress.
757           * @return true if a transfer was in progress, false otherwise           * @return true if a transfer was in progress, false otherwise
758           */           */
759          public boolean abort()    public boolean abort() throws IOException
760                  throws IOException    {
761          {      send(ABOR);
762                  send(ABOR);      FTPResponse response = getResponse();
763                  FTPResponse response = getResponse();      // Abort client DTP
764                  // Abort client DTP      if (dtp != null)
765                  if (dtp!=null)          dtp.abort();
766                                  dtp.abort();      switch (response.getCode())
767                  switch (response.getCode())      {
768                  {      case 226:                  // successful abort
769                          case 226: // successful abort        return false;
770                                  return false;        case 426:                 // interrupted
771                          case 426: // interrupted        response = getResponse();
772                                  response = getResponse();        if (response.getCode() == 226)
773                                  if (response.getCode()==226)          return true;
774                                          return true;        default:throw new FTPException(response);
775                          default:      }
776                                  throw new FTPException(response);    }
                 }  
         }  
777    
778          /**          /**
779           * Causes the file specified to be deleted at the server site.           * Causes the file specified to be deleted at the server site.
780           * @param filename the file to delete           * @param filename the file to delete
781           */           */
782          public boolean delete(String filename)    public boolean delete(String filename) throws IOException
783                  throws IOException    {
784          {      String cmd =
785                   String cmd = new StringBuffer(DELE)        new StringBuffer(DELE).append(' ').append(filename).toString();
786                           .append(' ')        send(cmd);
787                           .append(filename)      FTPResponse response = getResponse();
788                           .toString();      switch (response.getCode())
789                   send(cmd);      {
790                   FTPResponse response = getResponse();      case 250:                  // OK
791                   switch (response.getCode())        return true;
792                   {        case 450:                 // File unavailable
793                           case 250: // OK        case 550:                 // File not found
794                                   return true;        return false;
795                           case 450: // File unavailable        default:throw new FTPException(response);
796                           case 550: // File not found      }
797                                   return false;    }
                          default:  
                                 throw new FTPException(response);  
                  }  
         }  
798    
799          /**          /**
800           * Causes the directory specified to be deleted.           * Causes the directory specified to be deleted.
801           * This may be an absolute or relative pathname.           * This may be an absolute or relative pathname.
802           * @param pathname the directory to delete           * @param pathname the directory to delete
803           */           */
804          public boolean removeDirectory(String pathname)    public boolean removeDirectory(String pathname) throws IOException
805                  throws IOException    {
806          {      String cmd =
807                   String cmd = new StringBuffer(RMD)        new StringBuffer(RMD).append(' ').append(pathname).toString();
808                           .append(' ')        send(cmd);
809                           .append(pathname)      FTPResponse response = getResponse();
810                           .toString();      switch (response.getCode())
811                   send(cmd);      {
812                   FTPResponse response = getResponse();      case 250:                  // OK
813                   switch (response.getCode())        return true;
814                   {        case 550:                 // File not found
815                           case 250: // OK        return false;
816                                   return true;        default:throw new FTPException(response);
817                           case 550: // File not found      }
818                                   return false;    }
                          default:  
                                 throw new FTPException(response);  
                  }  
         }  
819    
820          /**          /**
821           * Causes the directory specified to be created at the server site.           * Causes the directory specified to be created at the server site.
822           * This may be an absolute or relative pathname.           * This may be an absolute or relative pathname.
823           * @param pathname the directory to create           * @param pathname the directory to create
824           */           */
825          public boolean makeDirectory(String pathname)    public boolean makeDirectory(String pathname) throws IOException
826                  throws IOException    {
827          {      String cmd =
828                   String cmd = new StringBuffer(MKD)        new StringBuffer(MKD).append(' ').append(pathname).toString();
829                           .append(' ')        send(cmd);
830                           .append(pathname)      FTPResponse response = getResponse();
831                           .toString();      switch (response.getCode())
832                   send(cmd);      {
833                   FTPResponse response = getResponse();      case 257:                  // Directory created
834                   switch (response.getCode())        return true;
835                   {        case 550:                 // File not found
836                           case 257: // Directory created        return false;
837                                   return true;        default:throw new FTPException(response);
838                           case 550: // File not found      }
839                                   return false;    }
                          default:  
                                 throw new FTPException(response);  
                  }  
         }  
840    
841          /**          /**
842           * Returns the current working directory.           * Returns the current working directory.
843           */           */
844          public String getWorkingDirectory()    public String getWorkingDirectory() throws IOException
845                  throws IOException    {
846          {      send(PWD);
847                  send(PWD);      FTPResponse response = getResponse();
848                  FTPResponse response = getResponse();      switch (response.getCode())
849                  switch (response.getCode())      {
850                  {      case 257:
851                          case 257:        String message = response.getMessage();
852                                  String message = response.getMessage();        if (message.charAt(0) == '"')
853                                  if (message.charAt(0)=='"')        {
854                                  {          int end = message.indexOf('"', 1);
855                                          int end = message.indexOf('"', 1);          if (end == -1)
856                                          if (end==-1)            throw new ProtocolException(message);
857                                                  throw new ProtocolException(message);            return message.substring(1, end);
858                                          return message.substring(1, end);        }
859                                  }        else
860                                  else        {
861                                  {          int end = message.indexOf(' ');
862                                          int end = message.indexOf(' ');          if (end == -1)
863                                          if (end==-1)            return message;
864                                                  return message;          else
865                                          else            return message.substring(0, end);
866                                                  return message.substring(0, end);        }
867                                  }      default:
868                          default:        throw new FTPException(response);
869                                  throw new FTPException(response);      }
870                  }    }
         }  
871    
872          /**          /**
873           * Returns a listing of information about the specified pathname.           * Returns a listing of information about the specified pathname.
874           * If the pathname specifies a directory or other group of files, the           * If the pathname specifies a directory or other group of files, the
875           * server should transfer a list of files in the specified directory.           * server should transfer a list of files in the specified directory.
# Line 947  public class FTPConnection Line 878  public class FTPConnection
878           * current working or default directory.           * current working or default directory.
879           * @param pathname the context pathname, or null           * @param pathname the context pathname, or null
880           */           */
881          public InputStream list(String pathname)    public InputStream list(String pathname) throws IOException
882                  throws IOException    {
883          {      if (dtp == null || transferMode == MODE_STREAM)
884                  if (dtp==null || transferMode==MODE_STREAM)        initialiseDTP();
885                          initialiseDTP();      if (pathname == null)
886                  if (pathname==null)        send(LIST);
887                          send(LIST);      else
888                  else      {
889                  {        String cmd =
890                          String cmd = new StringBuffer(LIST)          new StringBuffer(LIST).append(' ').append(pathname).toString();
891                                  .append(' ')          send(cmd);
892                                  .append(pathname)      }
893                                  .toString();      FTPResponse response = getResponse();
894                          send(cmd);      switch (response.getCode())
895                  }      {
896                  FTPResponse response = getResponse();      case 125:                  // Data connection already open; transfer starting
897                  switch (response.getCode())      case 150:                  // File status okay; about to open data connection
898                  {        return dtp.getInputStream();
899                          case 125: // Data connection already open; transfer starting      default:
900                          case 150: // File status okay; about to open data connection        throw new FTPException(response);
901                                  return dtp.getInputStream();      }
902                          default:    }
                                 throw new FTPException(response);  
                 }  
         }  
903    
904          /**          /**
905           * Returns a directory listing. The pathname should specify a           * Returns a directory listing. The pathname should specify a
906           * directory or other system-specific file group descriptor; a null           * directory or other system-specific file group descriptor; a null
907           * argument implies the user's current working or default directory.           * argument implies the user's current working or default directory.
908           * @param pathname the directory pathname, or null           * @param pathname the directory pathname, or null
909           * @return a list of filenames (strings)           * @return a list of filenames (strings)
910           */           */
911          public List nameList(String pathname)    public List nameList(String pathname) throws IOException
912                  throws IOException    {
913          {      if (dtp == null || transferMode == MODE_STREAM)
914                  if (dtp==null || transferMode==MODE_STREAM)        initialiseDTP();
915                          initialiseDTP();      if (pathname == null)
916                  if (pathname==null)        send(NLST);
917                          send(NLST);      else
918                  else      {
919                  {        String cmd =
920                          String cmd = new StringBuffer(NLST)          new StringBuffer(NLST).append(' ').append(pathname).toString();
921                                  .append(' ')          send(cmd);
922                                  .append(pathname)      }
923                                  .toString();      FTPResponse response = getResponse();
924                          send(cmd);      switch (response.getCode())
925                  }      {
926                  FTPResponse response = getResponse();      case 125:                  // Data connection already open; transfer starting
927                  switch (response.getCode())      case 150:                  // File status okay; about to open data connection
928                  {        InputStream in = dtp.getInputStream();
929                          case 125: // Data connection already open; transfer starting        in = new BufferedInputStream(in);
930                          case 150: // File status okay; about to open data connection        in = new CRLFInputStream(in);     // TODO ensure that TYPE is correct
931                                  InputStream in = dtp.getInputStream();        LineInputStream li = new LineInputStream(in);
932                                  in = new BufferedInputStream(in);        List ret = new ArrayList();
933                                  in = new CRLFInputStream(in); // TODO ensure that TYPE is correct        for (String line = li.readLine(); line != null; line = li.readLine())
934                                  LineInputStream li = new LineInputStream(in);          ret.add(line);
935                                  List ret = new ArrayList();        li.close();
936                                  for (String line = li.readLine(); line!=null; line = li.readLine())        return ret;
937                                          ret.add(line);      default:
938                                  li.close();        throw new FTPException(response);
939                                  return ret;      }
940                          default:    }
                                 throw new FTPException(response);  
                 }  
         }  
941    
942          /**          /**
943           * Returns the type of operating system at the server.           * Returns the type of operating system at the server.
944           */           */
945          public String system()    public String system() throws IOException
946                  throws IOException    {
947          {      send(SYST);
948                  send(SYST);      FTPResponse response = getResponse();
949                  FTPResponse response = getResponse();      switch (response.getCode())
950                  switch (response.getCode())      {
951                  {      case 215:
952                          case 215:        String message = response.getMessage();
953                                  String message = response.getMessage();        int end = message.indexOf(' ');
954                                  int end = message.indexOf(' ');        if (end == -1)
955                                  if (end==-1)          return message;
956                                          return message;        else
957                                  else            return message.substring(0, end);
958                                          return message.substring(0, end);        default:throw new FTPException(response);
959                          default:      }
960                                  throw new FTPException(response);    }
                 }  
         }  
961    
962          /**          /**
963           * Does nothing.           * Does nothing.
964           * 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
965           * out.           * out.
966           */           */
967          public void noop()    public void noop() throws IOException
968                  throws IOException    {
969          {      send(NOOP);
970                  send(NOOP);      FTPResponse response = getResponse();
971                  FTPResponse response = getResponse();      switch (response.getCode())
972                  switch (response.getCode())      {
973                  {      case 200:
974                          case 200:        break;
975                                  break;        default:throw new FTPException(response);
976                          default:      }
977                                  throw new FTPException(response);    }
                 }  
         }  
978    
979          // -- I/O --    // -- I/O --
980    
981          /**          /**
982           * Sends the specified command line to the server.           * Sends the specified command line to the server.
983           * The CRLF sequence is automatically appended.           * The CRLF sequence is automatically appended.
984           * @param cmd the command line to send           * @param cmd the command line to send
985           */           */
986          protected void send(String cmd)    protected void send(String cmd) throws IOException
987                  throws IOException    {
988          {      byte[] data = cmd.getBytes(US_ASCII);
989                  byte[] data = cmd.getBytes(US_ASCII);      out.write(data);
990                  out.write(data);      out.write(CRLF);
991                  out.write(CRLF);      out.flush();
992                  out.flush();    }
         }  
993    
994          /**          /**
995           * Reads the next response from the server.           * Reads the next response from the server.
996           * If the server sends the "transfer complete" code, this is handled here,           * If the server sends the "transfer complete" code, this is handled here,
997           * and the next response is passed to the caller.           * and the next response is passed to the caller.
998           */           */
999          protected FTPResponse getResponse()    protected FTPResponse getResponse() throws IOException
1000                  throws IOException    {
1001          {      FTPResponse response = readResponse();
1002                  FTPResponse response = readResponse();      if (response.getCode() == 226)
1003                  if (response.getCode()==226)      {
1004                  {        if (dtp != null)
1005                          if (dtp!=null)          dtp.transferComplete();
1006                                  dtp.transferComplete();        response = readResponse();
1007                          response = readResponse();      }
1008                  }      return response;
1009                  return response;    }
         }  
1010    
1011          /**          /**
1012           * Reads and parses the next response from the server.           * Reads and parses the next response from the server.
1013           */           */
1014          protected FTPResponse readResponse()    protected FTPResponse readResponse() throws IOException
1015                  throws IOException    {
1016          {      String line = in.readLine();
1017                  String line = in.readLine();      if (line == null)
1018                  if (line==null)        throw new ProtocolException("EOF");
1019                          throw new ProtocolException("EOF");      if (line.length() < 4)
1020                  if (line.length()<4)        throw new ProtocolException(line);
1021                          throw new ProtocolException(line);      int code = parseCode(line);
1022                  int code = parseCode(line);      if (code == -1)
1023                  if (code==-1)        throw new ProtocolException(line);
1024                          throw new ProtocolException(line);      char c = line.charAt(3);
1025                  char c = line.charAt(3);      if (c == ' ')
1026                  if (c==' ')        return new FTPResponse(code, line.substring(4));
1027                          return new FTPResponse(code, line.substring(4));      else if (c == '-')
1028                  else if (c=='-')      {
1029                  {        StringBuffer buf = new StringBuffer(line.substring(4));
1030                          StringBuffer buf = new StringBuffer(line.substring(4));          buf.append('\n');
1031                          buf.append('\n');        while (true)
1032                          while (true)        {
1033                          {          line = in.readLine();
1034                                  line = in.readLine();          if (line == null)
1035                                  if (line==null)            throw new ProtocolException("EOF");
1036                                          throw new ProtocolException("EOF");          if (line.length() >= 4 && line.charAt(3) == ' '
1037                                  if (line.length()>=4 && line.charAt(3)==' ' && parseCode(line)==code)              && parseCode(line) == code)
1038                                          return new FTPResponse(code, line.substring(4), buf.toString());            return new FTPResponse(code, line.substring(4), buf.toString());
1039                                  else          else
1040                                  {          {
1041                                          buf.append(line);            buf.append(line);
1042                                          buf.append('\n');            buf.append('\n');
1043                                  }          }
1044                                            
1045                          }        }
1046                  }      }
1047                  else      else
1048                          throw new ProtocolException(line);          throw new ProtocolException(line);
1049          }    }
1050    
1051          /*    /*
1052           * 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.
1053           * Returns -1 on failure.     * Returns -1 on failure.
1054           */     */
1055          static final int parseCode(String line)    static final int parseCode(String line)
1056          {    {
1057                  char[] c = { line.charAt(0), line.charAt(1), line.charAt(2) };      char[] c = { line.charAt(0), line.charAt(1), line.charAt(2) };
1058                  int ret = 0;      int ret = 0;
1059                  for (int i=0; i<3; i++)      for (int i = 0; i < 3; i++)
1060                  {      {
1061                          int digit = ((int)c[i])-0x30;        int digit = ((int) c[i]) - 0x30;
1062                          if (digit<0 || digit>9)        if (digit < 0 || digit > 9)
1063                                  return -1;          return -1;
1064                          // Computing integer powers is way too expensive in Java!        // Computing integer powers is way too expensive in Java!
1065                          switch (i)        switch (i)
1066                          {        {
1067                                  case 0:        case 0:
1068                                          ret += (100*digit);          ret += (100 * digit);
1069                                          break;          break;
1070                                  case 1:        case 1:
1071                                          ret += (10*digit);          ret += (10 * digit);
1072                                          break;          break;
1073                                  case 2:        case 2:
1074                                          ret += digit;          ret += digit;
1075                                          break;          break;
1076                          }        }
1077                  }      }
1078                  return ret;      return ret;
1079          }    }
1080    
1081  }  }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

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