KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > drftpd > master > BaseFtpConnection


1 /*
2  * This file is part of DrFTPD, Distributed FTP Daemon.
3  *
4  * DrFTPD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * DrFTPD is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with DrFTPD; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package net.sf.drftpd.master;
19
20 import java.io.BufferedReader JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.InputStreamReader JavaDoc;
23 import java.io.InterruptedIOException JavaDoc;
24 import java.io.OutputStreamWriter JavaDoc;
25 import java.io.PrintWriter JavaDoc;
26 import java.net.InetAddress JavaDoc;
27 import java.net.Socket JavaDoc;
28 import java.net.SocketException JavaDoc;
29 import java.rmi.RemoteException JavaDoc;
30
31 import javax.net.ServerSocketFactory;
32 import javax.net.SocketFactory;
33 import javax.net.ssl.SSLSocket;
34
35 import net.sf.drftpd.Bytes;
36 import net.sf.drftpd.ObjectNotFoundException;
37 import net.sf.drftpd.event.Event;
38 import net.sf.drftpd.event.UserEvent;
39 import net.sf.drftpd.master.command.CommandManager;
40 import net.sf.drftpd.master.command.plugins.DataConnectionHandler;
41 import net.sf.drftpd.master.config.FtpConfig;
42 import net.sf.drftpd.master.usermanager.NoSuchUserException;
43 import net.sf.drftpd.master.usermanager.User;
44 import net.sf.drftpd.remotefile.LinkedRemoteFile;
45 import net.sf.drftpd.slave.Transfer;
46 import net.sf.drftpd.util.ReplacerUtils;
47 import net.sf.drftpd.util.Time;
48
49 import org.apache.log4j.Level;
50 import org.apache.log4j.Logger;
51 import org.tanesha.replacer.FormatterException;
52 import org.tanesha.replacer.ReplacerEnvironment;
53 import org.tanesha.replacer.ReplacerFormat;
54
55 /**
56  * This is a generic ftp connection handler. It delegates
57  * the request to appropriate methods in subclasses.
58  *
59  * @author <a HREF="mailto:rana_b@yahoo.com">Rana Bhattacharyya</a>
60  * @author mog
61  * @version $Id: BaseFtpConnection.java,v 1.89.2.1 2004/06/19 23:37:26 mog Exp $
62  */

