1 18 package net.sf.drftpd.master; 19 20 import java.io.BufferedReader ; 21 import java.io.IOException ; 22 import java.io.InputStreamReader ; 23 import java.io.InterruptedIOException ; 24 import java.io.OutputStreamWriter ; 25 import java.io.PrintWriter ; 26 import java.net.InetAddress ; 27 import java.net.Socket ; 28 import java.net.SocketException ; 29 import java.rmi.RemoteException ; 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 63 public class BaseFtpConnection implements Runnable { 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 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 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 jprintf( 105 String baseName, 106 String key, 107 ReplacerEnvironment env, 108 User user) { 109 env = getReplacerEnvironment(env, user); 110 return ReplacerUtils.jprintf(key, env, baseName); 111 } 112 113 116 protected boolean _authenticated = false; 117 protected ConnectionManager _cm; 118 private CommandManager _commandManager; 119 protected Socket _controlSocket; 120 121 protected User _user; 122 123 protected LinkedRemoteFile currentDirectory; 124 125 128 protected boolean executing; 129 130 private BufferedReader in; 131 134 protected long lastActive; 135 136 protected PrintWriter out; 137 138 142 protected FtpRequest request; 143 144 147 protected boolean stopRequest = false; 148 protected String stopRequestMessage; 149 protected Thread thread; 150 protected BaseFtpConnection() { 151 } 152 public BaseFtpConnection(ConnectionManager connManager, Socket soc) 153 throws IOException { 154 _commandManager = 155 connManager.getCommandManagerFactory().initialize(this); 156 _cm = connManager; 157 setControlSocket(soc); 159 lastActive = System.currentTimeMillis(); 160 setCurrentDirectory(connManager.getRoot()); 161 } 162 163 166 protected void dispatchFtpEvent(Event event) { 167 getConnectionManager().dispatchFtpEvent(event); 168 } 169 170 173 public InetAddress 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 getControlSocket() { 190 return _controlSocket; 191 } 192 193 public PrintWriter 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 ( 208 "DataConnectionHandler must be available", 209 e); 210 } 211 } 212 public char getDirection() { 213 String 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 224 public long getLastActive() { 225 return lastActive; 226 } 227 228 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 252 public char getTransferDirection() { 253 String 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 ("Not transfering"); 260 } 261 } 262 263 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 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 300 public boolean isExecuting() { 301 return executing; 302 } 303 304 public boolean isSecure() { 305 return _controlSocket instanceof SSLSocket; 306 } 307 308 public String jprintf(Class baseName, String key) { 309 return jprintf(baseName.getName(), key, null); 310 } 311 312 public String jprintf( 313 Class class1, 314 String string, 315 ReplacerEnvironment env) { 316 return jprintf(class1.getName(), string, env); 317 } 318 319 public String jprintf(String baseName, String key) { 320 return jprintf(baseName, key, null); 321 } 322 323 326 public String jprintf( 327 String baseName, 328 String key, 329 ReplacerEnvironment env) { 330 return jprintf(baseName, key, env, getUserNull()); 331 } 332 333 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 347 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 String commandLine; 365 try { 366 commandLine = in.readLine(); 367 } catch (InterruptedIOException ex) { 368 continue; 369 } 370 if (stopRequest) 371 break; 372 if (commandLine == null) 374 break; 375 376 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 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 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 ex) { 417 logger.log(Level.INFO, "Exception, closing", ex); 418 } finally { 419 try { 420 in.close(); 421 out.close(); 422 } catch (Exception 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 436 public void service(FtpRequest request, PrintWriter out) 437 throws IOException { 438 FtpReply reply; 439 try { 440 reply = _commandManager.execute(this); 441 } catch (Throwable 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 socket) { 462 try { 463 _controlSocket = socket; 464 in = 465 new BufferedReader ( 466 new InputStreamReader ( 467 _controlSocket.getInputStream(), 468 "ISO-8859-1")); 469 470 out = 471 new PrintWriter ( 472 new OutputStreamWriter ( 473 _controlSocket.getOutputStream(), 474 "ISO-8859-1")); 475 } catch (IOException e) { 476 throw new RuntimeException (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 (this); 489 thread.start(); 490 } 492 493 496 public String status() { 497 return jprintf(BaseFtpConnection.class.getName(), "statusline"); 498 } 499 500 503 public void stop() { 504 stopRequest = true; 505 } 506 507 public void stop(String message) { 508 stopRequestMessage = message; 509 if (getDataConnectionHandler().isTransfering()) { 510 try { 511 getDataConnectionHandler().getTransfer().abort(); 512 } catch (RemoteException e) { 513 getDataConnectionHandler() 514 .getTranferSlave() 515 .handleRemoteException( 516 e); 517 } 518 } 519 stop(); 520 } 521 522 public String toString() { 523 StringBuffer buf = new StringBuffer ("[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 |