001: /*
002: *
003: * This file is part of DrFTPD, Distributed FTP Daemon.
004: *
005: * DrFTPD is free software; you can redistribute it and/or modify
006: * it under the terms of the GNU General Public License as published by
007: * the Free Software Foundation; either version 2 of the License, or
008: * (at your option) any later version.
009: *
010: * DrFTPD is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with DrFTPD; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019: package net.drmods.plugins.irc;
020:
021: import java.io.FileInputStream;
022: import java.io.FileNotFoundException;
023: import java.io.IOException;
024: import java.text.SimpleDateFormat;
025: import java.util.ArrayList;
026: import java.util.Date;
027: import java.util.HashMap;
028: import java.util.Hashtable;
029: import java.util.Iterator;
030: import java.util.List;
031: import java.util.Properties;
032: import java.util.StringTokenizer;
033: import java.util.TimeZone;
034: import java.util.Map.Entry;
035:
036: import net.sf.drftpd.FileExistsException;
037: import net.sf.drftpd.Nukee;
038: import net.sf.drftpd.ObjectNotFoundException;
039: import net.sf.drftpd.event.NukeEvent;
040: import net.sf.drftpd.util.ReplacerUtils;
041:
042: import org.apache.log4j.Logger;
043: import org.drftpd.GlobalContext;
044: import org.drftpd.commands.Nuke;
045: import org.drftpd.commands.UserManagement;
046: import org.drftpd.plugins.SiteBot;
047: import org.drftpd.remotefile.LinkedRemoteFile;
048: import org.drftpd.remotefile.LinkedRemoteFileInterface;
049: import org.drftpd.sitebot.IRCCommand;
050: import org.drftpd.usermanager.NoSuchUserException;
051: import org.drftpd.usermanager.User;
052: import org.drftpd.usermanager.UserFileException;
053: import org.tanesha.replacer.ReplacerEnvironment;
054:
055: import f00f.net.irc.martyr.commands.MessageCommand;
056: import f00f.net.irc.martyr.util.FullNick;
057:
058: /**
059: * @author Teflon
060: * @version $Id$
061: */
062: public class IRCNuke extends IRCCommand {
063: private static final Logger logger = Logger
064: .getLogger(IRCNuke.class);
065: private int _maxNukes;
066:
067: public IRCNuke(GlobalContext gctx) {
068: super (gctx);
069: loadConf("conf/drmods.conf");
070: }
071:
072: private void loadConf(String confFile) {
073: Properties cfg = new Properties();
074: FileInputStream file = null;
075: try {
076: file = new FileInputStream(confFile);
077: cfg.load(file);
078: String maxNukes = cfg.getProperty("nukes.max");
079: if (maxNukes == null) {
080: throw new RuntimeException(
081: "Unspecified value 'nukes.max' in " + confFile);
082: }
083: _maxNukes = Integer.parseInt(maxNukes);
084: } catch (Exception e) {
085: logger.error("Error reading " + confFile, e);
086: throw new RuntimeException(e.getMessage());
087: } finally {
088: try {
089: if (file != null) {
090: file.close();
091: }
092: } catch (IOException e) {
093: }
094: }
095: }
096:
097: public ArrayList<String> doNuke(String args, MessageCommand msgc) {
098: ArrayList<String> out = new ArrayList<String>();
099: ReplacerEnvironment env = new ReplacerEnvironment(
100: SiteBot.GLOBAL_ENV);
101: env.add("ircnick", msgc.getSource().getNick());
102:
103: User ftpuser = getUser(msgc.getSource());
104: if (ftpuser == null) {
105: out.add(ReplacerUtils.jprintf("ident.noident", env,
106: SiteBot.class));
107: return out;
108: }
109: env.add("ftpuser", ftpuser.getName());
110:
111: StringTokenizer st = new StringTokenizer(args);
112: // check number of arguments
113: if (st.countTokens() < 3) {
114: out.add(ReplacerUtils.jprintf("nuke.usage", env,
115: IRCNuke.class));
116: return out;
117: }
118:
119: // read parameters passed
120: String searchstr = st.nextToken();
121: env.add("searchstr", searchstr);
122: int nukemult;
123: try {
124: nukemult = Integer.parseInt(st.nextToken());
125: } catch (NumberFormatException e2) {
126: out.add(ReplacerUtils.jprintf("nuke.usage", env,
127: IRCNuke.class));
128: return out;
129: }
130: String nukemsg = st.nextToken("").trim();
131:
132: LinkedRemoteFileInterface nukeDir;
133: try {
134: nukeDir = LinkedRemoteFile.findLatestDir(getGlobalContext()
135: .getConnectionManager(), getGlobalContext()
136: .getRoot(), ftpuser, searchstr);
137: } catch (ObjectNotFoundException e) {
138: out.add(ReplacerUtils.jprintf("nuke.error", env,
139: IRCNuke.class));
140: return out;
141: }
142: String nukeDirPath = nukeDir.getPath();
143: env.add("nukedir", nukeDirPath);
144: // get nukees with string as key
145: Hashtable<String, Long> nukees = new Hashtable<String, Long>();
146: Nuke.nukeRemoveCredits(nukeDir, nukees);
147:
148: // // convert key from String to User ////
149: HashMap<User, Long> nukees2 = new HashMap<User, Long>(nukees
150: .size());
151: for (String username : nukees.keySet()) {
152:
153: // String username = (String) iter.next();
154: User user;
155: try {
156: user = getGlobalContext().getUserManager()
157: .getUserByName(username);
158: } catch (NoSuchUserException e1) {
159: out.add("Cannot remove credits from " + username + ": "
160: + e1.getMessage());
161: logger.warn("", e1);
162: user = null;
163: } catch (UserFileException e1) {
164: out.add("Cannot read user data for " + username + ": "
165: + e1.getMessage());
166: logger.warn("", e1);
167: return out;
168: }
169: // nukees contains credits as value
170: //if (user == null) we don't do anything below anyway
171: if (user != null) {
172: nukees2.put(user, (Long) nukees.get(username));
173: }
174: }
175:
176: // rename
177: String toDirPath;
178: String toName = "[NUKED]-" + nukeDir.getName();
179: try {
180: toDirPath = nukeDir.getParentFile().getPath();
181: } catch (FileNotFoundException ex) {
182: logger.fatal("", ex);
183: out.add("FileNotFoundException");
184: return out;
185: }
186: try {
187: nukeDir.renameTo(toDirPath, toName);
188: nukeDir.createDirectory(ftpuser.getName(), ftpuser
189: .getGroup(), "REASON-" + nukemsg);
190: } catch (IOException ex) {
191: logger.warn("", ex);
192: out.add(" cannot rename to \"" + toDirPath + "/" + toName
193: + "\": " + ex.getMessage());
194: return out;
195: }
196:
197: long nukeDirSize = 0;
198: long nukedAmount = 0;
199:
200: // update credits, nukedbytes, timesNuked, lastNuked
201: // for (Iterator iter = nukees2.keySet().iterator(); iter.hasNext();) {
202: for (Entry<User, Long> nukeeEntry : nukees2.entrySet()) {
203: // User nukee = (User) iter.next();
204: User nukee = nukeeEntry.getKey();
205: long size = nukeeEntry.getValue().longValue();
206:
207: long debt = Nuke.calculateNukedAmount(size,
208: getGlobalContext().getConfig().getCreditCheckRatio(
209: nukeDir, nukee), nukemult);
210:
211: nukedAmount += debt;
212: nukeDirSize += size;
213: nukee.updateCredits(-debt);
214: if (!getGlobalContext().getConfig().checkPathPermission(
215: "nostatsup", nukee, nukeDir)) {
216: nukee.updateUploadedBytes(-size);
217: nukee.getKeyedMap().incrementObjectLong(
218: Nuke.NUKEDBYTES, debt);
219: }
220: nukee.getKeyedMap().incrementObjectLong(Nuke.NUKED);
221: nukee.getKeyedMap().setObject(Nuke.LASTNUKED,
222: new Long(System.currentTimeMillis()));
223: try {
224: nukee.commit();
225: } catch (UserFileException e1) {
226: out.add("Error writing userfile: " + e1.getMessage());
227: logger.warn("Error writing userfile", e1);
228: }
229: }
230: NukeEvent nuke = new NukeEvent(ftpuser, "NUKE", nukeDirPath,
231: nukeDirSize, nukedAmount, nukemult, nukemsg, nukees);
232:
233: Nuke.getNukeLog().add(nuke);
234: getGlobalContext().getConnectionManager()
235: .dispatchFtpEvent(nuke);
236: return out;
237: }
238:
239: public ArrayList<String> doUnnuke(String args, MessageCommand msgc) {
240: ArrayList<String> out = new ArrayList<String>();
241: ReplacerEnvironment env = new ReplacerEnvironment(
242: SiteBot.GLOBAL_ENV);
243: env.add("ircnick", msgc.getSource().getNick());
244:
245: User ftpuser = getUser(msgc.getSource());
246: if (ftpuser == null) {
247: out.add(ReplacerUtils.jprintf("ident.noident", env,
248: SiteBot.class));
249: return out;
250: }
251: env.add("ftpuser", ftpuser.getName());
252:
253: StringTokenizer st = new StringTokenizer(args);
254: //check number of arguments
255: if (st.countTokens() < 1) {
256: out.add(ReplacerUtils.jprintf("unnuke.usage", env,
257: IRCNuke.class));
258: return out;
259: }
260:
261: //read parameters passed
262: String toName = st.nextToken();
263: String nukeName = "[NUKED]-" + toName;
264: String reason = st.hasMoreTokens() ? st.nextToken("").trim()
265: : "";
266:
267: env.add("searchstr", nukeName);
268:
269: LinkedRemoteFileInterface nukeDir;
270: try {
271: nukeDir = LinkedRemoteFile.findLatestDir(getGlobalContext()
272: .getConnectionManager(), getGlobalContext()
273: .getRoot(), ftpuser, nukeName);
274: } catch (ObjectNotFoundException e2) {
275: out.add(ReplacerUtils.jprintf("nuke.error", env,
276: IRCNuke.class));
277: return out;
278: }
279:
280: String toPath = nukeDir.getParentFileNull().getPath() + "/"
281: + toName;
282: String toDir = nukeDir.getParentFileNull().getPath();
283: NukeEvent nuke;
284: try {
285: nuke = Nuke.getNukeLog().get(toPath);
286: } catch (ObjectNotFoundException ex) {
287: out.add(ex.getMessage());
288: logger.warn(ex);
289: return out;
290: }
291:
292: for (Iterator iter = nuke.getNukees2().iterator(); iter
293: .hasNext();) {
294: Nukee nukeeObj = (Nukee) iter.next();
295: String nukeeName = nukeeObj.getUsername();
296: User nukee;
297: try {
298: nukee = getGlobalContext().getUserManager()
299: .getUserByName(nukeeName);
300: } catch (NoSuchUserException e) {
301: out.add(nukeeName + ": no such user");
302: continue;
303: } catch (UserFileException e) {
304: out.add(nukeeName + ": error reading userfile");
305: logger.fatal("error reading userfile", e);
306: continue;
307: }
308: long nukedAmount = Nuke.calculateNukedAmount(nukeeObj
309: .getAmount(), getGlobalContext().getConfig()
310: .getCreditCheckRatio(nukeDir, nukee), nuke
311: .getMultiplier());
312:
313: nukee.updateCredits(nukedAmount);
314: if (!getGlobalContext().getConfig().checkPathPermission(
315: "nostatsup", nukee, nukeDir)) {
316: nukee.updateUploadedBytes(nukeeObj.getAmount());
317: }
318: nukee.getKeyedMap().incrementObjectInt(Nuke.NUKED, -1);
319:
320: try {
321: nukee.commit();
322: } catch (UserFileException e3) {
323: logger.fatal("Eroror saving userfile for "
324: + nukee.getName(), e3);
325: out.add("Error saving userfile for " + nukee.getName());
326: }
327: }//for
328:
329: try {
330: Nuke.getNukeLog().remove(toPath);
331: } catch (ObjectNotFoundException e) {
332: logger.warn("Error removing nukelog entry", e);
333: }
334: try {
335: nukeDir.renameTo(toDir, toName);
336: } catch (FileExistsException e1) {
337: out.add("Error renaming nuke, target dir already exists");
338: } catch (IOException e1) {
339: //response.addComment("Error: " + e1.getMessage());
340: logger
341: .fatal(
342: "Illegaltargetexception: means parent doesn't exist",
343: e1);
344: }
345:
346: try {
347: LinkedRemoteFileInterface reasonDir = nukeDir
348: .getFile("REASON-" + nuke.getReason());
349: if (reasonDir.isDirectory())
350: reasonDir.delete();
351: } catch (FileNotFoundException e3) {
352: logger.debug("Failed to delete 'REASON-" + nuke.getReason()
353: + "' dir in UNNUKE", e3);
354: }
355:
356: nuke.setCommand("UNNUKE");
357: nuke.setReason(reason);
358: nuke.setUser(ftpuser);
359: getGlobalContext().getConnectionManager()
360: .dispatchFtpEvent(nuke);
361: return out;
362: }
363:
364: public ArrayList<String> doNukes(String args, MessageCommand msgc) {
365: ArrayList<String> out = new ArrayList<String>();
366: ReplacerEnvironment env = new ReplacerEnvironment(
367: SiteBot.GLOBAL_ENV);
368: env.add("ircnick", msgc.getSource().getNick());
369:
370: //check number of arguments
371: int nukeCount = 0;
372: if (!args.equals("")) {
373: try {
374: nukeCount = Integer.parseInt(args);
375: } catch (NumberFormatException e2) {
376: logger
377: .warn(
378: "parameter passed to !nukes is not a valid Integer",
379: e2);
380: out.add(ReplacerUtils.jprintf("nukes.usage", env,
381: IRCNuke.class));
382: return out;
383: }
384: }
385: if (nukeCount > _maxNukes || nukeCount <= 0)
386: nukeCount = _maxNukes;
387:
388: Nuke dpsn;
389: dpsn = (Nuke) getGlobalContext().getConnectionManager()
390: .getCommandManagerFactory().getHandlersMap().get(
391: Nuke.class);
392: List allNukes = dpsn.getNukeLog().getAll();
393: int count = 0;
394:
395: if (allNukes.size() == 0) {
396: out.add(ReplacerUtils.jprintf("nukes.nonukes", env,
397: IRCNuke.class));
398: } else {
399: for (int i = allNukes.size() - 1; i >= 0; i--) {
400: //for (Iterator iter = allNukes.iterator(); iter.hasNext(); ) {
401: if (count >= nukeCount)
402: break;
403: NukeEvent nuke = (NukeEvent) allNukes.get(i); //iter.next();
404: env.add("nukepath", nuke.getPath());
405: env.add("nukereason", nuke.getReason());
406: env.add("nukemult", Integer.toString(nuke
407: .getMultiplier()));
408: env.add("nuker", nuke.getUser().getName());
409: SimpleDateFormat dFormat = new SimpleDateFormat(
410: "MM/dd/yyyy h:mm a zzz");
411: dFormat.setTimeZone(TimeZone.getDefault());
412: env.add("nuketime", dFormat.format(new Date(nuke
413: .getTime())));
414:
415: out.add(ReplacerUtils.jprintf("nukes.msg", env,
416: IRCNuke.class));
417: count++;
418: }
419: }
420: return out;
421: }
422:
423: private User getUser(FullNick fn) {
424: String ident = fn.getNick() + "!" + fn.getUser() + "@"
425: + fn.getHost();
426: User user = null;
427: try {
428: user = getGlobalContext().getUserManager().getUserByIdent(
429: ident);
430: } catch (Exception e) {
431: logger.warn("Could not identify " + ident);
432: }
433: return user;
434: }
435:
436: }
|