63 public class BaseFtpConnection implements Runnable JavaDoc {
64     private static final Logger debuglogger =
65         Logger.getLogger(BaseFtpConnection.class.getName() + ".service");
66
67     private static final Logger logger =
68         Logger.getLogger(BaseFtpConnection.class);
69     public static final String JavaDoc NEWLINE = "\r\n";
70
71     public static ReplacerEnvironment getReplacerEnvironment(
72         ReplacerEnvironment env,
73         User user) {
74         env = new ReplacerEnvironment(env);
75
76         if (user != null) {
77             env.add("user", user.getUsername());
78             env.add("credits", Bytes.formatBytes(user.getCredits()));
79             env.add("ratio", "" + user.getRatio());
80             env.add("tagline", user.getTagline());
81             env.add("uploaded", Bytes.formatBytes(user.getUploadedBytes()));
82             env.add("downloaded", Bytes.formatBytes(user.getDownloadedBytes()));
83             env.add("group", user.getGroupName());
84             env.add(
85                 "avragespeed",
86                 Bytes.formatBytes(
87                     user.getUploadedMilliseconds()
88                         + user.getDownloadedMilliseconds() / 2));
89         } else {
90             env.add("user", "<unknown>");
91         }
92         return env;
93     }
94
95     public static String JavaDoc jprintf(
96         ReplacerFormat format,
97         ReplacerEnvironment env,
98         User user)
99         throws FormatterException {
100         env = getReplacerEnvironment(env, user);
101         return ReplacerUtils.finalJprintf(format, env);
102     }
103
104     public static String JavaDoc jprintf(
105         String JavaDoc baseName,
106         String JavaDoc key,
107         ReplacerEnvironment env,
108         User user) {
109         env = getReplacerEnvironment(env, user);
110         return ReplacerUtils.jprintf(key, env, baseName);
111     }
112
113     /**
114      * Is the current password authenticated?
115      */

116     protected boolean _authenticated = false;
117     protected ConnectionManager _cm;
118     private CommandManager _commandManager;
119     protected Socket JavaDoc _controlSocket;
120
121     protected User _user;
122
123     protected LinkedRemoteFile currentDirectory;
124
125     /**
126      * Is the client running a command?
127      */

128     protected boolean executing;
129
130     private BufferedReader JavaDoc in;
131     /**
132      * time when last command from the client finished execution
133      */

134     protected long lastActive;
135
136     protected PrintWriter JavaDoc out;
137
138     /**
139       * PRE Transfere
140       *
141       */

142     protected FtpRequest request;
143
144     /**
145      * Should this thread stop insted of continue looping?
146      */

147     protected boolean stopRequest = false;
148     protected String JavaDoc stopRequestMessage;
149     protected Thread JavaDoc thread;
150     protected BaseFtpConnection() {
151     }
152     public BaseFtpConnection(ConnectionManager connManager, Socket JavaDoc soc)
153         throws IOException JavaDoc {
154         _commandManager =
155             connManager.getCommandManagerFactory().initialize(this);
156         _cm = connManager;
157         //_controlSocket = soc;
158
setControlSocket(soc);
159         lastActive = System.currentTimeMillis();
160         setCurrentDirectory(connManager.getRoot());
161     }
162
163     /**
164      * @deprecated use getConnectionManager().dispatchFtpEvent()
165      */

166     protected void dispatchFtpEvent(Event event) {
167         getConnectionManager().dispatchFtpEvent(event);
168     }
169
170     /**
171      * Get client address
172      */

173     public InetAddress JavaDoc getClientAddress() {
174         return _controlSocket.getInetAddress();
175     }
176
177     public CommandManager getCommandManager() {
178         return _commandManager;
179     }
180
181     public FtpConfig getConfig() {
182         return getConnectionManager().getConfig();
183     }
184
185     public ConnectionManager getConnectionManager() {
186         return _cm;
187     }
188
189     public Socket JavaDoc getControlSocket() {
190         return _controlSocket;
191     }
192
193     public PrintWriter JavaDoc getControlWriter() {
194         return out;
195     }
196
197     public LinkedRemoteFile getCurrentDirectory() {
198         return currentDirectory;
199     }
200
201     public DataConnectionHandler getDataConnectionHandler() {
202         try {
203             return (DataConnectionHandler) getCommandManager()
204                 .getCommandHandler(
205                 DataConnectionHandler.class);
206         } catch (ObjectNotFoundException e) {
207             throw new RuntimeException JavaDoc(
208                 "DataConnectionHandler must be available",
209                 e);
210         }
211     }
212     public char getDirection() {
213         String JavaDoc cmd = getRequest().getCommand();
214         if ("RETR".equals(cmd))
215             return Transfer.TRANSFER_SENDING_DOWNLOAD;
216         if ("STOR".equals(cmd) || "APPE".equals(cmd))
217             return Transfer.TRANSFER_RECEIVING_UPLOAD;
218         return Transfer.TRANSFER_UNKNOWN;
219     }
220
221     /**
222      * Returns the "currentTimeMillis" when last command finished executing.
223      */

224     public long getLastActive() {
225         return lastActive;
226     }
227
228     /**
229      * Returns the FtpRequest of current or last command executed.
230      */

231     public FtpRequest getRequest() {
232         return request;
233     }
234
235     public ServerSocketFactory getServerSocketFactory() {
236         return ServerSocketFactory.getDefault();
237     }
238
239     public SlaveManagerImpl getSlaveManager() {
240         return getConnectionManager().getSlaveManager();
241     }
242
243     public SocketFactory getSocketFactory() {
244         return SocketFactory.getDefault();
245     }
246
247     /**
248      * Returns Transfer.TRANSFER_SENDING_DOWNLOAD if this connection is processing a RETR command
249      * or Transfer.TRANSFER_RECEIVING_UPLOAD if this connection is processing a STOR command.
250      * @throws IllegalStateException if the connection isn't processing a STOR or RETR command.
251      */

252     public char getTransferDirection() {
253         String JavaDoc cmd = getRequest().getCommand();
254         if (cmd.equals("RETR")) {
255             return Transfer.TRANSFER_SENDING_DOWNLOAD;
256         } else if (cmd.equals("STOR")) {
257             return Transfer.TRANSFER_RECEIVING_UPLOAD;
258         } else {
259             throw new IllegalStateException JavaDoc("Not transfering");
260         }
261     }
262
263     /**
264      * Get user object
265      */

266     public User getUser() throws NoSuchUserException {
267         if (_user == null || !isAuthenticated())
268             throw new NoSuchUserException("no user logged in for connection");
269         return _user;
270     }
271
272     public User getUserNull() {
273         return _user;
274     }
275
276     protected boolean hasPermission(FtpRequest request) {
277         if (isAuthenticated())
278             return true;
279
280         String JavaDoc cmd = request.getCommand();
281         if ("USER".equals(cmd)
282             || "PASS".equals(cmd)
283             || "QUIT".equals(cmd)
284             || "HELP".equals(cmd)
285             || "AUTH".equals(cmd)
286             || "PBSZ".equals(cmd)
287             || "IDNT".equals(cmd))
288             return true;
289
290         return false;
291     }
292
293     public boolean isAuthenticated() {
294         return _authenticated;
295     }
296
297     /**
298      * Returns true if client is executing a command.
299      */

300     public boolean isExecuting() {
301         return executing;
302     }
303
304     public boolean isSecure() {
305         return _controlSocket instanceof SSLSocket;
306     }
307
308     public String JavaDoc jprintf(Class JavaDoc baseName, String JavaDoc key) {
309         return jprintf(baseName.getName(), key, null);
310     }
311
312     public String JavaDoc jprintf(
313         Class JavaDoc class1,
314         String JavaDoc string,
315         ReplacerEnvironment env) {
316         return jprintf(class1.getName(), string, env);
317     }
318
319     public String JavaDoc jprintf(String JavaDoc baseName, String JavaDoc key) {
320         return jprintf(baseName, key, null);
321     }
322
323     /**
324      * @param env null for an empty parent replacerenvironment.
325      */

326     public String JavaDoc jprintf(
327         String JavaDoc baseName,
328         String JavaDoc key,
329         ReplacerEnvironment env) {
330         return jprintf(baseName, key, env, getUserNull());
331     }
332
333     /**
334      * Server one FTP connection.
335      */

336     public void run() {
337         lastActive = System.currentTimeMillis();
338         logger.info(
339             "Handling new request from " + getClientAddress().getHostAddress());
340         thread.setName("FtpConn from " + getClientAddress().getHostAddress());
341
342         try {
343             // in =
344
// new BufferedReader(
345
// new InputStreamReader(_controlSocket.getInputStream()));
346

347             // out = new PrintWriter(
348
// //new FtpWriter( no need for spying :P
349
// new BufferedWriter(
350
// new OutputStreamWriter(_controlSocket.getOutputStream())));
351

352             _controlSocket.setSoTimeout(1000);
353             if (getConnectionManager().isShutdown()) {
354                 stop(getConnectionManager().getShutdownMessage());
355             } else {
356                 FtpReply response =
357                     new FtpReply(220, getConfig().getLoginPrompt());
358                 out.print(response);
359             }
360             while (!stopRequest) {
361
362                 out.flush();
363                 //notifyObserver();
364
String JavaDoc commandLine;
365                 try {
366                     commandLine = in.readLine();
367                 } catch (InterruptedIOException JavaDoc ex) {
368                     continue;
369                 }
370                 if (stopRequest)
371                     break;
372                 // test command line
373
if (commandLine == null)
374                     break;
375
376                 //spyRequest(commandLine);
377
if (commandLine.equals(""))
378                     continue;
379
380                 request = new FtpRequest(commandLine);
381
382                 if(!request.getCommand().equals("PASS"))
383                 debuglogger.debug(
384                     "<< "
385                         + request.getCommandLine()
386                         + " [user="
387                         + _user
388                         + ",cwd="
389                         + currentDirectory.getPath()
390                         + ",host="
391                         + getClientAddress()
392                         + "]");
393                 if (!hasPermission(request)) {
394                     out.print(FtpReply.RESPONSE_530_NOT_LOGGED_IN);
395                     continue;
396                 }
397                 // execute command
398
executing = true;
399                 service(request, out);
400                 executing = false;
401                 lastActive = System.currentTimeMillis();
402             }
403             if (stopRequestMessage != null) {
404                 out.print(new FtpReply(421, stopRequestMessage));
405             } else {
406                 out.println("421 Connection closing");
407             }
408             out.flush();
409         } catch (SocketException JavaDoc ex) {
410             logger.log(
411                 Level.INFO,
412                 ex.getMessage()
413                     + ", closing for user "
414                     + (_user == null ? "<not logged in>" : _user.getUsername()),
415                 ex);
416         } catch (Exception JavaDoc ex) {
417             logger.log(Level.INFO, "Exception, closing", ex);
418         } finally {
419             try {
420                 in.close();
421                 out.close();
422             } catch (Exception JavaDoc ex2) {
423                 logger.log(Level.WARN, "Exception closing stream", ex2);
424             }
425             if (isAuthenticated()) {
426                 _user.updateLastAccessTime();
427                 dispatchFtpEvent(new UserEvent(_user, "LOGOUT"));
428             }
429             getConnectionManager().remove(this);
430         }
431     }
432
433     /**
434      * Execute the ftp command.
435      */

436     public void service(FtpRequest request, PrintWriter JavaDoc out)
437         throws IOException JavaDoc {
438         FtpReply reply;
439         try {
440             reply = _commandManager.execute(this);
441         } catch (Throwable JavaDoc e) {
442             reply = new FtpReply(500, e.getMessage());
443             logger.warn("", e);
444         }
445         if (reply != null)
446             out.print(reply);
447     }
448
449     public void setAuthenticated(boolean authenticated) {
450         _authenticated = authenticated;
451         if (authenticated)
452             thread.setName(
453                 "FtpConn from "
454                     + getClientAddress().getHostAddress()
455                     + " "
456                     + _user.getUsername()
457                     + "/"
458                     + _user.getGroupName());
459     }
460
461     public void setControlSocket(Socket JavaDoc socket) {
462         try {
463             _controlSocket = socket;
464             in =
465                 new BufferedReader JavaDoc(
466                     new InputStreamReader JavaDoc(
467                         _controlSocket.getInputStream(),
468                         "ISO-8859-1"));
469
470             out =
471                 new PrintWriter JavaDoc(
472                     new OutputStreamWriter JavaDoc(
473                         _controlSocket.getOutputStream(),
474                         "ISO-8859-1"));
475         } catch (IOException JavaDoc e) {
476             throw new RuntimeException JavaDoc(e);
477         }
478     }
479
480     public void setCurrentDirectory(LinkedRemoteFile file) {
481         currentDirectory = file;
482     }
483
484     public void setUser(User user) {
485         _user = user;
486     }
487     public void start() {
488         thread = new Thread JavaDoc(this);
489         thread.start();
490         // start() calls run() and execution will start in the background.
491
}
492
493     /**
494      * returns a two-line status
495      */

496     public String JavaDoc status() {
497         return jprintf(BaseFtpConnection.class.getName(), "statusline");
498     }
499
500     /**
501      * User logout and stop this thread.
502      */

503     public void stop() {
504         stopRequest = true;
505     }
506
507     public void stop(String JavaDoc message) {
508         stopRequestMessage = message;
509         if (getDataConnectionHandler().isTransfering()) {
510             try {
511                 getDataConnectionHandler().getTransfer().abort();
512             } catch (RemoteException JavaDoc e) {
513                 getDataConnectionHandler()
514                     .getTranferSlave()
515                     .handleRemoteException(
516                     e);
517             }
518         }
519         stop();
520     }
521
522     public String JavaDoc toString() {
523         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("[BaseFtpConnection");
524         if (_user != null) {
525             buf.append("[user: " + _user + "]");
526         }
527         if (request != null) {
528             buf.append("[command: " + request.getCommand() + "]");
529         }
530         if (isExecuting()) {
531             buf.append("[executing]");
532         } else {
533             buf.append(
534                 "[idle: "
535                     + Time.formatTime(
536                         System.currentTimeMillis() - getLastActive()));
537         }
538         buf.append("]");
539         return buf.toString();
540     }
541 }
Popular Tags