001: /*
002: * This file is part of DrFTPD, Distributed FTP Daemon.
003: *
004: * DrFTPD is free software; you can redistribute it and/or modify it under the
005: * terms of the GNU General Public License as published by the Free Software
006: * Foundation; either version 2 of the License, or (at your option) any later
007: * version.
008: *
009: * DrFTPD is distributed in the hope that it will be useful, but WITHOUT ANY
010: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
011: * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
012: *
013: * You should have received a copy of the GNU General Public License along with
014: * DrFTPD; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
015: * Suite 330, Boston, MA 02111-1307 USA
016: */
017: package org.drftpd.commands;
018:
019: import java.io.FileNotFoundException;
020: import java.util.ArrayList;
021: import java.util.Arrays;
022: import java.util.Collection;
023: import java.util.Collections;
024: import java.util.Date;
025: import java.util.HashMap;
026: import java.util.HashSet;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Map;
030: import java.util.NoSuchElementException;
031: import java.util.Map.Entry;
032: import java.util.regex.Matcher;
033: import java.util.regex.Pattern;
034:
035: import net.sf.drftpd.ObjectNotFoundException;
036: import net.sf.drftpd.master.BaseFtpConnection;
037: import net.sf.drftpd.master.FtpRequest;
038: import net.sf.drftpd.master.command.CommandManager;
039: import net.sf.drftpd.master.command.CommandManagerFactory;
040: import net.sf.drftpd.mirroring.Job;
041:
042: import org.drftpd.Bytes;
043: import org.drftpd.GlobalContext;
044: import org.drftpd.SFVFile;
045: import org.drftpd.SFVFile.SFVStatus;
046: import org.drftpd.master.RemoteSlave;
047: import org.drftpd.remotefile.LinkedRemoteFileInterface;
048: import org.drftpd.remotefile.MLSTSerialize;
049: import org.drftpd.usermanager.NoSuchUserException;
050: import org.drftpd.usermanager.User;
051: import org.drftpd.usermanager.UserFileException;
052:
053: /**
054: * SITE FIND <options>-action <action>Options: -user <user>-group
055: * <group>-nogroup -nouser Options: -mtime [-]n -type [f|d] -slave <slave>-size
056: * [-]size Options: -name <name>(* for wildcard) -incomplete -offline Actions:
057: * print, wipe, delete Multipe options and actions are allowed. If multiple
058: * options are given a file must match all options for action to be taken.
059: *
060: * @author pyrrhic
061: * @author mog
062: * @version $Id: Find.java 1177 2005-04-16 12:36:33Z zubov $
063: */
064: public class Find implements CommandHandler, CommandHandlerFactory {
065:
066: private static class ActionDeleteFromSlaves implements Action {
067: private HashSet<RemoteSlave> _deleteFromSlaves;
068:
069: public ActionDeleteFromSlaves(
070: HashSet<RemoteSlave> deleteFromSlaves) {
071: assert deleteFromSlaves != null;
072: _deleteFromSlaves = deleteFromSlaves;
073: }
074:
075: public String exec(BaseFtpConnection conn,
076: LinkedRemoteFileInterface file) {
077: HashSet<RemoteSlave> deleteFromSlaves = new HashSet<RemoteSlave>(
078: _deleteFromSlaves);
079: for (Iterator<RemoteSlave> iter = deleteFromSlaves
080: .iterator(); iter.hasNext();) {
081: RemoteSlave rslave = iter.next();
082: try {
083: file.deleteFromSlave(rslave);
084: } catch (IllegalArgumentException ex) {
085: iter.remove();
086: }
087: }
088: if (deleteFromSlaves.isEmpty())
089: return file.getPath()
090: + " was not present on any specified slaves";
091: String ret = file.getPath() + " deleted from ";
092: for (RemoteSlave rslave : deleteFromSlaves) {
093: ret = ret + rslave.getName() + ",";
094: }
095: return ret.substring(0, ret.length() - 1);
096: }
097: }
098:
099: private static interface Action {
100: public String exec(BaseFtpConnection conn,
101: LinkedRemoteFileInterface file);
102: }
103:
104: private static class ActionDelete implements Action {
105: private String doDELE(BaseFtpConnection conn,
106: LinkedRemoteFileInterface file) {
107: //FtpRequest request = conn.getRequest();
108: // argument check
109: //if (!request.hasArgument()) {
110: //out.print(FtpResponse.RESPONSE_501_SYNTAX_ERROR);
111: //return FtpReply.RESPONSE_501_SYNTAX_ERROR;
112: //}
113: // get filenames
114: //String fileName = file.getName();
115: //try {
116: //requestedFile = getVirtualDirectory().lookupFile(fileName);
117: //requestedFile = conn.getCurrentDirectory().lookupFile(fileName);
118: //} catch (FileNotFoundException ex) {
119: //return new FtpReply(550, "File not found: " + ex.getMessage());
120: //}
121: // check permission
122: if (file.getUsername().equals(conn.getUserNull().getName())) {
123: if (!conn.getGlobalContext().getConnectionManager()
124: .getGlobalContext().getConfig()
125: .checkPathPermission("deleteown",
126: conn.getUserNull(), file)) {
127: //return FtpReply.RESPONSE_530_ACCESS_DENIED;
128: return "Access denied for " + file.getPath();
129: }
130: } else if (!conn.getGlobalContext().getConnectionManager()
131: .getGlobalContext().getConfig()
132: .checkPathPermission("delete", conn.getUserNull(),
133: file)) {
134: //return FtpReply.RESPONSE_530_ACCESS_DENIED;
135: return "Access denied for " + file.getPath();
136: }
137:
138: //FtpReply reply = (FtpReply)
139: // FtpReply.RESPONSE_250_ACTION_OKAY.clone();
140: String reply = "Deleted " + file.getPath();
141: User uploader;
142:
143: try {
144: uploader = conn.getGlobalContext()
145: .getConnectionManager().getGlobalContext()
146: .getUserManager().getUserByName(
147: file.getUsername());
148: uploader
149: .updateCredits((long) -(file.length() * uploader
150: .getKeyedMap().getObjectFloat(
151: UserManagement.RATIO)));
152: } catch (UserFileException e) {
153: reply += ("Error removing credits: " + e.getMessage());
154: } catch (NoSuchUserException e) {
155: reply += ("Error removing credits: " + e.getMessage());
156: }
157:
158: //conn.getConnectionManager()
159: //.dispatchFtpEvent(
160: //new DirectoryFtpEvent(conn.getUserNull(), "DELE",
161: //requestedFile));
162: file.delete();
163:
164: return reply;
165: }
166:
167: /*
168: * (non-Javadoc)
169: *
170: * @see net.sf.drftpd.master.command.plugins.find.FindAction#exec(net.sf.drftpd.master.BaseFtpConnection,
171: * net.sf.drftpd.remotefile.LinkedRemoteFileInterface)
172: */
173: public String exec(BaseFtpConnection conn,
174: LinkedRemoteFileInterface file) {
175: return doDELE(conn, file);
176: }
177: }
178:
179: private static class ActionPrint implements Action {
180: /*
181: * (non-Javadoc)
182: *
183: * @see net.sf.drftpd.master.command.plugins.find.FindAction#exec(net.sf.drftpd.remotefile.LinkedRemoteFile)
184: */
185: public String exec(BaseFtpConnection conn,
186: LinkedRemoteFileInterface file) {
187: return file.getPath();
188: }
189: }
190:
191: private static class ActionPrintf implements Action {
192: private String _format;
193:
194: private String parent;
195:
196: public ActionPrintf(String f) {
197: _format = f;
198:
199: if (_format == null) {
200: throw new NullPointerException();
201: }
202: }
203:
204: public String exec(BaseFtpConnection conn,
205: LinkedRemoteFileInterface file) {
206: try {
207: parent = file.getParent();
208: } catch (FileNotFoundException e) {
209: parent = "/";
210: }
211:
212: String mlst = MLSTSerialize.toMLST(file);
213: String retval = null;
214:
215: try {
216: retval = formatMLST(mlst, file);
217: } catch (NumberFormatException e) {
218: return mlst;
219: }
220:
221: return retval;
222: }
223:
224: private String formatMLST(String mlst,
225: LinkedRemoteFileInterface file)
226: throws NumberFormatException {
227:
228: HashMap<String, String> formats = new HashMap<String, String>();
229: formats.put("#f", file.getName());
230: formats.put("#s", Bytes.formatBytes(file.length()));
231: formats.put("#u", file.getUsername());
232: formats.put("#g", file.getGroupname());
233: formats.put("#t", new Date(file.lastModified()).toString());
234: formats.put("#x", file.getSlaves().toString());
235: formats.put("#h", parent);
236:
237: String temp = _format;
238:
239: for (Map.Entry<String, String> entry : formats.entrySet()) {
240: temp = temp
241: .replaceAll(entry.getKey(), entry.getValue());
242: }
243:
244: return temp;
245: }
246:
247: private String getValue(String main, String sub) {
248: int index = main.indexOf(sub);
249: int endIndex = main.indexOf(";", index + 1);
250: String retval = main.substring(index + sub.length(),
251: endIndex);
252:
253: return retval;
254: }
255: }
256:
257: private static class ActionSendToSlaves implements Action {
258: private HashSet<RemoteSlave> _destSlaves;
259:
260: private int _priority;
261:
262: private int _transferNum;
263:
264: public ActionSendToSlaves(int transferNum,
265: HashSet<RemoteSlave> destSlaves, int priority) {
266: _transferNum = transferNum;
267: _destSlaves = destSlaves;
268: _priority = priority;
269: }
270:
271: public String exec(BaseFtpConnection conn,
272: LinkedRemoteFileInterface file) {
273: if (!file.isFile()) {
274: return file.getName()
275: + " is not a file, cannot send it";
276: }
277: conn.getGlobalContext().getJobManager()
278: .addJobToQueue(
279: new Job(file, _destSlaves, _priority,
280: _transferNum));
281: return file.getName() + " added to jobqueue";
282: }
283:
284: }
285:
286: private static class ActionWipe implements Action {
287: /*
288: * (non-Javadoc)
289: *
290: * @see net.sf.drftpd.master.command.plugins.find.FindAction#exec(net.sf.drftpd.master.BaseFtpConnection,
291: * net.sf.drftpd.remotefile.LinkedRemoteFileInterface)
292: */
293: public String exec(BaseFtpConnection conn,
294: LinkedRemoteFileInterface file) {
295: file.delete();
296:
297: return "Wiped " + file.getPath();
298: }
299: }
300:
301: private static interface Option {
302: public boolean isTrueFor(LinkedRemoteFileInterface file);
303: }
304:
305: private static class OptionGroup implements Option {
306: private String groupname;
307:
308: public OptionGroup(String g) {
309: groupname = g;
310: }
311:
312: public boolean isTrueFor(LinkedRemoteFileInterface file) {
313: return file.getGroupname().equals(groupname);
314: }
315: }
316:
317: private static class OptionIncomplete implements Option {
318: private int _minPercent;
319:
320: public OptionIncomplete() {
321: }
322:
323: public OptionIncomplete(int minPercent) {
324: _minPercent = minPercent;
325: }
326:
327: public boolean isTrueFor(LinkedRemoteFileInterface file) {
328: try {
329: SFVFile sfv = file.lookupSFVFile();
330: SFVStatus status = sfv.getStatus();
331: if (_minPercent == 0)
332: return !status.isFinished();
333: return status.getPresent() * 100 / sfv.size() < _minPercent;
334: } catch (Exception e) {
335: return false;
336: }
337: }
338: }
339:
340: private static class OptionMTime implements Option {
341: boolean after;
342:
343: private Date date;
344:
345: public OptionMTime(int h) {
346: after = true;
347:
348: if (h < 0) {
349: after = false;
350: h = Math.abs(h);
351: }
352:
353: long t = (long) h * 24 * 60 * 60 * 1000;
354: Date currentDate = new Date();
355: date = new Date(currentDate.getTime() - t);
356: }
357:
358: public boolean isTrueFor(LinkedRemoteFileInterface file) {
359: Date fileDate = new Date(file.lastModified());
360:
361: return after ? fileDate.after(date) : fileDate.before(date);
362: }
363: }
364:
365: private static class OptionName implements Option {
366: Pattern pattern;
367:
368: public OptionName(String str) {
369: str = str.replaceAll("\\[", "\\\\[");
370: str = str.replaceAll("\\]", "\\\\]");
371: str = str.replaceAll("\\(", "\\\\(");
372: str = str.replaceAll("\\)", "\\\\)");
373: str = str.replaceAll("[*]", ".*");
374: pattern = Pattern.compile(str);
375: }
376:
377: public boolean isTrueFor(LinkedRemoteFileInterface file) {
378: Matcher m = pattern.matcher(file.getName());
379:
380: return m.matches();
381: }
382: }
383:
384: private static class OptionOffline implements Option {
385: public boolean isTrueFor(LinkedRemoteFileInterface file) {
386: try {
387: return file.lookupSFVFile().getStatus().getOffline() != 0;
388: } catch (Exception e) {
389: return false;
390: }
391: }
392: }
393:
394: private static class OptionSize implements Option {
395: boolean bigger;
396:
397: long size;
398:
399: public OptionSize(long s, boolean b) {
400: bigger = b;
401: size = s;
402: }
403:
404: public boolean isTrueFor(LinkedRemoteFileInterface file) {
405: return bigger ? (file.length() >= size)
406: : (file.length() <= size);
407: }
408: }
409:
410: private static class OptionSlave implements Option {
411: RemoteSlave slave;
412:
413: public OptionSlave(RemoteSlave s) {
414: slave = s;
415: }
416:
417: public boolean isTrueFor(LinkedRemoteFileInterface file) {
418: return file.hasSlave(slave);
419: }
420: }
421:
422: private static class OptionType implements Option {
423: boolean dirs;
424:
425: boolean files;
426:
427: public OptionType(boolean f, boolean d) {
428: files = f;
429: dirs = d;
430: }
431:
432: /*
433: * (non-Javadoc)
434: *
435: * @see net.sf.drftpd.master.command.plugins.find.FindOption#isTrueFor(net.sf.drftpd.remotefile.LinkedRemoteFileInterface)
436: */
437: public boolean isTrueFor(LinkedRemoteFileInterface file) {
438: if (files && dirs) {
439: return true;
440: } else if (files && !dirs) {
441: return file.isFile();
442: } else if (!files && dirs) {
443: return file.isDirectory();
444: }
445:
446: return true;
447: }
448: }
449:
450: private static class OptionUser implements Option {
451: private String username;
452:
453: public OptionUser(String u) {
454: username = u;
455: }
456:
457: public boolean isTrueFor(LinkedRemoteFileInterface file) {
458: return file.getUsername().equals(username);
459: }
460: }
461:
462: private static class PeekingIterator<E> implements Iterator {
463: private Iterator<E> _i;
464:
465: private E _peek = null;
466:
467: public PeekingIterator(Iterator<E> i) {
468: _i = i;
469: }
470:
471: public boolean hasNext() {
472: return _peek != null || _i.hasNext();
473: }
474:
475: public E next() {
476: if (_peek != null) {
477: E peek = _peek;
478: _peek = null;
479: return peek;
480: }
481: return _i.next();
482: }
483:
484: public E peek() {
485: if (_peek != null)
486: return _peek;
487: return _peek = next();
488: }
489:
490: public void remove() {
491: _i.remove();
492: }
493: }
494:
495: private static void findFile(BaseFtpConnection conn,
496: Reply response, LinkedRemoteFileInterface dir,
497: Collection<Option> options, ArrayList actions,
498: boolean files, boolean dirs) {
499: //TODO optimize me, checking using regexp for all dirs is possibly slow
500: if (!conn.getGlobalContext().getConnectionManager()
501: .getGlobalContext().getConfig().checkPathPermission(
502: "privpath", conn.getUserNull(), dir, true)) {
503: //Logger.getLogger(Find.class).debug("privpath: " + dir.getPath());
504: return;
505: }
506:
507: for (Iterator<LinkedRemoteFileInterface> iter = new ArrayList<LinkedRemoteFileInterface>(
508: dir.getFiles2()).iterator(); iter.hasNext();) {
509: LinkedRemoteFileInterface file = iter.next();
510:
511: if (file.isDirectory()) {
512: findFile(conn, response, file, options, actions, files,
513: dirs);
514: }
515:
516: if ((dirs && file.isDirectory())
517: || (files && file.isFile())) {
518: boolean checkIt = true;
519:
520: for (Iterator<Option> iterator = options.iterator(); iterator
521: .hasNext();) {
522: if (response.size() >= 100) {
523: return;
524: }
525:
526: Option findOption = iterator.next();
527:
528: if (!findOption.isTrueFor(file)) {
529: checkIt = false;
530:
531: break;
532: }
533: }
534:
535: if (!checkIt) {
536: continue;
537: }
538:
539: for (Iterator i = actions.iterator(); i.hasNext();) {
540: Action findAction = (Action) i.next();
541: response.addComment(findAction.exec(conn, file));
542:
543: if (response.size() == 100 && actions.size() == 1
544: && actions.get(0) instanceof ActionPrint) {
545: response.addComment("<snip>");
546: return;
547: }
548: }
549: }
550: }
551: }
552:
553: private static String getArgs(String str) {
554: int start = str.indexOf("(");
555: int end = str.indexOf(")");
556:
557: if ((start == -1) || (end == -1)) {
558: return null;
559: }
560:
561: if (start > end) {
562: return null;
563: }
564:
565: return str.substring(start + 1, end);
566: }
567:
568: private GlobalContext _gctx;
569:
570: public Reply execute(BaseFtpConnection conn) throws ReplyException,
571: ImproperUsageException {
572: FtpRequest request = conn.getRequest();
573:
574: // if (!request.hasArgument()) {
575: // return getShortHelpMsg();
576: // }
577:
578: Collection<String> c = request.hasArgument() ? Arrays
579: .asList(request.getArgument().split(" "))
580: : Collections.EMPTY_LIST;
581:
582: // if (args.length == 0) {
583: // return getShortHelpMsg();
584: // }
585:
586: //Collection<String> c = Arrays.asList(args);
587: ArrayList<Option> options = new ArrayList<Option>();
588: ArrayList<Action> actions = new ArrayList<Action>();
589: boolean files = true;
590: boolean dirs = true;
591: boolean forceFilesOnly = false;
592: boolean forceDirsOnly = false;
593:
594: for (PeekingIterator<String> iter = new PeekingIterator<String>(
595: c.iterator()); iter.hasNext();) {
596: String arg = iter.next();
597:
598: if (arg.toLowerCase().equals("-user")) {
599: if (!iter.hasNext()) {
600: throw new ImproperUsageException();
601: }
602:
603: options.add(new OptionUser(iter.next()));
604: } else if (arg.toLowerCase().equals("-group")) {
605: if (!iter.hasNext()) {
606: throw new ImproperUsageException();
607: }
608:
609: options.add(new OptionGroup(iter.next()));
610: } else if (arg.toLowerCase().equals("-name")) {
611: if (!iter.hasNext()) {
612: throw new ImproperUsageException();
613: }
614:
615: options.add(new OptionName(iter.next()));
616: } else if (arg.toLowerCase().equals("-slave")) {
617: if (!iter.hasNext()) {
618: throw new ImproperUsageException();
619: }
620:
621: RemoteSlave rs = null;
622: String slaveName = iter.next();
623:
624: try {
625: rs = conn.getGlobalContext().getSlaveManager()
626: .getRemoteSlave(slaveName);
627: } catch (ObjectNotFoundException e) {
628: return new Reply(500, "Slave " + slaveName
629: + " was not found.");
630: }
631:
632: forceFilesOnly = true;
633: options.add(new OptionSlave(rs));
634: } else if (arg.toLowerCase().equals("-mtime")) {
635: if (!iter.hasNext()) {
636: throw new ImproperUsageException();
637: }
638:
639: int offset = 0;
640:
641: try {
642: offset = Integer.parseInt(iter.next());
643: } catch (NumberFormatException e) {
644: throw new ImproperUsageException();
645: }
646:
647: options.add(new OptionMTime(offset));
648: } else if (arg.toLowerCase().equals("-size")) {
649: if (!iter.hasNext()) {
650: throw new ImproperUsageException();
651: }
652:
653: long size = 0;
654: boolean bigger = true;
655: String bytes = iter.next();
656:
657: if (bytes.startsWith("-")) {
658: bigger = false;
659: bytes = bytes.substring(1);
660: }
661:
662: try {
663: size = Bytes.parseBytes(bytes);
664: } catch (NumberFormatException e) {
665: throw new ImproperUsageException();
666: }
667:
668: options.add(new OptionSize(size, bigger));
669: } else if (arg.toLowerCase().equals("-type")) {
670: if (!iter.hasNext()) {
671: throw new ImproperUsageException();
672: }
673:
674: String type = iter.next().toLowerCase();
675:
676: if (type.equals("f")) {
677: dirs = false;
678: } else if (type.equals("d")) {
679: files = false;
680: } else {
681: return Reply.RESPONSE_501_SYNTAX_ERROR;
682: }
683: } else if (arg.toLowerCase().equals("-help")) {
684: throw new ImproperUsageException();
685: } else if (arg.toLowerCase().equals("-nouser")) {
686: options.add(new OptionUser("nobody"));
687: } else if (arg.toLowerCase().equals("-incomplete")) {
688: forceDirsOnly = true;
689: String peek = null;
690: try {
691: peek = iter.peek();
692: } catch (NoSuchElementException fail) {
693: }
694: if (peek != null && peek.charAt(0) != '-') {
695: options.add(new OptionIncomplete(Integer
696: .parseInt(iter.next())));
697: } else {
698: options.add(new OptionIncomplete());
699: }
700: } else if (arg.toLowerCase().equals("-offline")) {
701: forceDirsOnly = true;
702: options.add(new OptionOffline());
703: } else if (arg.toLowerCase().equals("-nogroup")) {
704: options.add(new OptionGroup("drftpd"));
705: } else if (arg.toLowerCase().equals("-action")) {
706: if (!iter.hasNext()) {
707: throw new ImproperUsageException();
708: }
709:
710: String action = iter.next();
711:
712: if (action.indexOf("(") != -1) {
713: String cmd = action.substring(0, action
714: .indexOf("("));
715: boolean go = true;
716:
717: while (go) {
718: if (action.endsWith(")")) {
719: Action findAction = getActionWithArgs(cmd,
720: getArgs(action));
721: actions.add(findAction);
722: go = false;
723:
724: continue;
725: } else if (!iter.hasNext()) {
726: return Reply.RESPONSE_501_SYNTAX_ERROR;
727: } else {
728: action += (" " + iter.next());
729: }
730: }
731: } else if (action.equals("sendtoslaves")) {
732: if (!conn.getUserNull().isAdmin()) {
733: throw new ReplyPermissionDeniedException();
734: }
735: // -action sendtoslaves
736: // <numtransfers[:slave[,slave,..][:priority]]>
737: List<String> actionArgs = Arrays.asList(iter.next()
738: .split(":"));
739: int numOfSlaves = Integer.parseInt(actionArgs
740: .get(0));
741: int priority = 0;
742: if (actionArgs.size() >= 3) {
743: priority = Integer.parseInt(actionArgs.get(2));
744: }
745: HashSet<String> destSlavenames = new HashSet<String>(
746: Arrays.asList(actionArgs.get(1).split(",")));
747: HashSet<RemoteSlave> destSlaves = new HashSet<RemoteSlave>();
748: for (RemoteSlave rslave : getGlobalContext()
749: .getSlaveManager().getSlaves()) {
750: if (destSlavenames.contains(rslave.getName()))
751: destSlaves.add(rslave);
752: }
753: actions.add(new ActionSendToSlaves(numOfSlaves,
754: destSlaves, priority));
755: } else if (action.equals("deletefromslaves")) {
756: if (!conn.getUserNull().isAdmin()) {
757: throw new ReplyPermissionDeniedException();
758: }
759: // -action deletefromslaves <slave[,slave[,...]]>
760: HashSet<String> destSlaveNames = new HashSet<String>(
761: Arrays.asList(iter.next().split(",")));
762: HashSet<RemoteSlave> destSlaves = new HashSet<RemoteSlave>();
763: for (RemoteSlave rslave : getGlobalContext()
764: .getSlaveManager().getSlaves()) {
765: if (destSlaveNames.contains(rslave.getName()))
766: destSlaves.add(rslave);
767: }
768: actions.add(new ActionDeleteFromSlaves(destSlaves));
769: } else {
770: Action findAction = getAction(action.toLowerCase());
771:
772: if (findAction == null) {
773: throw new ImproperUsageException();
774: }
775:
776: if (findAction instanceof ActionWipe) {
777: if (!conn.getUserNull().isAdmin()) {
778: return Reply.RESPONSE_530_ACCESS_DENIED;
779: }
780: }
781:
782: actions.add(findAction);
783: }
784: } else {
785: return Reply.RESPONSE_501_SYNTAX_ERROR;
786: }
787: }
788:
789: Reply response = (Reply) Reply.RESPONSE_200_COMMAND_OK.clone();
790:
791: //if (actions.size() == 0 || options.size() == 0)
792: //return FtpReply.RESPONSE_501_SYNTAX_ERROR;
793: if (actions.size() == 0) {
794: actions.add(new ActionPrint());
795: }
796:
797: if (!dirs && !files) {
798: dirs = true;
799: files = true;
800: }
801:
802: //FtpReply response = (FtpReply)
803: // FtpReply.RESPONSE_200_COMMAND_OK.clone();
804: if (forceFilesOnly && forceDirsOnly) {
805: return new Reply(500,
806: "Option conflict. Possibly -slave and -incomplete.");
807: } else if (forceFilesOnly) {
808: dirs = false;
809: response
810: .addComment("Forcing a file only search because of -slave option.");
811: } else if (forceDirsOnly) {
812: files = false;
813: response.addComment("Forcing a dir only search.");
814: }
815:
816: options.add(new OptionType(files, dirs));
817: findFile(conn, response, conn.getCurrentDirectory(), options,
818: actions, files, dirs);
819:
820: return response;
821: }
822:
823: private Action getAction(String actionName) {
824: if (actionName.equals("print")) {
825: return new ActionPrint();
826: } else if (actionName.equals("wipe")) {
827: return new ActionWipe();
828: } else if (actionName.equals("delete")) {
829: return new ActionDelete();
830: } else {
831: return null;
832: }
833: }
834:
835: private Action getActionWithArgs(String actionName, String args) {
836: if (actionName.equals("printf")) {
837: return new ActionPrintf(args);
838: }
839:
840: return null;
841: }
842:
843: public String[] getFeatReplies() {
844: return null;
845: }
846:
847: private GlobalContext getGlobalContext() {
848: return _gctx;
849: }
850:
851: public CommandHandler initialize(BaseFtpConnection conn,
852: CommandManager initializer) {
853: return this ;
854: }
855:
856: public void load(CommandManagerFactory initializer) {
857: _gctx = initializer.getConnectionManager().getGlobalContext();
858: }
859:
860: public void unload() {
861: }
862: }
|