1 18 package net.sf.drftpd.event.listeners; 19 20 import java.io.FileInputStream ; 21 import java.io.FileNotFoundException ; 22 import java.io.IOException ; 23 import java.util.ArrayList ; 24 import java.util.Calendar ; 25 import java.util.Date ; 26 import java.util.Iterator ; 27 import java.util.Properties ; 28 import java.util.StringTokenizer ; 29 30 import net.sf.drftpd.Bytes; 31 import net.sf.drftpd.ObjectNotFoundException; 32 import net.sf.drftpd.event.Event; 33 import net.sf.drftpd.event.FtpListener; 34 import net.sf.drftpd.event.UserEvent; 35 import net.sf.drftpd.master.ConnectionManager; 36 import net.sf.drftpd.master.config.FtpConfig; 37 import net.sf.drftpd.master.config.Permission; 38 import net.sf.drftpd.master.usermanager.User; 39 import net.sf.drftpd.util.CalendarUtils; 40 41 import org.apache.log4j.Logger; 42 import org.drftpd.plugins.SiteBot; 43 44 48 public class Trial implements FtpListener { 49 public static class Limit { 50 private String _actionFailed; 51 private String _actionPassed; 52 private long _bytes; 53 private String _name; 54 private int _period; 55 private Permission _perm; 56 public Limit() { 57 } 58 59 public void doFailed(User user) { 60 Trial.doAction(getActionFailed(), user); 61 } 62 63 public void doPassed(User user) { 64 Trial.doAction(getActionPassed(), user); 65 } 66 67 public String getActionFailed() { 68 return _actionFailed; 69 } 70 71 public String getActionPassed() { 72 return _actionPassed; 73 } 74 75 public long getBytes() { 76 return _bytes; 77 } 78 79 public String getName() { 80 return _name; 81 } 82 83 public int getPeriod() { 84 return _period; 85 } 86 87 public Permission getPerm() { 88 return _perm; 89 } 90 91 public void setActionFailed(String action) { 92 validateAction(action); 93 _actionFailed = action; 94 } 95 96 public void setActionPassed(String action) { 97 validateAction(action); 98 _actionPassed = action; 99 } 100 101 public void setBytes(long bytes) { 102 _bytes = bytes; 103 } 104 105 public void setName(String name) { 106 _name = name; 107 } 108 109 public void setPeriod(int period) { 110 _period = period; 111 } 112 113 public void setPerm(Permission perm) { 114 _perm = perm; 115 } 116 117 public String toString() { 118 return "Limit[name=" 119 + _name 120 + ",bytes=" 121 + Bytes.formatBytes(_bytes) 122 + ",period=" 123 + Trial.getPeriodName(_period) 124 + "]"; 125 } 126 127 private void validateAction(String action) { 128 if (action == null) 129 return; 130 StringTokenizer st = new StringTokenizer (action); 132 if (!st.hasMoreTokens()) 133 return; 134 String cmd = st.nextToken(); 135 if (!("delete".equals(action) 136 || "purge".equals(action) 137 || "chgrp".equals(cmd) 138 || "setgrp".equals(cmd))) { 139 throw new IllegalArgumentException ( 140 cmd + " is not a valid action"); 141 } 142 if ("setgrp".equals(cmd)) { 143 st.nextToken(); 144 if (st.hasMoreTokens()) 145 throw new IllegalArgumentException ( 146 "extra tokens in \"" + action + "\""); 147 } 148 } 149 } 150 private static final Logger logger = Logger.getLogger(Trial.class); 151 152 public static final int PERIOD_ALL = 0; 153 154 public static final int PERIOD_DAILY = Calendar.DAY_OF_MONTH; public static final short PERIOD_MONTHLY = Calendar.MONTH; public static final short PERIOD_WEEKLY = Calendar.WEEK_OF_YEAR; public static void doAction(String action, User user) { 158 try { 159 if (action == null) 160 return; 161 StringTokenizer st = new StringTokenizer (action); 162 if (!st.hasMoreTokens()) { 163 logger.info(user.getUsername() + " no action specified"); 164 return; 165 } 166 String cmd = st.nextToken().toLowerCase(); 167 if ("chgrp".equals(cmd)) { 168 while (st.hasMoreTokens()) { 169 user.toggleGroup(st.nextToken()); 170 } 171 } else if ("setgrp".equals(cmd)) { 172 user.setGroup(st.nextToken("")); 173 logger.info( 174 user.getUsername() 175 + " primary group set to " 176 + user.getGroupName()); 177 } else if ("delete".equals(cmd)) { 178 user.setDeleted(true); 179 logger.info(user.getUsername() + " deleted"); 180 } else if ("purge".equals(cmd)) { 181 user.setDeleted(true); 182 user.purge(); 183 logger.info(user.getUsername() + " purged"); 184 } 185 } catch (java.util.NoSuchElementException e) { 186 logger.info("Error parsing \"" + action + "\"", e); 187 } 188 } 189 190 public static Calendar getCalendarForEndOfBonus(User user, int period) { 191 Calendar cal = Calendar.getInstance(); 192 cal.setTimeInMillis(user.getCreated()); 193 moveCalendarToEndOfPeriod(cal, period); 194 return cal; 195 } 196 197 200 public static Calendar getCalendarForEndOfFirstPeriod( 201 User user, 202 int period) { 203 Calendar cal = Calendar.getInstance(); 204 cal.setTime(new Date (user.getCreated())); 205 CalendarUtils.ceilAllLessThanDay(cal); 206 207 switch (period) { 208 case PERIOD_DAILY : 209 CalendarUtils.incrementDay(cal); 212 return cal; 213 case PERIOD_WEEKLY : 214 CalendarUtils.incrementWeek(cal); 218 return cal; 219 case PERIOD_MONTHLY : 220 CalendarUtils.incrementMonth(cal); 224 return cal; 225 default : 226 throw new IllegalArgumentException ( 227 "Don't know how to handle " + period); 228 } 229 } 230 public static Calendar getCalendarForEndOfPeriod(int period) { 231 Calendar cal = Calendar.getInstance(); 232 CalendarUtils.ceilAllLessThanDay(cal); 233 switch (period) { 234 case PERIOD_DAILY : 235 break; 236 case PERIOD_WEEKLY : 237 int dow = CalendarUtils.getLastDayOfWeek(cal); 238 if (dow < cal.get(Calendar.DAY_OF_WEEK)) { 240 cal.add(Calendar.WEEK_OF_YEAR, 1); 241 } 242 cal.set(Calendar.DAY_OF_WEEK, dow); 243 return cal; 244 case PERIOD_MONTHLY : 245 cal.set( 246 Calendar.DAY_OF_MONTH, 247 cal.getActualMaximum(Calendar.DAY_OF_MONTH)); 248 return cal; 249 default : 250 throw new IllegalArgumentException ("" + period); 251 } 252 return cal; 254 } 255 256 public static String getPeriodName(int s) { 257 switch (s) { 258 case PERIOD_DAILY : 259 return "day"; 260 case PERIOD_MONTHLY : 261 return "month"; 262 case PERIOD_WEEKLY : 263 return "week"; 264 default : 265 throw new IllegalArgumentException ("" + s); 266 } 267 } 268 269 public static String getPeriodName2(int s) { 270 switch (s) { 271 case PERIOD_DAILY : 272 return "daily"; 273 case PERIOD_MONTHLY : 274 return "monthly"; 275 case PERIOD_WEEKLY : 276 return "weekly"; 277 default : 278 throw new IllegalArgumentException ("" + s); 279 } 280 } 281 282 public static long getUploadedBytesForPeriod(User user, int period) { 283 if (isInFirstPeriod(user, period)) 284 return user.getDownloadedBytes(); 285 switch (period) { 286 case PERIOD_DAILY : 287 return user.getUploadedBytesDay(); 288 case PERIOD_WEEKLY : 289 return user.getUploadedBytesWeek(); 290 case PERIOD_MONTHLY : 291 return user.getUploadedBytesMonth(); 292 default : 293 throw new IllegalArgumentException (); 294 } 295 } 296 297 public static boolean isInFirstPeriod(User user, int period) { 298 return isInFirstPeriod(user, period, System.currentTimeMillis()); 299 } 300 301 public static boolean isInFirstPeriod(User user, int period, long time) { 302 return time <= getCalendarForEndOfBonus(user, period).getTimeInMillis(); 303 } 304 305 public static Calendar moveCalendarToEndOfPeriod( 306 Calendar cal, 307 int period) { 308 CalendarUtils.ceilAllLessThanDay(cal); 309 switch (period) { 310 case PERIOD_DAILY : 311 return cal; 313 case PERIOD_WEEKLY : 314 CalendarUtils.incrementWeek(cal); 315 return cal; 316 case PERIOD_MONTHLY : 317 CalendarUtils.incrementMonth(cal); 318 return cal; 319 default : 320 throw new IllegalArgumentException ("" + period); 321 } 322 } 323 324 private ConnectionManager _cm; 325 326 private ArrayList _limits; 327 private TrialSiteBot _siteBot; 328 329 public Trial() throws FileNotFoundException , IOException { 330 super(); 331 } 332 333 public void actionPerformed(Event event) { 334 if (!(event instanceof UserEvent)) 335 return; 336 UserEvent uevent = (UserEvent) event; 337 String cmd = event.getCommand(); 338 339 if ("RELOAD".equals(cmd)) { 340 reload(); 341 return; 342 } 343 344 349 if ("RESETDAY".equals(cmd)) { 350 351 Calendar cal; 352 353 cal = 355 getCalendarForEndOfFirstPeriod( 356 uevent.getUser(), 357 PERIOD_MONTHLY); 358 if (uevent.getUser().getLastReset() <= cal.getTimeInMillis() 361 && uevent.getTime() >= cal.getTimeInMillis()) { 362 checkPassed( 363 uevent.getUser(), 364 uevent.getUser().getUploadedBytes(), 365 PERIOD_MONTHLY); 366 } 367 368 if (uevent.getTime() < cal.getTimeInMillis()) { 371 cal = 372 getCalendarForEndOfFirstPeriod( 373 uevent.getUser(), 374 PERIOD_WEEKLY); 375 if (uevent.getUser().getLastReset() <= cal.getTimeInMillis() 378 && uevent.getTime() >= cal.getTimeInMillis()) { 379 checkPassed( 380 uevent.getUser(), 381 uevent.getUser().getUploadedBytes(), 382 PERIOD_WEEKLY); 383 } 384 } 385 386 if (uevent.getTime() < cal.getTimeInMillis()) { 389 cal = 390 getCalendarForEndOfFirstPeriod( 391 uevent.getUser(), 392 PERIOD_DAILY); 393 if (uevent.getUser().getLastReset() <= cal.getTimeInMillis() 396 && uevent.getTime() >= cal.getTimeInMillis()) { 397 checkPassed( 398 uevent.getUser(), 399 uevent.getUser().getUploadedBytes(), 400 PERIOD_DAILY); 401 } else if (uevent.getTime() > cal.getTimeInMillis()) { 403 checkPassed( 404 uevent.getUser(), 405 uevent.getUser().getUploadedBytesDay(), 406 PERIOD_DAILY); 407 } 408 } else { 409 checkPassed( 411 uevent.getUser(), 412 uevent.getUser().getUploadedBytesDay(), 413 PERIOD_DAILY); 414 } 415 } 416 if ("RESETWEEK".equals(cmd)) { 417 if (!isInFirstPeriod(uevent.getUser(), 418 PERIOD_WEEKLY, 419 uevent.getTime())) { 420 checkPassed( 421 uevent.getUser(), 422 uevent.getUser().getUploadedBytesWeek(), 423 PERIOD_WEEKLY); 424 } 425 } 426 if ("RESETMONTH".equals(cmd)) { 427 if (!isInFirstPeriod(uevent.getUser(), 428 PERIOD_MONTHLY, 429 uevent.getTime())) { 430 checkPassed( 431 uevent.getUser(), 432 uevent.getUser().getUploadedBytesMonth(), 433 PERIOD_MONTHLY); 434 } 435 } 436 } 437 438 private void checkPassed(User user, long bytes, int period) { 439 for (Iterator iter = _limits.iterator(); iter.hasNext();) { 440 Limit limit = (Limit) iter.next(); 441 if (limit.getPeriod() == period && limit.getPerm().check(user)) { 442 long bytesleft = limit.getBytes() - bytes; 443 if (bytesleft > 0) { 444 logger.info( 445 user.getUsername() 446 + " failed " 447 + limit.getName() 448 + " by " 449 + Bytes.formatBytes(bytesleft)); 450 limit.doFailed(user); 451 } else { 452 logger.info( 453 user.getUsername() 454 + " passed " 455 + limit.getName() 456 + " with " 457 + Bytes.formatBytes(-bytesleft) 458 + " extra"); 459 limit.doPassed(user); 460 } 461 } 462 } 463 } 464 465 ConnectionManager getConnectionManager() { 466 return _cm; 467 } 468 469 public ArrayList getLimits() { 470 return _limits; 471 } 472 public void init(ConnectionManager mgr) { 473 _cm = mgr; 474 reload(); 475 } 476 477 private void reload() { 478 Properties props = new Properties (); 479 try { 480 props.load(new FileInputStream ("conf/trial.conf")); 481 } catch (IOException e) { 482 throw new RuntimeException (e); 483 } 484 reload(props); 485 } 486 487 public void reload(ArrayList limits) { 488 _limits = limits; 489 490 if (_siteBot != null) { 491 _siteBot.disable(); 492 } 493 if (_cm != null) { 494 try { 495 SiteBot _irc = 496 (SiteBot) _cm.getFtpListener(SiteBot.class); 497 _siteBot = new TrialSiteBot(this, _irc); 498 } catch (ObjectNotFoundException e1) { 499 logger.warn("Error loading sitebot component, sitebot announcements disabled.", e1); 500 } 501 } 502 } 503 504 protected void reload(Properties props) { 505 ArrayList limits = new ArrayList (); 506 for (int i = 1;; i++) { 507 if (props.getProperty(i + ".quota") == null) 508 break; 509 Limit limit = new Limit(); 510 limit.setName(FtpConfig.getProperty(props, i + ".name")); 511 limit.setActionPassed( 512 props.getProperty( 513 i + ".pass", 514 props.getProperty(i + ".passed", ""))); 515 limit.setActionFailed( 516 props.getProperty(i + ".fail", "")); 517 if (limit.getActionFailed().equals("") 518 && limit.getActionPassed().equals("")) 519 throw new IllegalArgumentException ( 520 "Both .passed and .fail cannot be empty for " 521 + i 522 + " (" 523 + limit.getName() 524 + ")"); 525 String period = 526 FtpConfig.getProperty(props, i + ".period").toLowerCase(); 527 if ("monthly".equals(period)) { 528 limit.setPeriod(PERIOD_MONTHLY); 529 } else if ("weekly".equals(period)) { 530 limit.setPeriod(PERIOD_WEEKLY); 531 } else if ("daily".equals(period)) { 532 limit.setPeriod(PERIOD_DAILY); 533 } else { 534 throw new RuntimeException ( 535 new IOException (period + " is not a recognized period")); 536 } 537 String perm = props.getProperty(i + ".perm"); 538 if (perm == null) 539 perm = "*"; 540 limit.setPerm( 541 new Permission(FtpConfig.makeUsers(new StringTokenizer (perm)))); 542 limit.setBytes( 543 Bytes.parseBytes(FtpConfig.getProperty(props, i + ".quota"))); 544 limits.add(limit); 545 logger.debug("Limit: " + limit); 546 } 547 reload(limits); 548 } 549 550 public void unload() { 551 if(_siteBot != null) { 552 _siteBot.disable(); 553 } 554 } 555 } 556 | Popular Tags |