0001: // ftpc.java
0002: // -------------------------------------
0003: // (C) by Michael Peter Christen; mc@anomic.de
0004: // first published on http://www.anomic.de
0005: // Frankfurt, Germany, 2002, 2004, 2006
0006: // main implementation finished: 28.05.2002
0007: // last major change: 06.05.2004
0008: // added html generation for directories: 5.9.2006
0009: //
0010: // This program is free software; you can redistribute it and/or modify
0011: // it under the terms of the GNU General Public License as published by
0012: // the Free Software Foundation; either version 2 of the License, or
0013: // (at your option) any later version.
0014: //
0015: // This program is distributed in the hope that it will be useful,
0016: // but WITHOUT ANY WARRANTY; without even the implied warranty of
0017: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0018: // GNU General Public License for more details.
0019: //
0020: // You should have received a copy of the GNU General Public License
0021: // along with this program; if not, write to the Free Software
0022: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0023: //
0024: // Using this software in any meaning (reading, learning, copying, compiling,
0025: // running) means that you agree that the Author(s) is (are) not responsible
0026: // for cost, loss of data or any harm that may be caused directly or indirectly
0027: // by usage of this softare or this documentation. The usage of this software
0028: // is on your own risk. The installation and usage (starting/running) of this
0029: // software may allow other people or application to access your computer and
0030: // any attached devices and is highly dependent on the configuration of the
0031: // software which must be done by the user of the software; the author(s) is
0032: // (are) also not responsible for proper configuration and usage of the
0033: // software, even if provoked by documentation provided together with
0034: // the software.
0035: //
0036: // Any changes to this file according to the GPL as documented in the file
0037: // gpl.txt aside this file in the shipment you received can be done to the
0038: // lines that follows this copyright notice here, but changes must not be
0039: // done inside the copyright notive above. A re-distribution must contain
0040: // the intact and unchanged copyright notice.
0041: // Contributions and changes to the program code must be marked as such.
0042:
0043: package de.anomic.net;
0044:
0045: import java.io.BufferedOutputStream;
0046: import java.io.BufferedReader;
0047: import java.io.ByteArrayOutputStream;
0048: import java.io.DataInputStream;
0049: import java.io.DataOutputStream;
0050: import java.io.File;
0051: import java.io.FileDescriptor;
0052: import java.io.FileInputStream;
0053: import java.io.FileNotFoundException;
0054: import java.io.FileOutputStream;
0055: import java.io.IOException;
0056: import java.io.InputStream;
0057: import java.io.InputStreamReader;
0058: import java.io.OutputStream;
0059: import java.io.PrintStream;
0060: import java.io.RandomAccessFile;
0061: import java.lang.reflect.InvocationTargetException;
0062: import java.lang.reflect.Method;
0063: import java.net.InetAddress;
0064: import java.net.ServerSocket;
0065: import java.net.Socket;
0066: import java.text.DateFormat;
0067: import java.util.Date;
0068: import java.util.Enumeration;
0069: import java.util.Properties;
0070: import java.util.StringTokenizer;
0071: import java.util.Vector;
0072:
0073: import de.anomic.server.serverDomains;
0074:
0075: public class ftpc {
0076:
0077: private static final String vDATE = "20040506";
0078: private static final String logPrefix = "FTPC: ";
0079:
0080: private InputStream in;
0081: private PrintStream out;
0082: private PrintStream err;
0083: private boolean glob = true; // glob = false -> filenames are taken literally for mget, ..
0084:
0085: // transfer type
0086: private static final char transferType = 'i'; // transfer binary
0087:
0088: // block size [1K by default]
0089: private static final int blockSize = 1024;
0090:
0091: // client socket for commands
0092: private Socket ControlSocket = null;
0093:
0094: // socket timeout
0095: private int ControlSocketTimeout = 300000;
0096:
0097: // socket for data transactions
0098: private ServerSocket DataSocketActive = null;
0099: private Socket DataSocketPassive = null;
0100: private boolean DataSocketPassiveMode = true;
0101:
0102: // output and input streams for client control connection
0103: private BufferedReader clientInput = null;
0104: private DataOutputStream clientOutput = null;
0105:
0106: // client prompt
0107: private String prompt = "ftp [local]>";
0108:
0109: String[] cmd;
0110:
0111: // session parameters
0112: File currentPath;
0113: String account, password, host, remotemessage, remotegreeting,
0114: remotesystem;
0115: int port;
0116:
0117: public ftpc() {
0118: this (System.in, System.out, System.err);
0119: }
0120:
0121: public ftpc(java.io.InputStream ins, java.io.PrintStream outs,
0122: java.io.PrintStream errs) {
0123:
0124: //try {
0125: //System.setSecurityManager(new sm());
0126: //} catch (java.security.AccessControlException e) {
0127: //}
0128:
0129: this .in = ins;
0130: this .out = outs;
0131: this .err = errs;
0132:
0133: this .currentPath = new File(System.getProperty("user.dir"));
0134: try {
0135: this .currentPath = new File(this .currentPath
0136: .getCanonicalPath());
0137: } catch (IOException e) {
0138: }
0139:
0140: this .account = null;
0141: this .password = null;
0142: this .host = null;
0143: this .port = -1;
0144: this .remotemessage = null;
0145: this .remotegreeting = null;
0146: this .remotesystem = null;
0147: }
0148:
0149: public void shell(String server) {
0150: String command;
0151:
0152: java.io.PrintWriter pw = null;
0153: if (out != null) {
0154: pw = new java.io.PrintWriter(out);
0155: }
0156:
0157: try {
0158: java.io.BufferedReader stdin = new java.io.BufferedReader(
0159: new java.io.InputStreamReader(in));
0160: if (server != null)
0161: exec("open " + server, true);
0162: while (true) {
0163:
0164: // prompt
0165: if (pw != null) {
0166: pw.print(prompt);
0167: pw.flush();
0168: }
0169:
0170: // read a line
0171: while ((command = stdin.readLine()) == null)
0172: if (pw != null) {
0173: pw.print(prompt);
0174: pw.flush();
0175: }
0176:
0177: // execute
0178: if (!exec(command, false))
0179: break;
0180:
0181: }
0182: } catch (Exception e) {
0183: err.println(logPrefix + "---- Error - ftp exception: " + e);
0184: e.printStackTrace(err);
0185: }
0186: }
0187:
0188: public boolean exec(String command, boolean promptIt) {
0189: if ((command == null) || (command.length() == 0))
0190: return true;
0191: int pos;
0192: String com;
0193: boolean ret = true;
0194: while (command.length() > 0) {
0195: pos = command.indexOf(";");
0196: if (pos < 0)
0197: pos = command.indexOf("\n");
0198: if (pos < 0) {
0199: com = command;
0200: command = "";
0201: } else {
0202: com = command.substring(0, pos);
0203: command = command.substring(pos + 1);
0204: }
0205: if (promptIt)
0206: out.println(logPrefix + prompt + com);
0207: cmd = line2args(com);
0208: try {
0209: ret = (((Boolean) getClass().getMethod(
0210: cmd[0].toUpperCase(), new Class[0]).invoke(
0211: this , new Object[0])).booleanValue());
0212: } catch (InvocationTargetException e) {
0213: if (e.getMessage() == null) {
0214: } else if (ControlSocket == null) {
0215: // the error was probably caused because there is no connection
0216: err.println(logPrefix
0217: + "---- not connected. no effect.");
0218: e.printStackTrace();
0219: return ret;
0220: } else {
0221: err
0222: .println(logPrefix
0223: + "---- ftp internal exception: target exception "
0224: + e);
0225: return ret;
0226: }
0227: } catch (IllegalAccessException e) {
0228: err.println(logPrefix
0229: + "---- ftp internal exception: wrong access "
0230: + e);
0231: return ret;
0232: } catch (NoSuchMethodException e) {
0233: // consider first that the user attempted to execute a java command from
0234: // the current path; either local or remote
0235: if (ControlSocket == null) {
0236: // try a local exec
0237: try {
0238: javaexec(cmd);
0239: } catch (Exception ee) {
0240: err.println(logPrefix + "---- Command '"
0241: + cmd[0]
0242: + "' not supported. Try 'HELP'.");
0243: }
0244: } else {
0245: // try a remote exec
0246: exec("java " + com, false);
0247: }
0248: return ret;
0249: }
0250: }
0251: return ret;
0252: }
0253:
0254: private String[] line2args(String line) {
0255: // parse the command line
0256: if ((line == null) || (line.length() == 0))
0257: return null;
0258: // pre-parse
0259: String line1 = "";
0260: boolean quoted = false;
0261: for (int i = 0; i < line.length(); i++) {
0262: if (quoted) {
0263: if (line.charAt(i) == '"') {
0264: quoted = false;
0265: } else {
0266: line1 = line1 + line.charAt(i);
0267: }
0268: } else {
0269: if (line.charAt(i) == '"') {
0270: quoted = true;
0271: } else if (line.charAt(i) == ' ') {
0272: line1 = line1 + '|';
0273: } else {
0274: line1 = line1 + line.charAt(i);
0275: }
0276: }
0277: }
0278: // construct StringTokenizer
0279: String args[];
0280: StringTokenizer st = new StringTokenizer(line1, "|");
0281: // read tokens from string
0282: args = new String[st.countTokens()];
0283: for (int i = 0; st.hasMoreTokens(); i++) {
0284: args[i] = st.nextToken();
0285: }
0286: st = null;
0287: return args;
0288: }
0289:
0290: class cl extends ClassLoader {
0291:
0292: public cl() {
0293: super ();
0294: }
0295:
0296: public Class<?> loadClass(String classname, boolean resolve)
0297: throws ClassNotFoundException {
0298: Class<?> c = findLoadedClass(classname);
0299: if (c == null)
0300: try {
0301: // second try: ask the system
0302: c = findSystemClass(classname);
0303: } catch (ClassNotFoundException e) {
0304: // third try: load myself
0305: File f = new File(System.getProperty("user.dir"),
0306: classname + ".class");
0307: int length = (int) f.length();
0308: byte[] classbytes = new byte[length];
0309: try {
0310: DataInputStream in = new DataInputStream(
0311: new FileInputStream(f));
0312: in.readFully(classbytes);
0313: in.close();
0314: c = defineClass(classname, classbytes, 0,
0315: classbytes.length);
0316: } catch (FileNotFoundException ee) {
0317: throw new ClassNotFoundException();
0318: } catch (IOException ee) {
0319: throw new ClassNotFoundException();
0320: }
0321: }
0322: if (resolve)
0323: resolveClass(c);
0324: return c;
0325: }
0326:
0327: }
0328:
0329: private void javaexec(String[] inArgs) {
0330: String obj = inArgs[0];
0331: String[] args = new String[inArgs.length - 1];
0332:
0333: // remove the object name from the array of arguments
0334: System.arraycopy(inArgs, 1, args, 0, inArgs.length - 1);
0335:
0336: // Build the argument list for invoke() method.
0337: Object[] argList = new Object[1];
0338: argList[0] = args;
0339:
0340: Properties pr = System.getProperties();
0341: String origPath = (String) pr.get("java.class.path");
0342: try {
0343:
0344: // set the user.dir to the actual local path
0345: pr.put("user.dir", this .currentPath.toString());
0346:
0347: // add the current path to the classpath
0348: //pr.put("java.class.path", "" + pr.get("user.dir") + pr.get("path.separator") + origPath);
0349:
0350: //err.println(logPrefix + "System Properties: " + pr.toString());
0351:
0352: System.setProperties(pr);
0353:
0354: // locate object
0355: Class<?> c = (new cl()).loadClass(obj);
0356: //Class c = this.getClass().getClassLoader().loadClass(obj);
0357:
0358: // locate public static main(String[]) method
0359: Class<?>[] parameterType = new Class[1];
0360: parameterType[0] = Class.forName("[Ljava.lang.String;");
0361: Method m = c.getMethod("main", parameterType);
0362:
0363: // invoke object.main()
0364: Object result = m.invoke(null, argList);
0365: parameterType = null;
0366: m = null;
0367:
0368: // handle result
0369: if (result != null)
0370: out.println(logPrefix + "returns " + result);
0371:
0372: // set the local path to the user.dir (which may have changed)
0373: this .currentPath = new File((String) pr.get("user.dir"));
0374:
0375: } catch (ClassNotFoundException e) {
0376: // err.println(logPrefix + "---- cannot find class file " + obj + ".class");
0377: // class file does not exist, go silently over it to not show everybody that the
0378: // system attempted to load a class file
0379: err.println(logPrefix + "---- Command '" + obj
0380: + "' not supported. Try 'HELP'.");
0381: } catch (NoSuchMethodException e) {
0382: err
0383: .println(logPrefix
0384: + "---- no \"public static main(String args[])\" in "
0385: + obj);
0386: } catch (InvocationTargetException e) {
0387: Throwable orig = e.getTargetException();
0388: if (orig.getMessage() == null) {
0389: } else {
0390: err.println(logPrefix + "---- Exception from " + obj
0391: + ": " + orig.getMessage());
0392: orig.printStackTrace(err);
0393: }
0394: } catch (IllegalAccessException e) {
0395: err.println(logPrefix + "---- Illegal access for " + obj
0396: + ": class is probably not declared as public");
0397: e.printStackTrace(err);
0398: } catch (NullPointerException e) {
0399: err
0400: .println(logPrefix
0401: + "---- main(String args[]) is not defined as static for "
0402: + obj);
0403: /*
0404: } catch (IOException e) {
0405: // class file does not exist, go silently over it to not show everybody that the
0406: // system attempted to load a class file
0407: err.println(logPrefix + "---- Command '" + obj + "' not supported. Try 'HELP'.");
0408: */
0409: } catch (Exception e) {
0410: err.println(logPrefix + "---- Exception caught: " + e);
0411: e.printStackTrace(err);
0412: }
0413:
0414: // set the classpath to its original definition
0415: pr.put("java.class.path", origPath);
0416:
0417: }
0418:
0419: // FTP CLIENT COMMANDS ------------------------------------
0420:
0421: public boolean ASCII() {
0422: if (cmd.length != 1) {
0423: err.println(logPrefix
0424: + "---- Syntax: ASCII (no parameter)");
0425: return true;
0426: }
0427: try {
0428: literal("TYPE A");
0429: } catch (IOException e) {
0430: err
0431: .println(logPrefix
0432: + "---- Error: ASCII transfer type not supported by server.");
0433: }
0434: return true;
0435: }
0436:
0437: public boolean BINARY() {
0438: if (cmd.length != 1) {
0439: err.println(logPrefix
0440: + "---- Syntax: BINARY (no parameter)");
0441: return true;
0442: }
0443: try {
0444: literal("TYPE I");
0445: } catch (IOException e) {
0446: err
0447: .println(logPrefix
0448: + "---- Error: BINARY transfer type not supported by server.");
0449: }
0450: return true;
0451: }
0452:
0453: public boolean BYE() {
0454: return QUIT();
0455: }
0456:
0457: public boolean CD() {
0458: if (cmd.length != 2) {
0459: err.println(logPrefix + "---- Syntax: CD <path>");
0460: return true;
0461: }
0462: if (ControlSocket == null)
0463: return LCD();
0464: try {
0465: // send cwd command
0466: send("CWD " + cmd[1]);
0467:
0468: String reply = receive();
0469: if (Integer.parseInt(reply.substring(0, 1)) != 2)
0470: throw new IOException(reply);
0471: } catch (IOException e) {
0472: err
0473: .println(logPrefix
0474: + "---- Error: change of working directory to path "
0475: + cmd[1] + " failed.");
0476: }
0477: return true;
0478: }
0479:
0480: public boolean CLOSE() {
0481: return DISCONNECT();
0482: }
0483:
0484: private void rmForced(String path) throws IOException {
0485: // first try: send DELE command (to delete a file)
0486: send("DELE " + path);
0487: // read reply
0488: String reply1 = receive();
0489: if (Integer.parseInt(reply1.substring(0, 1)) != 2) {
0490: // second try: send a RMD command (to delete a directory)
0491: send("RMD " + path);
0492: // read reply
0493: String reply2 = receive();
0494: if (Integer.parseInt(reply2.substring(0, 1)) != 2) {
0495: // third try: test if this thing is a directory or file and send appropriate error message
0496: if (isFolder(path))
0497: throw new IOException(reply2);
0498: else
0499: throw new IOException(reply1);
0500: }
0501: }
0502: }
0503:
0504: public boolean DEL() {
0505: if (cmd.length != 2) {
0506: err.println(logPrefix + "---- Syntax: DEL <file>");
0507: return true;
0508: }
0509: if (ControlSocket == null)
0510: return LDEL();
0511: try {
0512: rmForced(cmd[1]);
0513: } catch (IOException e) {
0514: err.println(logPrefix + "---- Error: deletion of file "
0515: + cmd[1] + " failed.");
0516: }
0517: return true;
0518: }
0519:
0520: public boolean RM() {
0521: return DEL();
0522: }
0523:
0524: public boolean DIR() {
0525: if (cmd.length > 2) {
0526: err.println(logPrefix + "---- Syntax: DIR [<path>|<file>]");
0527: return true;
0528: }
0529: if (ControlSocket == null)
0530: return LDIR();
0531: try {
0532: Vector<String> l;
0533: if (cmd.length == 2)
0534: l = list(cmd[1], false);
0535: else
0536: l = list(".", false);
0537: Enumeration<String> x = l.elements();
0538: out
0539: .println(logPrefix
0540: + "---- v---v---v---v---v---v---v---v---v---v---v---v---v---v---v---v---v---v---v");
0541: while (x.hasMoreElements())
0542: out.println(logPrefix + x.nextElement());
0543: out
0544: .println(logPrefix
0545: + "---- ^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^");
0546: } catch (IOException e) {
0547: err.println(logPrefix
0548: + "---- Error: remote list not available");
0549: }
0550: return true;
0551: }
0552:
0553: public boolean DISCONNECT() {
0554: try {
0555: quit();
0556: out.println(logPrefix + "---- Connection closed.");
0557: } catch (IOException e) {
0558: err.println(logPrefix + "---- Connection to server lost.");
0559: }
0560: this .ControlSocket = null;
0561: this .DataSocketActive = null;
0562: this .DataSocketPassive = null;
0563: this .clientInput = null;
0564: this .clientOutput = null;
0565: this .prompt = "ftp [local]>";
0566: return true;
0567: }
0568:
0569: private String quit() throws IOException {
0570:
0571: // send delete command
0572: send("QUIT");
0573:
0574: // read status reply
0575: String reply = receive();
0576: if (Integer.parseInt(reply.substring(0, 1)) != 2)
0577: throw new IOException(reply);
0578:
0579: // cleanup
0580: if (ControlSocket != null) {
0581: clientOutput.close();
0582: clientInput.close();
0583: ControlSocket.close();
0584: }
0585:
0586: if (DataSocketActive != null)
0587: DataSocketActive.close();
0588: if (DataSocketPassive != null)
0589: DataSocketPassive.close();
0590:
0591: return reply;
0592: }
0593:
0594: public boolean EXIT() {
0595: return QUIT();
0596: }
0597:
0598: public boolean GET() {
0599: if ((cmd.length < 2) || (cmd.length > 3)) {
0600: err.println(logPrefix
0601: + "---- Syntax: GET <remote-file> [<local-file>]");
0602: return true;
0603: }
0604: String remote = cmd[1]; //(new File(cmd[1])).getName();
0605: File local;
0606: File l;
0607: if (cmd.length == 2) {
0608: l = new File(remote);
0609: if (l.isAbsolute())
0610: local = l;
0611: else
0612: local = new File(this .currentPath, remote);
0613: } else {
0614: l = new File(cmd[2]);
0615: if (l.isAbsolute())
0616: local = l;
0617: else
0618: local = new File(this .currentPath, cmd[2]);
0619: }
0620: if (local.exists()) {
0621: err.println(logPrefix + "---- Error: local file "
0622: + local.toString() + " already exists.");
0623: err.println(logPrefix + " File " + remote
0624: + " not retrieved. Local file unchanged.");
0625: } else {
0626: if (cmd.length == 2)
0627: retrieveFilesRecursively(remote, false);
0628: else
0629: try {
0630: get(local.getAbsolutePath(), remote);
0631: } catch (IOException e) {
0632: err.println(logPrefix
0633: + "---- Error: retrieving file " + remote
0634: + " failed. (" + e.getMessage() + ")");
0635: }
0636: }
0637: return true;
0638: }
0639:
0640: private void retrieveFilesRecursively(String remote, boolean delete) {
0641: File local;
0642: File l = new File(remote);
0643: if (l.isAbsolute())
0644: local = l;
0645: else
0646: local = new File(this .currentPath, remote);
0647: try {
0648: get(local.getAbsolutePath(), remote);
0649: try {
0650: if (delete)
0651: rmForced(remote);
0652: } catch (IOException eee) {
0653: err.println(logPrefix
0654: + "---- Warning: remote file or path " + remote
0655: + " cannot be removed.");
0656: }
0657: } catch (IOException e) {
0658: if (e.getMessage().startsWith("550")) {
0659: // maybe it's a "not a plain file" error message", then it can be a folder
0660: // test if this exists (then it should be a folder)
0661: if (isFolder(remote)) {
0662: // copy the whole directory
0663: exec("cd \"" + remote + "\";lmkdir \"" + remote
0664: + "\";lcd \"" + remote + "\"", true);
0665: //exec("mget *",true);
0666: try {
0667: Enumeration<String> files = list(".", false)
0668: .elements();
0669: while (files.hasMoreElements())
0670: retrieveFilesRecursively(files
0671: .nextElement(), delete);
0672: } catch (IOException ee) {
0673: }
0674: exec("cd ..;lcd ..", true);
0675: try {
0676: if (delete)
0677: rmForced(remote);
0678: } catch (IOException eee) {
0679: err.println(logPrefix
0680: + "---- Warning: remote file or path "
0681: + remote + " cannot be removed.");
0682: }
0683: } else {
0684: err.println(logPrefix
0685: + "---- Error: remote file or path "
0686: + remote + " does not exist.");
0687: }
0688: } else {
0689: err.println(logPrefix + "---- Error: retrieving file "
0690: + remote + " failed. (" + e.getMessage() + ")");
0691: }
0692: }
0693: }
0694:
0695: public boolean isFolder(String path) {
0696: try {
0697: send("CWD " + path);
0698: String reply = receive();
0699: if (Integer.parseInt(reply.substring(0, 1)) != 2)
0700: throw new IOException(reply);
0701: send("CWD ..");
0702: reply = receive();
0703: return true;
0704: } catch (IOException e) {
0705: return false;
0706: }
0707: }
0708:
0709: public boolean GLOB() {
0710: if (cmd.length != 1) {
0711: err
0712: .println(logPrefix
0713: + "---- Syntax: GLOB (no parameter)");
0714: return true;
0715: }
0716: this .glob = !this .glob;
0717: out.println(logPrefix + "---- globbing is now turned "
0718: + ((this .glob) ? "ON" : "OFF"));
0719: return true;
0720: }
0721:
0722: public boolean HASH() {
0723: err.println(logPrefix + "---- no games implemented");
0724: return true;
0725: }
0726:
0727: /*
0728: private static String[] shift(String args[]) {
0729: if ((args == null) || (args.length == 0)) return args; else {
0730: String[] newArgs = new String[args.length-1];
0731: System.arraycopy(args, 1, newArgs, 0, args.length-1);
0732: return newArgs;
0733: }
0734: }
0735: public boolean JAR() {
0736: //Sun proprietary API may be removed in a future Java release
0737: sun.tools.jar.Main.main(shift(cmd));
0738: return true;
0739: }
0740: */
0741:
0742: public boolean JJENCODE() {
0743: if (cmd.length != 2) {
0744: err.println(logPrefix + "---- Syntax: JJENCODE <path>");
0745: return true;
0746: }
0747: String path = cmd[1];
0748:
0749: File dir = new File(path);
0750: File newPath = dir.isAbsolute() ? dir : new File(
0751: this .currentPath, path);
0752: if (newPath.exists()) {
0753: if (newPath.isDirectory()) {
0754: // exec("cd \"" + remote + "\";lmkdir \"" + remote + "\";lcd \"" + remote + "\"",true);
0755: /*
0756: if not exist %1\nul goto :error
0757: cd %1
0758: c:\jdk1.2.2\bin\jar -cfM0 ..\%1.jar *.*
0759: cd ..
0760: c:\jdk1.2.2\bin\jar -cfM %1.jj %1.jar
0761: del %1.jar
0762: */
0763: String s = "";
0764: String[] l = newPath.list();
0765: for (int i = 0; i < l.length; i++)
0766: s = s + " \"" + l[i] + "\"";
0767: exec("cd \"" + path + "\";jar -cfM0 ../\"" + path
0768: + ".jar\"" + s, true);
0769: exec("cd ..;jar -cfM \"" + path + ".jj\" \"" + path
0770: + ".jar\"", true);
0771: exec("rm \"" + path + ".jar\"", true);
0772: } else {
0773: err.println(logPrefix + "---- Error: local path "
0774: + newPath.toString()
0775: + " denotes not to a directory.");
0776: }
0777: } else {
0778: err.println(logPrefix + "---- Error: local path "
0779: + newPath.toString() + " does not exist.");
0780: }
0781: return true;
0782: }
0783:
0784: public boolean JJDECODE() {
0785: if (cmd.length != 2) {
0786: err.println(logPrefix + "---- Syntax: JJENCODE <path>");
0787: return true;
0788: }
0789: String path = cmd[1];
0790: File dir = new File(path);
0791: File newPath = dir.isAbsolute() ? dir : new File(
0792: this .currentPath, path);
0793: File newFolder = new File(newPath.toString() + ".dir");
0794: if (newPath.exists()) {
0795: if (!newPath.isDirectory()) {
0796: if (!newFolder.mkdir()) {
0797: /*
0798: if not exist %1.jj goto :error
0799: mkdir %1.dir
0800: copy %1.jj %1.dir\ > %1.dummy && del %1.dummy
0801: cd %1.dir
0802: c:\jdk1.2.2\bin\jar -xf %1.jj
0803: del %1.jj
0804: c:\jdk1.2.2\bin\jar -xf %1.jar
0805: del %1.jar
0806: cd ..
0807: */
0808: exec("mkdir \"" + path + ".dir\"", true);
0809:
0810: } else {
0811: err.println(logPrefix + "---- Error: target dir "
0812: + newFolder.toString()
0813: + " cannot be created");
0814: }
0815: } else {
0816: err.println(logPrefix + "---- Error: local path "
0817: + newPath.toString()
0818: + " must denote to jar/jar file");
0819: }
0820: } else {
0821: err.println(logPrefix + "---- Error: local path "
0822: + newPath.toString() + " does not exist.");
0823: }
0824: return true;
0825: }
0826:
0827: private static String[] argList2StringArray(String argList) {
0828: // command line parser
0829: StringTokenizer tokens = new StringTokenizer(argList);
0830: String[] args = new String[tokens.countTokens()];
0831: for (int i = 0; tokens.hasMoreTokens(); i++)
0832: args[i] = tokens.nextToken();
0833: tokens = null; // free mem
0834: return args;
0835: }
0836:
0837: public boolean JOIN(String[] args) {
0838:
0839: // make sure the specified dest file does not exist
0840: String dest_name = args[1];
0841: File dest_file = new File(dest_name);
0842: if (dest_file.exists()) {
0843: err.println(logPrefix + "join: destination file "
0844: + dest_name + " already exists");
0845: return true;
0846: }
0847:
0848: // prepare or search file names of the input files to be joined
0849: String source_name;
0850: File source_file;
0851: int pc = -1;
0852: // create new string array with file names
0853: // scan first for the files
0854: pc = 0;
0855: source_name = dest_name + ".000";
0856: String argString = "";
0857: source_file = new File(source_name);
0858: while ((source_file.exists()) && (source_file.isFile())
0859: && (source_file.canRead())) {
0860: argString = argString + " " + source_name;
0861: pc++;
0862: source_name = dest_name
0863: + (pc < 10 ? ".00" + pc : (pc < 100 ? ".0" + pc
0864: : "." + pc));
0865: source_file = new File(source_name);
0866: }
0867: args = argList2StringArray(argString.substring(1));
0868:
0869: // do the join
0870: FileOutputStream dest = null;
0871: FileInputStream source = null;
0872: byte[] buffer;
0873: int bytes_read = 0;
0874:
0875: try {
0876: // open output file
0877: dest = new FileOutputStream(dest_file);
0878: buffer = new byte[1024];
0879:
0880: // append all source files
0881: for (pc = 0; pc < args.length; pc++) {
0882: // open the source file
0883: source_name = args[pc];
0884: source_file = new File(source_name);
0885: source = new FileInputStream(source_file);
0886:
0887: // start with the copy of one source file
0888: while (true) {
0889: bytes_read = source.read(buffer);
0890: if (bytes_read == -1)
0891: break;
0892: dest.write(buffer, 0, bytes_read);
0893: }
0894:
0895: // copy finished. close source file
0896: if (source != null)
0897: try {
0898: source.close();
0899: } catch (IOException e) {
0900: }
0901: }
0902: // close the output file
0903: if (dest != null)
0904: try {
0905: dest.close();
0906: } catch (IOException e) {
0907: }
0908:
0909: // if we come to this point then everything went fine
0910: // if the user wanted to delete the source it is save to do so now
0911: for (pc = 0; pc < args.length; pc++) {
0912: try {
0913: if (!(new File(args[pc])).delete())
0914: System.err.println(logPrefix
0915: + "join: unable to delete file "
0916: + args[pc]);
0917: } catch (SecurityException e) {
0918: System.err.println(logPrefix
0919: + "join: no permission to delete file "
0920: + args[pc]);
0921: }
0922: }
0923: } catch (FileNotFoundException e) {
0924: } catch (IOException e) {
0925: }
0926:
0927: // clean up
0928: finally {
0929: // close any opened streams
0930: if (dest != null)
0931: try {
0932: dest.close();
0933: } catch (IOException e) {
0934: }
0935: if (source != null)
0936: try {
0937: source.close();
0938: } catch (IOException e) {
0939: }
0940:
0941: // print appropriate message
0942: System.err.println(logPrefix + "join created output from "
0943: + args.length + " source files");
0944: }
0945: return true;
0946: }
0947:
0948: public boolean COPY(String[] args) {
0949: File dest_file = new File(args[2]);
0950: if (dest_file.exists()) {
0951: err.println(logPrefix + "copy: destination file " + args[2]
0952: + " already exists");
0953: return true;
0954: }
0955: int bytes_read = 0;
0956: try {
0957: // open output file
0958: FileOutputStream dest = new FileOutputStream(dest_file);
0959: byte[] buffer = new byte[1024];
0960:
0961: // open the source file
0962: File source_file = new File(args[1]);
0963: FileInputStream source = new FileInputStream(source_file);
0964:
0965: // start with the copy of one source file
0966: while (true) {
0967: bytes_read = source.read(buffer);
0968: if (bytes_read == -1)
0969: break;
0970: dest.write(buffer, 0, bytes_read);
0971: }
0972:
0973: // copy finished. close source file
0974: if (source != null)
0975: try {
0976: source.close();
0977: } catch (IOException e) {
0978: }
0979:
0980: // close the output file
0981: if (dest != null)
0982: try {
0983: dest.close();
0984: } catch (IOException e) {
0985: }
0986: } catch (FileNotFoundException e) {
0987: } catch (IOException e) {
0988: }
0989: return true;
0990: }
0991:
0992: public boolean JAVA() {
0993: String s = "JAVA";
0994: for (int i = 1; i < cmd.length; i++)
0995: s = s + " " + cmd[i];
0996: try {
0997: send(s);
0998: /*String reply =*/receive();
0999: } catch (IOException e) {
1000: }
1001: return true;
1002: }
1003:
1004: public boolean LCD() {
1005: if (cmd.length != 2) {
1006: err.println(logPrefix + "---- Syntax: LCD <path>");
1007: return true;
1008: }
1009: String path = cmd[1];
1010: File dir = new File(path);
1011: File newPath = dir.isAbsolute() ? dir : new File(
1012: this .currentPath, path);
1013: try {
1014: newPath = new File(newPath.getCanonicalPath());
1015: } catch (IOException e) {
1016: }
1017: if (newPath.exists()) {
1018: if (newPath.isDirectory()) {
1019: this .currentPath = newPath;
1020: out.println(logPrefix + "---- New local path: "
1021: + this .currentPath.toString());
1022: } else {
1023: err.println(logPrefix + "---- Error: local path "
1024: + newPath.toString()
1025: + " denotes not a directory.");
1026: }
1027: } else {
1028: err.println(logPrefix + "---- Error: local path "
1029: + newPath.toString() + " does not exist.");
1030: }
1031: return true;
1032: }
1033:
1034: public boolean LDEL() {
1035: return LRM();
1036: }
1037:
1038: public boolean LDIR() {
1039: if (cmd.length != 1) {
1040: err
1041: .println(logPrefix
1042: + "---- Syntax: LDIR (no parameter)");
1043: return true;
1044: }
1045: String[] name = this .currentPath.list();
1046: for (int n = 0; n < name.length; ++n)
1047: out.println(logPrefix
1048: + ls(new File(this .currentPath, name[n])));
1049: return true;
1050: }
1051:
1052: private String ls(File inode) {
1053: if ((inode == null) || (!inode.exists()))
1054: return "";
1055: String s = "";
1056: if (inode.isDirectory())
1057: s = s + "d";
1058: else if (inode.isFile())
1059: s = s + "-";
1060: //else if (inode.isHidden()) s = s + "h";
1061: else
1062: s = s + "?";
1063: if (inode.canRead())
1064: s = s + "r";
1065: else
1066: s = s + "-";
1067: if (inode.canWrite())
1068: s = s + "w";
1069: else
1070: s = s + "-";
1071: s = s + " " + lenformatted(Long.toString(inode.length()), 9);
1072: DateFormat df = DateFormat.getDateTimeInstance();
1073: s = s + " " + df.format(new Date(inode.lastModified()));
1074: s = s + " " + inode.getName();
1075: if (inode.isDirectory())
1076: s = s + "/";
1077: return s;
1078: }
1079:
1080: private String lenformatted(String s, int l) {
1081: l = l - s.length();
1082: while (l > 0) {
1083: s = " " + s;
1084: l--;
1085: }
1086: return s;
1087: }
1088:
1089: public boolean LITERAL() {
1090: if (cmd.length == 1) {
1091: err
1092: .println(logPrefix
1093: + "---- Syntax: LITERAL <ftp-command> [<command-argument>] (see RFC959)");
1094: return true;
1095: }
1096: String s = "";
1097: for (int i = 1; i < cmd.length; i++)
1098: s = s + " " + cmd[i];
1099: try {
1100: literal(s.substring(1));
1101: } catch (IOException e) {
1102: err
1103: .println(logPrefix
1104: + "---- Error: Syntax of FTP-command wrong. See RFC959 for details.");
1105: }
1106: return true;
1107: }
1108:
1109: public boolean LLS() {
1110: return LDIR();
1111: }
1112:
1113: public boolean LMD() {
1114: return LMKDIR();
1115: }
1116:
1117: public boolean LMKDIR() {
1118: if (cmd.length != 2) {
1119: err
1120: .println(logPrefix
1121: + "---- Syntax: LMKDIR <folder-name>");
1122: return true;
1123: }
1124: File f = new File(this .currentPath, cmd[1]);
1125: if (f.exists()) {
1126: err.println(logPrefix + "---- Error: local file/folder "
1127: + cmd[1] + " already exists");
1128: } else {
1129: if (!f.mkdir())
1130: err.println(logPrefix
1131: + "---- Error: creation of local folder "
1132: + cmd[1] + " failed");
1133: }
1134: return true;
1135: }
1136:
1137: public boolean LMV() {
1138: if (cmd.length != 3) {
1139: err.println(logPrefix + "---- Syntax: LMV <from> <to>");
1140: return true;
1141: }
1142: File from = new File(cmd[1]);
1143: File to = new File(cmd[2]);
1144: if (!to.exists()) {
1145: if (from.renameTo(to)) {
1146: out.println(logPrefix + "---- \"" + from.toString()
1147: + "\" renamed to \"" + to.toString() + "\"");
1148: } else
1149: err.println(logPrefix + "rename failed");
1150: } else
1151: err.println(logPrefix + "\"" + to.toString()
1152: + "\" already exists");
1153: return true;
1154: }
1155:
1156: public boolean LPWD() {
1157: if (cmd.length != 1) {
1158: err
1159: .println(logPrefix
1160: + "---- Syntax: LPWD (no parameter)");
1161: return true;
1162: }
1163: out.println(logPrefix + "---- Local path: "
1164: + this .currentPath.toString());
1165: return true;
1166: }
1167:
1168: public boolean LRD() {
1169: return LMKDIR();
1170: }
1171:
1172: public boolean LRMDIR() {
1173: if (cmd.length != 2) {
1174: err
1175: .println(logPrefix
1176: + "---- Syntax: LRMDIR <folder-name>");
1177: return true;
1178: }
1179: File f = new File(this .currentPath, cmd[1]);
1180: if (!f.exists()) {
1181: err.println(logPrefix + "---- Error: local folder "
1182: + cmd[1] + " does not exist");
1183: } else {
1184: if (!f.delete())
1185: err.println(logPrefix
1186: + "---- Error: deletion of local folder "
1187: + cmd[1] + " failed");
1188: }
1189: return true;
1190: }
1191:
1192: public boolean LRM() {
1193: if (cmd.length != 2) {
1194: err.println(logPrefix + "---- Syntax: LRM <file-name>");
1195: return true;
1196: }
1197: File f = new File(this .currentPath, cmd[1]);
1198: if (!f.exists()) {
1199: err.println(logPrefix + "---- Error: local file " + cmd[1]
1200: + " does not exist");
1201: } else {
1202: if (!f.delete())
1203: err.println(logPrefix + "---- Error: deletion of file "
1204: + cmd[1] + " failed");
1205: }
1206: return true;
1207: }
1208:
1209: public boolean LS() {
1210: if (cmd.length > 2) {
1211: err.println(logPrefix + "---- Syntax: LS [<path>|<file>]");
1212: return true;
1213: }
1214: if (ControlSocket == null)
1215: return LLS();
1216: try {
1217: Vector<String> l;
1218: if (cmd.length == 2)
1219: l = list(cmd[1], true);
1220: else
1221: l = list(".", true);
1222: Enumeration<String> x = l.elements();
1223: out
1224: .println(logPrefix
1225: + "---- v---v---v---v---v---v---v---v---v---v---v---v---v---v---v---v---v---v---v");
1226: while (x.hasMoreElements())
1227: out.println(logPrefix + (String) x.nextElement());
1228: out
1229: .println(logPrefix
1230: + "---- ^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^---^");
1231: } catch (IOException e) {
1232: err.println(logPrefix
1233: + "---- Error: remote list not available");
1234: }
1235: return true;
1236: }
1237:
1238: private Vector<String> list(String path, boolean extended)
1239: throws IOException {
1240: // prepare data channel
1241: if (DataSocketPassiveMode)
1242: createPassiveDataPort();
1243: else
1244: createActiveDataPort();
1245:
1246: // send command to the control port
1247: if (extended)
1248: send("LIST " + path);
1249: else
1250: send("NLST " + path);
1251:
1252: // read status of the command from the control port
1253: String reply = receive();
1254:
1255: // get status code
1256: int status = Integer.parseInt(reply.substring(0, 1));
1257:
1258: // starting data transaction
1259: if (status == 1) {
1260: Socket data;
1261: if (DataSocketPassiveMode) {
1262: data = DataSocketPassive;
1263: } else {
1264: data = DataSocketActive.accept();
1265: }
1266: BufferedReader ClientStream = new BufferedReader(
1267: new InputStreamReader(data.getInputStream()));
1268:
1269: // read file system data
1270: String line;
1271: Vector<String> files = new Vector<String>();
1272: while ((line = ClientStream.readLine()) != null)
1273: if (!line.startsWith("total "))
1274: files.addElement(line);
1275:
1276: // after stream is empty we should get control completion echo
1277: //reply = receive();
1278:
1279: //boolean success = (Integer.parseInt(reply.substring(0, 1)) == 2);
1280:
1281: // shutdown connection
1282: ClientStream.close();
1283: data.close();
1284:
1285: //if (!success) throw new IOException(reply);
1286:
1287: files.trimToSize();
1288: return files;
1289: } else
1290: throw new IOException(reply);
1291: }
1292:
1293: public boolean MDIR() {
1294: return MKDIR();
1295: }
1296:
1297: public boolean MKDIR() {
1298: if (cmd.length != 2) {
1299: err.println(logPrefix + "---- Syntax: MKDIR <folder-name>");
1300: return true;
1301: }
1302: if (ControlSocket == null)
1303: return LMKDIR();
1304: try {
1305: // send mkdir command
1306: send("MKD " + cmd[1]);
1307: // read reply
1308: String reply = receive();
1309: if (Integer.parseInt(reply.substring(0, 1)) != 2)
1310: throw new IOException(reply);
1311: } catch (IOException e) {
1312: err.println(logPrefix + "---- Error: creation of folder "
1313: + cmd[1] + " failed");
1314: }
1315: return true;
1316: }
1317:
1318: public boolean MGET() {
1319: if (cmd.length != 2) {
1320: err.println(logPrefix + "---- Syntax: MGET <file-pattern>");
1321: return true;
1322: }
1323: try {
1324: mget(cmd[1], false);
1325: } catch (IOException e) {
1326: err.println(logPrefix + "---- Error: mget failed ("
1327: + e.getMessage() + ")");
1328: }
1329: return true;
1330: }
1331:
1332: private void mget(String pattern, boolean remove)
1333: throws IOException {
1334: Vector<String> l = list(".", false);
1335: Enumeration<String> x = l.elements();
1336: String remote;
1337: File local;
1338: //int idx; // the search for " " is only for improper lists from the server. this fails if the file name has a " " in it
1339: while (x.hasMoreElements()) {
1340: remote = (String) x.nextElement();
1341: //idx = remote.lastIndexOf(" ");
1342: //if (idx >= 0) remote = remote.substring(idx + 1);
1343: if (matches(remote, pattern)) {
1344: local = new File(this .currentPath, remote);
1345: if (local.exists()) {
1346: err.println(logPrefix + "---- Warning: local file "
1347: + local.toString() + " overwritten.");
1348: local.delete();
1349: }
1350: retrieveFilesRecursively(remote, remove);
1351: }
1352: }
1353: }
1354:
1355: public boolean MOVEDOWN() {
1356: if (cmd.length != 2) {
1357: err.println(logPrefix
1358: + "---- Syntax: MOVEDOWN <file-pattern>");
1359: return true;
1360: }
1361: try {
1362: mget(cmd[1], true);
1363: } catch (IOException e) {
1364: err.println(logPrefix + "---- Error: movedown failed ("
1365: + e.getMessage() + ")");
1366: }
1367: return true;
1368: }
1369:
1370: /*
1371: public boolean MOVEUP() {
1372: }
1373: */
1374:
1375: public boolean MV() {
1376: if (cmd.length != 3) {
1377: err.println(logPrefix + "---- Syntax: MV <from> <to>");
1378: return true;
1379: }
1380: if (ControlSocket == null)
1381: return LMV();
1382: try {
1383: // send rename commands
1384: send("RNFR " + cmd[1]);
1385: // read reply
1386: String reply = receive();
1387: if (Integer.parseInt(reply.substring(0, 1)) != 2)
1388: throw new IOException(reply);
1389: send("RNTO " + cmd[2]);
1390: // read reply
1391: reply = receive();
1392: if (Integer.parseInt(reply.substring(0, 1)) != 2)
1393: throw new IOException(reply);
1394: } catch (IOException e) {
1395: err.println(logPrefix + "---- Error: rename of " + cmd[1]
1396: + " to " + cmd[2] + " failed.");
1397: }
1398: return true;
1399: }
1400:
1401: public boolean NOOP() {
1402: if (cmd.length != 1) {
1403: err
1404: .println(logPrefix
1405: + "---- Syntax: NOOP (no parameter)");
1406: return true;
1407: }
1408: try {
1409: literal("NOOP");
1410: } catch (IOException e) {
1411: err
1412: .println(logPrefix
1413: + "---- Error: server does not know how to do nothing");
1414: }
1415: return true;
1416: }
1417:
1418: public boolean OPEN() {
1419: if ((cmd.length < 2) || (cmd.length > 3)) {
1420: err
1421: .println(logPrefix
1422: + "---- Syntax: OPEN <host> [<port>]");
1423: return true;
1424: }
1425: int port = 21;
1426: if (cmd.length == 3) {
1427: try {
1428: port = java.lang.Integer.parseInt(cmd[2]);
1429: } catch (NumberFormatException e) {
1430: port = 21;
1431: }
1432: }
1433: if (cmd[1].indexOf(":") > 0) {
1434: // port is given
1435: port = java.lang.Integer.parseInt(cmd[1].substring(cmd[1]
1436: .indexOf(":") + 1));
1437: cmd[1] = cmd[1].substring(0, cmd[1].indexOf(":"));
1438: }
1439: try {
1440: open(cmd[1], port);
1441: out.println(logPrefix + "---- Connection to " + cmd[1]
1442: + " established.");
1443: prompt = "ftp [" + cmd[1] + "]>";
1444: } catch (IOException e) {
1445: err.println(logPrefix + "---- Error: connecting " + cmd[1]
1446: + " on port " + port + " failed.");
1447: }
1448: return true;
1449: }
1450:
1451: private void open(String host, int port) throws IOException {
1452: if (ControlSocket != null)
1453: exec("close", false); // close any existing connections first
1454:
1455: ControlSocket = new Socket(host, port);
1456: ControlSocket.setSoTimeout(this .ControlSocketTimeout);
1457: clientInput = new BufferedReader(new InputStreamReader(
1458: ControlSocket.getInputStream()));
1459: clientOutput = new DataOutputStream(new BufferedOutputStream(
1460: ControlSocket.getOutputStream()));
1461:
1462: // read and return server message
1463: this .host = host;
1464: this .port = port;
1465: this .remotemessage = receive();
1466: if ((remotemessage != null) && (remotemessage.length() > 3))
1467: remotemessage = remotemessage.substring(4);
1468: }
1469:
1470: public boolean PROMPT() {
1471: err.println(logPrefix + "---- prompt is always off");
1472: return true;
1473: }
1474:
1475: public boolean PUT() {
1476: if ((cmd.length < 2) || (cmd.length > 3)) {
1477: err.println(logPrefix
1478: + "---- Syntax: PUT <local-file> [<remote-file>]");
1479: return true;
1480: }
1481: File local = new File(this .currentPath, cmd[1]);
1482: String remote = (cmd.length == 2) ? local.getName() : cmd[2];
1483: if (!local.exists()) {
1484: err.println(logPrefix + "---- Error: local file "
1485: + local.toString() + " does not exist.");
1486: err.println(logPrefix + " Remote file " + remote
1487: + " not overwritten.");
1488: } else {
1489: try {
1490: put(local.getAbsolutePath(), remote);
1491: } catch (IOException e) {
1492: err.println(logPrefix
1493: + "---- Error: transmitting file "
1494: + local.toString() + " failed.");
1495: }
1496: }
1497: return true;
1498: }
1499:
1500: public boolean PWD() {
1501: if (cmd.length > 1) {
1502: err.println(logPrefix + "---- Syntax: PWD (no parameter)");
1503: return true;
1504: }
1505: if (ControlSocket == null)
1506: return LPWD();
1507: try {
1508: // send pwd command
1509: send("PWD");
1510:
1511: // read current directory
1512: String reply = receive();
1513: if (Integer.parseInt(reply.substring(0, 1)) != 2)
1514: throw new IOException(reply);
1515:
1516: // parse directory name out of the reply
1517: reply = reply.substring(5);
1518: reply = reply.substring(0, reply.lastIndexOf('"'));
1519:
1520: out.println(logPrefix + "---- Current remote path is: "
1521: + reply);
1522: } catch (IOException e) {
1523: err.println(logPrefix
1524: + "---- Error: remote path not available");
1525: }
1526: return true;
1527: }
1528:
1529: public boolean REMOTEHELP() {
1530: if (cmd.length != 1) {
1531: err.println(logPrefix
1532: + "---- Syntax: REMOTEHELP (no parameter)");
1533: return true;
1534: }
1535: try {
1536: literal("HELP");
1537: } catch (IOException e) {
1538: err
1539: .println(logPrefix
1540: + "---- Error: remote help not supported by server.");
1541: }
1542: return true;
1543: }
1544:
1545: public boolean RMDIR() {
1546: if (cmd.length != 2) {
1547: err.println(logPrefix + "---- Syntax: RMDIR <folder-name>");
1548: return true;
1549: }
1550: if (ControlSocket == null)
1551: return LRMDIR();
1552: try {
1553: rmForced(cmd[1]);
1554: } catch (IOException e) {
1555: err.println(logPrefix + "---- Error: deletion of folder "
1556: + cmd[1] + " failed.");
1557: }
1558: return true;
1559: }
1560:
1561: public boolean QUIT() {
1562: if (ControlSocket != null)
1563: exec("close", false);
1564: return false;
1565: }
1566:
1567: public boolean RECV() {
1568: return GET();
1569: }
1570:
1571: public int size(String path) throws IOException {
1572: // get the size of a file. If the given path targets to a directory, a -1 is returned
1573: // this function is not supported by standard rfc 959. The method is descibed in
1574: // http://www.ietf.org/internet-drafts/draft-ietf-ftpext-mlst-16.txt
1575: // if the method is not supported by the target server, this throws an IOException with the
1576: // server response as exception message
1577:
1578: // send command to the control port
1579: send("SIZE " + path);
1580:
1581: // read status of the command from the control port
1582: String reply = receive();
1583:
1584: // get status code
1585: int status = Integer.parseInt(reply.substring(0, 3));
1586:
1587: // starting data transaction
1588: if (status == 213) {
1589: try {
1590: return Integer.parseInt(reply.substring(4));
1591: } catch (NumberFormatException e) {
1592: throw new IOException(reply);
1593: }
1594: } else {
1595: throw new IOException(reply);
1596: }
1597: }
1598:
1599: public boolean USER() {
1600: if (cmd.length != 3) {
1601: err.println(logPrefix
1602: + "---- Syntax: USER <user-name> <password>");
1603: return true;
1604: }
1605: try {
1606: login(cmd[1], cmd[2]);
1607: out.println(logPrefix + "---- Granted access for user "
1608: + cmd[1] + ".");
1609: } catch (IOException e) {
1610: err.println(logPrefix
1611: + "---- Error: authorization of user " + cmd[1]
1612: + " failed.");
1613: }
1614: return true;
1615: }
1616:
1617: public boolean APPEND() {
1618: err.println(logPrefix + "---- not yet supported");
1619: return true;
1620: }
1621:
1622: public boolean HELP() {
1623: out.println(logPrefix + "---- ftp HELP ----");
1624: out.println(logPrefix + "");
1625: out
1626: .println(logPrefix
1627: + "This ftp client shell can act as command shell for the local host as well for the");
1628: out
1629: .println(logPrefix
1630: + "remote host. Commands that point to the local host are preceded by 'L'.");
1631: out.println(logPrefix + "");
1632: out.println(logPrefix + "Supported Commands:");
1633: out.println(logPrefix + "ASCII");
1634: out.println(logPrefix
1635: + " switch remote server to ASCII transfer mode");
1636: out.println(logPrefix + "BINARY");
1637: out.println(logPrefix
1638: + " switch remote server to BINARY transfer mode");
1639: out.println(logPrefix + "BYE");
1640: out.println(logPrefix
1641: + " quit the command shell (same as EXIT)");
1642: out.println(logPrefix + "CD <path>");
1643: out.println(logPrefix + " change remote path");
1644: out.println(logPrefix + "CLOSE");
1645: out
1646: .println(logPrefix
1647: + " close connection to remote host (same as DISCONNECT)");
1648: out.println(logPrefix + "DEL <file>");
1649: out.println(logPrefix
1650: + " delete file on remote server (same as RM)");
1651: out.println(logPrefix + "RM <file>");
1652: out.println(logPrefix
1653: + " remove file from remote server (same as DEL)");
1654: out.println(logPrefix + "DIR [<path>|<file>] ");
1655: out
1656: .println(logPrefix
1657: + " print file information for remote directory or file");
1658: out.println(logPrefix + "DISCONNECT");
1659: out.println(logPrefix
1660: + " disconnect from remote server (same as CLOSE)");
1661: out.println(logPrefix + "EXIT");
1662: out.println(logPrefix
1663: + " quit the command shell (same as BYE)");
1664: out.println(logPrefix + "GET <remote-file> [<local-file>]");
1665: out
1666: .println(logPrefix
1667: + " load <remote-file> from remote server and store it locally,");
1668: out
1669: .println(logPrefix
1670: + " optionally to <local-file>. if the <remote-file> is a directory,");
1671: out.println(logPrefix
1672: + " then all files in that directory are retrieved,");
1673: out.println(logPrefix
1674: + " including recursively all subdirectories.");
1675: out.println(logPrefix + "GLOB");
1676: out
1677: .println(logPrefix
1678: + " toggles globbing: matching with wild cards or not");
1679: out.println(logPrefix + "COPY");
1680: out.println(logPrefix + " copies local files");
1681: out.println(logPrefix + "LCD <path>");
1682: out.println(logPrefix + " local directory change");
1683: out.println(logPrefix + "LDEL <file>");
1684: out.println(logPrefix + " local file delete");
1685: out.println(logPrefix + "LDIR");
1686: out.println(logPrefix + " shows local directory content");
1687: out.println(logPrefix
1688: + "LITERAL <ftp-command> [<command-argument>]");
1689: out.println(logPrefix
1690: + " Sends FTP commands as documented in RFC959");
1691: out.println(logPrefix + "LLS");
1692: out.println(logPrefix + " as LDIR");
1693: out.println(logPrefix + "LMD");
1694: out.println(logPrefix + " as LMKDIR");
1695: out.println(logPrefix + "LMV <local-from> <local-to>");
1696: out.println(logPrefix + " copies local files");
1697: out.println(logPrefix + "LPWD");
1698: out.println(logPrefix + " prints local path");
1699: out.println(logPrefix + "LRD");
1700: out.println(logPrefix + " as LMKDIR");
1701: out.println(logPrefix + "LRMD <folder-name>");
1702: out.println(logPrefix
1703: + " deletes local directory <folder-name>");
1704: out.println(logPrefix + "LRM <file-name>");
1705: out.println(logPrefix + " deletes local file <file-name>");
1706: out.println(logPrefix + "LS [<path>|<file>]");
1707: out
1708: .println(logPrefix
1709: + " prints list of remote directory <path> or information of file <file>");
1710: out.println(logPrefix + "MDIR");
1711: out.println(logPrefix + " as MKDIR");
1712: out.println(logPrefix + "MGET <file-pattern>");
1713: out
1714: .println(logPrefix
1715: + " copies files from remote server that fits into the");
1716: out.println(logPrefix
1717: + " pattern <file-pattern> to the local path.");
1718: out.println(logPrefix + "MOVEDOWN <file-pattern>");
1719: out.println(logPrefix
1720: + " copies files from remote server as with MGET");
1721: out
1722: .println(logPrefix
1723: + " and deletes them afterwards on the remote server");
1724: out.println(logPrefix + "MV <from> <to>");
1725: out.println(logPrefix
1726: + " moves or renames files on the local host");
1727: out.println(logPrefix + "NOOP");
1728: out
1729: .println(logPrefix
1730: + " sends the NOOP command to the remote server (which does nothing)");
1731: out
1732: .println(logPrefix
1733: + " This command is usually used to measure the speed of the remote server.");
1734: out.println(logPrefix + "OPEN <host[':'port]> [<port>]");
1735: out
1736: .println(logPrefix
1737: + " connects the ftp shell to the remote server <host>. Optionally,");
1738: out
1739: .println(logPrefix
1740: + " a port number can be given, the default port number is 21.");
1741: out
1742: .println(logPrefix
1743: + " Example: OPEN localhost:2121 or OPEN 192.168.0.1 2121");
1744: out.println(logPrefix + "PROMPT");
1745: out
1746: .println(logPrefix
1747: + " compatibility command, that usually toggles beween prompting on or off.");
1748: out
1749: .println(logPrefix
1750: + " ftp has prompting switched off by default and cannot switched on.");
1751: out.println(logPrefix + "PUT <local-file> [<remote-file>]");
1752: out
1753: .println(logPrefix
1754: + " copies the <local-file> to the remote server to the current remote path or");
1755: out.println(logPrefix
1756: + " optionally to the given <remote-file> path.");
1757: out.println(logPrefix + "PWD");
1758: out.println(logPrefix
1759: + " prints current path on the remote server.");
1760: out.println(logPrefix + "REMOTEHELP");
1761: out
1762: .println(logPrefix
1763: + " asks the remote server to print the help text of the remote server");
1764: out.println(logPrefix + "RMDIR <folder-name>");
1765: out
1766: .println(logPrefix
1767: + " removes the directory <folder-name> on the remote server");
1768: out.println(logPrefix + "QUIT");
1769: out.println(logPrefix + " exits the ftp application");
1770: out.println(logPrefix + "RECV");
1771: out.println(logPrefix + " as GET");
1772: out.println(logPrefix + "USER <user-name> <password>");
1773: out
1774: .println(logPrefix
1775: + " logs into the remote server with the user <user-name>");
1776: out.println(logPrefix + " and the password <password>");
1777: out.println(logPrefix + "");
1778: out.println(logPrefix + "");
1779: out.println(logPrefix + "EXAMPLE:");
1780: out.println(logPrefix + "a standard sessions looks like this");
1781: out.println(logPrefix + ">open 192.168.0.1:2121");
1782: out.println(logPrefix + ">user anonymous bob");
1783: out.println(logPrefix + ">pwd");
1784: out.println(logPrefix + ">ls");
1785: out.println(logPrefix + ">.....");
1786: out.println(logPrefix + "");
1787: out.println(logPrefix + "");
1788: return true;
1789: }
1790:
1791: public boolean QUOTE() {
1792: err.println(logPrefix + "---- not yet supported");
1793: return true;
1794: }
1795:
1796: public boolean BELL() {
1797: err.println(logPrefix + "---- not yet supported");
1798: return true;
1799: }
1800:
1801: public boolean MDELETE() {
1802: err.println(logPrefix + "---- not yet supported");
1803: return true;
1804: }
1805:
1806: public boolean SEND() {
1807: err.println(logPrefix + "---- not yet supported");
1808: return true;
1809: }
1810:
1811: public boolean DEBUG() {
1812: err.println(logPrefix + "---- not yet supported");
1813: return true;
1814: }
1815:
1816: public boolean MLS() {
1817: err.println(logPrefix + "---- not yet supported");
1818: return true;
1819: }
1820:
1821: public boolean TRACE() {
1822: err.println(logPrefix + "---- not yet supported");
1823: return true;
1824: }
1825:
1826: public boolean MPUT() {
1827: err.println(logPrefix + "---- not yet supported");
1828: return true;
1829: }
1830:
1831: public boolean TYPE() {
1832: err.println(logPrefix + "---- not yet supported");
1833: return true;
1834: }
1835:
1836: public boolean CREATE() {
1837: err.println(logPrefix + "---- not yet supported");
1838: return true;
1839: }
1840:
1841: // helper functions
1842:
1843: private boolean matches(String name, String pattern) {
1844: // checks whether the string name matches with the pattern
1845: // the pattern may contain characters '*' as wildcard for several
1846: // characters (also none) and '?' to match exactly one characters
1847: //out.println(logPrefix + "MATCH " + name + " " + pattern);
1848: if (!this .glob)
1849: return name.equals(pattern);
1850: if (pattern.equals("*"))
1851: return true;
1852: if ((pattern.startsWith("*")) && (pattern.endsWith("*")))
1853: return // avoid recursion deadlock
1854: ((matches(name, pattern.substring(1))) || (matches(name,
1855: pattern.substring(0, pattern.length() - 1))));
1856: try {
1857: int i = pattern.indexOf("?");
1858: if (i >= 0) {
1859: if (!(matches(name.substring(0, i), pattern.substring(
1860: 0, i))))
1861: return false;
1862: return (matches(name.substring(i + 1), pattern
1863: .substring(i + 1)));
1864: }
1865: i = pattern.indexOf("*");
1866: if (i >= 0) {
1867: if (!(name.substring(0, i).equals(pattern.substring(0,
1868: i))))
1869: return false;
1870: if (pattern.length() == i + 1)
1871: return true; // pattern would be '*'
1872: return (matches(reverse(name.substring(i)),
1873: reverse(pattern.substring(i + 1)) + "*"));
1874: }
1875: return name.equals(pattern);
1876: } catch (java.lang.StringIndexOutOfBoundsException e) {
1877: // this is normal. it's a lazy implementation
1878: return false;
1879: }
1880: }
1881:
1882: private String reverse(String s) {
1883: if (s.length() < 2)
1884: return s;
1885: return reverse(s.substring(1)) + s.charAt(0);
1886: }
1887:
1888: // protocoll socket commands
1889:
1890: private void send(String buf) throws IOException {
1891: clientOutput.writeBytes(buf);
1892: clientOutput.write('\r');
1893: clientOutput.write('\n');
1894: clientOutput.flush();
1895: if (buf.startsWith("PASS")) {
1896: if (out != null)
1897: out.println(logPrefix + "> PASS ********");
1898: } else {
1899: if (out != null)
1900: out.println(logPrefix + "> " + buf);
1901: }
1902: }
1903:
1904: private String receive() throws IOException {
1905: // last reply starts with 3 digit number followed by space
1906: String reply;
1907:
1908: while (true) {
1909: reply = clientInput.readLine();
1910:
1911: // sanity check
1912: if (reply == null)
1913: throw new IOException(
1914: "Server has presumably shut down the connection.");
1915:
1916: if (out != null)
1917: out.println(logPrefix + "< " + reply);
1918: //serverResponse.addElement(reply);
1919:
1920: if (reply.length() >= 4
1921: && Character.isDigit(reply.charAt(0))
1922: && Character.isDigit(reply.charAt(1))
1923: && Character.isDigit(reply.charAt(2))
1924: && (reply.charAt(3) == ' '))
1925: break; // end of reply
1926: }
1927: // return last reply line
1928: return reply;
1929: }
1930:
1931: private void sendTransferType(char type) throws IOException {
1932: send("TYPE " + type);
1933:
1934: String reply = receive();
1935: if (Integer.parseInt(reply.substring(0, 1)) != 2)
1936: throw new IOException(reply);
1937: }
1938:
1939: private void createActiveDataPort() throws IOException {
1940: // create data socket and bind it to free port available
1941: DataSocketActive = new ServerSocket(0);
1942:
1943: // get port socket has been bound to
1944: int DataPort = DataSocketActive.getLocalPort();
1945:
1946: // client ip
1947: //InetAddress LocalIp = serverCore.publicIP();
1948: // InetAddress LocalIp = DataSocketActive.getInetAddress().getLocalHost();
1949:
1950: // save ip address in high byte order
1951: //byte[] Bytes = LocalIp.getAddress();
1952: byte[] Bytes = serverDomains.myPublicIP().getBytes();
1953:
1954: // bytes greater than 127 should not be printed as negative
1955: short[] Shorts = new short[4];
1956: for (int i = 0; i < 4; i++) {
1957: Shorts[i] = Bytes[i];
1958: if (Shorts[i] < 0)
1959: Shorts[i] += 256;
1960: }
1961:
1962: // send port command via control socket:
1963: // four ip address shorts encoded and two port shorts encoded
1964: send("PORT "
1965: +
1966: //"127,0,0,1," +
1967: Shorts[0] + "," + Shorts[1] + "," + Shorts[2] + ","
1968: + Shorts[3] + "," + ((DataPort & 0xff00) >> 8) + ","
1969: + (DataPort & 0x00ff));
1970:
1971: // read status of the command from the control port
1972: String reply = receive();
1973:
1974: // check status code
1975: if (Integer.parseInt(reply.substring(0, 1)) != 2)
1976: throw new IOException(reply);
1977:
1978: DataSocketPassiveMode = false;
1979: }
1980:
1981: private void createPassiveDataPort() throws IOException {
1982: // send port command via control socket:
1983: // four ip address shorts encoded and two port shorts encoded
1984: send("PASV");
1985:
1986: // read status of the command from the control port
1987: String reply = receive();
1988:
1989: // check status code
1990: if (!(reply.substring(0, 3).equals("227")))
1991: throw new IOException(reply);
1992:
1993: // parse the status return: address should start at the first number
1994: int pos = 4;
1995: while ((pos < reply.length())
1996: && ((reply.charAt(pos) < '0') || (reply.charAt(pos) > '9')))
1997: pos++;
1998: if (pos >= reply.length())
1999: throw new IOException(reply
2000: + " [could not parse return code]");
2001: reply = reply.substring(pos);
2002: pos = reply.length() - 1;
2003: while ((pos >= 0)
2004: && ((reply.charAt(pos) < '0') || (reply.charAt(pos) > '9')))
2005: pos--;
2006: if (pos < 0)
2007: throw new IOException(
2008: "[could not parse return code: no numbers]");
2009: reply = reply.substring(0, pos + 1);
2010: StringTokenizer st = new StringTokenizer(reply, ",");
2011: if (st.countTokens() != 6)
2012: throw new IOException(
2013: "[could not parse return code: wrong number of numbers]");
2014:
2015: // set the data host and port
2016: int a = Integer.parseInt(st.nextToken());
2017: int b = Integer.parseInt(st.nextToken());
2018: int c = Integer.parseInt(st.nextToken());
2019: int d = Integer.parseInt(st.nextToken());
2020: InetAddress datahost = InetAddress.getByName(a + "." + b + "."
2021: + c + "." + d);
2022: int high = Integer.parseInt(st.nextToken());
2023: int low = Integer.parseInt(st.nextToken());
2024: if (high < 0 || high > 255 || low < 0 || low > 255)
2025: throw new IOException(
2026: "[could not parse return code: syntax error]");
2027: int dataport = (high << 8) + low;
2028:
2029: DataSocketPassive = new Socket(datahost, dataport);
2030: DataSocketPassiveMode = true;
2031: }
2032:
2033: private void get(String fileDest, String fileName)
2034: throws IOException {
2035: // store time for statistics
2036: long start = System.currentTimeMillis();
2037:
2038: // prepare data channel
2039: if (DataSocketPassiveMode)
2040: createPassiveDataPort();
2041: else
2042: createActiveDataPort();
2043:
2044: // set type of the transfer
2045: sendTransferType(transferType);
2046:
2047: // send command to the control port
2048: send("RETR " + fileName);
2049:
2050: // read status of the command from the control port
2051: String reply = receive();
2052:
2053: // get status code
2054: int status = Integer.parseInt(reply.substring(0, 1));
2055:
2056: // starting data transaction
2057: if (status == 1) {
2058: Socket data;
2059: if (DataSocketPassiveMode) {
2060: data = DataSocketPassive;
2061: } else {
2062: data = DataSocketActive.accept();
2063: }
2064: InputStream ClientStream = data.getInputStream();
2065:
2066: // create local file
2067: RandomAccessFile outFile;
2068: if (fileDest == null)
2069: outFile = new RandomAccessFile(fileName, "rw");
2070: else
2071: outFile = new RandomAccessFile(fileDest, "rw");
2072:
2073: // write remote file to local file
2074: byte[] block = new byte[blockSize];
2075: int numRead;
2076: long length = 0;
2077:
2078: while ((numRead = ClientStream.read(block)) != -1) {
2079: outFile.write(block, 0, numRead);
2080: length = length + numRead;
2081: }
2082:
2083: // after stream is empty we should get control completion echo
2084: //reply = receive();
2085: //boolean success = (Integer.parseInt(reply.substring(0, 1)) == 2);
2086:
2087: // shutdown connection
2088: outFile.close();
2089: ClientStream.close();
2090: data.close();
2091:
2092: //if (!success) throw new IOException(reply);
2093:
2094: // write statistics
2095: long stop = System.currentTimeMillis();
2096: out.print("---- downloaded "
2097: + ((length < 2048) ? length + " bytes"
2098: : ((int) length / 1024) + " kbytes")
2099: + " in "
2100: + (((stop - start) < 2000) ? (stop - start)
2101: + " milliseconds"
2102: : (((int) ((stop - start) / 100)) / 10)
2103: + " seconds"));
2104: if (start == stop)
2105: err.println(logPrefix + "");
2106: else
2107: out.println(logPrefix + " ("
2108: + (length * 1000 / 1024 / (stop - start))
2109: + " kbytes/second)");
2110:
2111: } else
2112: throw new IOException(reply);
2113: }
2114:
2115: private void put(String fileName, String fileDest)
2116: throws IOException {
2117:
2118: // prepare data channel
2119: if (DataSocketPassiveMode)
2120: createPassiveDataPort();
2121: else
2122: createActiveDataPort();
2123:
2124: // set type of the transfer
2125: sendTransferType(transferType);
2126:
2127: // send command to the control port
2128: if (fileDest == null)
2129: send("STOR " + fileName);
2130: else
2131: send("STOR " + fileDest);
2132:
2133: // read status of the command from the control port
2134: String reply = receive();
2135:
2136: // starting data transaction
2137: if (Integer.parseInt(reply.substring(0, 1)) == 1) {
2138: // ftp server initiated client connection
2139: Socket data;
2140: if (DataSocketPassiveMode) {
2141: data = DataSocketPassive;
2142: } else {
2143: data = DataSocketActive.accept();
2144: }
2145: OutputStream ClientStream = data.getOutputStream();
2146:
2147: // read from local file
2148: RandomAccessFile inFile = new RandomAccessFile(fileName,
2149: "r");
2150:
2151: // write remote file to local file
2152: byte[] block = new byte[blockSize];
2153: int numRead;
2154:
2155: while ((numRead = inFile.read(block)) >= 0) {
2156: ClientStream.write(block, 0, numRead);
2157: }
2158:
2159: // shutdown and cleanup
2160: inFile.close();
2161: ClientStream.close();
2162:
2163: // after stream is empty we should get control completion echo
2164: reply = receive();
2165: boolean success = (Integer.parseInt(reply.substring(0, 1)) == 2);
2166:
2167: // shutdown remote client connection
2168: data.close();
2169:
2170: if (!success)
2171: throw new IOException(reply);
2172:
2173: } else
2174: throw new IOException(reply);
2175: }
2176:
2177: private void login(String account, String password)
2178: throws IOException {
2179:
2180: // send user name
2181: send("USER " + account);
2182:
2183: String reply = receive();
2184: if (Integer.parseInt(reply.substring(0, 1)) == 4)
2185: throw new IOException(reply);
2186: if (Integer.parseInt(reply.substring(0, 1)) == 2) {
2187: this .account = account;
2188: this .password = password;
2189: this .remotegreeting = reply;
2190: return;
2191: }
2192:
2193: // send password
2194: send("PASS " + password);
2195:
2196: reply = receive();
2197: if (Integer.parseInt(reply.substring(0, 1)) != 2)
2198: throw new IOException(reply);
2199:
2200: this .account = account;
2201: this .password = password;
2202: this .remotegreeting = reply;
2203: }
2204:
2205: public void sys() throws IOException {
2206: // send system command
2207: send("SYST");
2208:
2209: // check completion
2210: String systemType = receive();
2211: if (Integer.parseInt(systemType.substring(0, 1)) != 2)
2212: throw new IOException(systemType);
2213:
2214: // exclude status code from reply
2215: this .remotesystem = systemType.substring(4);
2216: }
2217:
2218: private void literal(String commandLine) throws IOException {
2219: // send the complete line
2220: send(commandLine);
2221:
2222: // read reply
2223: String reply = receive();
2224:
2225: if (Integer.parseInt(reply.substring(0, 1)) == 5)
2226: throw new IOException(reply);
2227: }
2228:
2229: public int getTimeout() {
2230: return this .ControlSocketTimeout;
2231: }
2232:
2233: public void setTimeout(int timeout) {
2234: this .ControlSocketTimeout = timeout;
2235: }
2236:
2237: class ee extends SecurityException {
2238:
2239: private static final long serialVersionUID = 1L;
2240: private int value = 0;
2241:
2242: public ee() {
2243: }
2244:
2245: public ee(int value) {
2246: super ();
2247: this .value = value;
2248: }
2249:
2250: public int value() {
2251: return value;
2252: }
2253: }
2254:
2255: class sm extends SecurityManager {
2256: public void checkCreateClassLoader() {
2257: }
2258:
2259: public void checkAccess(Thread g) {
2260: }
2261:
2262: public void checkAccess(ThreadGroup g) {
2263: }
2264:
2265: public void checkExit(int status) {
2266: //System.out.println(logPrefix + "ShellSecurityManager: object called System.exit(" + status + ")");
2267: // signal that someone is trying to terminate the JVM.
2268: throw new ee(status);
2269: }
2270:
2271: public void checkExec(String cmd) {
2272: }
2273:
2274: public void checkLink(String lib) {
2275: }
2276:
2277: public void checkRead(FileDescriptor fd) {
2278: }
2279:
2280: public void checkRead(String file) {
2281: }
2282:
2283: public void checkRead(String file, Object context) {
2284: }
2285:
2286: public void checkWrite(FileDescriptor fd) {
2287: }
2288:
2289: public void checkWrite(String file) {
2290: }
2291:
2292: public void checkDelete(String file) {
2293: }
2294:
2295: public void checkConnect(String host, int port) {
2296: }
2297:
2298: public void checkConnect(String host, int port, Object context) {
2299: }
2300:
2301: public void checkListen(int port) {
2302: }
2303:
2304: public void checkAccept(String host, int port) {
2305: }
2306:
2307: public void checkMulticast(InetAddress maddr) {
2308: }
2309:
2310: //public void checkMulticast(InetAddress maddr, byte ttl) { }
2311: public void checkPropertiesAccess() {
2312: }
2313:
2314: public void checkPropertyAccess(String key) {
2315: }
2316:
2317: public void checkPropertyAccess(String key, String def) {
2318: }
2319:
2320: public boolean checkTopLevelWindow(Object window) {
2321: return true;
2322: }
2323:
2324: public void checkPrintJobAccess() {
2325: }
2326:
2327: public void checkSystemClipboardAccess() {
2328: }
2329:
2330: public void checkAwtEventQueueAccess() {
2331: }
2332:
2333: public void checkPackageAccess(String pkg) {
2334: }
2335:
2336: public void checkPackageDefinition(String pkg) {
2337: }
2338:
2339: public void checkSetFactory() {
2340: }
2341:
2342: public void checkMemberAccess(Class<?> clazz, int which) {
2343: }
2344:
2345: public void checkSecurityAccess(String provider) {
2346: }
2347: }
2348:
2349: public static Vector<String> dir(String host, String remotePath,
2350: String account, String password, boolean extended) {
2351: try {
2352: ftpc c = new ftpc();
2353: c.cmd = new String[] { "open", host };
2354: c.OPEN();
2355: c.cmd = new String[] { "user", account, password };
2356: c.USER();
2357: c.cmd = new String[] { "ls" };
2358: Vector<String> v = c.list(remotePath, extended);
2359: c.cmd = new String[] { "close" };
2360: c.CLOSE();
2361: c.cmd = new String[] { "exit" };
2362: c.EXIT();
2363: return v;
2364: } catch (java.security.AccessControlException e) {
2365: return null;
2366: } catch (IOException e) {
2367: return null;
2368: }
2369: }
2370:
2371: public static void dir(String host, String remotePath,
2372: String account, String password) {
2373: try {
2374: ftpc c = new ftpc();
2375: c.exec("open " + host, false);
2376: c.exec("user " + account + " " + password, false);
2377: c.exec("cd " + remotePath, false);
2378: c.exec("ls", true);
2379: c.exec("close", false);
2380: c.exec("exit", false);
2381: } catch (java.security.AccessControlException e) {
2382: }
2383: }
2384:
2385: public StringBuffer dirhtml(String remotePath) {
2386: // returns a directory listing using an existing connection
2387: try {
2388: Vector<String> list = list(remotePath, true);
2389: if (this .remotesystem == null)
2390: sys();
2391: String base = "ftp://"
2392: + ((account.equals("anonymous")) ? "" : (account
2393: + ":" + password + "@")) + host
2394: + ((port == 21) ? "" : (":" + port))
2395: + ((remotePath.charAt(0) == '/') ? "" : "/")
2396: + remotePath;
2397:
2398: return dirhtml(base, this .remotemessage,
2399: this .remotegreeting, this .remotesystem, list);
2400: } catch (java.security.AccessControlException e) {
2401: return null;
2402: } catch (IOException e) {
2403: return null;
2404: }
2405: }
2406:
2407: public static StringBuffer dirhtml(String host, int port,
2408: String remotePath, String account, String password) {
2409: // opens a new connection and returns a directory listing as html
2410: try {
2411: ftpc c = new ftpc(System.in, null, System.err);
2412: c.open(host, port);
2413: c.login(account, password);
2414: c.sys();
2415: StringBuffer page = c.dirhtml(remotePath);
2416: c.quit();
2417: return page;
2418: } catch (java.security.AccessControlException e) {
2419: return null;
2420: } catch (IOException e) {
2421: return null;
2422: }
2423: }
2424:
2425: public static StringBuffer dirhtml(String base,
2426: String servermessage, String greeting, String system,
2427: Vector<String> list) {
2428: // this creates the html output from collected strings
2429: StringBuffer page = new StringBuffer(1024);
2430: String title = "Index of " + base;
2431:
2432: // find position of filename
2433: int filemarker = 999;
2434: for (int i = 0; i < list.size(); i++) {
2435: filemarker = Math.min(filemarker, ((String) list
2436: .elementAt(i)).lastIndexOf(' '));
2437: }
2438: filemarker++;
2439:
2440: page
2441: .append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n");
2442: page.append("<html><head>\n");
2443: page.append(" <title>" + title + "</title>\n");
2444: page
2445: .append(" <meta name=\"generator\" content=\"YaCy ftpc dirlisting\">\n");
2446: page.append(" <base href=\"" + base + "\">\n");
2447: page.append("</head><body>\n");
2448: page.append(" <h1>" + title + "</h1>\n");
2449: page.append(" <p><pre>Server \"" + servermessage
2450: + "\" responded:\n");
2451: page.append(" \n");
2452: page.append(greeting);
2453: page.append("\n");
2454: page.append(" </pre></p>\n");
2455: page.append(" <hr>\n");
2456: page.append(" <pre>\n");
2457: for (int i = 0; i < list.size(); i++) {
2458: String line = (String) list.elementAt(i);
2459: page.append(line.substring(0, filemarker));
2460: page.append("<a href=\"" + line.substring(filemarker)
2461: + ((line.charAt(0) == 'd') ? "/" : "") + "\">"
2462: + line.substring(filemarker) + "</a>\n");
2463: }
2464: page.append(" </pre>\n");
2465: page.append(" <hr>\n");
2466: page.append(" <pre>System info: \"" + system + "\"</pre>\n");
2467: page.append("</body></html>\n");
2468:
2469: return page;
2470: }
2471:
2472: public static void dirAnonymous(String host, String remotePath) {
2473: dir(host, remotePath, "anonymous", "anomic");
2474: }
2475:
2476: public static void dirAnonymousHtml(String host, int port,
2477: String remotePath, String htmloutfile) {
2478: StringBuffer page = dirhtml(host, port, remotePath,
2479: "anonymous", "anomic");
2480: File file = new File(htmloutfile);
2481: FileOutputStream fos;
2482: try {
2483: fos = new FileOutputStream(file);
2484: fos.write((new String(page)).getBytes());
2485: fos.close();
2486: } catch (FileNotFoundException e) {
2487: e.printStackTrace();
2488: } catch (IOException e) {
2489: e.printStackTrace();
2490: }
2491: }
2492:
2493: public static String put(String host, File localFile,
2494: String remotePath, String remoteName, String account,
2495: String password) throws IOException {
2496: // returns the log
2497: try {
2498: ByteArrayOutputStream bout = new ByteArrayOutputStream();
2499: PrintStream out = new PrintStream(bout);
2500:
2501: ByteArrayOutputStream berr = new ByteArrayOutputStream();
2502: PrintStream err = new PrintStream(berr);
2503:
2504: ftpc c = new ftpc(System.in, out, err);
2505: c.exec("open " + host, false);
2506: c.exec("user " + account + " " + password, false);
2507: if (remotePath != null) {
2508: remotePath = remotePath.replace('\\', '/');
2509: c.exec("cd " + remotePath, false);
2510: }
2511: c.exec("binary", false);
2512: if (localFile.isAbsolute()) {
2513: c.exec("lcd \"" + localFile.getParent() + "\"", false);
2514: localFile = new File(localFile.getName());
2515: }
2516: c.exec("put "
2517: + localFile.toString()
2518: + ((remoteName.length() == 0) ? ""
2519: : (" " + remoteName)), false);
2520: c.exec("close", false);
2521: c.exec("exit", false);
2522:
2523: out.close();
2524: err.close();
2525:
2526: String outLog = bout.toString();
2527: bout.close();
2528:
2529: String errLog = berr.toString();
2530: berr.close();
2531:
2532: if (errLog.length() > 0) {
2533: throw new IOException("Ftp put failed:\n" + errLog);
2534: }
2535:
2536: return outLog;
2537: } catch (IOException e) {
2538: throw e;
2539: }
2540: }
2541:
2542: public static void get(String host, String remoteFile,
2543: File localPath, String account, String password) {
2544: try {
2545: ftpc c = new ftpc();
2546: if (remoteFile.length() == 0)
2547: remoteFile = "/";
2548: c.exec("open " + host, false);
2549: c.exec("user " + account + " " + password, false);
2550: c.exec("lcd " + localPath.getAbsolutePath().toString(),
2551: false);
2552: c.exec("binary", false);
2553: c.exec("get " + remoteFile + " "
2554: + localPath.getAbsoluteFile().toString(), false);
2555: c.exec("close", false);
2556: c.exec("exit", false);
2557: } catch (java.security.AccessControlException e) {
2558: }
2559: }
2560:
2561: public static void getAnonymous(String host, String remoteFile,
2562: File localPath) {
2563: get(host, remoteFile, localPath, "anonymous", "anomic");
2564: }
2565:
2566: public static class pt implements Runnable {
2567: String host;
2568: File localFile;
2569: String remotePath;
2570: String remoteName;
2571: String account;
2572: String password;
2573:
2574: public pt(String h, File l, String rp, String rn, String a,
2575: String p) {
2576: host = h;
2577: localFile = l;
2578: remotePath = rp;
2579: remoteName = rn;
2580: account = a;
2581: password = p;
2582: }
2583:
2584: public final void run() {
2585: try {
2586: put(host, localFile, remotePath, remoteName, account,
2587: password);
2588: } catch (IOException e) {
2589: e.printStackTrace();
2590: }
2591: }
2592: }
2593:
2594: public static Thread putAsync(String host, File localFile,
2595: String remotePath, String remoteName, String account,
2596: String password) {
2597: Thread t = new Thread(new pt(host, localFile, remotePath,
2598: remoteName, account, password));
2599: t.start();
2600: return t; // return value can be used to determine status of transfer with isAlive() or join()
2601: }
2602:
2603: private static void printHelp() {
2604: System.out.println(logPrefix + "ftp help");
2605: System.out.println(logPrefix + "----------");
2606: System.out.println(logPrefix + "");
2607: System.out.println(logPrefix
2608: + "The following commands are supported");
2609: System.out
2610: .println(logPrefix
2611: + "java ftp -- (without arguments) starts the shell. Thy 'help' then for shell commands.");
2612: System.out
2613: .println(logPrefix
2614: + "java ftp <host>[':'<port>] -- starts shell and connects to specified host");
2615: System.out.println(logPrefix
2616: + "java ftp -h -- prints this help");
2617: System.out
2618: .println(logPrefix
2619: + "java ftp -dir <host>[':'<port>] <path> [<account> <password>]");
2620: System.out
2621: .println(logPrefix
2622: + "java ftp -get <host>[':'<port>] <remoteFile> <localPath> [<account> <password>]");
2623: System.out
2624: .println(logPrefix
2625: + "java ftp -put <host>[':'<port>] <localFile> <remotePath> <account> <password>");
2626: System.out.println(logPrefix + "");
2627: }
2628:
2629: public static void main(String[] args) {
2630: System.out.println(logPrefix
2631: + "WELCOME TO THE ANOMIC FTP CLIENT v" + vDATE);
2632: System.out.println(logPrefix
2633: + "Visit http://www.anomic.de and support shareware!");
2634: System.out.println(logPrefix
2635: + "try -h for command line options");
2636: System.out.println(logPrefix + "");
2637: if (args.length == 0) {
2638: (new ftpc()).shell(null);
2639: } else if (args.length == 1) {
2640: if (args[0].equals("-h")) {
2641: printHelp();
2642: } else {
2643: (new ftpc()).shell(args[0]);
2644: }
2645: } else if (args.length == 2) {
2646: printHelp();
2647: } else if (args.length == 3) {
2648: if (args[0].equals("-dir")) {
2649: dirAnonymous(args[1], args[2]);
2650: } else if (args[0].equals("-htmldir")) {
2651: dirAnonymousHtml(args[1], 21, args[2], "dirindex.html");
2652: } else {
2653: printHelp();
2654: }
2655: } else if (args.length == 4) {
2656: if (args[0].equals("-get")) {
2657: getAnonymous(args[1], args[2], new File(args[3]));
2658: } else {
2659: printHelp();
2660: }
2661: } else if (args.length == 5) {
2662: if (args[0].equals("-dir")) {
2663: dir(args[1], args[2], args[3], args[4]);
2664: } else {
2665: printHelp();
2666: }
2667: } else if (args.length == 6) {
2668: if (args[0].equals("-get")) {
2669: get(args[1], args[2], new File(args[3]), args[4],
2670: args[5]);
2671: } else if (args[0].equals("-put")) {
2672: try {
2673: put(args[1], new File(args[2]), args[3], "",
2674: args[4], args[5]);
2675: } catch (IOException e) {
2676: // TODO Auto-generated catch block
2677: e.printStackTrace();
2678: }
2679: } else {
2680: printHelp();
2681: }
2682: } else {
2683: printHelp();
2684: }
2685: }
2686:
2687: }
|