001/*
002 * Version 0.70 01/04/2002
003 *
004 * Visit my url for update: http://www.geocities.com/beapetrovicova/
005 * 
006 * jFtp was developed by Bea Petrovicova <beapetrovicova@yahoo.com>.
007 * The design and implementation of jFtp are available for royalty-free 
008 * adoption and use. This software is provided 'as is' without any 
009 * guarantees. Copyright is retained by Bea Petrovicova. Redistribution 
010 * of any part of jFtp or any derivative works must include this notice.
011 * 
012 */  
013
014package cz.dhl.ftp;
015
016import java.io.BufferedReader;
017import java.io.BufferedWriter;
018import java.io.IOException;
019import java.io.InputStream;
020import java.io.InputStreamReader;
021import java.io.OutputStream;
022import java.io.OutputStreamWriter;
023import java.io.Reader;
024import java.io.Writer;
025import java.net.InetAddress;
026import java.net.Socket;
027import java.net.UnknownHostException;
028
029final class FtpControlSocket
030{
031   private Socket control = null;
032   
033   private BufferedReader in  = null;
034   private BufferedWriter out  = null;
035   
036   private FtpContext context = null;
037   private String replyline = null;
038   String server = null;
039   
040   FtpControlSocket(FtpContext context) {this.context = context;}
041   
042   synchronized boolean connect(String server,int port)
043   {  boolean done = false;
044
045      if(control==null)
046      {  try
047         {  /* Get host name */
048            context.printlog("Getting host by name: " + server);
049            InetAddress addr = InetAddress.getByName(server);
050      
051            /* Connect to host */
052            context.printlog("Connecting to host: " + addr.getHostAddress());
053            control = new Socket(addr, port); 
054            control.setSoTimeout(60000);
055
056            /* Open input / output streams */
057            in = new BufferedReader(new InputStreamReader(control.getInputStream()));
058            out = new BufferedWriter(new OutputStreamWriter(control.getOutputStream()));
059
060            this.server = server;
061            done = true;
062         }
063         catch(UnknownHostException e)
064         {  context.printlog("< Ctrl: Can't resolve host address! >"); }
065         catch(IOException e)
066         {  disconnect();
067            context.printlog("< Ctrl: Can't obtain connection to host! >"); }
068         catch (Exception e) 
069         {  context.printlog("< Ctrl: Permission denied! >"); }
070      }
071      return done;
072   }
073   
074   synchronized void disconnect()
075   {  while(in!=null || out!=null)
076      {  try 
077         {  Reader r; Writer w;
078            if(in!=null) { r=in; in=null; r.close(); }
079            if(out!=null) { w=out; out=null; w.close(); }
080         } catch(IOException e) { context.printerr(e); }
081      }
082      
083      if(control!=null)
084      {
085         try {  control.close(); }
086         catch(IOException e) { context.printerr(e); }
087         finally
088         {  control=null; 
089            context.printlog("< Ctrl: Disconnected! >"); }
090      }
091      server = null; 
092   }
093   
094   private synchronized void writeLine(String line) throws IOException
095   {  if(out!=null) 
096      {  try
097            { out.write(line + "\r\n"); out.flush(); }
098         catch(IOException e)
099            { throw new IOException("Ctrl: Write, failed!\n"+e); }
100      } else throw new IOException("Ctrl: Write, No connection!");
101   }
102      
103   private synchronized String readLine()  throws IOException
104   {  String line = null;
105      if(in!=null) 
106      {  try
107            { line = in.readLine(); }
108         catch(IOException e)
109            { throw new IOException("Ctrl: Read, Error!\n"+e); }
110         if(line == null)
111         {  disconnect(); /* NULL on END OF THE STREAM */
112            throw new IOException("Ctrl: Read, End Of File!"); 
113         } 
114      } else throw new IOException("Ctrl: Read, No connection!");
115      return line;
116   }
117
118   private synchronized String readReply() throws IOException
119   {  String line = null;
120      do 
121      {  line=readLine(); 
122         context.printlog(line);
123           /* Skip empty lines */
124      } while(line.length()==0 ||
125           /* Skip intermediate replies. */
126              line.indexOf("-")==3 ||
127           /* Skip lines that don't start with digit */
128              "0123456789".indexOf(line.charAt(0))<0);
129      return line;
130   }
131
132   synchronized boolean manualCommand(String commandline)
133   {  if(!FtpInterpret.allowManualExecution(commandline))
134      {  context.printlog("< Ctrl: Command, No Manual Execution! >");
135         return false;
136      } else return executeCommand(commandline);
137   }
138   
139   synchronized boolean executeCommand(String commandline)
140   {  if(writeCommand(commandline))
141         return completeCommand(FtpInterpret.getReplies(commandline));
142      else return false; }
143   
144   synchronized boolean writeCommand(String commandline) 
145   {  if(commandline.startsWith("PASS"))
146         context.printlog("Ftp> PASS ******");
147      else context.printlog("Ftp> " + commandline);
148      if(!FtpInterpret.allowExecution(commandline))
149      {  context.printlog("< Ctrl: Command, Not Implemented! >");
150         return false;
151      } else
152      {  boolean done = true;
153         try
154         {  replyline = null;
155            writeLine(commandline.trim());
156         } catch (IOException e) 
157         {  done = false; 
158            if(e.getMessage()!=null) 
159               context.printlog("< "+e.getMessage()+" >");
160            else context.printerr(e); }
161         return done;
162      }
163   }
164
165   synchronized boolean completeCommand(String replies[])
166   {  boolean done = false; 
167      try
168      {  replyline=readReply(); 
169         done = FtpInterpret.startsWith(replyline,replies);
170      } catch (IOException e)
171      {  if(e.getMessage()!=null) 
172            context.printlog("< "+e.getMessage()+" >");
173         else context.printerr(e); }
174      return done;
175   }
176
177   String replyOfCommand() throws IOException
178   {  if(replyline != null) 
179         return replyline; 
180      else throw new IOException("Ctrl: No Reply!"); }
181
182   boolean isConnected() { return (control!=null); }
183}