Advertisement
Guest User

Untitled

a guest
Jun 12th, 2017
527
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 85.79 KB | None | 0 0
  1. /* VERSIO 0.25B INTEGRAMENT MODIFICADA PER TOMEU CANALS! */
  2.  
  3.  
  4. /*
  5.  * This file is part of DrFTPD, Distributed FTP Daemon.
  6.  *
  7.  *
  8.  * DrFTPD is free software; you can redistribute it and/or modify it under the
  9.  * terms of the GNU General Public License as published by the Free Software
  10.  * Foundation; either version 2 of the License, or (at your option) any later
  11.  * version.
  12.  *
  13.  * DrFTPD is distributed in the hope that it will be useful, but WITHOUT ANY
  14.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  15.  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License along with
  18.  * DrFTPD; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
  19.  * Suite 330, Boston, MA 02111-1307 USA
  20.  */
  21. package org.drftpd.commands;
  22.  
  23. import java.text.ParseException;
  24. import java.text.SimpleDateFormat;
  25. import java.util.ArrayList;
  26. import java.util.Collection;
  27. import java.util.Date;
  28. import java.util.Iterator;
  29. import java.util.MissingResourceException;
  30. import java.util.NoSuchElementException;
  31. import java.util.ResourceBundle;
  32. import java.util.StringTokenizer;
  33.  
  34. import net.sf.drftpd.DuplicateElementException;
  35. import net.sf.drftpd.ObjectNotFoundException;
  36. import net.sf.drftpd.master.BaseFtpConnection;
  37. import net.sf.drftpd.master.FtpRequest;
  38. import net.sf.drftpd.master.command.CommandManager;
  39. import net.sf.drftpd.master.command.CommandManagerFactory;
  40. import net.sf.drftpd.master.config.FtpConfig;
  41. import net.sf.drftpd.util.ReplacerUtils;
  42.  
  43. import org.apache.log4j.Level;
  44. import org.apache.log4j.Logger;
  45. import org.drftpd.Bytes;
  46. import org.drftpd.Time;
  47. import org.drftpd.dynamicdata.Key;
  48. import org.drftpd.permissions.Permission;
  49. import org.drftpd.plugins.Statistics;
  50. import org.drftpd.slave.Transfer;
  51. import org.drftpd.thirdparty.plus.Default;
  52. import org.drftpd.thirdparty.plus.config.PlusConfig;
  53. import org.drftpd.usermanager.HostMask;
  54. import org.drftpd.usermanager.NoSuchUserException;
  55. import org.drftpd.usermanager.User;
  56. import org.drftpd.usermanager.UserExistsException;
  57. import org.drftpd.usermanager.UserFileException;
  58. import org.tanesha.replacer.FormatterException;
  59. import org.tanesha.replacer.ReplacerEnvironment;
  60. import org.tanesha.replacer.ReplacerFormat;
  61. import org.tanesha.replacer.SimplePrintf;
  62.  
  63. /**
  64.  * @author mog
  65.  * @author zubov
  66.  * @version $Id$
  67.  */
  68. public class UserManagement implements CommandHandler, CommandHandlerFactory {
  69.     private static final Logger logger = Logger.getLogger(UserManagement.class);
  70.  
  71.     public static final Key TAGLINE = new Key(UserManagement.class, "tagline", String.class);
  72.     public static final Key DEBUG = new Key(UserManagement.class, "debug", Boolean.class);
  73.     public static final Key RATIO = new Key(UserManagement.class, "ratio", Float.class);
  74.     public static final Key CREATED = new Key(UserManagement.class, "created", Date.class);
  75.     public static final Key COMMENT = new Key(UserManagement.class, "comment", String.class);
  76.     public static final Key REASON = new Key(UserManagement.class, "reason", String.class);
  77.     public static final Key IRCIDENT = new Key(UserManagement.class, "ircident", String.class);
  78.     public static final Key GROUPSLOTS = new Key(UserManagement.class, "groupslots", Integer.class);
  79.     public static final Key LEECHSLOTS = new Key(UserManagement.class, "leechslots", Integer.class);
  80.     public static final Key MAXLOGINS = new Key(UserManagement.class, "maxlogins", Integer.class);
  81.     public static final Key MAXLOGINSIP = new Key(UserManagement.class, "maxloginsip", Integer.class);
  82.     public static final Key MINRATIO = new Key(UserManagement.class, "minratio", Float.class);
  83.     public static final Key MAXRATIO = new Key(UserManagement.class, "maxratio", Float.class);
  84.     public static final Key MAXSIMUP = new Key(UserManagement.class, "maxsimup", Integer.class);
  85.     public static final Key MAXSIMDN = new Key(UserManagement.class, "maxsimdn", Integer.class);
  86.     public static final Key LASTSEEN = new Key(UserManagement.class, "lastseen", Date.class);
  87.     public static final Key WKLY_ALLOTMENT = new Key(UserManagement.class, "wkly_allotment", Long.class);
  88.     public static final Key BAN_TIME = new Key(UserManagement.class, "ban_time", Date.class);
  89.     public static final Key BAN_REASON = new Key(UserManagement.class, "ban_reason", String.class);
  90.  
  91.     private Reply doSITE_ADDIP(BaseFtpConnection conn) throws ImproperUsageException {
  92.         FtpRequest request = conn.getRequest();
  93.  
  94.         if (!conn.getUserNull().isAdmin() &&
  95.                 !conn.getUserNull().isGroupAdmin()) {
  96.             return Reply.RESPONSE_530_ACCESS_DENIED;
  97.         }
  98.  
  99.         if (!request.hasArgument()) {
  100.             throw new ImproperUsageException();
  101.         }
  102.  
  103.         String[] args = request.getArgument().split(" ");
  104.  
  105.         if (args.length < 2) {
  106.             return new Reply(501,
  107.                 conn.jprintf(UserManagement.class, "addip.specify"));
  108.         }
  109.  
  110.         Reply response = new Reply(200);
  111.         User myUser;
  112.  
  113.         try {
  114.             myUser = conn.getGlobalContext().getUserManager().getUserByName(args[0]);
  115.  
  116.             if (conn.getUserNull().isGroupAdmin() &&
  117.                     !conn.getUserNull().getGroup().equals(myUser.getGroup())) {
  118.                 return Reply.RESPONSE_530_ACCESS_DENIED;
  119.             }
  120.  
  121.             ReplacerEnvironment env = new ReplacerEnvironment();
  122.             env.add("targetuser", myUser.getName());
  123.  
  124.             for (int i = 1; i < args.length; i++) {
  125.                 String string = args[i].replace(",",""); // strip commas (for easy copy+paste);
  126.                 env.add("mask", string);
  127.  
  128.                 if ((new HostMask(string)).isAllowed()) {
  129.                 try {
  130.                     myUser.addIPMask(string);
  131.                     response.addComment(conn.jprintf(UserManagement.class,
  132.                             "addip.success", env));
  133.                     logger.info("'" + conn.getUserNull().getName() +
  134.                         "' added ip '" + string + "' to '" +
  135.                         myUser.getName() + "'");
  136.                 } catch (DuplicateElementException e) {
  137.                     response.addComment(conn.jprintf(UserManagement.class,
  138.                             "addip.dupe", env));
  139.                 }
  140.                 } else {
  141.                     response.addComment(conn.jprintf(UserManagement.class,
  142.                             "addip.invalid", env));
  143.                     logger.info("'" + conn.getUserNull().getName() +
  144.                             "' was denied the add of ip '" + string + "' to '" +
  145.                             myUser.getName() + "'");
  146.                 }
  147.             }
  148.  
  149.             myUser.commit(); // throws UserFileException
  150.  
  151.             //userManager.save(user2);
  152.         } catch (NoSuchUserException ex) {
  153.             return new Reply(452, "No such user: " + args[0]);
  154.         } catch (UserFileException ex) {
  155.             response.addComment(ex.getMessage());
  156.  
  157.             return response;
  158.         }
  159.  
  160.         return response;
  161.     }
  162.  
  163.     /**
  164.      * USAGE: site adduser <user><password>[ <ident@ip#1>... <ident@ip#5>] Adds
  165.      * a user. You can have wild cards for users that have dynamic ips Examples:
  166.      * *@192.168.1.* , frank@192.168.*.* , bob@192.*.*.* (*@192.168.1.1[5-9]
  167.      * will allow only 192.168.1.15-19 to connect but no one else)
  168.      *
  169.      * If a user is added by a groupadmin, that user will have the GLOCK flag
  170.      * enabled and will inherit the groupadmin's home directory.
  171.      *
  172.      * All default values for the user are read from file default.user in
  173.      * /glftpd/ftp-data/users. Comments inside describe what is what. Gadmins
  174.      * can be assigned their own default. <group>userfiles as templates to be
  175.      * used when they add a user, if one is not found, default.user will be
  176.      * used. default.groupname files will also be used for "site gadduser".
  177.      *
  178.      * ex. site ADDUSER Archimede mypassword
  179.      *
  180.      * This would add the user 'Archimede' with the password 'mypassword'.
  181.      *
  182.      * ex. site ADDUSER Archimede mypassword *@127.0.0.1
  183.      *
  184.      * This would do the same as above + add the ip '*@127.0.0.1' at the same
  185.      * time.
  186.      *
  187.      * HOMEDIRS: After login, the user will automatically be transferred into
  188.      * his/her homedir. As of 1.16.x this dir is now "kinda" chroot'ed and they
  189.      * are now unable to "cd ..".
  190.      *
  191.      *
  192.      *
  193.      * USAGE: site gadduser <group><user><password>[ <ident@ip#1 ..
  194.      * ident@ip#5>] Adds a user and changes his/her group to <group>. If
  195.      * default.group exists, it will be used as a base instead of default.user.
  196.      *
  197.      * Only public groups can be used as <group>.
  198.      * @throws ImproperUsageException
  199.      */
  200.     private Reply doSITE_ADDUSER(BaseFtpConnection conn) throws ImproperUsageException {
  201.         FtpRequest request = conn.getRequest();
  202.         boolean isGAdduser = request.getCommand().equals("SITE GADDUSER");
  203.  
  204.         if (!request.hasArgument()) {
  205.             throw new ImproperUsageException();
  206.         }
  207.  
  208.         String newGroup = null;
  209.  
  210.         if (conn.getUserNull().isGroupAdmin()) {
  211.             if (isGAdduser) {
  212.                 return Reply.RESPONSE_530_ACCESS_DENIED;
  213.             }
  214.  
  215.             int users;
  216.  
  217.             try {
  218.                 users = conn.getGlobalContext().getUserManager()
  219.                             .getAllUsersByGroup(conn.getUserNull().getGroup())
  220.                             .size();
  221.                 logger.debug("Group " + conn.getUserNull().getGroup() +
  222.                     " is " +
  223.                     conn.getGlobalContext().getUserManager().getAllUsersByGroup(conn.getUserNull()
  224.                                                                                     .getGroup()));
  225.  
  226.                 if (users >= conn.getUserNull().getKeyedMap().getObjectInt(UserManagement.GROUPSLOTS)) {
  227.                     return new Reply(452,
  228.                         conn.jprintf(UserManagement.class, "adduser.noslots"));
  229.                 }
  230.             } catch (UserFileException e1) {
  231.                 logger.warn("", e1);
  232.  
  233.                 return new Reply(452, e1.getMessage());
  234.             }
  235.  
  236.             newGroup = conn.getUserNull().getGroup();
  237.         } else if (!conn.getUserNull().isAdmin()) {
  238.             return Reply.RESPONSE_530_ACCESS_DENIED;
  239.         }
  240.  
  241.         StringTokenizer st = new StringTokenizer(request.getArgument());
  242.         User newUser;
  243.         Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
  244.         Reply badipmasks = (Reply) Reply.RESPONSE_501_SYNTAX_ERROR.clone();
  245.         ReplacerEnvironment env = new ReplacerEnvironment();
  246.  
  247.         try {
  248.             if (isGAdduser) {
  249.                 newGroup = st.nextToken();
  250.             }
  251.  
  252.             String newUsername = st.nextToken();
  253.             env.add("targetuser", newUsername);
  254.  
  255.             String pass = st.nextToken();
  256.  
  257.             Default def = Default.getInstance();
  258.  
  259.             //action, no more NoSuchElementException below here
  260.             newUser = conn.getGlobalContext().getUserManager().create(newUsername);
  261.             newUser.setPasswordEnc(pass);
  262.             newUser.getKeyedMap().setObject(UserManagement.CREATED, new Date());
  263.             newUser.getKeyedMap().setObject(UserManagement.COMMENT, "Added by " + conn.getUserNull().getName());
  264.             newUser.getKeyedMap().setObject(UserManagement.RATIO, def.RATIO);
  265.             newUser.getKeyedMap().setObject(UserManagement.GROUPSLOTS,0);
  266.             newUser.getKeyedMap().setObject(UserManagement.LEECHSLOTS,0);
  267.             newUser.getKeyedMap().setObject(UserManagement.MAXLOGINS, def.MAXLOGINS);
  268.             newUser.getKeyedMap().setObject(UserManagement.MAXLOGINSIP, def.MAXLOGINSIP);
  269.             newUser.getKeyedMap().setObject(UserManagement.MINRATIO, def.MINRATIO);
  270.             newUser.getKeyedMap().setObject(UserManagement.MAXRATIO, def.MAXRATIO);
  271.             newUser.getKeyedMap().setObject(UserManagement.MAXSIMUP, def.MAXSIMUP);
  272.             newUser.getKeyedMap().setObject(UserManagement.MAXSIMDN, def.MAXSIMDN);
  273.             newUser.getKeyedMap().setObject(Statistics.LOGINS,0);
  274.             newUser.getKeyedMap().setObject(UserManagement.CREATED, new Date());
  275.             newUser.getKeyedMap().setObject(UserManagement.LASTSEEN, new Date());
  276.             newUser.getKeyedMap().setObject(UserManagement.WKLY_ALLOTMENT, def.WKLYALLOT);
  277.             newUser.getKeyedMap().setObject(UserManagement.IRCIDENT, "N/A");
  278.             newUser.getKeyedMap().setObject(UserManagement.TAGLINE, def.TAGLINE);
  279.             newUser.getKeyedMap().setObject(UserManagement.BAN_TIME, new Date());
  280.             newUser.getKeyedMap().setObject(Nuke.NUKED,0);
  281.             newUser.getKeyedMap().setObject(Nuke.NUKEDBYTES,new Long(0));
  282.             newUser.setIdleTime(def.IDLETIME);
  283.             newUser.setCredits(def.CREDITS);
  284.  
  285.             if (newGroup != null) {
  286.                 newUser.setGroup(newGroup);
  287.                 logger.info("'" + conn.getUserNull().getName() +
  288.                     "' added '" + newUser.getName() + "' with group " +
  289.                     newUser.getGroup() + "'");
  290.                 env.add("primgroup", newUser.getGroup());
  291.                 response.addComment(conn.jprintf(UserManagement.class,
  292.                         "adduser.primgroup", env));
  293.             } else {
  294.                 logger.info("'" + conn.getUserNull().getName() +
  295.                     "' added '" + newUser.getName() + "'");
  296.                 newUser.setGroup(def.GROUP);
  297.             }
  298.             response.addComment(conn.jprintf(UserManagement.class, "adduser.success", env));
  299.  
  300.         } catch (NoSuchElementException ex) {
  301.             return new Reply(501,
  302.                 conn.jprintf(UserManagement.class, "adduser.missingpass"));
  303.         } catch (UserFileException ex) {
  304.             return new Reply(452, ex.getMessage());
  305.         }
  306.  
  307.         try {
  308.             while (st.hasMoreTokens()) {
  309.                 String string = st.nextToken().replace(",",""); // strip commas (for easy copy+paste);
  310.                 env.add("mask", string);
  311.  
  312.                 if ((new HostMask(string)).isAllowed()) {
  313.                     try {
  314.                         newUser.addIPMask(string);
  315.                         response.addComment(conn.jprintf(UserManagement.class,
  316.                                 "addip.success", env));
  317.                         logger.info("'" + conn.getUserNull().getName() +
  318.                                 "' added ip '" + string + "' to '" +
  319.                                 newUser.getName() + "'");
  320.                     } catch (DuplicateElementException e1) {
  321.                         response.addComment(conn.jprintf(UserManagement.class,
  322.                                 "addip.dupe", env));
  323.                     }
  324.                 } else {
  325.                     response.addComment(conn.jprintf(UserManagement.class,
  326.                             "addip.invalid", env));
  327.                     badipmasks.addComment(conn.jprintf(UserManagement.class,
  328.                             "addip.invalid", env));
  329.                     logger.info("'" + conn.getUserNull().getName() +
  330.                             "' was denied the add of ip '" + string + "' to '" +
  331.                             newUser.getName() + "'");
  332.                 }
  333.             }
  334.  
  335.             newUser.commit();
  336.  
  337.             if (newUser.getHostMaskCollection().size() < 1) {
  338.                 newUser.purge();
  339.                 badipmasks.addComment(conn.jprintf(UserManagement.class,
  340.                         "adduser.noipmask", env));
  341.                 return badipmasks;
  342.             }
  343.         } catch (UserFileException ex) {
  344.             logger.warn("", ex);
  345.  
  346.             return new Reply(452, ex.getMessage());
  347.         }
  348.  
  349.         return response;
  350.     }
  351.  
  352.     /**
  353.      * USAGE: site change <user><field><value>- change a field for a user site
  354.      * change =<group><field><value>- change a field for each member of group
  355.      * <group>site change {<user1><user2>.. }<field><value>- change a field
  356.      * for each user in the list site change *<field><value>- change a field
  357.      * for everyone
  358.      *
  359.      * Type "site change user help" in glftpd for syntax.
  360.      *
  361.      * Fields available:
  362.      *
  363.      * Field Description
  364.      * ------------------------------------------------------------- ratio
  365.      * Upload/Download ratio. 0 = Unlimited (Leech) wkly_allotment The number of
  366.      * kilobytes that this user will be given once a week (you need the reset
  367.      * binary enabled in your crontab). Syntax: site change user wkly_allotment
  368.      * "#,###" The first number is the section number (0=default section), the
  369.      * second is the number of kilobytes to give. (user's credits are replaced,
  370.      * not added to, with this value) Only one section at a time is supported,
  371.      * homedir This will change the user's homedir. NOTE: This command is
  372.      * disabled by default. To enable it, add "min_homedir /site" to your config
  373.      * file, where "/site" is the minimum directory that users can have, i.e.
  374.      * you can't change a user's home directory to /ftp-data or anything that
  375.      * doesn't have "/site" at the beginning. Important: don't use a trailing
  376.      * slash for homedir! Users CAN NOT cd, list, upload/download, etc, outside
  377.      * of their home dir. It acts similarly to chroot() (try man chroot).
  378.      * startup_dir The directory to start in. ex: /incoming will start the user
  379.      * in /glftpd/site/incoming if rootpath is /glftpd and homedir is /site.
  380.      * Users CAN cd, list, upload/download, etc, outside of startup_dir.
  381.      * idle_time Sets the default and maximum idle time for this user (overrides
  382.      * the -t and -T settings on glftpd command line). If -1, it is disabled; if
  383.      * 0, it is the same as the idler flag. credits Credits left to download.
  384.      * flags +1ABC or +H or -3, type "site flags" for a list of flags.
  385.      * num_logins # # : number of simultaneous logins allowed. The second number
  386.      * is number of sim. logins from the same IP. timeframe # # : the hour from
  387.      * which to allow logins and the hour when logins from this user will start
  388.      * being rejected. This is set in a 24 hour format. If a user is online past
  389.      * his timeframe, he'll be disconnected the next time he does a 'CWD'.
  390.      * time_limit Time limits, per LOGIN SESSION. (set in minutes. 0 =
  391.      * Unlimited) tagline User's tagline. group_slots Number of users a GADMIN
  392.      * is allowed to add. If you specify a second argument, it will be the
  393.      * number of leech accounts the gadmin can give (done by "site change user
  394.      * ratio 0") (2nd arg = leech slots) comment Changes the user's comment (max
  395.      * 50 characters). Comments are displayed by the comment cookie (see below).
  396.      * max_dlspeed Downstream bandwidth control (KBytes/sec) (0 = Unlimited)
  397.      * max_ulspeed Same but for uploads max_sim_down Maximum number of
  398.      * simultaneous downloads for this user (-1 = unlimited, 0 = zero [user
  399.      * can't download]) max_sim_up Maximum number of simultaneous uploads for
  400.      * this user (-1 = unlimited, 0 = zero [user can't upload]) sratio
  401.      * <SECTIONNAME><#>This is to change the ratio of a section (other than
  402.      * default).
  403.      *
  404.      * Flags available:
  405.      *
  406.      * Flagname Flag Description
  407.      * ------------------------------------------------------------- SITEOP 1
  408.      * User is siteop. GADMIN 2 User is Groupadmin of his/her first public group
  409.      * (doesn't work for private groups). GLOCK 3 User cannot change group.
  410.      * EXEMPT 4 Allows to log in when site is full. Also allows user to do "site
  411.      * idle 0", which is the same as having the idler flag. Also exempts the
  412.      * user from the sim_xfers limit in config file. COLOR 5 Enable/Disable the
  413.      * use of color (toggle with "site color"). DELETED 6 User is deleted.
  414.      * USEREDIT 7 "Co-Siteop" ANON 8 User is anonymous (per-session like login).
  415.      *
  416.      * NOTE* The 1 flag is not GOD mode, you must have the correct flags for the
  417.      * actions you wish to perform. NOTE* If you have flag 1 then you DO NOT
  418.      * WANT flag 2
  419.      *
  420.      * Restrictions placed on users flagged ANONYMOUS. 1. '!' on login is
  421.      * ignored. 2. They cannot DELETE, RMDIR, or RENAME. 3. Userfiles do not
  422.      * update like usual, meaning no stats will be kept for these users. The
  423.      * userfile only serves as a template for the starting environment of the
  424.      * logged in user. Use external scripts if you must keep records of their
  425.      * transfer stats.
  426.      *
  427.      * NUKE A User is allowed to use site NUKE. UNNUKE B User is allowed to use
  428.      * site UNNUKE. UNDUPE C User is allowed to use site UNDUPE. KICK D User is
  429.      * allowed to use site KICK. KILL E User is allowed to use site KILL/SWHO.
  430.      * TAKE F User is allowed to use site TAKE. GIVE G User is allowed to use
  431.      * site GIVE. USERS/USER H This allows you to view users ( site USER/USERS )
  432.      * IDLER I User is allowed to idle forever. CUSTOM1 J Custom flag 1 CUSTOM2
  433.      * K Custom flag 2 CUSTOM3 L Custom flag 3 CUSTOM4 M Custom flag 4 CUSTOM5 N
  434.      * Custom flag 5
  435.      *
  436.      * You can use custom flags in the config file to give some users access to
  437.      * certain things without having to use private groups. These flags will
  438.      * only show up in "site flags" if they're turned on.
  439.      *
  440.      * ex. site change Archimede ratio 5
  441.      *
  442.      * This would set the ratio to 1:5 for the user 'Archimede'.
  443.      *
  444.      * ex. site change Archimede flags +2-AG
  445.      *
  446.      * This would make the user 'Archimede' groupadmin and remove his ability to
  447.      * use the commands site nuke and site give.
  448.      *
  449.      * NOTE: The flag DELETED can not be changed with site change, it will
  450.      * change when someone does a site deluser/readd.
  451.      * @throws ImproperUsageException
  452.      */
  453.     private Reply doSITE_CHANGE(BaseFtpConnection conn) throws ImproperUsageException {
  454.         FtpRequest request = conn.getRequest();
  455.  
  456.         if (!conn.getUserNull().isAdmin() && !conn.getUserNull().isGroupAdmin()) {
  457.             return Reply.RESPONSE_530_ACCESS_DENIED;
  458.         }
  459.  
  460.         if (!request.hasArgument()) {
  461.             throw new ImproperUsageException();
  462.         }
  463.  
  464.         Collection<User> users = new ArrayList<User>();
  465.         User userToChange;
  466.         Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
  467.         ReplacerEnvironment env = new ReplacerEnvironment();
  468.  
  469.         StringTokenizer arguments = new StringTokenizer(request.getArgument());
  470.  
  471.         if (!arguments.hasMoreTokens()) {
  472.             throw new ImproperUsageException();
  473.         }
  474.  
  475.         String username = arguments.nextToken();
  476.  
  477.         try {
  478.             if (username.startsWith("=")) {
  479.                 String group = username.replace("=", "");
  480.                 users = conn.getGlobalContext().getUserManager().getAllUsersByGroup(group);
  481.             } else if (username.equals("*")) {
  482.                 users = conn.getGlobalContext().getUserManager().getAllUsers();
  483.             } else {
  484.                 users.add(conn.getGlobalContext().getUserManager()
  485.                         .getUserByNameUnchecked(username));
  486.             }
  487.         } catch (NoSuchUserException e) {
  488.             return new Reply(550,
  489.                     "User " + username + " not found: " + e.getMessage());
  490.         } catch (UserFileException e) {
  491.             logger.log(Level.ERROR, "Error loading user", e);
  492.  
  493.             return new Reply(550, "Error loading user: " + e.getMessage());
  494.         }
  495.  
  496.         if (!arguments.hasMoreTokens()) {
  497.             throw new ImproperUsageException();
  498.         }
  499.  
  500.         String command = arguments.nextToken().toLowerCase();
  501.  
  502.         if (conn.getUserNull().isGroupAdmin() && !command.equals("ratio")) {
  503.             return Reply.RESPONSE_530_ACCESS_DENIED;
  504.         }
  505.  
  506.         // String args[] = request.getArgument().split(" ");
  507.         // String command = args[1].toLowerCase();
  508.         // 0 = user
  509.         // 1 = command
  510.         // 2- = argument
  511.         String[] commandArguments = new String[arguments.countTokens()];
  512.         String fullCommandArgument = "";
  513.  
  514.         for (int x = 0; arguments.hasMoreTokens(); x++) {
  515.             commandArguments[x] = arguments.nextToken();
  516.             fullCommandArgument = fullCommandArgument + " "
  517.                     + commandArguments[x];
  518.         }
  519.  
  520.         fullCommandArgument = fullCommandArgument.trim();
  521.  
  522.         Iterator<User> userIterator = users.iterator();
  523.  
  524.         while (userIterator.hasNext()) {
  525.             userToChange = userIterator.next();
  526.  
  527.             if ("ratio".equals(command)) {
  528.                 ////// Ratio //////
  529.                 if (commandArguments.length != 1) {
  530.                     throw new ImproperUsageException();
  531.                 }
  532.  
  533.                 float ratio = Float.parseFloat(commandArguments[0]);
  534.  
  535.                 if (conn.getUserNull().isGroupAdmin()
  536.                         && !conn.getUserNull().isAdmin()) {
  537.                     ////// Group Admin Ratio //////
  538.                     if (!conn.getUserNull().getGroup().equals(userToChange.getGroup())) {
  539.                         return Reply.RESPONSE_530_ACCESS_DENIED;
  540.                     }
  541.  
  542.                     if (ratio == 0F) {
  543.                         int usedleechslots = 0;
  544.  
  545.                         try {
  546.                             for (Iterator iter = conn.getGlobalContext()
  547.                                     .getUserManager().getAllUsersByGroup(
  548.                                             conn.getUserNull().getGroup())
  549.                                     .iterator(); iter.hasNext();) {
  550.                                 if (((User) iter.next()).getKeyedMap()
  551.                                         .getObjectFloat(UserManagement.RATIO) == 0F) {
  552.                                     usedleechslots++;
  553.                                 }
  554.                             }
  555.                         } catch (UserFileException e1) {
  556.                             return new Reply(452,
  557.                                     "IO error reading userfiles: " + e1.getMessage());
  558.                         }
  559.  
  560.                         if (usedleechslots >= conn.getUserNull().getKeyedMap().getObjectInt(UserManagement.LEECHSLOTS)) {
  561.                             return new Reply(452, conn.jprintf(
  562.                                     UserManagement.class,
  563.                                     "changeratio.nomoreslots"));
  564.                         }
  565.                     } else if (ratio < conn.getUserNull().getMinRatio()
  566.                             || ratio > conn.getUserNull().getMaxRatio()) {
  567.                         env.add("minratio", conn.getUserNull().getMinRatio());
  568.                         env.add("maxratio", conn.getUserNull().getMaxRatio());
  569.                         return new Reply(452, conn.jprintf(
  570.                                 UserManagement.class,
  571.                                 "changeratio.invalidratio", env));
  572.                     }
  573.  
  574.                     logger.info("'"
  575.                             + conn.getUserNull().getName()
  576.                             + "' changed ratio for '"
  577.                             + userToChange.getName()
  578.                             + "' from '"
  579.                             + userToChange.getKeyedMap().getObjectFloat(
  580.                                 UserManagement.RATIO) + "' to '" + ratio
  581.                             + "'");
  582.                     userToChange.getKeyedMap().setObject(UserManagement.RATIO, new Float(ratio));
  583.                     env.add("newratio", Float.toString(userToChange.getKeyedMap()
  584.                                 .getObjectFloat(UserManagement.RATIO)));
  585.                     response.addComment(conn.jprintf(UserManagement.class,
  586.                             "changeratio.success", env));
  587.                 } else {
  588.                     // Ratio changes by an admin //
  589.                     logger.info("'"
  590.                             + conn.getUserNull().getName()
  591.                             + "' changed ratio for '"
  592.                             + userToChange.getName()
  593.                             + "' from '"
  594.                             + userToChange.getKeyedMap().getObjectFloat(
  595.                                     UserManagement.RATIO) + " to '" + ratio
  596.                             + "'");
  597.                     userToChange.getKeyedMap().setObject(UserManagement.RATIO,
  598.                             new Float(ratio));
  599.                     env.add("newratio", Float
  600.                             .toString(userToChange.getKeyedMap()
  601.                                     .getObjectFloat(UserManagement.RATIO)));
  602.                     response.addComment(conn.jprintf(UserManagement.class,
  603.                             "changeratio.success", env));
  604.                 }
  605.             } else if ("credits".equals(command)) {
  606.                 if (commandArguments.length != 1) {
  607.                     throw new ImproperUsageException();
  608.                 }
  609.  
  610.                 long credits = Bytes.parseBytes(commandArguments[0]);
  611.                 logger.info("'" + conn.getUserNull().getName()
  612.                         + "' changed credits for '" + userToChange.getName()
  613.                         + "' from '" + userToChange.getCredits() + " to '"
  614.                         + credits + "'");
  615.                 userToChange.setCredits(credits);
  616.                 env.add("newcredits", Bytes.formatBytes(userToChange.getCredits()));
  617.                 response.addComment(conn.jprintf(UserManagement.class,
  618.                         "changecredits.success", env));
  619.             } else if ("comment".equals(command)) {
  620.                 logger.info("'"
  621.                         + conn.getUserNull().getName()
  622.                         + "' changed comment for '"
  623.                         + userToChange.getName()
  624.                         + "' from '"
  625.                         + userToChange.getKeyedMap().getObjectString(
  626.                                 UserManagement.COMMENT) + " to '"
  627.                         + fullCommandArgument + "'");
  628.                 userToChange.getKeyedMap().setObject(UserManagement.COMMENT, fullCommandArgument);
  629.                 env.add("comment", userToChange.getKeyedMap().getObjectString(
  630.                         UserManagement.COMMENT));
  631.                 response.addComment(conn.jprintf(UserManagement.class,
  632.                         "changecomment.success", env));
  633.             } else if ("idle_time".equals(command)) {
  634.                 if (commandArguments.length != 1) {
  635.                     throw new ImproperUsageException();
  636.                 }
  637.  
  638.                 int idleTime = Integer.parseInt(commandArguments[0]);
  639.                 env.add("oldidletime", "" + userToChange.getIdleTime());
  640.                 logger.info("'" + conn.getUserNull().getName()
  641.                         + "' changed idle_time for '" + userToChange.getName()
  642.                         + "' from '" + userToChange.getIdleTime() + " to '"
  643.                         + idleTime + "'");
  644.                 userToChange.setIdleTime(idleTime);
  645.                 env.add("newidletime", "" + idleTime);
  646.                 response.addComment(conn.jprintf(UserManagement.class,
  647.                         "changeidletime.success", env));
  648.             } else if ("num_logins".equals(command)) {
  649.                 // [# sim logins] [# sim logins/ip]
  650.                 try {
  651.                     int numLogins;
  652.                     int numLoginsIP;
  653.  
  654.                     if ((commandArguments.length < 1)
  655.                             || (commandArguments.length > 2)) {
  656.                         return Reply.RESPONSE_501_SYNTAX_ERROR;
  657.                     }
  658.  
  659.                     numLogins = Integer.parseInt(commandArguments[0]);
  660.  
  661.                     if (commandArguments.length == 2) {
  662.                         numLoginsIP = Integer.parseInt(commandArguments[1]);
  663.                     } else {
  664.                         numLoginsIP = userToChange.getKeyedMap().getObjectInt(UserManagement.MAXLOGINSIP);
  665.                     }
  666.  
  667.                     logger.info("'"
  668.                             + conn.getUserNull().getName()
  669.                             + "' changed num_logins for '"
  670.                             + userToChange.getName()
  671.                             + "' from '"
  672.                             + userToChange.getKeyedMap().getObjectInt(
  673.                                     UserManagement.MAXLOGINS)
  674.                             + "' '"
  675.                             + userToChange.getKeyedMap().getObjectInt(
  676.                                     UserManagement.MAXLOGINSIP) + "' to '"
  677.                             + numLogins + "' '" + numLoginsIP + "'");
  678.                     userToChange.getKeyedMap().setObject(
  679.                             UserManagement.MAXLOGINS, numLogins);
  680.                     userToChange.getKeyedMap().setObject(
  681.                             UserManagement.MAXLOGINSIP, numLoginsIP);
  682.                     env.add("numlogins", "" + numLogins);
  683.                     env.add("numloginsip", "" + numLoginsIP);
  684.                     response.addComment(conn.jprintf(UserManagement.class,
  685.                             "changenumlogins.success", env));
  686.                 } catch (NumberFormatException ex) {
  687.                     return Reply.RESPONSE_501_SYNTAX_ERROR;
  688.                 }
  689.  
  690.                 // } else if ("max_dlspeed".equalsIgnoreCase(command)) {
  691.                 // myUser.setMaxDownloadRate(Integer.parseInt(commandArgument));
  692.                 // } else if ("max_ulspeed".equals(command)) {
  693.                 // myUser.setMaxUploadRate(Integer.parseInt(commandArgument));
  694.             } else if ("group_ratio".equals(command)) {
  695.                 // [# min] [# max]
  696.                 if (commandArguments.length != 2) {
  697.                     return Reply.RESPONSE_501_SYNTAX_ERROR;
  698.                 }
  699.  
  700.                 try {
  701.                     float minRatio = Float.parseFloat(commandArguments[0]);
  702.                     float maxRatio = Float.parseFloat(commandArguments[1]);
  703.  
  704.                     env.add("minratio", "" + minRatio);
  705.                     env.add("maxratio", "" + maxRatio);
  706.  
  707.                     logger.info("'" + conn.getUserNull().getName()
  708.                             + "' changed gadmin min/max ratio for user '"
  709.                             + userToChange.getName() + "' group '"
  710.                             + userToChange.getGroup() + "' from '"
  711.                             + userToChange.getMinRatio() + "/"
  712.                             + userToChange.getMaxRatio() + "' to '" + minRatio
  713.                             + "/" + maxRatio + "'");
  714.  
  715.                     if (minRatio < 1 || maxRatio < minRatio)
  716.                         return Reply.RESPONSE_501_SYNTAX_ERROR;
  717.  
  718.                     userToChange.setMinRatio(minRatio);
  719.                     userToChange.setMaxRatio(maxRatio);
  720.  
  721.                     response.addComment(conn.jprintf(UserManagement.class,
  722.                             "changegadminratio.success", env));
  723.  
  724.                 } catch (NumberFormatException ex) {
  725.                     return Reply.RESPONSE_501_SYNTAX_ERROR;
  726.                 }
  727.             } else if ("max_sim".equals(command)) {
  728.                 // [# DN] [# UP]
  729.  
  730.                 try {
  731.                     int maxup;
  732.                     int maxdn;
  733.  
  734.                     if (commandArguments.length != 2) {
  735.                         return Reply.RESPONSE_501_SYNTAX_ERROR;
  736.                     }
  737.  
  738.                     maxdn = Integer.parseInt(commandArguments[0]);
  739.                     maxup = Integer.parseInt(commandArguments[1]);
  740.  
  741.                     logger.info("'"
  742.                                     + conn.getUserNull().getName()
  743.                                     + "' changed max simultaneous download/upload slots for '"
  744.                                     + userToChange.getName() + "' from '"
  745.                                     + userToChange.getMaxSimDown() + "' '"
  746.                                     + userToChange.getMaxSimUp() + "' to '"
  747.                                     + maxdn + "' '" + maxup + "'");
  748.  
  749.                     userToChange.setMaxSimUp(maxup);
  750.                     userToChange.setMaxSimDown(maxdn);
  751.                     env.add("maxdn", "" + maxdn);
  752.                     env.add("maxup", "" + maxup);
  753.                     response.addComment(conn.jprintf(UserManagement.class,
  754.                             "changemaxsim.success", env));
  755.  
  756.                 } catch (NumberFormatException ex) {
  757.                     return Reply.RESPONSE_501_SYNTAX_ERROR;
  758.                 }
  759.             } else if ("group".equals(command)) {
  760.                 if (commandArguments.length != 1) {
  761.                     throw new ImproperUsageException();
  762.                 }
  763.  
  764.                 logger.info("'" + conn.getUserNull().getName()
  765.                         + "' changed primary group for '"
  766.                         + userToChange.getName() + "' from '"
  767.                         + userToChange.getGroup() + "' to '"
  768.                         + commandArguments[0] + "'");
  769.                 userToChange.setGroup(commandArguments[0]);
  770.                 env.add("primgroup", userToChange.getGroup());
  771.                 response.addComment(conn.jprintf(UserManagement.class,
  772.                         "changeprimgroup.success", env));
  773.  
  774.                 // group_slots Number of users a GADMIN is allowed to add.
  775.                 // If you specify a second argument, it will be the
  776.                 // number of leech accounts the gadmin can give (done by
  777.                 // "site change user ratio 0") (2nd arg = leech slots)
  778.             } else if ("group_slots".equals(command)) {
  779.                 try {
  780.                     if ((commandArguments.length < 1)
  781.                             || (commandArguments.length > 2)) {
  782.                         return Reply.RESPONSE_501_SYNTAX_ERROR;
  783.                     }
  784.  
  785.                     int groupSlots = Short.parseShort(commandArguments[0]);
  786.                     int groupLeechSlots;
  787.  
  788.                     if (commandArguments.length >= 2) {
  789.                         groupLeechSlots = Integer.parseInt(commandArguments[1]);
  790.                     } else {
  791.                         groupLeechSlots = userToChange.getKeyedMap().getObjectInt(UserManagement.LEECHSLOTS);
  792.                     }
  793.  
  794.                     logger.info("'"
  795.                             + conn.getUserNull().getName()
  796.                             + "' changed group_slots for '"
  797.                             + userToChange.getName()
  798.                             + "' from '"
  799.                             + userToChange.getKeyedMap().getObjectInt(
  800.                                     UserManagement.GROUPSLOTS)
  801.                             + "' "
  802.                             + userToChange.getKeyedMap().getObjectInt(
  803.                                     UserManagement.LEECHSLOTS) + "' to '"
  804.                             + groupSlots + "' '" + groupLeechSlots + "'");
  805.                     userToChange.getKeyedMap().setObject(
  806.                             UserManagement.GROUPSLOTS, groupSlots);
  807.                     userToChange.getKeyedMap().setObject(
  808.                             UserManagement.LEECHSLOTS, groupLeechSlots);
  809.                     env.add("groupslots", ""
  810.                             + userToChange.getKeyedMap().getObjectInt(
  811.                                     UserManagement.GROUPSLOTS));
  812.                     env.add("groupleechslots", ""
  813.                             + userToChange.getKeyedMap().getObjectInt(
  814.                                     UserManagement.LEECHSLOTS));
  815.                     response.addComment(conn.jprintf(UserManagement.class,
  816.                             "changegroupslots.success", env));
  817.                 } catch (NumberFormatException ex) {
  818.                     return Reply.RESPONSE_501_SYNTAX_ERROR;
  819.                 }
  820.             } else if ("created".equals(command)) {
  821.                 Date myDate;
  822.  
  823.                 if (commandArguments.length == 0) {
  824.                     try {
  825.                         myDate = new SimpleDateFormat("yyyy-MM-dd")
  826.                                 .parse(commandArguments[0]);
  827.                     } catch (ParseException e1) {
  828.                         logger.log(Level.INFO, e1);
  829.  
  830.                         return new Reply(452, e1.getMessage());
  831.                     }
  832.                 } else {
  833.                     myDate = new Date();
  834.                 }
  835.  
  836.                 logger.info("'"
  837.                         + conn.getUserNull().getName()
  838.                         + "' changed created for '"
  839.                         + userToChange.getName()
  840.                         + "' from '"
  841.                         + new Date(userToChange.getKeyedMap().getObjectLong(
  842.                                 UserManagement.CREATED)) + "' to '" + myDate
  843.                         + "'");
  844.                 userToChange.getKeyedMap().setObject(UserManagement.CREATED,
  845.                         myDate);
  846.  
  847.                 response = new Reply(200, conn.jprintf(UserManagement.class,
  848.                         "changecreated.success", env));
  849.             } else if ("wkly_allotment".equals(command)) {
  850.                 if (commandArguments.length != 1) {
  851.                     throw new ImproperUsageException();
  852.                 }
  853.  
  854.                 long weeklyAllotment = Bytes.parseBytes(commandArguments[0]);
  855.                 logger.info("'"
  856.                         + conn.getUserNull().getName()
  857.                         + "' changed wkly_allotment for '"
  858.                         + userToChange.getName()
  859.                         + "' from '"
  860.                         + userToChange.getKeyedMap().getObjectLong(
  861.                                 UserManagement.WKLY_ALLOTMENT) + "' to "
  862.                         + weeklyAllotment + "'");
  863.                 userToChange.getKeyedMap().setObject(
  864.                         UserManagement.WKLY_ALLOTMENT, weeklyAllotment);
  865.  
  866.                 response = Reply.RESPONSE_200_COMMAND_OK;
  867.             } else if ("tagline".equals(command)) {
  868.                 if (commandArguments.length < 1) {
  869.                     throw new ImproperUsageException();
  870.                 }
  871.  
  872.                 logger.info("'" + conn.getUserNull().getName()
  873.                         + "' changed tagline for '" + userToChange.getName()
  874.                         + "' from '"
  875.                         + userToChange.getKeyedMap().getObject(TAGLINE, "")
  876.                         + "' to '" + fullCommandArgument + "'");
  877.                 userToChange.getKeyedMap().setObject(UserManagement.TAGLINE,
  878.                         fullCommandArgument);
  879.  
  880.                 response = Reply.RESPONSE_200_COMMAND_OK;
  881.             } else {
  882.                 throw new ImproperUsageException();
  883.             }
  884.  
  885.             try {
  886.                 userToChange.commit();
  887.             } catch (UserFileException e) {
  888.                 logger.warn("", e);
  889.                 response.addComment(e.getMessage());
  890.             }
  891.         }
  892.         return response;
  893.     }
  894.  
  895.     /**
  896.      * USAGE: site chgrp <user><group>[ <group>] Adds/removes a user from
  897.      * group(s).
  898.      *
  899.      * ex. site chgrp archimede ftp This would change the group to 'ftp' for the
  900.      * user 'archimede'.
  901.      *
  902.      * ex1. site chgrp archimede ftp This would remove the group ftp from the
  903.      * user 'archimede'.
  904.      *
  905.      * ex2. site chgrp archimede ftp eleet This moves archimede from ftp group
  906.      * to eleet group.
  907.      *
  908.      * @throws ImproperUsageException
  909.      */
  910.     private Reply doSITE_CHGRP(BaseFtpConnection conn) throws ReplyException, ImproperUsageException {
  911.         FtpRequest request = conn.getRequest();
  912.  
  913.         if (!conn.getUserNull().isAdmin()) {
  914.             return Reply.RESPONSE_530_ACCESS_DENIED;
  915.         }
  916.  
  917.         if (!request.hasArgument()) {
  918.             throw new ImproperUsageException();
  919.         }
  920.  
  921.         String[] args = request.getArgument().split("[ ,]");
  922.  
  923.         if (args.length < 2) {
  924.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  925.         }
  926.  
  927.         User myUser;
  928.  
  929.         try {
  930.             myUser = conn.getGlobalContext().getUserManager().getUserByName(args[0]);
  931.         } catch (NoSuchUserException e) {
  932.             return new Reply(452, "User not found: " + e.getMessage());
  933.         } catch (UserFileException e) {
  934.             logger.log(Level.FATAL, "IO error reading user", e);
  935.  
  936.             return new Reply(452, "IO error reading user: " +
  937.                 e.getMessage());
  938.         }
  939.  
  940.         Reply response = new Reply(200);
  941.  
  942.         for (int i = 1; i < args.length; i++) {
  943.             String string = args[i];
  944.  
  945.             try {
  946.                 myUser.removeSecondaryGroup(string);
  947.                 logger.info("'" + conn.getUserNull().getName() +
  948.                     "' removed '" + myUser.getName() + "' from group '" +
  949.                     string + "'");
  950.                 response.addComment(myUser.getName() +
  951.                     " removed from group " + string);
  952.             } catch (NoSuchFieldException e1) {
  953.                 try {
  954.                     myUser.addSecondaryGroup(string);
  955.                     logger.info("'" + conn.getUserNull().getName() +
  956.                         "' added '" + myUser.getName() + "' to group '" +
  957.                         string + "'");
  958.                     response.addComment(myUser.getName() +
  959.                         " added to group " + string);
  960.                 } catch (DuplicateElementException e2) {
  961.                     throw new RuntimeException("Error, user was not a member before",
  962.                         e2);
  963.                 }
  964.             }
  965.         }
  966.         try {
  967.             myUser.commit();
  968.         } catch(UserFileException e) {
  969.             throw new ReplyException(e);
  970.         }
  971.         return response;
  972.     }
  973.  
  974.     /**
  975.      * USAGE: site chpass <user> <password> - Change users password, Ex. site chpass Archimede newpassword<br />
  976.      * This would change the password to 'newpassword' for the user 'Archimede'.<br />
  977.      * See "site passwd" for more info if you get a "Password is not secure
  978.      * enough" error. <br />
  979.      * <br />
  980.      * <b>&#42;</b> denotes any password, ex. site chpass arch &#42;<br />
  981.      * This will &#42; allow arch to login with any password<br>
  982.      * <br />
  983.      * <b>&#64;</b> Denotes any email-like
  984.      * password, ex. site chpass arch &#64;<br />
  985.      * This will allow arch to login with a&#64;b.com but not ab.com
  986.      * @throws ImproperUsageException
  987.      */
  988.     private Reply doSITE_CHPASS(BaseFtpConnection conn) throws ImproperUsageException {
  989.         FtpRequest request = conn.getRequest();
  990.  
  991.         if (!conn.getUserNull().isAdmin()) {
  992.             return Reply.RESPONSE_530_ACCESS_DENIED;
  993.         }
  994.  
  995.         if (!request.hasArgument()) {
  996.             throw new ImproperUsageException();
  997.         }
  998.  
  999.         String[] args = request.getArgument().split(" ");
  1000.  
  1001.         if (args.length != 2) {
  1002.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  1003.         }
  1004.  
  1005.         try {
  1006.             User myUser = conn.getGlobalContext().getUserManager()
  1007.                               .getUserByName(args[0]);
  1008.             myUser.setPasswordEnc(args[1]);
  1009.             myUser.commit();
  1010.             logger.info("'" + conn.getUserNull().getName() +
  1011.                 "' changed password for '" + myUser.getName() + "'");
  1012.  
  1013.             return Reply.RESPONSE_200_COMMAND_OK;
  1014.         } catch (NoSuchUserException e) {
  1015.             return new Reply(452, "User not found: " + e.getMessage());
  1016.         } catch (UserFileException e) {
  1017.             logger.log(Level.FATAL, "Error reading userfile", e);
  1018.  
  1019.             return new Reply(452, "Error reading userfile: " +
  1020.                 e.getMessage());
  1021.         }
  1022.     }
  1023.  
  1024.     /**
  1025.      * USAGE: site delip <user><ident@ip>...
  1026.      *
  1027.      * @param request
  1028.      * @param out
  1029.      * @throws ImproperUsageException
  1030.      */
  1031.     private Reply doSITE_DELIP(BaseFtpConnection conn) throws ImproperUsageException {
  1032.         FtpRequest request = conn.getRequest();
  1033.  
  1034.         if (!conn.getUserNull().isAdmin() &&
  1035.                 !conn.getUserNull().isGroupAdmin()) {
  1036.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1037.         }
  1038.  
  1039.         if (!request.hasArgument()) {
  1040.             throw new ImproperUsageException();
  1041.         }
  1042.  
  1043.         String[] args = request.getArgument().split(" ");
  1044.  
  1045.         if (args.length < 2) {
  1046.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  1047.         }
  1048.  
  1049.         User myUser;
  1050.  
  1051.         try {
  1052.             myUser = conn.getGlobalContext().getUserManager().getUserByName(args[0]);
  1053.         } catch (NoSuchUserException e) {
  1054.             return new Reply(452, e.getMessage());
  1055.         } catch (UserFileException e) {
  1056.             logger.log(Level.FATAL, "IO error", e);
  1057.  
  1058.             return new Reply(452, "IO error: " + e.getMessage());
  1059.         }
  1060.  
  1061.         if (conn.getUserNull().isGroupAdmin() &&
  1062.                 !conn.getUserNull().getGroup().equals(myUser.getGroup())) {
  1063.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1064.         }
  1065.  
  1066.         Reply response = new Reply(200);
  1067.  
  1068.         for (int i = 1; i < args.length; i++) {
  1069.             String string = args[i].replace(",",""); // strip commas (for easy copy+paste);
  1070.  
  1071.             try {
  1072.                 myUser.removeIpMask(string);
  1073.                 logger.info("'" + conn.getUserNull().getName() +
  1074.                     "' removed ip '" + string + "' from '" + myUser + "'");
  1075.                 response.addComment("Removed " + string);
  1076.             } catch (NoSuchFieldException e1) {
  1077.                 response.addComment("Mask " + string + " not found: " +
  1078.                     e1.getMessage());
  1079.  
  1080.                 continue;
  1081.             }
  1082.         }
  1083.  
  1084.         return response;
  1085.     }
  1086.  
  1087.     private Reply doSITE_DELUSER(BaseFtpConnection conn) throws ReplyException, ImproperUsageException {
  1088.         FtpRequest request = conn.getRequest();
  1089.  
  1090.         if (!request.hasArgument()) {
  1091.             throw new ImproperUsageException();
  1092.         }
  1093.  
  1094.         if (!conn.getUserNull().isAdmin() &&
  1095.                 !conn.getUserNull().isGroupAdmin()) {
  1096.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1097.         }
  1098.  
  1099.         StringTokenizer st = new StringTokenizer(request.getArgument());
  1100.         String delUsername = st.nextToken();
  1101.         User myUser;
  1102.  
  1103.         try {
  1104.             myUser = conn.getGlobalContext().getUserManager().getUserByName(delUsername);
  1105.         } catch (NoSuchUserException e) {
  1106.             return new Reply(452, e.getMessage());
  1107.         } catch (UserFileException e) {
  1108.             return new Reply(452, "Couldn't getUser: " + e.getMessage());
  1109.         }
  1110.  
  1111.         if (conn.getUserNull().isGroupAdmin() &&
  1112.                 !conn.getUserNull().getGroup().equals(myUser.getGroup())) {
  1113.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1114.         }
  1115.  
  1116.         myUser.setDeleted(true);
  1117.         String reason = "";
  1118.         if(st.hasMoreTokens()) {
  1119.             myUser.getKeyedMap().setObject(UserManagement.REASON, reason = st.nextToken("").substring(1));
  1120.         }
  1121.         try {
  1122.             myUser.commit();
  1123.         } catch (UserFileException e1) {
  1124.             logger.error("", e1);
  1125.             throw new ReplyException(e1);
  1126.         }
  1127.         logger.info("'" + conn.getUserNull().getName() +
  1128.             "' deleted user '" + myUser.getName() + "' with reason '"+reason+"'");
  1129.         logger.debug("reason "+myUser.getKeyedMap().getObjectString(UserManagement.REASON));
  1130.         return Reply.RESPONSE_200_COMMAND_OK;
  1131.     }
  1132.  
  1133.     private Reply doSITE_GINFO(BaseFtpConnection conn) throws ImproperUsageException {
  1134.         FtpRequest request = conn.getRequest();
  1135.         //security
  1136.         if (!conn.getUserNull().isAdmin() && !conn.getUserNull().isGroupAdmin()) {
  1137.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1138.         }
  1139.         //syntax
  1140.         if (!request.hasArgument()) {
  1141.             throw new ImproperUsageException();
  1142.         }
  1143.         //gadmin
  1144.         String group = request.getArgument();
  1145.  
  1146.         if (conn.getUserNull().isGroupAdmin()
  1147.                 && !conn.getUserNull().getGroup().equals(group)) {
  1148.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1149.         }
  1150.  
  1151.         Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
  1152.  
  1153.         ResourceBundle bundle = ResourceBundle.getBundle(UserManagement.class.getName());
  1154.         ReplacerEnvironment env = new ReplacerEnvironment();
  1155.         env.add("group", group);
  1156.         env.add("sp", " ");
  1157.  
  1158.         //add header
  1159.         String head = bundle.getString("ginfo.head");
  1160.         try {
  1161.             response.addComment(SimplePrintf.jprintf(head, env));
  1162.         } catch (MissingResourceException e) {
  1163.             logger.warn("",e);
  1164.             response.addComment(e.getMessage());
  1165.         } catch (FormatterException e) {
  1166.             logger.warn("",e);
  1167.             response.addComment(e.getMessage());
  1168.         }
  1169.  
  1170.         //vars for total stats
  1171.         int numUsers = 0;
  1172.         int numLeechUsers = 0;
  1173.         int allfup = 0;
  1174.         int allfdn = 0;
  1175.         long allmbup = 0;
  1176.         long allmbdn = 0;
  1177.  
  1178.         Collection users;
  1179.         try {
  1180.             users = conn.getGlobalContext().getUserManager()
  1181.                     .getAllUsers();
  1182.         } catch (UserFileException e) {
  1183.             return new Reply(452, "IO error: " + e.getMessage());
  1184.         }
  1185.         for (Iterator iter = users.iterator(); iter.hasNext();) {
  1186.             User user = (User) iter.next();
  1187.             if (!user.isMemberOf(group))
  1188.                 continue;
  1189.  
  1190.             char status = ' ';
  1191.             if (user.isGroupAdmin()) {
  1192.                 status = '+';
  1193.             } else if (user.isAdmin()) {
  1194.                 status = '*';
  1195.             } else if (user.isDeleted()) {
  1196.                 status = '!';
  1197.             }
  1198.  
  1199.             try {
  1200.                 String body = bundle.getString("ginfo.user");
  1201.                 env.add("user", status + user.getName());
  1202.                 env.add("fup", "" + user.getUploadedFiles());
  1203.                 env.add("mbup", Bytes.formatBytes(user.getUploadedBytes()));
  1204.                 env.add("fdn", "" + user.getDownloadedFiles());
  1205.                 env.add("mbdn", Bytes.formatBytes(user.getDownloadedBytes()));
  1206.                 env.add("ratio", "1:" + (int) user.getKeyedMap().getObjectFloat(UserManagement.RATIO));
  1207.                 env.add("wkly", Bytes.formatBytes(user.getKeyedMap().getObjectLong(UserManagement.WKLY_ALLOTMENT)));
  1208.                 response.addComment(SimplePrintf.jprintf(body, env));
  1209.             } catch (MissingResourceException e) {
  1210.                 response.addComment(e.getMessage());
  1211.             } catch (FormatterException e1) {
  1212.                 response.addComment(e1.getMessage());
  1213.             }
  1214.  
  1215.             //update totals
  1216.             numUsers++;
  1217.             if ((int) user.getKeyedMap().getObjectFloat(UserManagement.RATIO) == 0) {
  1218.                 numLeechUsers++;
  1219.             }
  1220.             allfup += user.getUploadedFiles();
  1221.             allfdn += user.getDownloadedFiles();
  1222.             allmbup += user.getUploadedBytes();
  1223.             allmbdn += user.getDownloadedBytes();
  1224.         }
  1225.  
  1226.         //add tail
  1227.         env.add("allfup", "" + allfup);
  1228.         env.add("allmbup", Bytes.formatBytes(allmbup));
  1229.         env.add("allfdn", "" + allfdn);
  1230.         env.add("allmbdn", Bytes.formatBytes(allmbdn));
  1231.         env.add("numusers", "" + numUsers);
  1232.         env.add("numleech", "" + numLeechUsers);
  1233.  
  1234.         String tail = bundle.getString("ginfo.tail");
  1235.         try {
  1236.             response.addComment(SimplePrintf.jprintf(tail, env));
  1237.         } catch (MissingResourceException e) {
  1238.             logger.warn("",e);
  1239.             response.addComment(e.getMessage());
  1240.         } catch (FormatterException e) {
  1241.             logger.warn("",e);
  1242.             response.addComment(e.getMessage());
  1243.         }
  1244.  
  1245.         return response;
  1246.     }
  1247.  
  1248.     private Reply doSITE_GIVE(BaseFtpConnection conn) throws ImproperUsageException {
  1249.         FtpRequest request = conn.getRequest();
  1250.  
  1251.         if (!conn.getGlobalContext().getConfig().checkPermission("give", conn.getUserNull())) {
  1252.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1253.         }
  1254.  
  1255.         if (!request.hasArgument()) {
  1256.             throw new ImproperUsageException();
  1257.         }
  1258.  
  1259.         StringTokenizer st = new StringTokenizer(request.getArgument());
  1260.  
  1261.         if (!st.hasMoreTokens()) {
  1262.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  1263.         }
  1264.  
  1265.         User myUser;
  1266.  
  1267.         try {
  1268.             myUser = conn.getGlobalContext().getUserManager().getUserByName(st.nextToken());
  1269.         } catch (Exception e) {
  1270.             logger.warn("", e);
  1271.  
  1272.             return new Reply(200, e.getMessage());
  1273.         }
  1274.  
  1275.         if (!st.hasMoreTokens()) {
  1276.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  1277.         }
  1278.         long credits = 0;
  1279.         String amt = null;
  1280.         try {
  1281.             amt = st.nextToken();
  1282.             credits = Bytes.parseBytes(amt);
  1283.         } catch (NumberFormatException ex) {
  1284.             return new Reply(452, "The string " + amt + " cannot be interpreted");
  1285.         }
  1286.  
  1287.         if (0 > credits) {
  1288.             return new Reply(452, credits + " is not a positive number.");
  1289.         }
  1290.  
  1291.         if (!conn.getUserNull().isAdmin()) {
  1292.             if (credits > conn.getUserNull().getCredits()) {
  1293.                 return new Reply(452,
  1294.                     "You cannot give more credits than you have.");
  1295.             }
  1296.  
  1297.             conn.getUserNull().updateCredits(-credits);
  1298.         }
  1299.  
  1300.         logger.info("'" + conn.getUserNull().getName() + "' transfered " +
  1301.             Bytes.formatBytes(credits) + " ('" + credits + "') to '" +
  1302.             myUser.getName() + "'");
  1303.         myUser.updateCredits(credits);
  1304.  
  1305.         return new Reply(200,
  1306.             "OK, gave " + Bytes.formatBytes(credits) + " of your credits to " +
  1307.             myUser.getName());
  1308.     }
  1309.  
  1310.     /**
  1311.      * @deprecated Users can reproduce this feature with SITE_USER by passing =group instead of a user.
  1312.      */
  1313.     private Reply doSITE_GROUP(BaseFtpConnection conn) throws ImproperUsageException {
  1314.         FtpRequest request = conn.getRequest();
  1315.  
  1316.         boolean ip = false;
  1317.         float ratio = 0;
  1318.         int numLogin = 0, numLoginIP = 0, maxUp = 0, maxDn = 0, idle = 0;
  1319.         String opt, group;
  1320.  
  1321.         if (!conn.getUserNull().isAdmin()) {
  1322.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1323.         }
  1324.  
  1325.         if (!request.hasArgument()) {
  1326.             throw new ImproperUsageException();
  1327.         }
  1328.  
  1329.         StringTokenizer st = new StringTokenizer(request.getArgument());
  1330.  
  1331.         if (!st.hasMoreTokens()) { return Reply.RESPONSE_501_SYNTAX_ERROR; }
  1332.         group = st.nextToken();
  1333.  
  1334.         if (!st.hasMoreTokens()) { return Reply.RESPONSE_501_SYNTAX_ERROR; }
  1335.         opt = st.nextToken();
  1336.  
  1337.         if (!st.hasMoreTokens()) { return Reply.RESPONSE_501_SYNTAX_ERROR; }
  1338.  
  1339.         if (opt.equals("num_logins")) {
  1340.             numLogin = Integer.parseInt(st.nextToken());
  1341.             if (st.hasMoreTokens()) {
  1342.                 ip = true;
  1343.                 numLoginIP = Integer.parseInt(st.nextToken());
  1344.             }
  1345.         } else if (opt.equals("ratio")) {
  1346.             ratio = Float.parseFloat(st.nextToken());
  1347.         } else if (opt.equals("max_sim")) {
  1348.             maxUp = Integer.parseInt(st.nextToken());
  1349.             if (!st.hasMoreTokens()) {
  1350.                 throw new ImproperUsageException();
  1351.             }
  1352.             maxDn = Integer.parseInt(st.nextToken());
  1353.         } else if (opt.equals("idle_time")) {
  1354.             idle = Integer.parseInt(st.nextToken());
  1355.         } else {
  1356.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  1357.         }
  1358.  
  1359.         // getting data
  1360.  
  1361.         Reply response = new Reply(200);
  1362.  
  1363.         Collection users = null;
  1364.  
  1365.         try {
  1366.             users = conn.getGlobalContext().getUserManager().getAllUsersByGroup(group);
  1367.         } catch (UserFileException ex) {
  1368.             logger.fatal("IO error from getAllUsersByGroup(" + group + ")", ex);
  1369.             return new Reply(200, "IO error: " + ex.getMessage());
  1370.         }
  1371.         response.addComment("Changing '" + group + "' members " + opt);
  1372.  
  1373.         for (Iterator iter = users.iterator(); iter.hasNext();) {
  1374.             User userToChange = (User) iter.next();
  1375.  
  1376.             if (userToChange.getGroup().equals(group)) {
  1377.                 if (opt.equals("num_logins")) {
  1378.                     userToChange.getKeyedMap().setObject(UserManagement.MAXLOGINS, numLogin);
  1379.                     if (ip) { userToChange.getKeyedMap().setObject(UserManagement.MAXLOGINSIP, numLoginIP); }
  1380.                 } else if (opt.equals("max_sim")) {
  1381.                     userToChange.setMaxSimDown(maxDn);
  1382.                     userToChange.setMaxSimUp(maxUp);
  1383.                 } else if (opt.equals("ratio")) {
  1384.                     userToChange.getKeyedMap().setObject(UserManagement.RATIO, new Float(ratio));
  1385.                 } else if (opt.equals("idle_time")) {
  1386.                     userToChange.setIdleTime(new Integer(idle));
  1387.                 }
  1388.                 response.addComment("Changed " + userToChange.getName() + "!");
  1389.             }
  1390.         }
  1391.  
  1392.         response.addComment("Done!");
  1393.  
  1394.         return response;
  1395.     }
  1396.  
  1397.     private Reply doSITE_GROUPS(BaseFtpConnection conn) {
  1398.         Collection groups;
  1399.  
  1400.         try {
  1401.             groups = conn.getGlobalContext().getUserManager().getAllGroups();
  1402.         } catch (UserFileException e) {
  1403.             logger.log(Level.FATAL, "IO error from getAllGroups()", e);
  1404.  
  1405.             return new Reply(452, "IO error: " + e.getMessage());
  1406.         }
  1407.  
  1408.         Reply response = new Reply(200);
  1409.         response.addComment("All groups:");
  1410.  
  1411.         for (Iterator iter = groups.iterator(); iter.hasNext();) {
  1412.             String element = (String) iter.next();
  1413.             response.addComment(element);
  1414.         }
  1415.  
  1416.         return response;
  1417.     }
  1418.  
  1419.     private Reply doSITE_GRPREN(BaseFtpConnection conn) throws ImproperUsageException {
  1420.         FtpRequest request = conn.getRequest();
  1421.  
  1422.         if (!conn.getUserNull().isAdmin()) {
  1423.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1424.         }
  1425.  
  1426.         if (!request.hasArgument()) {
  1427.             throw new ImproperUsageException();
  1428.         }
  1429.  
  1430.         StringTokenizer st = new StringTokenizer(request.getArgument());
  1431.  
  1432.         if (!st.hasMoreTokens()) {
  1433.             throw new ImproperUsageException();
  1434.         }
  1435.  
  1436.         String oldGroup = st.nextToken();
  1437.  
  1438.         if (!st.hasMoreTokens()) {
  1439.             throw new ImproperUsageException();
  1440.         }
  1441.  
  1442.         String newGroup = st.nextToken();
  1443.         Collection users = null;
  1444.  
  1445.         try {
  1446.             if (!conn.getGlobalContext().getUserManager()
  1447.                          .getAllUsersByGroup(newGroup).isEmpty()) {
  1448.                 return new Reply(500, newGroup + " already exists");
  1449.             }
  1450.  
  1451.             users = conn.getGlobalContext().getUserManager().getAllUsersByGroup(oldGroup);
  1452.         } catch (UserFileException e) {
  1453.             logger.log(Level.FATAL,
  1454.                 "IO error from getAllUsersByGroup(" + oldGroup + ")", e);
  1455.  
  1456.             return new Reply(200, "IO error: " + e.getMessage());
  1457.         }
  1458.  
  1459.         Reply response = new Reply(200);
  1460.         response.addComment("Renaming group " + oldGroup + " to " + newGroup);
  1461.  
  1462.         for (Iterator iter = users.iterator(); iter.hasNext();) {
  1463.             User userToChange = (User) iter.next();
  1464.  
  1465.             if (userToChange.getGroup().equals(oldGroup)) {
  1466.                 userToChange.setGroup(newGroup);
  1467.             } else {
  1468.                 try {
  1469.                     userToChange.removeSecondaryGroup(oldGroup);
  1470.                 } catch (NoSuchFieldException e1) {
  1471.                     throw new RuntimeException(
  1472.                         "User was not in group returned by getAllUsersByGroup");
  1473.                 }
  1474.  
  1475.                 try {
  1476.                     userToChange.addSecondaryGroup(newGroup);
  1477.                 } catch (DuplicateElementException e2) {
  1478.                     throw new RuntimeException("group " + newGroup +
  1479.                         " already exists");
  1480.                 }
  1481.             }
  1482.  
  1483.             response.addComment("Changed user " + userToChange.getName());
  1484.         }
  1485.  
  1486.         return response;
  1487.     }
  1488.  
  1489.     private Reply doSITE_KICK(BaseFtpConnection conn) throws ImproperUsageException {
  1490.         FtpRequest request = conn.getRequest();
  1491.  
  1492.         if (!conn.getUserNull().isAdmin()) {
  1493.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1494.         }
  1495.  
  1496.         if (!request.hasArgument()) {
  1497.             throw new ImproperUsageException();
  1498.         }
  1499.  
  1500.         String arg = request.getArgument();
  1501.         int pos = arg.indexOf(' ');
  1502.         String username;
  1503.         String message = "Kicked by " + conn.getUserNull().getName();
  1504.  
  1505.         if (pos == -1) {
  1506.             username = arg;
  1507.         } else {
  1508.             username = arg.substring(0, pos);
  1509.             message = arg.substring(pos + 1);
  1510.         }
  1511.  
  1512.         Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
  1513.         ArrayList<BaseFtpConnection> conns = new ArrayList<BaseFtpConnection>(conn.getGlobalContext()
  1514.                                             .getConnectionManager()
  1515.                                             .getConnections());
  1516.  
  1517.         for (Iterator iter = conns.iterator(); iter.hasNext();) {
  1518.             BaseFtpConnection conn2 = (BaseFtpConnection) iter.next();
  1519.  
  1520.             try {
  1521.                 if (conn2.getUser().getName().equals(username)) {
  1522.                     conn2.stop(message);
  1523.                 }
  1524.             } catch (NoSuchUserException e) {
  1525.             }
  1526.         }
  1527.  
  1528.         return response;
  1529.     }
  1530.  
  1531.     private Reply doSITE_PASSWD(BaseFtpConnection conn) throws ImproperUsageException {
  1532.         FtpRequest request = conn.getRequest();
  1533.  
  1534.         if (!request.hasArgument()) {
  1535.             throw new ImproperUsageException();
  1536.         }
  1537.  
  1538.         logger.info("'" + conn.getUserNull().getName() +
  1539.             "' changed their password");
  1540.         conn.getUserNull().setPasswordEnc(request.getArgument());
  1541.  
  1542.         return Reply.RESPONSE_200_COMMAND_OK;
  1543.     }
  1544.  
  1545.     private Reply doSITE_PURGE(BaseFtpConnection conn) throws ImproperUsageException {
  1546.         FtpRequest request = conn.getRequest();
  1547.  
  1548.         if (!conn.getUserNull().isAdmin() &&
  1549.                 !conn.getUserNull().isGroupAdmin()) {
  1550.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1551.         }
  1552.  
  1553.         if (!request.hasArgument()) {
  1554.             throw new ImproperUsageException();
  1555.         }
  1556.  
  1557.         String delUsername = request.getArgument();
  1558.         User myUser;
  1559.  
  1560.         try {
  1561.             myUser = conn.getGlobalContext().getUserManager()
  1562.                          .getUserByNameUnchecked(delUsername);
  1563.         } catch (NoSuchUserException e) {
  1564.             return new Reply(452, e.getMessage());
  1565.         } catch (UserFileException e) {
  1566.             return new Reply(452, "Couldn't getUser: " + e.getMessage());
  1567.         }
  1568.  
  1569.         if (!myUser.isDeleted()) {
  1570.             return new Reply(452, "User isn't deleted");
  1571.         }
  1572.  
  1573.         if (conn.getUserNull().isGroupAdmin() &&
  1574.                 !conn.getUserNull().getGroup().equals(myUser.getGroup())) {
  1575.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1576.         }
  1577.  
  1578.         myUser.purge();
  1579.         logger.info("'" + conn.getUserNull().getName() + "' purged '" +
  1580.             myUser.getName() + "'");
  1581.  
  1582.         return Reply.RESPONSE_200_COMMAND_OK;
  1583.     }
  1584.  
  1585.     private Reply doSITE_READD(BaseFtpConnection conn) throws ReplyException, ImproperUsageException {
  1586.         FtpRequest request = conn.getRequest();
  1587.  
  1588.         if (!conn.getUserNull().isAdmin() &&
  1589.                 !conn.getUserNull().isGroupAdmin()) {
  1590.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1591.         }
  1592.  
  1593.         if (!request.hasArgument()) {
  1594.             throw new ImproperUsageException();
  1595.         }
  1596.  
  1597.         User myUser;
  1598.  
  1599.         try {
  1600.             myUser = conn.getGlobalContext().getUserManager()
  1601.                          .getUserByNameUnchecked(request.getArgument());
  1602.         } catch (NoSuchUserException e) {
  1603.             return new Reply(452, e.getMessage());
  1604.         } catch (UserFileException e) {
  1605.             return new Reply(452, "IO error: " + e.getMessage());
  1606.         }
  1607.  
  1608.         if (conn.getUserNull().isGroupAdmin() &&
  1609.                 !conn.getUserNull().getGroup().equals(myUser.getGroup())) {
  1610.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1611.         }
  1612.  
  1613.         if (!myUser.isDeleted()) {
  1614.             return new Reply(452, "User wasn't deleted");
  1615.         }
  1616.  
  1617.         myUser.setDeleted(false);
  1618.         myUser.getKeyedMap().remove(UserManagement.REASON);
  1619.         logger.info("'" + conn.getUserNull().getName() + "' readded '" +
  1620.             myUser.getName() + "'");
  1621.         try {
  1622.             myUser.commit();
  1623.         } catch (UserFileException e1) {
  1624.             logger.error(e1);
  1625.             throw new ReplyException(e1);
  1626.         }
  1627.         return Reply.RESPONSE_200_COMMAND_OK;
  1628.     }
  1629.  
  1630.     private Reply doSITE_RENUSER(BaseFtpConnection conn) throws ImproperUsageException {
  1631.         FtpRequest request = conn.getRequest();
  1632.  
  1633.         if (!conn.getUserNull().isAdmin()) {
  1634.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1635.         }
  1636.  
  1637.         if (!request.hasArgument()) {
  1638.             throw new ImproperUsageException();
  1639.         }
  1640.  
  1641.         String[] args = request.getArgument().split(" ");
  1642.  
  1643.         if (args.length != 2) {
  1644.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  1645.         }
  1646.  
  1647.         try {
  1648.             User myUser = conn.getGlobalContext().getUserManager()
  1649.                               .getUserByName(args[0]);
  1650.             String oldUsername = myUser.getName();
  1651.             myUser.rename(args[1]);
  1652.             logger.info("'" + conn.getUserNull().getName() + "' renamed '" +
  1653.                 oldUsername + "' to '" + myUser.getName() + "'");
  1654.         } catch (NoSuchUserException e) {
  1655.             return new Reply(452, "No such user: " + e.getMessage());
  1656.         } catch (UserExistsException e) {
  1657.             return new Reply(452, "Target username is already taken");
  1658.         } catch (UserFileException e) {
  1659.             return new Reply(452, e.getMessage());
  1660.         }
  1661.  
  1662.         return Reply.RESPONSE_200_COMMAND_OK;
  1663.     }
  1664.  
  1665.     private Reply doSITE_SEEN(BaseFtpConnection conn) throws ImproperUsageException {
  1666.         FtpRequest request = conn.getRequest();
  1667.  
  1668.         if (!request.hasArgument()) {
  1669.             throw new ImproperUsageException();
  1670.         }
  1671.  
  1672.         User user;
  1673.  
  1674.         try {
  1675.             user = conn.getGlobalContext().getUserManager().getUserByName(request.getArgument());
  1676.         } catch (NoSuchUserException e) {
  1677.             return new Reply(452, e.getMessage());
  1678.         } catch (UserFileException e) {
  1679.             logger.log(Level.FATAL, "", e);
  1680.  
  1681.             return new Reply(452, "Error reading userfile: " +
  1682.                 e.getMessage());
  1683.         }
  1684.  
  1685.         return new Reply(200,
  1686.             "User was last seen: " + user.getKeyedMap().getObjectDate(UserManagement.LASTSEEN));
  1687.     }
  1688.  
  1689.     private Reply doSITE_TAGLINE(BaseFtpConnection conn) throws ReplyException, ImproperUsageException {
  1690.         FtpRequest request = conn.getRequest();
  1691.  
  1692.         if (!request.hasArgument()) {
  1693.             throw new ImproperUsageException();
  1694.         }
  1695.  
  1696.         try {
  1697.             logger.info("'" + conn.getUserNull().getName()
  1698.                     + "' changed his tagline from '"
  1699.                     + conn.getUserNull().getKeyedMap().getObject(TAGLINE, "")
  1700.                     + "' to '" + request.getArgument() + "'");
  1701.             conn.getUserNull().getKeyedMap().setObject(UserManagement.TAGLINE, request.getArgument());
  1702.             conn.getUserNull().commit();
  1703.         } catch (UserFileException e) {
  1704.             throw new ReplyException(e);
  1705.         }
  1706.         return Reply.RESPONSE_200_COMMAND_OK;
  1707.     }
  1708.  
  1709.     private Reply doSITE_DEBUG(BaseFtpConnection conn) throws ReplyException {
  1710.         User user = conn.getUserNull();
  1711.         if(!conn.getRequest().hasArgument()) {
  1712.             user.getKeyedMap().setObject(UserManagement.DEBUG, Boolean.valueOf(!user.getKeyedMap().getObjectBoolean(UserManagement.DEBUG)));
  1713.         } else {
  1714.             String arg = conn.getRequest().getArgument();
  1715.             user.getKeyedMap().setObject(UserManagement.DEBUG, Boolean.valueOf(arg.equals("true") || arg.equals("on")));
  1716.         }
  1717.         try {
  1718.             user.commit();
  1719.         } catch(UserFileException e) {
  1720.             throw new ReplyException(e);
  1721.         }
  1722.         return new Reply(200, conn.jprintf(UserManagement.class, "debug"));
  1723.     }
  1724.  
  1725.     /**
  1726.      * USAGE: site take <user><kbytes>[ <message>] Removes credit from user
  1727.      *
  1728.      * ex. site take Archimede 100000 haha
  1729.      *
  1730.      * This will remove 100mb of credits from the user 'Archimede' and send the
  1731.      * message haha to him.
  1732.      * @throws ImproperUsageException
  1733.      */
  1734.     private Reply doSITE_TAKE(BaseFtpConnection conn) throws ImproperUsageException {
  1735.         FtpRequest request = conn.getRequest();
  1736.  
  1737.         if (!conn.getGlobalContext().getConfig().checkPermission("take", conn.getUserNull())) {
  1738.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1739.         }
  1740.  
  1741.         if (!request.hasArgument()) {
  1742.             throw new ImproperUsageException();
  1743.         }
  1744.  
  1745.         StringTokenizer st = new StringTokenizer(request.getArgument());
  1746.  
  1747.         if (!st.hasMoreTokens()) {
  1748.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  1749.         }
  1750.  
  1751.         User myUser;
  1752.         long credits;
  1753.         String amt = null;
  1754.  
  1755.         try {
  1756.             myUser = conn.getGlobalContext().getUserManager().getUserByName(st.nextToken());
  1757.  
  1758.             if (!st.hasMoreTokens()) {
  1759.                 return Reply.RESPONSE_501_SYNTAX_ERROR;
  1760.             }
  1761.             amt = st.nextToken();
  1762.             credits = Bytes.parseBytes(amt); // B, not KiB
  1763.  
  1764.             if (0 > credits) {
  1765.                 return new Reply(452, "Credits must be a positive number.");
  1766.             }
  1767.  
  1768.             logger.info("'" + conn.getUserNull().getName() + "' took " +
  1769.                 Bytes.formatBytes(credits) + " ('" + credits + "') from '" +
  1770.                 myUser.getName() + "'");
  1771.             myUser.updateCredits(-credits);
  1772.         } catch (NumberFormatException ex) {
  1773.             return new Reply(452, "The string " + amt + " cannot be interpreted");
  1774.         } catch (Exception ex) {
  1775.             logger.debug("",ex);
  1776.             return new Reply(452, ex.getMessage());
  1777.         }
  1778.  
  1779.         return new Reply(200,
  1780.             "OK, removed " + Bytes.formatBytes(credits) + " from " + myUser.getName() + ".");
  1781.     }
  1782.  
  1783.     /**
  1784.      * USAGE: site user [ <user>] Lists users / Shows detailed info about a
  1785.      * user.
  1786.      *
  1787.      * ex. site user
  1788.      *
  1789.      * This will display a list of all users currently on site.
  1790.      *
  1791.      * ex. site user Archimede
  1792.      *
  1793.      * This will show detailed information about user 'Archimede'.
  1794.      * @throws ImproperUsageException
  1795.      */
  1796.     private Reply doSITE_USER(BaseFtpConnection conn) throws ReplyException, ImproperUsageException {
  1797.         FtpRequest request = conn.getRequest();
  1798.  
  1799.         if (!conn.getUserNull().isAdmin() &&
  1800.                 !conn.getUserNull().isGroupAdmin()) {
  1801.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1802.         }
  1803.  
  1804.         if (!request.hasArgument()) {
  1805.             throw new ImproperUsageException();
  1806.         }
  1807.  
  1808.         Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
  1809.         User myUser;
  1810.  
  1811.         try {
  1812.             myUser = conn.getGlobalContext().getUserManager()
  1813.                          .getUserByNameUnchecked(request.getArgument());
  1814.         } catch (NoSuchUserException ex) {
  1815.             response.setMessage("User " + request.getArgument() + " not found");
  1816.  
  1817.             return response;
  1818.  
  1819.             //return FtpResponse.RESPONSE_200_COMMAND_OK);
  1820.         } catch (UserFileException ex) {
  1821.             throw new ReplyException(ex);
  1822.         }
  1823.  
  1824.         if (conn.getUserNull().isGroupAdmin() &&
  1825.                 !conn.getUserNull().getGroup().equals(myUser.getGroup())) {
  1826.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  1827.         }
  1828.  
  1829.         //int i = (int) (myUser.getTimeToday() / 1000);
  1830.         //int hours = i / 60;
  1831.         //int minutes = i - hours * 60;
  1832.         //response.addComment("time on today: " + hours + ":" + minutes);
  1833. //        ReplacerEnvironment env = new ReplacerEnvironment();
  1834.  
  1835. //        env.add("username", myUser.getName());
  1836. //        env.add("created", new Date(myUser.getObjectLong(UserManagement.CREATED)));
  1837. //        env.add("comment", myUser.getObjectString(UserManagement.COMMENT));
  1838. //        env.add("lastseen", new Date(myUser.getLastAccessTime()));
  1839. //        env.add("totallogins", Long.toString(myUser.getLogins()));
  1840. //        env.add("idletime", Long.toString(myUser.getIdleTime()));
  1841. //        env.add("userratio",
  1842. //            Float.toString(myUser.getObjectFloat(UserManagement.RATIO)));
  1843. //        env.add("usercredits", Bytes.formatBytes(myUser.getCredits()));
  1844. //        env.add("maxlogins", Long.toString(myUser.getMaxLogins()));
  1845. //        env.add("maxloginsip", Long.toString(myUser.getMaxLoginsPerIP()));
  1846. //        env.add("groupslots", Long.toString(myUser.getGroupSlots()));
  1847. //        env.add("groupleechslots", Long.toString(myUser.getGroupLeechSlots()));
  1848. //        env.add("useruploaded", Bytes.formatBytes(myUser.getUploadedBytes()));
  1849. //        env.add("userdownloaded", Bytes.formatBytes(myUser.getDownloadedBytes()));
  1850.  
  1851.         //ReplacerEnvironment env = BaseFtpConnection.getReplacerEnvironment(null, myUser);
  1852.         response.addComment(BaseFtpConnection.jprintf(UserManagement.class, "user", null, myUser));
  1853.         return response;
  1854.     }
  1855.  
  1856.     private Reply doSITE_USERS(BaseFtpConnection conn) throws ReplyException {
  1857.         FtpRequest request = conn.getRequest();
  1858.  
  1859.         if (!conn.getUserNull().isAdmin()) {
  1860.             return Reply.RESPONSE_530_ACCESS_DENIED;
  1861.         }
  1862.  
  1863.         Reply response = new Reply(200);
  1864.         Collection myUsers;
  1865.  
  1866.         try {
  1867.             myUsers = conn.getGlobalContext().getUserManager().getAllUsers();
  1868.         } catch (UserFileException e) {
  1869.             logger.log(Level.FATAL, "IO error reading all users", e);
  1870.  
  1871.             throw new ReplyException(e);
  1872.         }
  1873.  
  1874.         if (request.hasArgument()) {
  1875.             Permission perm = new Permission(FtpConfig.makeUsers(
  1876.                         new StringTokenizer(request.getArgument())), true);
  1877.  
  1878.             for (Iterator iter = myUsers.iterator(); iter.hasNext();) {
  1879.                 User element = (User) iter.next();
  1880.  
  1881.                 if (!perm.check(element)) {
  1882.                     iter.remove();
  1883.                 }
  1884.             }
  1885.         }
  1886.  
  1887.         for (Iterator iter = myUsers.iterator(); iter.hasNext();) {
  1888.             User myUser = (User) iter.next();
  1889.             response.addComment(myUser.getName());
  1890.         }
  1891.  
  1892.         response.addComment("Ok, " + myUsers.size() + " users listed.");
  1893.  
  1894.         return response;
  1895.     }
  1896.  
  1897.     /**
  1898.      * Lists currently connected users.
  1899.      */
  1900.     private Reply doSITE_WHO(BaseFtpConnection conn) {
  1901.         Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
  1902.         long users = 0;
  1903.         long speedup = 0;
  1904.         long speeddn = 0;
  1905.         long speed = 0;
  1906.  
  1907.         try {
  1908.             ReplacerFormat formatup = ReplacerUtils.finalFormat(UserManagement.class,
  1909.                     "who.up");
  1910.             ReplacerFormat formatdown = ReplacerUtils.finalFormat(UserManagement.class,
  1911.                     "who.down");
  1912.             ReplacerFormat formatidle = ReplacerUtils.finalFormat(UserManagement.class,
  1913.                     "who.idle");
  1914.             ReplacerFormat formatcommand = ReplacerUtils.finalFormat(UserManagement.class,
  1915.                     "who.command");
  1916.             ReplacerEnvironment env = new ReplacerEnvironment();
  1917.             ArrayList<BaseFtpConnection> conns = new ArrayList<BaseFtpConnection>(conn.getGlobalContext()
  1918.                                                 .getConnectionManager()
  1919.                                                 .getConnections());
  1920.  
  1921.             for (Iterator iter = conns.iterator(); iter.hasNext();) {
  1922.                 BaseFtpConnection conn2 = (BaseFtpConnection) iter.next();
  1923.  
  1924.                 if (conn2.isAuthenticated()) {
  1925.                     users++;
  1926.  
  1927.                     User user;
  1928.  
  1929.                     try {
  1930.                         user = conn2.getUser();
  1931.                     } catch (NoSuchUserException e) {
  1932.                         continue;
  1933.                     }
  1934.  
  1935.                     if (conn.getGlobalContext().getConfig().checkPathPermission("hideinwho", user, conn2.getCurrentDirectory())) {
  1936.                         continue;
  1937.                     }
  1938.  
  1939.                     //StringBuffer status = new StringBuffer();
  1940.                     env.add("idle",
  1941.                         Time.formatTime(System.currentTimeMillis() -
  1942.                             conn2.getLastActive()));
  1943.                     env.add("targetuser", user.getName());
  1944.                     synchronized (conn2.getDataConnectionHandler()) {
  1945.                         if (!conn2.isExecuting()) {
  1946.                             response.addComment(SimplePrintf.jprintf(
  1947.                                     formatidle, env));
  1948.                         } else if (conn2.getDataConnectionHandler()
  1949.                                 .isTransfering()) {
  1950.                             try {
  1951.                                 speed = conn2.getDataConnectionHandler()
  1952.                                         .getTransfer().getXferSpeed();
  1953.                             } catch (ObjectNotFoundException e) {
  1954.                                 logger.debug("This is a bug, please report it",
  1955.                                         e);
  1956.                                 speed = 0;
  1957.                             }
  1958.                             env.add("speed", Bytes.formatBytes(speed) + "/s");
  1959.                             env.add("file", conn2.getDataConnectionHandler()
  1960.                                     .getTransferFile().getName());
  1961.                             env.add("slave", conn2.getDataConnectionHandler()
  1962.                                     .getTranferSlave().getName());
  1963.  
  1964.                             if (conn2.getDirection() == Transfer.TRANSFER_RECEIVING_UPLOAD) {
  1965.                                 response.addComment(SimplePrintf.jprintf(
  1966.                                         formatup, env));
  1967.                                 speedup += speed;
  1968.                             } else if (conn2.getDirection() == Transfer.TRANSFER_SENDING_DOWNLOAD) {
  1969.                                 response.addComment(SimplePrintf.jprintf(
  1970.                                         formatdown, env));
  1971.                                 speeddn += speed;
  1972.                             }
  1973.                         } else {
  1974.                             env.add("command", conn2.getRequest().getCommand());
  1975.                             response.addComment(SimplePrintf.jprintf(
  1976.                                     formatcommand, env));
  1977.                         }
  1978.                     }
  1979.                 }
  1980.             }
  1981.  
  1982.             env.add("currentusers", "" + users);
  1983.             env.add("maxusers", ""
  1984.                     + conn.getGlobalContext().getConfig().getMaxUsersTotal());
  1985.             env.add("totalupspeed", Bytes.formatBytes(speedup) + "/s");
  1986.             env.add("totaldnspeed", Bytes.formatBytes(speeddn) + "/s");
  1987.             response.addComment("");
  1988.             response.addComment(conn.jprintf(UserManagement.class,
  1989.                     "who.statusspeed", env));
  1990.             response.addComment(conn.jprintf(UserManagement.class,
  1991.                     "who.statususers", env));
  1992.  
  1993.             return response;
  1994.         } catch (FormatterException e) {
  1995.             return new Reply(452, e.getMessage());
  1996.         }
  1997.     }
  1998.  
  1999.     private Reply doSITE_SWHO(BaseFtpConnection conn) {
  2000.         Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
  2001.         long users = 0;
  2002.         long speedup = 0;
  2003.         long speeddn = 0;
  2004.         long speed = 0;
  2005.  
  2006.         try {
  2007.             ReplacerFormat formatup = ReplacerUtils.finalFormat(UserManagement.class,
  2008.                     "swho.up");
  2009.             ReplacerFormat formatdown = ReplacerUtils.finalFormat(UserManagement.class,
  2010.                     "swho.down");
  2011.             ReplacerFormat formatidle = ReplacerUtils.finalFormat(UserManagement.class,
  2012.                     "swho.idle");
  2013.             ReplacerFormat formatcommand = ReplacerUtils.finalFormat(UserManagement.class,
  2014.                     "swho.command");
  2015.             ReplacerEnvironment env = new ReplacerEnvironment();
  2016.             ArrayList<BaseFtpConnection> conns = new ArrayList<BaseFtpConnection>(conn.getGlobalContext()
  2017.                                                 .getConnectionManager()
  2018.                                                 .getConnections());
  2019.  
  2020.             for (Iterator iter = conns.iterator(); iter.hasNext();) {
  2021.                 BaseFtpConnection conn2 = (BaseFtpConnection) iter.next();
  2022.  
  2023.                 if (conn2.isAuthenticated()) {
  2024.                     users++;
  2025.  
  2026.                     User user;
  2027.  
  2028.                     try {
  2029.                         user = conn2.getUser();
  2030.                     } catch (NoSuchUserException e) {
  2031.                         continue;
  2032.                     }
  2033.  
  2034.                     //if (conn.getGlobalContext().getConfig().checkPathPermission("hideinwho", user, conn2.getCurrentDirectory())) {
  2035.                     //    continue;
  2036.                     //}
  2037.  
  2038.                     //StringBuffer status = new StringBuffer();
  2039.                     env.add("idle",
  2040.                         Time.formatTime(System.currentTimeMillis() -
  2041.                             conn2.getLastActive()));
  2042.                     env.add("targetuser", user.getName());
  2043.                     env.add("ip", conn2.getClientAddress().getHostAddress());
  2044.  
  2045.  
  2046.                     synchronized (conn2.getDataConnectionHandler()) {
  2047.                         if (!conn2.isExecuting()) {
  2048.                             response.addComment(SimplePrintf.jprintf(
  2049.                                     formatidle, env));
  2050.                         } else if (conn2.getDataConnectionHandler()
  2051.                                 .isTransfering()) {
  2052.                             try {
  2053.                                 speed = conn2.getDataConnectionHandler()
  2054.                                         .getTransfer().getXferSpeed();
  2055.                             } catch (ObjectNotFoundException e) {
  2056.                                 logger.debug("This is a bug, please report it",
  2057.                                         e);
  2058.                             }
  2059.                             env.add("speed", Bytes.formatBytes(speed) + "/s");
  2060.                             env.add("file", conn2.getDataConnectionHandler()
  2061.                                     .getTransferFile().getName());
  2062.                             env.add("slave", conn2.getDataConnectionHandler()
  2063.                                     .getTranferSlave().getName());
  2064.  
  2065.                             if (conn2.getTransferDirection() == Transfer.TRANSFER_RECEIVING_UPLOAD) {
  2066.                                 response.addComment(SimplePrintf.jprintf(
  2067.                                         formatup, env));
  2068.                                 speedup += speed;
  2069.                             } else if (conn2.getTransferDirection() == Transfer.TRANSFER_SENDING_DOWNLOAD) {
  2070.                                 response.addComment(SimplePrintf.jprintf(
  2071.                                         formatdown, env));
  2072.                                 speeddn += speed;
  2073.                             }
  2074.                         } else {
  2075.                             env.add("command", conn2.getRequest().getCommand());
  2076.                             response.addComment(SimplePrintf.jprintf(
  2077.                                     formatcommand, env));
  2078.                         }
  2079.                     }
  2080.                 }
  2081.             }
  2082.  
  2083.             env.add("currentusers", "" + users);
  2084.             env.add("maxusers", ""
  2085.                     + conn.getGlobalContext().getConfig().getMaxUsersTotal());
  2086.             env.add("totalupspeed", Bytes.formatBytes(speedup) + "/s");
  2087.             env.add("totaldnspeed", Bytes.formatBytes(speeddn) + "/s");
  2088.             response.addComment("");
  2089.             response.addComment(conn.jprintf(UserManagement.class,
  2090.                     "swho.statusspeed", env));
  2091.             response.addComment(conn.jprintf(UserManagement.class,
  2092.                     "swho.statususers", env));
  2093.  
  2094.             return response;
  2095.         } catch (FormatterException e) {
  2096.             return new Reply(452, e.getMessage());
  2097.         }
  2098.     }
  2099.  
  2100.     private Reply doSITE_BAN(BaseFtpConnection conn) throws ImproperUsageException {
  2101.         FtpRequest request = conn.getRequest();
  2102.  
  2103.         if (!request.hasArgument()) {
  2104.             throw new ImproperUsageException();
  2105.         }
  2106.  
  2107.         StringTokenizer st = new StringTokenizer(request.getArgument());
  2108.  
  2109.         if (!st.hasMoreTokens()) {
  2110.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  2111.         }
  2112.  
  2113.         User myUser;
  2114.         try {
  2115.             myUser = conn.getGlobalContext().getUserManager().getUserByName(st.nextToken());
  2116.         } catch (Exception e) {
  2117.             logger.warn("", e);
  2118.             return new Reply(200, e.getMessage());
  2119.         }
  2120.  
  2121.         if (!st.hasMoreTokens()) {
  2122.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  2123.         }
  2124.  
  2125.         long banTime;
  2126.         try {
  2127.             banTime = Long.parseLong(st.nextToken());
  2128.         } catch (NumberFormatException e) {
  2129.             logger.warn("", e);
  2130.             return new Reply(200, e.getMessage());
  2131.         }
  2132.  
  2133.         String banMsg;
  2134.         if (st.hasMoreTokens()) {
  2135.             banMsg = "[" + conn.getUserNull().getName() + "]";
  2136.             while (st.hasMoreTokens())
  2137.                 banMsg += " " + st.nextToken();
  2138.         } else {
  2139.             banMsg = "Banned by " + conn.getUserNull().getName() + " for " + banTime + "m";
  2140.         }
  2141.  
  2142.         myUser.getKeyedMap().setObject(UserManagement.BAN_TIME,
  2143.                                     new Date(System.currentTimeMillis() + (banTime*60000)));
  2144.         myUser.getKeyedMap().setObject(UserManagement.BAN_REASON, banMsg);
  2145.         try {
  2146.             myUser.commit();
  2147.         } catch (UserFileException e) {
  2148.             logger.warn("", e);
  2149.             return new Reply(200, e.getMessage());
  2150.         }
  2151.  
  2152.         return Reply.RESPONSE_200_COMMAND_OK;
  2153.     }
  2154.  
  2155.     private Reply doSITE_UNBAN(BaseFtpConnection conn) throws ImproperUsageException {
  2156.         FtpRequest request = conn.getRequest();
  2157.  
  2158.         if (!request.hasArgument()) {
  2159.             throw new ImproperUsageException();
  2160.         }
  2161.  
  2162.         StringTokenizer st = new StringTokenizer(request.getArgument());
  2163.  
  2164.         if (!st.hasMoreTokens()) {
  2165.             return Reply.RESPONSE_501_SYNTAX_ERROR;
  2166.         }
  2167.  
  2168.         User myUser;
  2169.         try {
  2170.             myUser = conn.getGlobalContext().getUserManager().getUserByName(st.nextToken());
  2171.         } catch (Exception e) {
  2172.             logger.warn("", e);
  2173.             return new Reply(200, e.getMessage());
  2174.         }
  2175.  
  2176.         myUser.getKeyedMap().setObject(UserManagement.BAN_TIME, new Date());
  2177.         myUser.getKeyedMap().setObject(UserManagement.BAN_REASON, "");
  2178.  
  2179.         try {
  2180.             myUser.commit();
  2181.         } catch (UserFileException e) {
  2182.             logger.warn("", e);
  2183.             return new Reply(200, e.getMessage());
  2184.         }
  2185.  
  2186.         return Reply.RESPONSE_200_COMMAND_OK;
  2187.     }
  2188.  
  2189.     private Reply doSITE_BANS(BaseFtpConnection conn) throws ReplyException {
  2190.         Collection<User> myUsers;
  2191.         try {
  2192.             myUsers = conn.getGlobalContext().getUserManager().getAllUsers();
  2193.         } catch (UserFileException e) {
  2194.             logger.log(Level.FATAL, "IO error reading all users", e);
  2195.             throw new ReplyException(e);
  2196.         }
  2197.  
  2198.         Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
  2199.         for (User user : myUsers) {
  2200.             long timeleft = user.getKeyedMap().getObjectDate(UserManagement.BAN_TIME).getTime() -
  2201.                 System.currentTimeMillis();
  2202.             if (timeleft > 0) {
  2203.                 ReplacerEnvironment env = new ReplacerEnvironment();
  2204.                 env.add("timeleft",""+(timeleft/60000));
  2205.                 response.addComment(BaseFtpConnection.jprintf(UserManagement.class, "bans", env, user));
  2206.             }
  2207.         }
  2208.  
  2209.         return response;
  2210.     }
  2211.  
  2212.     public Reply execute(BaseFtpConnection conn)
  2213.         throws ReplyException, ImproperUsageException {
  2214.         String cmd = conn.getRequest().getCommand();
  2215.  
  2216.         if ("SITE ADDIP".equals(cmd)) {
  2217.             return doSITE_ADDIP(conn);
  2218.         }
  2219.  
  2220.         if ("SITE CHANGE".equals(cmd)) {
  2221.             return doSITE_CHANGE(conn);
  2222.         }
  2223.  
  2224.         if ("SITE CHGRP".equals(cmd)) {
  2225.             return doSITE_CHGRP(conn);
  2226.         }
  2227.  
  2228.         if ("SITE CHPASS".equals(cmd)) {
  2229.             return doSITE_CHPASS(conn);
  2230.         }
  2231.  
  2232.         if("SITE DEBUG".equals(cmd))
  2233.             return doSITE_DEBUG(conn);
  2234.  
  2235.         if ("SITE DELIP".equals(cmd)) {
  2236.             return doSITE_DELIP(conn);
  2237.         }
  2238.  
  2239.         if ("SITE DELUSER".equals(cmd)) {
  2240.             return doSITE_DELUSER(conn);
  2241.         }
  2242.  
  2243.         if ("SITE ADDUSER".equals(cmd) || "SITE GADDUSER".equals(cmd)) {
  2244.             return doSITE_ADDUSER(conn);
  2245.         }
  2246.  
  2247.         if ("SITE GINFO".equals(cmd)) {
  2248.             return doSITE_GINFO(conn);
  2249.         }
  2250.  
  2251.         if ("SITE GIVE".equals(cmd)) {
  2252.             return doSITE_GIVE(conn);
  2253.         }
  2254.  
  2255.         if ("SITE GROUP".equals(cmd)) {
  2256.             return doSITE_GROUP(conn);
  2257.         }
  2258.  
  2259.         if ("SITE GROUPS".equals(cmd)) {
  2260.             return doSITE_GROUPS(conn);
  2261.         }
  2262.  
  2263.         if ("SITE GRPREN".equals(cmd)) {
  2264.             return doSITE_GRPREN(conn);
  2265.         }
  2266.  
  2267.         if ("SITE KICK".equals(cmd)) {
  2268.             return doSITE_KICK(conn);
  2269.         }
  2270.  
  2271.         if ("SITE PASSWD".equals(cmd)) {
  2272.             return doSITE_PASSWD(conn);
  2273.         }
  2274.  
  2275.         if ("SITE PURGE".equals(cmd)) {
  2276.             return doSITE_PURGE(conn);
  2277.         }
  2278.  
  2279.         if ("SITE READD".equals(cmd)) {
  2280.             return doSITE_READD(conn);
  2281.         }
  2282.  
  2283.         if ("SITE RENUSER".equals(cmd)) {
  2284.             return doSITE_RENUSER(conn);
  2285.         }
  2286.  
  2287.         if ("SITE SEEN".equals(cmd)) {
  2288.             return doSITE_SEEN(conn);
  2289.         }
  2290.  
  2291.         if ("SITE TAGLINE".equals(cmd)) {
  2292.             return doSITE_TAGLINE(conn);
  2293.         }
  2294.  
  2295.         if ("SITE TAKE".equals(cmd)) {
  2296.             return doSITE_TAKE(conn);
  2297.         }
  2298.  
  2299.         if ("SITE USER".equals(cmd)) {
  2300.             return doSITE_USER(conn);
  2301.         }
  2302.  
  2303.         if ("SITE USERS".equals(cmd)) {
  2304.             return doSITE_USERS(conn);
  2305.         }
  2306.  
  2307.         if ("SITE WHO".equals(cmd)) {
  2308.             return doSITE_WHO(conn);
  2309.         }
  2310.  
  2311.         if ("SITE SWHO".equals(cmd)) {
  2312.             return doSITE_SWHO(conn);
  2313.         }
  2314.  
  2315.         if ("SITE BAN".equals(cmd)) {
  2316.             return doSITE_BAN(conn);
  2317.         }
  2318.  
  2319.         if ("SITE UNBAN".equals(cmd)) {
  2320.             return doSITE_UNBAN(conn);
  2321.         }
  2322.  
  2323.         if ("SITE BANS".equals(cmd)) {
  2324.             return doSITE_BANS(conn);
  2325.         }
  2326.  
  2327.         throw UnhandledCommandException.create(UserManagement.class,
  2328.             conn.getRequest());
  2329.     }
  2330.  
  2331.     public String[] getFeatReplies() {
  2332.         return null;
  2333.     }
  2334.  
  2335.     public CommandHandler initialize(BaseFtpConnection conn,
  2336.         CommandManager initializer) {
  2337.         return this;
  2338.     }
  2339.  
  2340.     public void load(CommandManagerFactory initializer) {
  2341.     }
  2342.  
  2343.     public void unload() {
  2344.     }
  2345. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement