KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > drftpd > master > command > plugins > Nuke


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

18 package net.sf.drftpd.master.command.plugins;
19
20 import java.io.FileNotFoundException JavaDoc;
21 import java.io.FileReader JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Hashtable JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.StringTokenizer JavaDoc;
29
30 import net.sf.drftpd.Bytes;
31 import net.sf.drftpd.FileExistsException;
32 import net.sf.drftpd.Nukee;
33 import net.sf.drftpd.ObjectNotFoundException;
34 import net.sf.drftpd.event.NukeEvent;
35 import net.sf.drftpd.master.BaseFtpConnection;
36 import net.sf.drftpd.master.FtpReply;
37 import net.sf.drftpd.master.command.CommandManager;
38 import net.sf.drftpd.master.command.CommandManagerFactory;
39 import net.sf.drftpd.master.queues.NukeLog;
40 import net.sf.drftpd.master.usermanager.AbstractUser;
41 import net.sf.drftpd.master.usermanager.NoSuchUserException;
42 import net.sf.drftpd.master.usermanager.User;
43 import net.sf.drftpd.master.usermanager.UserFileException;
44 import net.sf.drftpd.remotefile.LinkedRemoteFileInterface;
45
46 import org.apache.log4j.Level;
47 import org.apache.log4j.Logger;
48 import org.drftpd.commands.CommandHandler;
49 import org.drftpd.commands.CommandHandlerFactory;
50 import org.drftpd.commands.UnhandledCommandException;
51 import org.jdom.Document;
52 import org.jdom.Element;
53 import org.jdom.input.SAXBuilder;
54
55 /**
56  * nukedamount -> amount after multiplier
57  * amount -> amount before multiplier
58  *
59  * @author mog
60  * @version $Id: Nuke.java,v 1.18.2.2 2004/06/27 22:22:49 mog Exp $
61  */

62 public class Nuke implements CommandHandlerFactory, CommandHandler {
63
64     private static final Logger logger = Logger.getLogger(Nuke.class);
65
66     public static long calculateNukedAmount(
67         long size,
68         float ratio,
69         int multiplier) {
70         return (long) (size * ratio + size * (multiplier - 1));
71     }
72
73     private static void nukeRemoveCredits(
74         LinkedRemoteFileInterface nukeDir,
75         Hashtable JavaDoc nukees) {
76         for (Iterator JavaDoc iter = nukeDir.getFiles().iterator(); iter.hasNext();) {
77             LinkedRemoteFileInterface file =
78                 (LinkedRemoteFileInterface) iter.next();
79             if (file.isDirectory()) {
80                 nukeRemoveCredits(file, nukees);
81             }
82             if (file.isFile()) {
83                 String JavaDoc owner = file.getUsername();
84                 Long JavaDoc total = (Long JavaDoc) nukees.get(owner);
85                 if (total == null)
86                     total = new Long JavaDoc(0);
87                 total = new Long JavaDoc(total.longValue() + file.length());
88                 nukees.put(owner, total);
89             }
90         }
91     }
92     private NukeLog _nukelog;
93     public Nuke() {
94     }
95
96     /**
97      * USAGE: site nuke <directory> <multiplier> <message>
98      * Nuke a directory
99      *
100      * ex. site nuke shit 2 CRAP
101      *
102      * This will nuke the directory 'shit' and remove x2 credits with the
103      * comment 'CRAP'.
104      *
105      * NOTE: You can enclose the directory in braces if you have spaces in the name
106      * ex. site NUKE {My directory name} 1 because_i_dont_like_it
107      *
108      * Q) What does the multiplier in 'site nuke' do?
109      * A) Multiplier is a penalty measure. If it is 0, the user doesn't lose any
110      * credits for the stuff being nuked. If it is 1, user only loses the
111      * amount of credits he gained by uploading the files (which is calculated
112      * by multiplying total size of file by his/her ratio). If multiplier is more
113      * than 1, the user loses the credits he/she gained by uploading, PLUS some
114      * extra credits. The formula is this: size * ratio + size * (multiplier - 1).
115      * This way, multiplier of 2 causes user to lose size * ratio + size * 1,
116      * so the additional penalty in this case is the size of nuked files. If the
117      * multiplier is 3, user loses size * ratio + size * 2, etc.
118      */

119     private FtpReply doSITE_NUKE(BaseFtpConnection conn) {
120         if (!conn.getUserNull().isNuker())
121             return FtpReply.RESPONSE_530_ACCESS_DENIED;
122
123         if (!conn.getRequest().hasArgument()) {
124             return new FtpReply(501, conn.jprintf(Nuke.class, "nuke.usage"));
125         }
126
127         StringTokenizer JavaDoc st =
128             new StringTokenizer JavaDoc(conn.getRequest().getArgument(), " ");
129
130         if (!st.hasMoreTokens()) {
131             return FtpReply.RESPONSE_501_SYNTAX_ERROR;
132         }
133
134         int multiplier;
135         LinkedRemoteFileInterface nukeDir;
136         String JavaDoc nukeDirName;
137         try {
138             nukeDirName = st.nextToken();
139             nukeDir = conn.getCurrentDirectory().getFile(nukeDirName);
140         } catch (FileNotFoundException JavaDoc e) {
141             FtpReply response = new FtpReply(550, e.getMessage());
142             return response;
143         }
144         if (!nukeDir.isDirectory()) {
145             FtpReply response =
146                 new FtpReply(550, nukeDirName + ": not a directory");
147             return response;
148         }
149         String JavaDoc nukeDirPath = nukeDir.getPath();
150
151         if (!st.hasMoreTokens()) {
152             return FtpReply.RESPONSE_501_SYNTAX_ERROR;
153         }
154
155         try {
156             multiplier = Integer.parseInt(st.nextToken());
157         } catch (NumberFormatException JavaDoc ex) {
158             logger.warn("", ex);
159             return new FtpReply(501, "Invalid multiplier: " + ex.getMessage());
160         }
161
162         String JavaDoc reason;
163         if (st.hasMoreTokens()) {
164             reason = st.nextToken("").trim();
165         } else {
166             reason = "";
167         }
168         //get nukees with string as key
169
Hashtable JavaDoc nukees = new Hashtable JavaDoc();
170         nukeRemoveCredits(nukeDir, nukees);
171
172         FtpReply response = new FtpReply(200, "NUKE suceeded");
173
174         //// convert key from String to User ////
175
HashMap JavaDoc nukees2 = new HashMap JavaDoc(nukees.size());
176         for (Iterator JavaDoc iter = nukees.keySet().iterator(); iter.hasNext();) {
177
178             String JavaDoc username = (String JavaDoc) iter.next();
179             User user;
180             try {
181                 user =
182                     conn.getConnectionManager().getUserManager().getUserByName(
183                         username);
184             } catch (NoSuchUserException e1) {
185                 response.addComment(
186                     "Cannot remove credits from "
187                         + username
188                         + ": "
189                         + e1.getMessage());
190                 logger.warn("", e1);
191                 user = null;
192             } catch (UserFileException e1) {
193                 response.addComment(
194                     "Cannot read user data for "
195                         + username
196                         + ": "
197                         + e1.getMessage());
198                 logger.warn("", e1);
199                 response.setMessage("NUKE failed");
200                 return response;
201             }
202             // nukees contains credits as value
203
if (user == null) {
204                 Long JavaDoc add = (Long JavaDoc) nukees2.get(null);
205                 if (add == null) {
206                     add = new Long JavaDoc(0);
207                 }
208                 nukees2.put(
209                     user,
210                     new Long JavaDoc(
211                         add.longValue()
212                             + ((Long JavaDoc) nukees.get(username)).longValue()));
213             } else {
214                 nukees2.put(user, nukees.get(username));
215             }
216         }
217         //rename
218
String JavaDoc toDirPath;
219         String JavaDoc toName = "[NUKED]-" + nukeDir.getName();
220         try {
221             toDirPath = nukeDir.getParentFile().getPath();
222         } catch (FileNotFoundException JavaDoc ex) {
223             logger.fatal("", ex);
224             return FtpReply.RESPONSE_553_REQUESTED_ACTION_NOT_TAKEN;
225         }
226         try {
227             nukeDir = nukeDir.renameTo(toDirPath, toName);
228             nukeDir.createDirectory(
229                 conn.getUserNull().getUsername(),
230                 conn.getUserNull().getGroupName(),
231                 "REASON-" + reason);
232         } catch (IOException JavaDoc ex) {
233             logger.warn("", ex);
234             response.addComment(
235                 " cannot rename to \""
236                     + toDirPath
237                     + "/"
238                     + toName
239                     + "\": "
240                     + ex.getMessage());
241             response.setCode(500);
242             response.setMessage("NUKE failed");
243             return response;
244         }
245
246         long nukeDirSize = 0;
247         long nukedAmount = 0;
248
249         //update credits, nukedbytes, timesNuked, lastNuked
250
for (Iterator JavaDoc iter = nukees2.keySet().iterator(); iter.hasNext();) {
251             AbstractUser nukee = (AbstractUser) iter.next();
252             if (nukee == null)
253                 continue;
254             long size = ((Long JavaDoc) nukees2.get(nukee)).longValue();
255
256             long debt =
257                 calculateNukedAmount(size, nukee.getRatio(), multiplier);
258
259             nukedAmount += debt;
260             nukeDirSize += size;
261             nukee.updateCredits(-debt);
262             nukee.updateUploadedBytes(-size);
263             nukee.updateNukedBytes(debt);
264             nukee.updateTimesNuked(1);
265             nukee.setLastNuked(System.currentTimeMillis());
266             try {
267                 nukee.commit();
268             } catch (UserFileException e1) {
269                 response.addComment(
270                     "Error writing userfile: " + e1.getMessage());
271                 logger.log(Level.WARN, "Error writing userfile", e1);
272             }
273             response.addComment(
274                 nukee.getUsername() + " " + Bytes.formatBytes(debt));
275         }
276         NukeEvent nuke =
277             new NukeEvent(
278                 conn.getUserNull(),
279                 "NUKE",
280                 nukeDirPath,
281                 nukeDirSize,
282                 nukedAmount,
283                 multiplier,
284                 reason,
285                 nukees);
286         getNukeLog().add(nuke);
287         conn.getConnectionManager().dispatchFtpEvent(nuke);
288         return response;
289     }
290
291     private FtpReply doSITE_NUKES(BaseFtpConnection conn) {
292         FtpReply response = (FtpReply) FtpReply.RESPONSE_200_COMMAND_OK.clone();
293         for (Iterator JavaDoc iter = getNukeLog().getAll().iterator();
294             iter.hasNext();
295             ) {
296             response.addComment(iter.next());
297         }
298         return response;
299     }
300
301     /**
302      * USAGE: site unnuke <directory> <message>
303      * Unnuke a directory.
304      *
305      * ex. site unnuke shit NOT CRAP
306      *
307      * This will unnuke the directory 'shit' with the comment 'NOT CRAP'.
308      *
309      * NOTE: You can enclose the directory in braces if you have spaces in the name
310      * ex. site unnuke {My directory name} justcause
311      *
312      * You need to configure glftpd to keep nuked files if you want to unnuke.
313      * See the section about glftpd.conf.
314      */

315     private FtpReply doSITE_UNNUKE(BaseFtpConnection conn) {
316         if (!conn.getUserNull().isNuker())
317             return FtpReply.RESPONSE_530_ACCESS_DENIED;
318
319         StringTokenizer JavaDoc st =
320             new StringTokenizer JavaDoc(conn.getRequest().getArgument());
321         if (!st.hasMoreTokens()) {
322             return FtpReply.RESPONSE_501_SYNTAX_ERROR;
323         }
324
325         String JavaDoc toName = st.nextToken();
326         String JavaDoc toPath;
327         {
328             StringBuffer JavaDoc toPath2 =
329                 new StringBuffer JavaDoc(conn.getCurrentDirectory().getPath());
330             if (toPath2.length() != 1)
331                 toPath2.append("/"); // isn't /
332
toPath2.append(toName);
333             toPath = toPath2.toString();
334         }
335         String JavaDoc toDir = conn.getCurrentDirectory().getPath();
336         String JavaDoc nukeName = "[NUKED]-" + toName;
337
338         String JavaDoc reason;
339         if (st.hasMoreTokens()) {
340             reason = st.nextToken("");
341         } else {
342             reason = "";
343         }
344
345         LinkedRemoteFileInterface nukeDir;
346         try {
347             nukeDir = conn.getCurrentDirectory().getFile(nukeName);
348         } catch (FileNotFoundException JavaDoc e2) {
349             return new FtpReply(
350                 200,
351                 nukeName + " doesn't exist: " + e2.getMessage());
352         }
353
354         FtpReply response = (FtpReply) FtpReply.RESPONSE_200_COMMAND_OK.clone();
355         NukeEvent nuke;
356         try {
357             nuke = getNukeLog().get(toPath);
358         } catch (ObjectNotFoundException ex) {
359             response.addComment(ex.getMessage());
360             return response;
361         }
362
363         //Map nukees2 = new Hashtable();
364
// for (Iterator iter = nuke.getNukees().entrySet().iterator();
365
// iter.hasNext();
366
// ) {
367
for (Iterator JavaDoc iter = nuke.getNukees2().iterator(); iter.hasNext();) {
368             //Map.Entry entry = (Map.Entry) iter.next();
369
Nukee nukeeObj = (Nukee) iter.next();
370             //String nukeeName = (String) entry.getKey();
371
String JavaDoc nukeeName = nukeeObj.getUsername();
372             User nukee;
373             try {
374                 nukee =
375                     conn.getConnectionManager().getUserManager().getUserByName(
376                         nukeeName);
377             } catch (NoSuchUserException e) {
378                 response.addComment(nukeeName + ": no such user");
379                 continue;
380             } catch (UserFileException e) {
381                 response.addComment(nukeeName + ": error reading userfile");
382                 logger.fatal("error reading userfile", e);
383                 continue;
384             }
385             long nukedAmount =
386                 calculateNukedAmount(
387                     nukeeObj.getAmount(),
388                     nukee.getRatio(),
389                     nuke.getMultiplier());
390
391             nukee.updateCredits(nukedAmount);
392             nukee.updateUploadedBytes(nukeeObj.getAmount());
393             nukee.updateTimesNuked(-1);
394
395             try {
396                 nukee.commit();
397             } catch (UserFileException e3) {
398                 logger.log(
399                     Level.FATAL,
400                     "Eroror saveing userfile for " + nukee.getUsername(),
401                     e3);
402                 response.addComment(
403                     "Error saving userfile for " + nukee.getUsername());
404             }
405
406             response.addComment(
407                 nukeeName + ": restored " + Bytes.formatBytes(nukedAmount));
408         }
409         try {
410             getNukeLog().remove(toPath);
411         } catch (ObjectNotFoundException e) {
412             response.addComment("Error removing nukelog entry");
413         }
414         try {
415             nukeDir = nukeDir.renameTo(toDir, toName);
416         } catch (FileExistsException e1) {
417             response.addComment(
418                 "Error renaming nuke, target dir already exists");
419         } catch (IOException JavaDoc e1) {
420             response.addComment("Error: " + e1.getMessage());
421             logger.log(
422                 Level.FATAL,
423                 "Illegaltargetexception: means parent doesn't exist",
424                 e1);
425         }
426
427         try {
428             LinkedRemoteFileInterface reasonDir =
429                 nukeDir.getFile("REASON-" + nuke.getReason());
430             if (reasonDir.isDirectory())
431                 reasonDir.delete();
432         } catch (FileNotFoundException JavaDoc e3) {
433             logger.debug(
434                 "Failed to delete 'REASON-" + reason + "' dir in UNNUKE",
435                 e3);
436         }
437
438         nuke.setCommand("UNNUKE");
439         nuke.setReason(reason);
440         nuke.setUser(conn.getUserNull());
441         conn.getConnectionManager().dispatchFtpEvent(nuke);
442         return response;
443     }
444
445     public FtpReply execute(BaseFtpConnection conn)
446         throws UnhandledCommandException {
447         if (_nukelog == null) {
448             return new FtpReply(500, "You must reconnect to use NUKE");
449         }
450         String JavaDoc cmd = conn.getRequest().getCommand();
451         if ("SITE NUKE".equals(cmd))
452             return doSITE_NUKE(conn);
453         if ("SITE NUKES".equals(cmd))
454             return doSITE_NUKES(conn);
455         if ("SITE UNNUKE".equals(cmd))
456             return doSITE_UNNUKE(conn);
457         throw UnhandledCommandException.create(Nuke.class, conn.getRequest());
458     }
459
460     public String JavaDoc[] getFeatReplies() {
461         return null;
462     }
463
464     private NukeLog getNukeLog() {
465         return _nukelog;
466     }
467
468     public CommandHandler initialize(
469         BaseFtpConnection conn,
470         CommandManager initializer) {
471         return this;
472     }
473
474     public void load(CommandManagerFactory initializer) {
475         _nukelog = new NukeLog();
476         try {
477             Document doc =
478                 new SAXBuilder().build(new FileReader JavaDoc("nukelog.xml"));
479             List JavaDoc nukes = doc.getRootElement().getChildren();
480             for (Iterator JavaDoc iter = nukes.iterator(); iter.hasNext();) {
481                 Element nukeElement = (Element) iter.next();
482
483                 User user =
484                     initializer
485                         .getConnectionManager()
486                         .getUserManager()
487                         .getUserByName(
488                         nukeElement.getChildText("user"));
489                 String JavaDoc directory = nukeElement.getChildText("path");
490                 long time = Long.parseLong(nukeElement.getChildText("time"));
491                 int multiplier =
492                     Integer.parseInt(nukeElement.getChildText("multiplier"));
493                 String JavaDoc reason = nukeElement.getChildText("reason");
494
495                 long size = Long.parseLong(nukeElement.getChildText("size"));
496                 long nukedAmount =
497                     Long.parseLong(nukeElement.getChildText("nukedAmount"));
498
499                 Map JavaDoc nukees = new Hashtable JavaDoc();
500                 List JavaDoc nukeesElement =
501                     nukeElement.getChild("nukees").getChildren("nukee");
502                 for (Iterator JavaDoc iterator = nukeesElement.iterator();
503                     iterator.hasNext();
504                     ) {
505                     Element nukeeElement = (Element) iterator.next();
506                     String JavaDoc nukeeUsername =
507                         nukeeElement.getChildText("username");
508                     Long JavaDoc nukeeAmount =
509                         new Long JavaDoc(nukeeElement.getChildText("amount"));
510
511                     nukees.put(nukeeUsername, nukeeAmount);
512                 }
513                 _nukelog.add(
514                     new NukeEvent(
515                         user,
516                         "NUKE",
517                         directory,
518                         time,
519                         size,
520                         nukedAmount,
521                         multiplier,
522                         reason,
523                         nukees));
524             }
525         } catch (FileNotFoundException JavaDoc ex) {
526             logger.log(
527                 Level.DEBUG,
528                 "nukelog.xml not found, will create it after first nuke.");
529         } catch (Exception JavaDoc ex) {
530             logger.log(
531                 Level.INFO,
532                 "Error loading nukelog from nukelog.xml",
533                 ex);
534         }
535     }
536     public void unload() {
537         _nukelog = null;
538     }
539
540 }
541
Popular Tags