0001: /*
0002: * This program is free software; you can redistribute it and/or
0003: * modify it under the terms of the GNU General Public License
0004: * as published by the Free Software Foundation; either version 2
0005: * of the License, or (at your option) any later version.
0006: *
0007: * This program is distributed in the hope that it will be useful,
0008: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0009: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0010: * GNU General Public License for more details.
0011: *
0012: * You should have received a copy of the GNU General Public License
0013: * along with this program; if not, write to the Free Software
0014: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
0015: */
0016: package net.sf.jftp.net;
0017:
0018: //***now all config files are imported
0019: import java.io.BufferedReader;
0020: import java.io.DataInputStream;
0021: import java.io.File;
0022: import java.io.IOException;
0023: import java.io.InputStream;
0024: import java.io.OutputStream;
0025: import java.net.InetAddress;
0026: import java.net.ServerSocket;
0027: import java.net.UnknownHostException;
0028: import java.util.Date;
0029: import java.util.StringTokenizer;
0030: import java.util.Vector;
0031:
0032: import javax.swing.JLabel;
0033: import javax.swing.JOptionPane;
0034:
0035: import net.sf.jftp.config.LoadSet;
0036: import net.sf.jftp.config.SaveSet;
0037: import net.sf.jftp.config.Settings;
0038: import net.sf.jftp.system.StringUtils;
0039: import net.sf.jftp.system.logging.Log;
0040:
0041: /**
0042: * All control transactions are made here.
0043: * See doc/FtpDownload.java for examples and note
0044: * that this class is event-driven and not Exception-based!
0045: * You might want to take a look at ConnectionListener, too.
0046: *
0047: * @author David Hansmann, hansmann.d@debitel.net
0048: * @version 1.30+, June 2003
0049: */
0050: public class FtpConnection implements BasicConnection, FtpConstants {
0051: private static final boolean TESTMODE = false;
0052:
0053: // everything starting with this will be treated
0054: // as a negative response
0055: private final static String NEGATIVE = "5";
0056: private final static String NEGATIVE2 = "4";
0057:
0058: // everything starting with this will be treated
0059: // as a positive response
0060: private final static String POSITIVE = "2";
0061:
0062: // for resuming
0063: private final static String PROCEED = "3"; //"350";
0064: private final static char MORE_LINES_APPENDED = '-';
0065:
0066: /** Internal download constant */
0067: public final static String DOWNLOAD = "DOWNLOAD";
0068:
0069: /** Internal upload constant */
0070: public final static String UPLOAD = "UPLOAD";
0071:
0072: /** Internal abort command constant */
0073: public final static String ABOR = "ABOR";
0074:
0075: //*** 1.44: if LIST is not set, then load it from advanced settings
0076: //*** And if the file for it is not found, then create it
0077: //*** with LIST -laL as the default
0078: public static String LIST_DEFAULT = "LIST -laL";
0079: public static String LIST = "default";
0080: public final static String ASCII = "A";
0081: public final static String BINARY = "I";
0082: public final static String EBCDIC = "E";
0083: public final static String L8 = "L 8";
0084: public final static String STREAM = "S";
0085: public final static String BLOCKED = "B";
0086: public final static String COMPRESSED = "C";
0087: private static boolean useStream = true;
0088: private static boolean useBlocked = true;
0089: private static boolean useCompressed = true;
0090:
0091: // active ftp ports
0092: private static int porta = 5; // 5 * 256 + 1 = 1281
0093: private static int portb = 1;
0094:
0095: //***
0096:
0097: /**
0098: * Used to determine the type of transfer.
0099: */
0100: public boolean hasUploaded = false;
0101: public boolean work = true;
0102: private boolean msg = true;
0103: private boolean ok = true;
0104: private String pwd = "";
0105: private String initCWD = Settings.defaultDir;
0106: private String[] loginAck = new String[] {
0107: FTP331_USER_OK_NEED_PASSWORD, FTP230_LOGGED_IN };
0108: private String osType = "";
0109: private String dataType;
0110: private FtpTransfer lastTransfer = null;
0111: private boolean modeStreamSet = false;
0112: private DataConnection dcon = null;
0113: private Vector listeners = new Vector();
0114: private ConnectionHandler handler = new ConnectionHandler();
0115:
0116: // directory downloaded to
0117: private String localPath = null;
0118:
0119: /** the host */
0120: private String host = "";
0121:
0122: /** the user */
0123: private String username;
0124:
0125: /** the password */
0126: private String password;
0127:
0128: /** the port */
0129: private int port = 21;
0130:
0131: /** the InputStream of the control connection */
0132: private BufferedReader in;
0133:
0134: /** the OutputStream of the control connection */
0135: private JConnection jcon;
0136:
0137: /** we are disconnected */
0138: private boolean connected = false;
0139: private boolean shortProgress = false;
0140: private boolean isDirUpload = false;
0141: private String baseFile;
0142: private int fileCount;
0143: private String typeNow = "";
0144: private String crlf = null;
0145:
0146: /**
0147: * May contain date listing
0148: */
0149: public Vector dateVector = new Vector();
0150: public Vector currentListing = new Vector();
0151: public Vector currentFiles = new Vector();
0152: public Vector currentSizes = new Vector();
0153: public Vector currentPerms = new Vector();
0154:
0155: /**
0156: * Create an instance with a given host
0157: *
0158: * @param host The host to connect to
0159: */
0160: public FtpConnection(String host) {
0161: this .host = host;
0162:
0163: File f = new File(".");
0164: setLocalPath(f.getAbsolutePath());
0165: }
0166:
0167: /**
0168: * Create an instance with a given host, port and initial remote working directory
0169: *
0170: * @param host The host to connect to
0171: * @param port The port used for the control connection, usually 21
0172: * @param initCWD The initial remote working directory
0173: */
0174: public FtpConnection(String host, int port, String initCWD) {
0175: this .host = host;
0176: this .port = port;
0177: this .initCWD = initCWD;
0178:
0179: File f = new File(".");
0180: setLocalPath(f.getAbsolutePath());
0181: }
0182:
0183: /**
0184: * Connect to the server an log in.
0185: *
0186: * Does also fire directory update and connection initialized event if successful or
0187: * connection failed event if failed.
0188: *
0189: * @param username The username
0190: * @param password The password
0191: * @param initCWD The initial remote working directory
0192: * @param crlfx \n, \r, \r\n, CR, LF or CRLF - line break style of the server
0193: * @return WRONG_LOGIN_DATA, OFFLINE, GENERIC_FAILED or LOGIN_OK status code
0194: */
0195: public FtpConnection(String host, int port, String initCWD,
0196: String crlfx) {
0197: this .host = host;
0198: this .port = port;
0199: this .initCWD = initCWD;
0200:
0201: if (crlfx != null) {
0202: if (crlfx.equals("\n") || crlfx.equals("\r")
0203: || crlfx.equals("\r\n"))
0204: this .crlf = crlfx;
0205: crlfx = crlfx.trim().toUpperCase();
0206: if (crlfx.equals("LF"))
0207: this .crlf = "\n";
0208: else if (crlfx.equals("CR"))
0209: this .crlf = "\r";
0210: else if (crlfx.equals("CRLF"))
0211: this .crlf = "\r\n";
0212: }
0213: //Log.out("\n\nCRLF:---"+crlf+"---\n\n");
0214:
0215: File f = new File(".");
0216: setLocalPath(f.getAbsolutePath());
0217: }
0218:
0219: /**
0220: * Connect to the server an log in.
0221: *
0222: * Does also fire directory update and connection initialized event if successful or
0223: * connection failed event if failed.
0224: *
0225: * @param username The username
0226: * @param password The password
0227: * @return WRONG_LOGIN_DATA, OFFLINE, GENERIC_FAILED or LOGIN_OK status code
0228: */
0229: public int login(String username, String password) {
0230: this .username = username;
0231: this .password = password;
0232:
0233: int status = LOGIN_OK;
0234:
0235: if (msg) {
0236: Log.debug("Connecting to " + host);
0237: }
0238:
0239: jcon = new JConnection(host, port);
0240:
0241: if (jcon.isThere()) {
0242: in = jcon.getReader();
0243:
0244: if (getLine(POSITIVE) == null)//FTP220_SERVICE_READY) == null)
0245: {
0246: ok = false;
0247: Log
0248: .debug("Server closed Connection, maybe too many users...");
0249: status = OFFLINE;
0250: }
0251:
0252: if (msg) {
0253: Log.debug("Connection established...");
0254: }
0255:
0256: jcon.send(USER + " " + username);
0257:
0258: if (!getLine(loginAck).startsWith(POSITIVE))//FTP230_LOGGED_IN))
0259: {
0260: jcon.send(PASS + " " + password);
0261:
0262: if (success(POSITIVE))//FTP230_LOGGED_IN))
0263: {
0264: if (msg) {
0265: Log.debug("Logged in...");
0266: }
0267: } else {
0268: Log.debug("Wrong password!");
0269: ok = false;
0270: status = WRONG_LOGIN_DATA;
0271: }
0272: }
0273:
0274: // end if(jcon)...
0275: } else {
0276: if (msg) {
0277: Log.debug("FTP not available!");
0278: ok = false;
0279: status = GENERIC_FAILED;
0280: }
0281: }
0282:
0283: if (ok) {
0284: connected = true;
0285: system();
0286:
0287: //if(getOsType().indexOf("MVS") < 0)
0288: binary();
0289:
0290: if (initCWD.trim().equals(Settings.defaultDir)
0291: || !chdirNoRefresh(initCWD)) {
0292: //System.out.println("default dir...");
0293: //if(!chdirNoRefresh(getPWD()))
0294: //{
0295: //System.out.println("FtpConnection should not do this...");
0296: // if(!chdirNoRefresh("~"))
0297: // {
0298: // chdirNoRefresh("/");
0299: // }
0300: //}
0301: updatePWD();
0302: }
0303:
0304: //Array of length 6 created, as that is maximum LoadSet size (need
0305: //public variable with that constant there for it to refer to?)
0306: String[] advSettings = new String[6];
0307:
0308: if (getOsType().indexOf("OS/2") >= 0) {
0309: LIST_DEFAULT = "LIST";
0310: }
0311:
0312: if (LIST.equals("default")) {
0313: //just get the first item (somehow it knows first is the
0314: //FTP list command)
0315: advSettings = LoadSet.loadSet(Settings.adv_settings);
0316:
0317: //*** IF FILE NOT FOUND, CREATE IT AND SET IT TO LIST_DEFAULT
0318: if (advSettings == null) {
0319: LIST = LIST_DEFAULT;
0320:
0321: SaveSet s = new SaveSet(Settings.adv_settings, LIST);
0322: } else {
0323: LIST = advSettings[0];
0324:
0325: if (LIST == null) {
0326: LIST = LIST_DEFAULT;
0327: }
0328: }
0329: }
0330:
0331: if (getOsType().indexOf("MVS") >= 0) {
0332: LIST = "LIST";
0333: }
0334:
0335: //***
0336: fireDirectoryUpdate(this );
0337: fireConnectionInitialized(this );
0338: } else {
0339: fireConnectionFailed(this , new Integer(status).toString());
0340: }
0341:
0342: return status;
0343: }
0344:
0345: /**
0346: * Sort the filesizes an return an array.
0347: *
0348: * The Array should be in sync with the other sort*-Methods
0349: *
0350: * @return An String-array of sizes containing the size or -1 if failed or 0 for directories
0351: */
0352: public String[] sortSize() {
0353: try {
0354: currentSizes.removeAllElements();
0355:
0356: for (int i = 0; i < currentListing.size(); i++) {
0357: String tmp = (String) currentListing.get(i);
0358:
0359: // ------------- VMS override -------------------
0360: if (getOsType().indexOf("VMS") >= 0) {
0361: if (tmp.indexOf(";") < 0) {
0362: continue;
0363: }
0364:
0365: currentSizes.add("-1");
0366:
0367: continue;
0368: }
0369:
0370: // ------------- MVS override -------------------
0371: if (getOsType().indexOf("MVS") >= 0) {
0372: if (tmp.startsWith("Volume")
0373: || (tmp.indexOf(" ") < 0)) {
0374: continue;
0375: }
0376:
0377: currentSizes.add("-1");
0378:
0379: continue;
0380: }
0381:
0382: // ------------------------------------------------
0383: else if (getOsType().indexOf("WINDOW") >= 0) {
0384: StringTokenizer to = new StringTokenizer(tmp, " ",
0385: false);
0386:
0387: if (to.countTokens() >= 4) {
0388: to.nextToken();
0389: to.nextToken();
0390:
0391: String size = to.nextToken();
0392:
0393: if (size.equals("<DIR>")) {
0394: currentSizes.add("0");
0395: } else {
0396: try {
0397: Long.parseLong(size);
0398: currentSizes.add(size);
0399: } catch (Exception ex) {
0400: currentSizes.add("-1");
0401: Log
0402: .out("WARNING: filesize can not be determined - value is "
0403: + size);
0404: }
0405: }
0406: }
0407: }
0408:
0409: // ------------------------------------------------
0410: else if (getOsType().indexOf("OS/2") >= 0) {
0411: StringTokenizer to = new StringTokenizer(tmp, " ",
0412: false);
0413: tmp = giveSize(to, 0);
0414: Log.out("OS/2 parser (size): " + tmp);
0415: currentSizes.add(tmp);
0416: } else {
0417: //Log.out("\n\nparser\n\n");
0418: StringTokenizer to = new StringTokenizer(tmp, " ",
0419: false);
0420:
0421: if (to.countTokens() >= 8) // unix
0422: {
0423: tmp = giveSize(to, 4);
0424: currentSizes.add(tmp);
0425:
0426: //Log.out(tmp);
0427: } else if (to.countTokens() == 7) // unix, too
0428: {
0429: Log
0430: .out("WARNING: 7 token backup size parser activated!");
0431: tmp = giveSize(to, 4);
0432: currentSizes.add(tmp);
0433: } else {
0434: Log.debug("cannot parse line: " + tmp);
0435: }
0436: }
0437: }
0438: } catch (Exception ex) {
0439: Log.debug(ex.toString() + " @FtpConnection::sortSize#1");
0440: return new String[0];
0441: }
0442:
0443: return toArray(currentSizes);
0444: }
0445:
0446: private String[] toArray(Vector in) {
0447: String ret[] = new String[in.size()];
0448:
0449: for (int i = 0; i < in.size(); i++) {
0450: ret[i] = (String) in.get(i);
0451: }
0452:
0453: return ret;
0454: }
0455:
0456: /**
0457: * Sort the permissions an return an array.
0458: *
0459: * The Array should be in sync with the other sort*-Methods
0460: *
0461: * @param file The file containing the raw server listing, usually Settings.ls_out
0462: * @return An int-array of sizes containing W, R or DENIED for each file
0463: */
0464: public int[] getPermissions() {
0465: try {
0466: currentPerms.removeAllElements();
0467:
0468: for (int i = 0; i < currentListing.size(); i++) {
0469: String tmp = (String) currentListing.get(i);
0470:
0471: // ------------- VMS override -------------------
0472: if (getOsType().indexOf("VMS") >= 0) {
0473: if (tmp.indexOf(";") < 0) {
0474: continue;
0475: }
0476:
0477: currentPerms.add("r");
0478:
0479: continue;
0480: }
0481:
0482: // ------------- MVS override -------------------
0483: if (getOsType().indexOf("MVS") >= 0) {
0484: if (tmp.startsWith("Volume")) {
0485: continue;
0486: }
0487:
0488: currentPerms.add("r");
0489:
0490: continue;
0491: }
0492:
0493: // ------------------------------------------------
0494:
0495: StringTokenizer to = new StringTokenizer(tmp.trim(),
0496: " ", false);
0497:
0498: if (!(to.countTokens() > 3)
0499: || (tmp.startsWith("/") && (tmp
0500: .indexOf("denied") > 0))) {
0501: continue;
0502: }
0503:
0504: tmp = to.nextToken();
0505:
0506: if (tmp.length() != 10) {
0507: //System.out.println(tmp + " - e");
0508: return null; // exotic bug, hardlinks are not found or something ("/bin/ls: dir: no such file or directy" in ls output) - we have no permissions then
0509: }
0510:
0511: char ur = tmp.charAt(1);
0512: char uw = tmp.charAt(2);
0513: char ar = tmp.charAt(7);
0514: char aw = tmp.charAt(8);
0515:
0516: to.nextToken();
0517:
0518: String user = to.nextToken();
0519:
0520: //System.out.println(""+ur+":"+ar+":"+tmp);
0521: if (aw == 'w') {
0522: currentPerms.add("w");
0523: } else if (user.equals(username) && (uw == 'w')) {
0524: currentPerms.add("w");
0525: } else if (ar == 'r') {
0526: currentPerms.add("r");
0527: } else if (user.equals(username) && (ur == 'r')) {
0528: currentPerms.add("r");
0529: } else {
0530: //System.out.println(ur+":"+ar+":"+user+":"+username+":");
0531: currentPerms.add("n");
0532: }
0533: }
0534: } catch (Exception ex) {
0535: Log.debug(ex.toString()
0536: + " @FtpConnection::getPermissions#1");
0537: }
0538:
0539: int[] ret = new int[currentPerms.size()];
0540:
0541: for (int i = 0; i < currentPerms.size(); i++) {
0542: String fx = (String) currentPerms.get(i);
0543:
0544: if (fx.equals("w")) {
0545: ret[i] = W;
0546: } else if (fx.equals("n")) {
0547: ret[i] = DENIED;
0548: } else {
0549: ret[i] = R;
0550: }
0551: //System.out.println(ret[i]);
0552: }
0553:
0554: return ret;
0555: }
0556:
0557: /**
0558: * Sort the filenames of the current working dir an return an array.
0559: *
0560: * The Array should be in sync with the other sort*-Methods
0561: *
0562: * @return An String-array of sizes containing the name of the file (symlinks are resolved)
0563: */
0564: public String[] sortLs() {
0565: try {
0566: boolean newUnixDateStyle = false;
0567: dateVector = new Vector();
0568: currentFiles.removeAllElements();
0569:
0570: for (int i = 0; i < currentListing.size(); i++) {
0571: String tmp = (String) currentListing.get(i);
0572:
0573: // ------------------- VMS override --------------------
0574: if (getOsType().indexOf("VMS") >= 0) {
0575: int x = tmp.indexOf(";");
0576:
0577: if (x < 0) {
0578: continue;
0579: }
0580:
0581: tmp = tmp.substring(0, x);
0582:
0583: if (tmp.endsWith("DIR")) {
0584: currentFiles.add(tmp.substring(0, tmp
0585: .lastIndexOf("."))
0586: + "/");
0587: } else {
0588: currentFiles.add(tmp);
0589: }
0590:
0591: //Log.out("listing - (vms parser): " + tmp);
0592:
0593: continue;
0594: } else if (getOsType().indexOf("OS/2") >= 0) {
0595: StringTokenizer to2 = new StringTokenizer(tmp, " ",
0596: true);
0597:
0598: if (giveFile(to2, 2).indexOf("DIR") >= 0) {
0599: to2 = new StringTokenizer(tmp, " ", true);
0600: tmp = giveFile(to2, 5);
0601: tmp = tmp + "/";
0602: } else {
0603: to2 = new StringTokenizer(tmp, " ", true);
0604:
0605: if (giveFile(to2, 1).indexOf("DIR") >= 0) {
0606: //Log.out("OS/2 parser (DIRFIX): " + tmp);
0607: to2 = new StringTokenizer(tmp, " ", true);
0608: tmp = giveFile(to2, 4);
0609: tmp = tmp + "/";
0610: } else {
0611: to2 = new StringTokenizer(tmp, " ", true);
0612: tmp = giveFile(to2, 4);
0613: }
0614: }
0615:
0616: Log.out("OS/2 parser: " + tmp);
0617: currentFiles.add(tmp);
0618:
0619: continue;
0620: }
0621:
0622: // -------------------------------------------------------
0623: // ------------------- MVS override --------------------
0624: if (getOsType().indexOf("MVS") >= 0) {
0625: if (tmp.startsWith("Volume")
0626: || (tmp.indexOf(" ") < 0)) {
0627: Log.out("->" + tmp);
0628:
0629: continue;
0630: }
0631:
0632: String f = tmp.substring(tmp.lastIndexOf(" "))
0633: .trim();
0634: String isDir = tmp.substring(
0635: tmp.lastIndexOf(" ") - 5, tmp
0636: .lastIndexOf(" "));
0637:
0638: if (isDir.indexOf("PO") >= 0) {
0639: currentFiles.add(f + "/");
0640: } else {
0641: currentFiles.add(f);
0642: }
0643:
0644: Log.out("listing - (mvs parser): " + tmp + " -> "
0645: + f);
0646: continue;
0647: } else if (getOsType().indexOf("OS/2") >= 0) {
0648: StringTokenizer to2 = new StringTokenizer(tmp, " ",
0649: true);
0650:
0651: if (giveFile(to2, 2).indexOf("DIR") >= 0) {
0652: to2 = new StringTokenizer(tmp, " ", true);
0653: tmp = giveFile(to2, 5);
0654: tmp = tmp + "/";
0655: } else {
0656: to2 = new StringTokenizer(tmp, " ", true);
0657:
0658: if (giveFile(to2, 1).indexOf("DIR") >= 0) {
0659: //Log.out("OS/2 parser (DIRFIX): " + tmp);
0660: to2 = new StringTokenizer(tmp, " ", true);
0661: tmp = giveFile(to2, 4);
0662: tmp = tmp + "/";
0663: } else {
0664: to2 = new StringTokenizer(tmp, " ", true);
0665: tmp = giveFile(to2, 4);
0666: }
0667: }
0668:
0669: Log.out("OS/2 parser: " + tmp);
0670: currentFiles.add(tmp);
0671:
0672: continue;
0673: }
0674:
0675: // -------------------------------------------------------
0676: // ------------------- Unix, Windows and others -----
0677: boolean isDir = false;
0678: boolean isLink = false;
0679:
0680: if (tmp.startsWith("d") || (tmp.indexOf("<DIR>") >= 0)) {
0681: isDir = true;
0682: }
0683:
0684: if (tmp.startsWith("l")) {
0685: isLink = true;
0686: }
0687:
0688: if (tmp.startsWith("/") && (tmp.indexOf("denied") > 0)) {
0689: continue;
0690: }
0691:
0692: StringTokenizer to = new StringTokenizer(tmp, " ",
0693: false);
0694: StringTokenizer to2 = new StringTokenizer(tmp, " ",
0695: true);
0696:
0697: int tokens = to.countTokens();
0698:
0699: //Log.out("listing: tokens: " + tokens + " - " + tmp);
0700: boolean set = false;
0701:
0702: //-----preparsing-----
0703: int lcount = 0;
0704:
0705: if (!newUnixDateStyle) {
0706: try {
0707: StringTokenizer tx = new StringTokenizer(tmp,
0708: " ", false);
0709: tx.nextToken();
0710: tx.nextToken();
0711: tx.nextToken();
0712: tx.nextToken();
0713: tx.nextToken();
0714:
0715: String date = tx.nextToken();
0716: int x = date.indexOf("-");
0717: int y = date.lastIndexOf("-");
0718:
0719: if (y > x) {
0720: Log.debug("Using new Unix date parser");
0721: newUnixDateStyle = true;
0722: }
0723: } catch (Exception ex) {
0724: Log.out("could not preparse line: " + tmp);
0725: lcount++;
0726:
0727: //ex.printStackTrace();
0728: }
0729: }
0730:
0731: //--------------------
0732: //Log.out("tmp: " + tmp);
0733: if (newUnixDateStyle) // unix, too
0734: {
0735: set = true;
0736:
0737: //Log.out("listing - (unix parser #2, token 7): " + tmp);
0738: //------- date parser testing ---------
0739: try {
0740: //Log.out(">>> date parser: " + tmp);
0741: StringTokenizer to3 = new StringTokenizer(tmp,
0742: " ", true);
0743: String date = giveFile(to3, 5);
0744: String date2 = date
0745: .substring(date.indexOf("-") + 1);
0746: date2 = date2.substring(date.indexOf("-") + 2);
0747:
0748: //Log.out("date1: "+date+"/"+"date2: "+date2);
0749: String t = date;
0750: String y = t.substring(0, t.indexOf("-"));
0751: String m = t.substring(t.indexOf("-") + 1, t
0752: .indexOf("-") + 3);
0753: String m1 = t.substring(t.indexOf("-") + 1);
0754: String day = m1.substring(m1.indexOf("-") + 1,
0755: m1.indexOf("-") + 3);
0756: String h = date2.substring(0, date2
0757: .indexOf(":"));
0758: String min = date2.substring(
0759: date2.indexOf(":") + 1, date2
0760: .indexOf(":") + 3);
0761:
0762: //Log.out("day:"+day+"year:"+y+"mon:"+m+"hour:"+h+"m:"+min);
0763: Date d = new Date();
0764: d.setDate(Integer.parseInt(day));
0765: d.setYear(Integer.parseInt(y));
0766: d.setMonth(Integer.parseInt(m) - 1);
0767: d.setHours(Integer.parseInt(h));
0768: d.setMinutes(Integer.parseInt(min));
0769:
0770: dateVector.add(d);
0771:
0772: //Log.out("+++ date: \"" + d.toString() + "\"");
0773: } catch (Exception ex) {
0774: ex.printStackTrace();
0775:
0776: //set = false;
0777: }
0778:
0779: // -----------------------------
0780: tmp = giveFile(to2, 7);
0781:
0782: if (lcount > 1) {
0783: dateVector = new Vector();
0784: }
0785: } else if (tokens > 8) // unix
0786: {
0787: set = true;
0788: tmp = giveFile(to2, 8);
0789:
0790: //Log.out("listing - (unix parser, token 8): " + tmp);
0791: } else if (tokens > 3) // windows
0792: {
0793: set = true;
0794: tmp = giveFile(to2, 3);
0795:
0796: if (tmp.startsWith("<error>")) {
0797: tmp = giveFile(to2, 4);
0798:
0799: //Log.out("listing - (windows parser, token 4): " + tmp);
0800: } else {
0801: //Log.out("listing - (windows parser, token 3): " + tmp);
0802: }
0803: }
0804:
0805: if (tmp.startsWith("<error>") || !set) {
0806: if (tokens < 3) {
0807: continue;
0808: }
0809:
0810: tmp = giveFile(to2, tokens);
0811: Log
0812: .out("listing - WARNING: listing style unknown, using last token as filename!");
0813: Log
0814: .out("listing - this may work but may also fail, filesizes and permissions will probably fail, too...");
0815: Log
0816: .out("listing - please send us a feature request with the serveraddress to let us support this listing style :)");
0817: Log.out("listing - (backup parser, token " + tokens
0818: + " ): " + tmp);
0819: }
0820:
0821: if (isDir) {
0822: tmp = tmp + "/";
0823: } else if (isLink) {
0824: tmp = tmp + "###";
0825: }
0826:
0827: currentFiles.add(tmp);
0828: // -------------------------------------------------------------
0829: }
0830:
0831: String[] files = toArray(currentFiles);
0832:
0833: for (int i = 0; i < files.length; i++) {
0834: files[i] = parseSymlink(files[i]);
0835:
0836: //System.out.println("> " + files[i]+":"+dateVector.elementAt(i));
0837: //System.out.println("> " + files.length+":"+dateVector.size());
0838: }
0839:
0840: return files;
0841: } catch (Exception ex) {
0842: Log.debug(ex.toString() + " @FtpConnection::sortLs");
0843: ex.printStackTrace();
0844: }
0845:
0846: //------- date parser test ------
0847:
0848: /*
0849: String[] x = (String[]) dateVector.toArray();
0850: for(int i=0; i<x.length; i++)
0851: {
0852: Log.out(":"+x[i]);
0853: }
0854: */
0855:
0856: //-------------------------------
0857: return new String[0];
0858: }
0859:
0860: /** get a filename */
0861: private String giveFile(StringTokenizer to, int lev) {
0862: String t2 = null;
0863:
0864: for (int i = 0; i < lev; i++) {
0865: if (to.hasMoreTokens()) {
0866: String t = to.nextToken();
0867:
0868: //Log.out("> "+t);
0869: if (t.equals(" ") || t.equals("\t")) {
0870: // -
0871:
0872: /*
0873: while(to.hasMoreTokens())
0874: {
0875: t2 = to.nextToken();
0876: if(!t.equals(" ") && !t.equals("\t")) break;
0877: }
0878: */
0879: i--;
0880: }
0881: }
0882: }
0883:
0884: String tmp = "<error>";
0885:
0886: /*
0887: if(t2 != null)
0888: {
0889: tmp = t2;
0890: }
0891: */
0892: while (tmp.equals(" ") || tmp.equals("\t")
0893: || tmp.equals("<error>")) {
0894: if (to.hasMoreTokens()) {
0895: tmp = to.nextToken();
0896: } else {
0897: break;
0898: }
0899: }
0900:
0901: while (to.hasMoreTokens()) {
0902: tmp = tmp + to.nextToken();
0903: }
0904:
0905: //Log.out(">>> "+tmp);
0906: return tmp;
0907: }
0908:
0909: /** get a filesize */
0910: private String giveSize(StringTokenizer to, int lev) {
0911: for (int i = 0; i < lev; i++) {
0912: if (to.hasMoreTokens()) {
0913: if (to.nextToken().equals(" ")) {
0914: i--;
0915: }
0916: }
0917: }
0918:
0919: while (to.hasMoreTokens()) {
0920: String tmp = to.nextToken();
0921:
0922: if (!tmp.equals(" ")) {
0923: try {
0924: Integer.parseInt(tmp);
0925: } catch (NumberFormatException ex) {
0926: return "-1";
0927: }
0928:
0929: return tmp;
0930: }
0931: }
0932:
0933: return "-2";
0934: }
0935:
0936: /**
0937: * Try to determine the os-type.
0938: * (Used internally to check how to parse the ls-output)
0939: *
0940: * @return A Part of the SYST comman server response
0941: */
0942: public String getOsType() {
0943: if (TESTMODE) {
0944: return "MVS";
0945: } else {
0946: return osType;
0947: }
0948: }
0949:
0950: private void setOsType(String os) {
0951: osType = os.toUpperCase();
0952: }
0953:
0954: private int getPasvPort(String str) {
0955: int start = str.lastIndexOf(",");
0956: String lo = "";
0957: start++;
0958:
0959: while (start < str.length()) {
0960: char c = str.charAt(start);
0961:
0962: if (!Character.isDigit(c)) {
0963: break;
0964: }
0965:
0966: lo = lo + c;
0967: start++;
0968: }
0969:
0970: System.out.println("\n\n\n" + str);
0971:
0972: String hi = "";
0973: start = str.lastIndexOf(",");
0974: start--;
0975:
0976: while (true) {
0977: char c = str.charAt(start);
0978:
0979: if (!Character.isDigit(c)) {
0980: break;
0981: }
0982:
0983: hi = c + hi;
0984: start--;
0985: }
0986:
0987: //System.out.print(hi+":"+lo+" - ");
0988: return ((Integer.parseInt(hi) * 256) + Integer.parseInt(lo));
0989: }
0990:
0991: private int getActivePort() {
0992: return (getPortA() * 256) + getPortB();
0993: }
0994:
0995: /** parse a symlink */
0996: private String parseSymlink(String file) {
0997: if (file.indexOf("->") >= 0) {
0998: //System.out.print(file+" :-> symlink converted to:");
0999: file = file.substring(0, file.indexOf("->")).trim();
1000: file = file + "###";
1001:
1002: //System.out.println(file);
1003: }
1004:
1005: return file;
1006: }
1007:
1008: /** parse a symlink and cut the back */
1009: private String parseSymlinkBack(String file) {
1010: if (file.indexOf("->") >= 0) {
1011: //System.out.print(file+" :-> symlink converted to:");
1012: file = file.substring(file.indexOf("->") + 2).trim();
1013:
1014: //System.out.println(file);
1015: }
1016:
1017: return file;
1018: }
1019:
1020: /** test for symlink */
1021: private boolean isSymlink(String file) {
1022: if (file.indexOf("->") >= 0) {
1023: return true;
1024: }
1025:
1026: return false;
1027: }
1028:
1029: /** Download a file or directory.
1030: * Uses multithreading if enabled and does not block.
1031: *
1032: * @param file The file to download
1033: * @return An int-statuscode, see constants defined in this class for details
1034: */
1035: public int handleDownload(String file) {
1036: if (Settings.getEnableMultiThreading()) {
1037: Log.out("spawning new thread for this download.");
1038:
1039: FtpTransfer t = new FtpTransfer(host, port, getLocalPath(),
1040: getCachedPWD(), file, username, password,
1041: Transfer.DOWNLOAD, handler, listeners, crlf);
1042: lastTransfer = t;
1043:
1044: return NEW_TRANSFER_SPAWNED;
1045: } else {
1046: Log.out("multithreading is completely disabled.");
1047:
1048: return download(file);
1049: }
1050: }
1051:
1052: /**
1053: * Download a file or directory, block until finished.
1054: *
1055: * @param file The file to download
1056: * @return An int returncode
1057: */
1058: public int download(String file) {
1059: //Log.out("ftp download started:" + this);
1060:
1061: int stat;
1062:
1063: if (file.endsWith("/")) {
1064: shortProgress = true;
1065: fileCount = 0;
1066: baseFile = file;
1067: dataType = DataConnection.GETDIR;
1068:
1069: stat = downloadDir(file);
1070:
1071: //pause(100);
1072: fireActionFinished(this );
1073: fireProgressUpdate(baseFile, DataConnection.DFINISHED + ":"
1074: + fileCount, -1);
1075: shortProgress = false;
1076: } else {
1077: dataType = DataConnection.GET;
1078:
1079: stat = rawDownload(file);
1080:
1081: if (Settings.enableFtpDelays) {
1082: try {
1083: Thread.sleep(100);
1084: } catch (Exception ex) {
1085: }
1086: }
1087:
1088: fireActionFinished(this );
1089: }
1090:
1091: if (Settings.enableFtpDelays) {
1092: try {
1093: Thread.sleep(400);
1094: } catch (Exception ex) {
1095: }
1096: }
1097:
1098: return stat;
1099: }
1100:
1101: /**
1102: * Get download InputStream.
1103: *
1104: * @param file The file to download
1105: * @return An InputStream
1106: */
1107: public InputStream getDownloadInputStream(String file) {
1108: Log.out("ftp stream download started:" + this );
1109: file = parse(file);
1110:
1111: try {
1112: int p = 0;
1113: dataType = DataConnection.GET;
1114: file = StringUtils.getFile(file);
1115:
1116: String path = getLocalPath() + file;
1117:
1118: BufferedReader in = jcon.getReader();
1119:
1120: modeStream();
1121: p = negotiatePort();
1122:
1123: dcon = new DataConnection(this , p, host, path, dataType,
1124: false, true);
1125:
1126: while (!dcon.isThere()) {
1127: pause(10);
1128: }
1129:
1130: jcon.send(RETR + " " + file);
1131:
1132: return dcon.getInputStream();
1133: } catch (Exception ex) {
1134: ex.printStackTrace();
1135: Log.debug(ex.toString()
1136: + " @FtpConnection::getDownloadInputStream");
1137:
1138: return null;
1139: }
1140: }
1141:
1142: private int rawDownload(String file) {
1143: file = parse(file);
1144:
1145: //String path = file;
1146: try {
1147: int p = 0;
1148:
1149: //if(isRelative(file)) path = getLocalPath() + file;
1150: file = StringUtils.getFile(file);
1151:
1152: String path = getLocalPath() + file;
1153:
1154: //System.out.println(file + " : " + path);
1155: //BufferedReader in = jcon.getReader();
1156: modeStream();
1157:
1158: //binary();
1159: p = negotiatePort();
1160:
1161: File f = new File(path);
1162:
1163: //System.out.println("path: "+path);
1164: boolean resume = false;
1165:
1166: if (f.exists() && Settings.enableResuming) {
1167: jcon.send(REST + " " + f.length());
1168:
1169: if (getLine(PROCEED) != null) {
1170: resume = true;
1171: }
1172: }
1173:
1174: dcon = new DataConnection(this , p, host, path, dataType,
1175: resume); //, new Updater());
1176:
1177: while (!dcon.isThere()) {
1178: pause(10);
1179: }
1180:
1181: jcon.send(RETR + " " + file);
1182:
1183: String line = getLine(POSITIVE);
1184: Log.debug(line);
1185:
1186: // file has been created even if not downloaded, delete it
1187: if (line.startsWith(NEGATIVE)) {
1188: File f2 = new File(path);
1189:
1190: if (f2.exists() && (f2.length() == 0)) {
1191: f2.delete();
1192: }
1193:
1194: return PERMISSION_DENIED;
1195: } else if (!line.startsWith(POSITIVE)
1196: && !line.startsWith(PROCEED)) {
1197: return TRANSFER_FAILED;
1198: }
1199:
1200: // we need to block since some ftp-servers do not want the
1201: // refresh command that dirpanel sends otherwise
1202: while (!dcon.finished) {
1203: pause(10);
1204: }
1205: } catch (Exception ex) {
1206: ex.printStackTrace();
1207: Log.debug(ex.toString() + " @FtpConnection::download");
1208:
1209: return TRANSFER_FAILED;
1210: }
1211:
1212: return TRANSFER_SUCCESSFUL;
1213: }
1214:
1215: private int downloadDir(String dir) {
1216: if (!dir.endsWith("/")) {
1217: dir = dir + "/";
1218: }
1219:
1220: if (StringUtils.isRelative(dir)) {
1221: dir = getCachedPWD() + dir;
1222: }
1223:
1224: String path = getLocalPath() + StringUtils.getDir(dir);
1225:
1226: //System.out.println("path: "+path);
1227: String pwd = getCachedPWD() + StringUtils.getDir(dir);
1228:
1229: String oldDir = getLocalPath();
1230: String oldPwd = getCachedPWD();
1231:
1232: File f = new File(path);
1233:
1234: if (!f.exists()) {
1235: if (!f.mkdir()) {
1236: Log.debug("Can't create directory: " + dir);
1237: } else {
1238: Log.debug("Created directory...");
1239: }
1240: }
1241:
1242: setLocalPath(path);
1243:
1244: if (!chdirNoRefresh(pwd)) {
1245: return CHDIR_FAILED;
1246: }
1247:
1248: try {
1249: list();
1250: } catch (IOException ex) {
1251: return PERMISSION_DENIED;
1252: }
1253:
1254: String[] tmp = sortLs();
1255:
1256: setLocalPath(path);
1257:
1258: for (int i = 0; i < tmp.length; i++) {
1259: if (tmp[i].endsWith("/")) {
1260: if (tmp[i].trim().equals("../")
1261: || tmp[i].trim().equals("./")) {
1262: Log.debug("Skipping " + tmp[i].trim());
1263: } else {
1264: if (!work) {
1265: return TRANSFER_STOPPED;
1266: }
1267:
1268: if (downloadDir(tmp[i]) < 0) {
1269: ; // return TRANSFER_FAILED;
1270: }
1271: }
1272: } else {
1273: //System.out.println( "file: " + getLocalPath() + tmp[i] + "\n\n");
1274: if (!work) {
1275: return TRANSFER_STOPPED;
1276: }
1277:
1278: fileCount++;
1279:
1280: if (rawDownload(getLocalPath() + tmp[i]) < 0) {
1281: ; // return TRANSFER_FAILED;
1282: }
1283: }
1284: }
1285:
1286: chdirNoRefresh(oldPwd);
1287: setLocalPath(oldDir);
1288:
1289: return TRANSFER_SUCCESSFUL;
1290: }
1291:
1292: /** Upload a file or directory.
1293: * Uses multithreading if enabled and does not block.
1294: *
1295: * @param file The file to upload
1296: * @return An int-statuscode, NEW_TRANSFER_SPAWNED,TRANSFER_FAILED or TRANSFER_SUCCESSFUL
1297: */
1298: public int handleUpload(String file) {
1299: return handleUpload(file, null);
1300: }
1301:
1302: /** Upload a file or directory.
1303: * Uses multithreading if enabled and does not block.
1304: *
1305: * @param file The file to upload
1306: * @param realName The file to rename the uploaded file to
1307: * @return An int-statuscode, NEW_TRANSFER_SPAWNED,TRANSFER_FAILED or TRANSFER_SUCCESSFUL
1308: */
1309: public int handleUpload(String file, String realName) {
1310: if (Settings.getEnableMultiThreading()
1311: && (!Settings.getNoUploadMultiThreading())) {
1312: Log.out("spawning new thread for this upload.");
1313:
1314: FtpTransfer t;
1315:
1316: if (realName != null) {
1317: t = new FtpTransfer(host, port, getLocalPath(),
1318: getCachedPWD(), file, username, password,
1319: Transfer.UPLOAD, handler, listeners, realName,
1320: crlf);
1321: } else {
1322: t = new FtpTransfer(host, port, getLocalPath(),
1323: getCachedPWD(), file, username, password,
1324: Transfer.UPLOAD, handler, listeners, crlf);
1325: }
1326:
1327: lastTransfer = t;
1328:
1329: return NEW_TRANSFER_SPAWNED;
1330: } else {
1331: if (Settings.getNoUploadMultiThreading()) {
1332: Log.out("upload multithreading is disabled.");
1333: } else {
1334: Log.out("multithreading is completely disabled.");
1335: }
1336:
1337: return (realName == null) ? upload(file) : upload(file,
1338: realName);
1339: }
1340: }
1341:
1342: /**
1343: * Upload a file or directory, block until finished.
1344: *
1345: * @param file The file to upload
1346: * @return An int returncode
1347: */
1348: public int upload(String file) {
1349: return upload(file, file);
1350: }
1351:
1352: /**
1353: * Upload and a file or directory under a given name, block until finished.
1354: * Note that setting realName does not affect directory transfers
1355: *
1356: * @param file The file to upload
1357: * @param realName The file to rename the uploaded file to
1358: * @return An int responsecode
1359: */
1360: public int upload(String file, String realName) {
1361: return upload(file, realName, null);
1362: }
1363:
1364: /**
1365: * Upload from an InputStream, block until finished.
1366: *
1367: * @param file The file to upload
1368: * @param in InputStream to read from
1369: * @return An int responsecode
1370: */
1371: public int upload(String file, InputStream in) {
1372: return upload(file, file, in);
1373: }
1374:
1375: /**
1376: * Upload and a file or directory under a given name, block until finished.
1377: * Note that setting realName does not affect directory transfers
1378: *
1379: * @param file The file to upload
1380: * @param realName The file to rename the uploaded file to
1381: * @param in InputStream to read from
1382: * @return An int responsecode
1383: */
1384: public int upload(String file, String realName, InputStream in) {
1385: hasUploaded = true;
1386: Log.out("ftp upload started: " + this );
1387:
1388: int stat;
1389:
1390: if ((in == null) && new File(file).isDirectory()) {
1391: shortProgress = true;
1392: fileCount = 0;
1393: baseFile = file;
1394: dataType = DataConnection.PUTDIR;
1395: isDirUpload = true;
1396:
1397: stat = uploadDir(file);
1398:
1399: shortProgress = false;
1400:
1401: //System.out.println(fileCount + ":" + baseFile);
1402: fireProgressUpdate(baseFile, DataConnection.DFINISHED + ":"
1403: + fileCount, -1);
1404:
1405: fireActionFinished(this );
1406: fireDirectoryUpdate(this );
1407: } else {
1408: dataType = DataConnection.PUT;
1409: stat = rawUpload(file, realName, in);
1410:
1411: try {
1412: Thread.sleep(100);
1413: } catch (Exception ex) {
1414: }
1415:
1416: fireActionFinished(this );
1417: fireDirectoryUpdate(this );
1418: }
1419:
1420: try {
1421: Thread.sleep(500);
1422: } catch (Exception ex) {
1423: }
1424:
1425: return stat;
1426: }
1427:
1428: private int rawUpload(String file) {
1429: return rawUpload(file, file);
1430: }
1431:
1432: private int rawUpload(String file, String realName) {
1433: return rawUpload(file, realName, null);
1434: }
1435:
1436: /** uploads a file */
1437: private int rawUpload(String file, String realName, InputStream in) {
1438: if (!file.equals(realName)) {
1439: Log.debug("File: " + file + ", stored as " + realName);
1440: } else {
1441: Log.debug("File: " + file);
1442: realName = null;
1443: }
1444:
1445: file = parse(file);
1446:
1447: String path = file;
1448:
1449: try {
1450: int p = 0;
1451:
1452: if (StringUtils.isRelative(file)) {
1453: path = getLocalPath() + file;
1454: }
1455:
1456: file = StringUtils.getFile(file);
1457:
1458: //BufferedReader in = jcon.getReader();
1459: boolean resume = false;
1460: String size = "0";
1461:
1462: if (Settings.enableUploadResuming && (in == null)) {
1463: list();
1464:
1465: String[] ls = sortLs();
1466: String[] sizes = sortSize();
1467:
1468: if ((ls == null) || (sizes == null)) {
1469: Log
1470: .out(">>> ls out of sync (skipping resume check)");
1471: } else {
1472: for (int i = 0; i < ls.length; i++) {
1473: //Log.out(ls[i] + ":" + sizes[i]);
1474: if (realName != null) {
1475: if (ls[i].equals(realName)) {
1476: resume = true;
1477: size = sizes[i];
1478:
1479: break;
1480: }
1481: } else {
1482: if (ls[i].equals(file)) {
1483: resume = true;
1484: size = sizes[i];
1485: }
1486: }
1487: }
1488:
1489: File f = new File(path);
1490:
1491: if (f.exists()
1492: && (f.length() <= Integer.parseInt(size))) {
1493: Log
1494: .out("skipping resuming, file is <= filelength");
1495: resume = false;
1496: } else if (f.exists() && Integer.parseInt(size) > 0) {
1497: if (!Settings.noUploadResumingQuestion) {
1498: if (JOptionPane
1499: .showConfirmDialog(
1500: new JLabel(),
1501: "A file smaller than the one to be uploaded already exists on the server,\n do you want to resume the upload?",
1502: "Resume upload?",
1503: JOptionPane.YES_NO_OPTION) != JOptionPane.OK_OPTION) {
1504: resume = false;
1505: }
1506: }
1507: Log
1508: .out("resume: " + resume + ", size: "
1509: + size);
1510: } else {
1511: Log
1512: .out("resume: " + resume + ", size: "
1513: + size);
1514: }
1515: }
1516: }
1517:
1518: modeStream();
1519:
1520: //binary();
1521: p = negotiatePort();
1522:
1523: if (resume && Settings.enableUploadResuming) {
1524: jcon.send(REST + " " + size);
1525:
1526: if (getLine(PROCEED) == null) {
1527: resume = false;
1528: }
1529: }
1530:
1531: dcon = new DataConnection(this , p, host, path, dataType,
1532: resume, Integer.parseInt(size), in); //, new Updater());
1533:
1534: while (!dcon.isThere()) {
1535: pause(10);
1536: }
1537:
1538: //System.out.println(path + " : " + file);
1539: if (realName != null) {
1540: jcon.send(STOR + " " + realName);
1541: } else {
1542: jcon.send(STOR + " " + file);
1543: }
1544:
1545: String tmp = getLine(POSITIVE);
1546:
1547: if (!tmp.startsWith(POSITIVE) && !tmp.startsWith(PROCEED)) {
1548: return TRANSFER_FAILED;
1549: }
1550:
1551: Log.debug(tmp);
1552:
1553: // we need to block since some ftp-servers do not want the
1554: // refresh command that dirpanel sends otherwise
1555: while (!dcon.finished) {
1556: pause(10);
1557: }
1558: } catch (Exception ex) {
1559: ex.printStackTrace();
1560: Log.debug(ex.toString() + " @FtpConnection::upload");
1561:
1562: return TRANSFER_FAILED;
1563: }
1564:
1565: return TRANSFER_SUCCESSFUL;
1566: }
1567:
1568: private int uploadDir(String dir) {
1569: //System.out.println("up");
1570: if (dir.endsWith("\\")) {
1571: System.out
1572: .println("Something's wrong with the selected directory - please report this bug!");
1573: }
1574:
1575: if (!dir.endsWith("/")) {
1576: dir = dir + "/";
1577: }
1578:
1579: if (StringUtils.isRelative(dir)) {
1580: dir = getLocalPath() + dir;
1581: }
1582:
1583: String single = StringUtils.getDir(dir);
1584: String path = dir.substring(0, dir.indexOf(single));
1585:
1586: String remoteDir = getCachedPWD() + single; //StringUtils.removeStart(dir,path);
1587: String oldDir = getCachedPWD();
1588:
1589: if (Settings.safeMode) {
1590: noop();
1591: }
1592:
1593: boolean successful = mkdir(remoteDir);
1594:
1595: if (!successful) {
1596: return MKDIR_FAILED;
1597: }
1598:
1599: if (Settings.safeMode) {
1600: noop();
1601: }
1602:
1603: chdirNoRefresh(remoteDir);
1604:
1605: File f2 = new File(dir);
1606: String[] tmp = f2.list();
1607:
1608: for (int i = 0; i < tmp.length; i++) {
1609: String res = dir + tmp[i];
1610: File f3 = new File(res);
1611:
1612: if (f3.isDirectory()) {
1613: if (!work) {
1614: return TRANSFER_STOPPED;
1615: }
1616:
1617: uploadDir(res);
1618: } else {
1619: //System.out.println(">>>\nlp: "+path+single + "\nrp: ");
1620: //System.out.println(remoteDir +"\nres: "+res);
1621: if (!work) {
1622: return TRANSFER_STOPPED;
1623: }
1624:
1625: fileCount++;
1626:
1627: if (rawUpload(res) < 0) {
1628: ; //return TRANSFER_STOPPED;
1629: }
1630: }
1631: }
1632:
1633: chdirNoRefresh(oldDir);
1634:
1635: return TRANSFER_SUCCESSFUL;
1636: }
1637:
1638: private String parse(String file) {
1639: file = parseSymlink(file);
1640:
1641: return file;
1642: }
1643:
1644: /** recursive delete remote directory */
1645: private int cleanDir(String dir, String path) {
1646: if (dir.equals("")) {
1647: return 0;
1648: }
1649:
1650: if (!dir.endsWith("/")) {
1651: dir = dir + "/";
1652: }
1653:
1654: String remoteDir = StringUtils.removeStart(dir, path);
1655:
1656: String oldDir = pwd;
1657: chdirNoRefresh(pwd + remoteDir);
1658:
1659: try {
1660: list();
1661: } catch (IOException ex) {
1662: // probably we don't have permission to ls here
1663: return PERMISSION_DENIED;
1664: }
1665:
1666: String[] tmp = sortLs();
1667: chdirNoRefresh(oldDir);
1668:
1669: if (tmp == null) {
1670: return GENERIC_FAILED;
1671: }
1672:
1673: for (int i = 0; i < tmp.length; i++) {
1674: Log.out("cleanDir: " + tmp);
1675:
1676: if (isSymlink(tmp[i])) {
1677: Log.debug("WARNING: Skipping symlink, remove failed.");
1678: Log
1679: .debug("This is necessary to prevent possible data loss when removing those symlinks.");
1680:
1681: tmp[i] = null;
1682: }
1683:
1684: if (tmp[i] != null) {
1685: tmp[i] = parseSymlink(tmp[i]);
1686: }
1687:
1688: if ((tmp[i] == null) || tmp[i].equals("./")
1689: || tmp[i].equals("../")) {
1690: //System.out.println(tmp[i]+"\n\n\n");
1691: continue;
1692: }
1693:
1694: //System.out.println(tmp[i]);
1695: //pause(500);
1696: if (tmp[i].endsWith("/")) {
1697: // System.out.println(dir);
1698: cleanDir(dir + tmp[i], path);
1699:
1700: int x = removeFileOrDir(dir + tmp[i]);
1701:
1702: if (x < 0) {
1703: return x;
1704: }
1705: } else {
1706: // System.out.println(dir+tmp[i]);
1707: int x = removeFileOrDir(dir + tmp[i]);
1708:
1709: if (x < 0) {
1710: return x;
1711: }
1712: }
1713: }
1714:
1715: return REMOVE_SUCCESSFUL;
1716: }
1717:
1718: /**
1719: * Remove a remote file or directory.
1720: *
1721: * @param file The file to remove
1722: * @return REMOVE_SUCCESSFUL, REMOVE_FAILED, PERMISSION_DENIED or GENERIC_FAILED
1723: */
1724: public int removeFileOrDir(String file) {
1725: if (file == null) {
1726: return 0;
1727: }
1728:
1729: if (file.trim().equals(".") || file.trim().equals("..")) {
1730: Log
1731: .debug("ERROR: Catching attempt to delete . or .. directories");
1732:
1733: return GENERIC_FAILED;
1734: }
1735:
1736: if (isSymlink(file)) {
1737: Log.debug("WARNING: Skipping symlink, remove failed.");
1738: Log
1739: .debug("This is necessary to prevent possible data loss when removing those symlinks.");
1740:
1741: return REMOVE_FAILED;
1742: }
1743:
1744: file = parseSymlink(file);
1745:
1746: if (file.endsWith("/")) {
1747: int ret = cleanDir(file, getCachedPWD());
1748:
1749: if (ret < 0) {
1750: return ret;
1751: }
1752:
1753: jcon.send(RMD + " " + file);
1754: } else {
1755: jcon.send(DELE + " " + file);
1756: }
1757:
1758: if (success(POSITIVE))//FTP250_COMPLETED))
1759: {
1760: return REMOVE_SUCCESSFUL;
1761: } else {
1762: return REMOVE_FAILED;
1763: }
1764: }
1765:
1766: /**
1767: * Disconnect from the server.
1768: * The connection is marked ad closed even if the server does not respond correctly -
1769: * if it fails for any reason the connection should just time out
1770: *
1771: */
1772: public void disconnect() {
1773: jcon.send(QUIT);
1774: getLine(POSITIVE);//FTP221_SERVICE_CLOSING);
1775: connected = false;
1776: }
1777:
1778: /**
1779: * Execute a remote command.
1780: * Sends noops before and after the command
1781: *
1782: * @param cmd The raw command that is to be sent to the server
1783: */
1784: public void sendRawCommand(String cmd) {
1785: noop();
1786: Log.clearCache();
1787: jcon.send(cmd);
1788: noop();
1789: }
1790:
1791: /**
1792: * Reads the response until line found or error.
1793: * (Used internally)
1794: *
1795: * @param until The String the response line hast to start with, 2 for succesful return codes for example
1796: */
1797: public String getLine(String until) {
1798: return getLine(new String[] { until });
1799: }
1800:
1801: /**
1802: * Reads the response until line found or error.
1803: * (Used internally)
1804: */
1805: public String getLine(String[] until) {
1806: BufferedReader in = null;
1807:
1808: try {
1809: in = jcon.getReader();
1810: } catch (Exception ex) {
1811: Log.debug(ex.toString() + " @FtpConnection::getLine");
1812: }
1813:
1814: //String resultString = null;
1815: String tmp;
1816:
1817: while (true) {
1818: try {
1819: tmp = in.readLine();
1820:
1821: if (tmp == null) {
1822: break;
1823: }
1824:
1825: Log.debug(tmp);
1826:
1827: if (((tmp.startsWith(NEGATIVE) || (tmp
1828: .startsWith(NEGATIVE2))) && (tmp.charAt(3) != MORE_LINES_APPENDED))
1829: || tmp.startsWith(PROCEED)) {
1830: return tmp;
1831: } else {
1832: for (int i = 0; i < until.length; i++) {
1833: if (tmp.startsWith(until[i])) {
1834: //if(resultString == null) resultString = tmp;
1835: //else resultString = resultString + "\n" + tmp;
1836: if (tmp.charAt(3) != MORE_LINES_APPENDED) {
1837: return tmp;
1838: }
1839: }
1840: }
1841: }
1842: } catch (Exception ex) {
1843: Log.debug(ex.toString() + " @FtpConnection::getLine");
1844:
1845: break;
1846: }
1847: }
1848:
1849: return null;
1850: }
1851:
1852: /**
1853: * Check if login() was successful.
1854: *
1855: * @return True if connected, false otherwise
1856: */
1857: public boolean isConnected() {
1858: return connected;
1859: }
1860:
1861: /**
1862: * Get the current remote directory.
1863: *
1864: * @return The server's CWD
1865: */
1866: public String getPWD() {
1867: if (connected) {
1868: updatePWD();
1869: }
1870:
1871: if (TESTMODE) {
1872: return "HUGO.user.";
1873: }
1874:
1875: return pwd;
1876: }
1877:
1878: /**
1879: * Returns current remote directory (cached)
1880: *
1881: * @return The cached CWD
1882: */
1883: public String getCachedPWD() {
1884: return pwd;
1885: }
1886:
1887: /**
1888: * updates PWD
1889: */
1890: private void updatePWD() {
1891: jcon.send(PWD);
1892:
1893: String tmp = getLine(POSITIVE);//FTP257_PATH_CREATED);
1894:
1895: if (tmp == null) {
1896: return;
1897: }
1898:
1899: if (TESTMODE) {
1900: tmp = "\"'T759F.'\"";
1901: }
1902:
1903: String x1 = tmp;
1904:
1905: if (x1.indexOf("\"") >= 0) {
1906: x1 = tmp.substring(tmp.indexOf("\"") + 1);
1907: x1 = x1.substring(0, x1.indexOf("\""));
1908: }
1909:
1910: if (getOsType().indexOf("MVS") >= 0) {
1911: //if(x1.indexOf("'") == 0) {
1912: // String x2 = x1.substring(1, x1.lastIndexOf("'"));
1913: // x1 = x2;
1914: //}
1915: Log.out("pwd: " + x1);
1916: } else if (!x1.endsWith("/")) {
1917: x1 = x1 + "/";
1918: }
1919:
1920: pwd = x1;
1921: }
1922:
1923: /**
1924: * Change directory unparsed.
1925: * Use chdir instead if you do not parse the dir correctly...
1926: *
1927: * @param dirName The raw directory name
1928: * @return True if successful, false otherwise
1929: */
1930: public boolean chdirRaw(String dirName) {
1931: jcon.send(CWD + " " + dirName);
1932:
1933: return success(POSITIVE);//FTP250_COMPLETED);
1934: }
1935:
1936: private boolean success(String op) {
1937: String tmp = getLine(op);
1938:
1939: if ((tmp != null) && tmp.startsWith(op)) {
1940: return true;
1941: } else {
1942: return false;
1943: }
1944: }
1945:
1946: /**
1947: * Change to the parent of the current working directory.
1948: * The CDUP command is a special case of CWD, and is included
1949: * to simplify the implementation of programs for transferring
1950: * directory trees between operating systems having different
1951: * syntaxes for naming the parent directory.
1952: *
1953: * @return True if successful, false otherwise
1954: */
1955: public boolean cdup() {
1956: jcon.send(CDUP);
1957:
1958: return success(POSITIVE);//FTP200_OK);
1959: }
1960:
1961: /**
1962: * Create a directory with the given name.
1963: *
1964: * @param dirName The name of the directory to create
1965: * @return True if successful, false otherwise
1966: */
1967: public boolean mkdir(String dirName) {
1968: jcon.send(MKD + " " + dirName);
1969:
1970: boolean ret = success(POSITIVE); // Filezille server bugfix, was: FTP257_PATH_CREATED);
1971: Log.out("mkdir(" + dirName + ") returned: " + ret);
1972:
1973: //*** Added 03/20/2005
1974: fireDirectoryUpdate(this );
1975:
1976: //***
1977: return ret;
1978: }
1979:
1980: private int negotiatePort() throws IOException {
1981: String tmp = "";
1982:
1983: if (Settings.getFtpPasvMode()) {
1984: jcon.send(PASV);
1985:
1986: tmp = getLine(FTP227_ENTERING_PASSIVE_MODE);
1987:
1988: if ((tmp != null) && !tmp.startsWith(NEGATIVE)) {
1989: return getPasvPort(tmp);
1990: }
1991: }
1992:
1993: tmp = getActivePortCmd();
1994: jcon.send(tmp);
1995: getLine(FTP200_OK);
1996:
1997: return getActivePort();
1998: }
1999:
2000: /**
2001: * List remote directory.
2002: * Note that you have to get the output using the
2003: * sort*-methods.
2004: *
2005: * @param outfile The file to save the output to, usually Settings.ls_out
2006: */
2007: public void list() throws IOException {
2008: String oldType = "";
2009:
2010: try {
2011: BufferedReader in = jcon.getReader();
2012:
2013: int p = 0;
2014:
2015: modeStream();
2016:
2017: oldType = getTypeNow();
2018: ascii();
2019:
2020: p = negotiatePort();
2021: dcon = new DataConnection(this , p, host, null,
2022: DataConnection.GET, false, true); //,null);
2023:
2024: //System.out.println("2...");
2025: while (dcon.getInputStream() == null) {
2026: //System.out.print("#");
2027: pause(10);
2028: }
2029:
2030: DataInputStream input = new DataInputStream(dcon
2031: .getInputStream());
2032:
2033: jcon.send(LIST);
2034: getLine(POSITIVE); //FTP226_CLOSING_DATA_REQUEST_SUCCESSFUL);
2035:
2036: String line;
2037: currentListing.removeAllElements();
2038:
2039: while ((line = input.readLine()) != null) {
2040: //System.out.println("-> "+line);
2041: if (!line.trim().equals("")) {
2042: currentListing.add(line);
2043: }
2044: }
2045:
2046: input.close();
2047:
2048: //System.out.println("4...");
2049: if (!oldType.equals(ASCII)) {
2050: type(oldType);
2051: }
2052: } catch (Exception ex) {
2053: Log.debug("Cannot list remote directory!");
2054:
2055: if (!oldType.equals(ASCII)) {
2056: type(oldType);
2057: }
2058:
2059: ex.printStackTrace();
2060: throw new IOException(ex.getMessage());
2061: }
2062: }
2063:
2064: /**
2065: * Parses directory and does a chdir().
2066: * Does also fire a directory update event.
2067: *
2068: * @return True is successful, false otherwise
2069: */
2070: public boolean chdir(String p) {
2071: //Log.out("Change directory to: "+p);
2072: String tmpPath = p;
2073:
2074: boolean tmp = chdirWork(p);
2075:
2076: if (!tmp) {
2077: return false;
2078: } else {
2079: fireDirectoryUpdate(this );
2080:
2081: return true;
2082: }
2083: }
2084:
2085: /**
2086: * Parses directory and does a chdir(), but does not send an update signal
2087: *
2088: * @return True is successful, false otherwise
2089: */
2090: public boolean chdirNoRefresh(String p) {
2091: return chdirWork(p);
2092: }
2093:
2094: private boolean chdirWork(String p) {
2095: if (Settings.safeMode) {
2096: noop();
2097: }
2098:
2099: p = parseSymlinkBack(p);
2100:
2101: if (getOsType().indexOf("OS/2") >= 0) {
2102: return chdirRaw(p);
2103: } else if (getOsType().indexOf("MVS") >= 0) {
2104: boolean cdup = false;
2105:
2106: System.out.print("MVS parser: " + p + " -> ");
2107:
2108: //TODO: handle relative unix paths
2109: if (!getPWD().startsWith("/")) //return chdirRaw(p);
2110: {
2111: if (p.endsWith("..")) {
2112: cdup = true;
2113: }
2114: //TODO let dirlister form correct syntax
2115:
2116: p = p.replaceAll("/", "");
2117: boolean ew = p.startsWith("'");
2118: String tmp = null;
2119:
2120: if (p.startsWith("'") && !p.endsWith("'")) {
2121: if (cdup) {
2122: p = p.substring(0, p.length() - 4);
2123: if (p.indexOf(".") > 0) {
2124: p = p.substring(0, p.lastIndexOf("."));
2125: }
2126: p += "'";
2127: }
2128:
2129: tmp = p.substring(0, p.lastIndexOf("'"));
2130: p = p.substring(p.lastIndexOf("'") + 1);
2131: ew = false;
2132: } else if (cdup) {
2133: p = p.substring(0, p.length() - 3);
2134: if (p.indexOf(".") > 0) {
2135: p = p.substring(0, p.lastIndexOf("."));
2136: }
2137: }
2138:
2139: if (p.indexOf(".") > 0 && !ew) {
2140: p = p.substring(0, p.indexOf("."));
2141: }
2142:
2143: if (tmp != null)
2144: p = tmp + p + "'";
2145:
2146: System.out.println(p);
2147: Log.out("MVS parser: " + p);
2148:
2149: return chdirRaw(p);
2150: }
2151: }
2152:
2153: try {
2154: // check if we don't have a relative path
2155: if (!p.startsWith("/") && !p.startsWith("~")) {
2156: p = pwd + p;
2157: }
2158:
2159: // argh, we should document that!
2160: if (p.endsWith("..")) {
2161: boolean home = p.startsWith("~");
2162: StringTokenizer stok = new StringTokenizer(p, "/");
2163:
2164: //System.out.println("path p :"+p +" Tokens: "+stok.countTokens());
2165: if (stok.countTokens() > 2) {
2166: String pold1 = "";
2167: String pold2 = "";
2168: String pnew = "";
2169:
2170: while (stok.hasMoreTokens()) {
2171: pold1 = pold2;
2172: pold2 = pnew;
2173: pnew = pnew + "/" + stok.nextToken();
2174: }
2175:
2176: p = pold1;
2177: } else {
2178: p = "/";
2179: }
2180:
2181: if (home) {
2182: p = p.substring(1);
2183: }
2184: }
2185:
2186: //System.out.println("path: "+p);
2187: if (!chdirRaw(p)) {
2188: return false;
2189: }
2190: } catch (Exception ex) {
2191: Log
2192: .debug("(remote) Can not get pathname! " + pwd
2193: + ":" + p);
2194: ex.printStackTrace();
2195:
2196: return false;
2197: }
2198:
2199: //fireDirectoryUpdate(this);
2200:
2201: // --------------------------------------
2202: updatePWD();
2203:
2204: return true;
2205: }
2206:
2207: /**
2208: * Waits a specified amount of time
2209: *
2210: * @param time The time to sleep in milliseconds
2211: */
2212: public void pause(int time) {
2213: try {
2214: Thread.sleep(time);
2215: } catch (Exception ex) {
2216: ex.printStackTrace();
2217: }
2218: }
2219:
2220: /**
2221: * Return the local working directory
2222: *
2223: * @return The local CWD
2224: */
2225: public String getLocalPath() {
2226: return localPath;
2227: }
2228:
2229: /**
2230: * Set the local working directory
2231: *
2232: * @param newPath The new local CWD
2233: * @return Always true in the current implementation
2234: */
2235: public boolean setLocalPath(String newPath) {
2236: localPath = newPath;
2237:
2238: if (!localPath.endsWith("/")) {
2239: localPath = localPath + "/";
2240: }
2241:
2242: return true;
2243: }
2244:
2245: /**
2246: * Checks wheter a file exists.
2247: *
2248: * @param file the name of the file
2249: * @return An int-code: CHDIR_FAILED, PERMISSION_DENIED (no listing allowed), R, W or DENIED
2250: */
2251: public int exists(String file) {
2252: String dir = null;
2253: String tmpPWD = getCachedPWD();
2254:
2255: if (file.indexOf("/") >= 0) {
2256: dir = file.substring(0, file.lastIndexOf("/") + 1);
2257: Log.out("checking dir: " + dir);
2258:
2259: if (!chdir(dir)) {
2260: return CHDIR_FAILED;
2261: }
2262: }
2263:
2264: try {
2265: list();
2266: } catch (IOException ex) {
2267: ex.printStackTrace();
2268:
2269: return PERMISSION_DENIED;
2270: }
2271:
2272: String f = file.substring(file.lastIndexOf("/") + 1);
2273: Log.out("checking file: " + f);
2274:
2275: String[] files = sortLs();
2276: int[] perms = getPermissions();
2277:
2278: int y = -1;
2279:
2280: for (int x = 0; x < files.length; x++) {
2281: if (files[x].equals(f)) {
2282: y = x;
2283:
2284: break;
2285: }
2286: }
2287:
2288: if (y == -1) {
2289: return FILE_NOT_FOUND;
2290: }
2291:
2292: if (dir != null) {
2293: chdir(tmpPWD);
2294: }
2295:
2296: return perms[y];
2297: }
2298:
2299: /** Moves or renames remote file.
2300: * @param from remote file to move or rename.
2301: * @param to new file name.
2302: * @return <code>true</code> if completed successfully; <code>false</code> otherwise.
2303: */
2304: public boolean rename(String from, String to) {
2305: jcon.send("RNFR " + from);
2306:
2307: if (success(RC350)) {
2308: jcon.send("RNTO " + to);
2309:
2310: if (success(POSITIVE))//FTP250_COMPLETED))
2311: {
2312: return true;
2313: }
2314: }
2315:
2316: return false;
2317: }
2318:
2319: /**
2320: * Get the port.
2321: *
2322: * @return The port used by the FTP control connection
2323: */
2324: public int getPort() {
2325: return port;
2326: }
2327:
2328: private int getPortA() {
2329: return porta;
2330: }
2331:
2332: private int getPortB() {
2333: return portb;
2334: }
2335:
2336: private void incrementPort() {
2337: portb++;
2338: }
2339:
2340: /*
2341: private String getActivePortCmd() throws UnknownHostException, IOException
2342: {
2343: InetAddress ipaddr = jcon.getLocalAddress();
2344: String ip = ipaddr.getHostAddress().replace('.', ',');
2345:
2346: incrementPort();
2347:
2348: int a = getPortA();
2349: int b = getPortB();
2350: String ret = "PORT " + ip + "," + a + "," + b;
2351:
2352: //System.out.println(ret);
2353: return ret;
2354: }
2355: */
2356:
2357: private String getActivePortCmd() throws UnknownHostException,
2358: IOException {
2359: InetAddress ipaddr = jcon.getLocalAddress();
2360: String ip = ipaddr.getHostAddress().replace('.', ',');
2361:
2362: ServerSocket aSock = new ServerSocket(0);
2363: int availPort = aSock.getLocalPort();
2364: aSock.close();
2365: porta = availPort / 256;
2366: portb = availPort % 256;
2367: String ret = "PORT " + ip + "," + porta + "," + portb;
2368:
2369: // System.out.println(ret);
2370: return ret;
2371: }
2372:
2373: /**
2374: * Tell server we want binary data connections.
2375: */
2376: public void binary() { // possible responses 200, 500, 501, 504, 421 and 530
2377: type(BINARY);
2378: }
2379:
2380: /**
2381: * Tell server we want ascii data connections.
2382: */
2383: public void ascii() {
2384: type(ASCII);
2385: }
2386:
2387: /**
2388: * Set type (L8,I,A for example).
2389: *
2390: * @return True if the type was changed successfully, false otherwise
2391: */
2392: public boolean type(String code) {
2393: jcon.send(TYPE + " " + code);
2394:
2395: String tmp = getLine(POSITIVE);//FTP200_OK);
2396:
2397: if ((tmp != null) && tmp.startsWith(POSITIVE))//FTP200_OK))
2398: {
2399: typeNow = code;
2400:
2401: return true;
2402: }
2403:
2404: return false;
2405: }
2406:
2407: /**
2408: * Returns the type used.
2409: *
2410: * @return The type String, I, A, L8 for example
2411: */
2412: public String getTypeNow() {
2413: return typeNow;
2414: }
2415:
2416: /**
2417: * Do nothing, but flush buffers
2418: */
2419: public void noop() {
2420: jcon.send(NOOP);
2421: getLine(POSITIVE);//FTP200_OK);
2422: }
2423:
2424: /**
2425: * Try to abort the transfer.
2426: */
2427: public void abort() {
2428: jcon.send(ABOR);
2429: getLine(POSITIVE); // 226
2430: }
2431:
2432: /**
2433: * This command is used to find out the type of operating
2434: * system at the server. The reply shall have as its first
2435: * word one of the system names listed in the current version
2436: * of the Assigned Numbers document (RFC 943).
2437: *
2438: * @return The server response of the SYST command
2439: */
2440: public String system() { // possible responses 215, 500, 501, 502, and 421
2441: jcon.send(SYST);
2442:
2443: String response = getLine(POSITIVE);//FTP215_SYSTEM_TYPE);
2444:
2445: if (response != null) {
2446: //StringTokenizer st = new StringTokenizer(response);
2447: //if (st.countTokens() >= 2)
2448: //{
2449: // st.nextToken();
2450: // String os = st.nextToken();
2451: // setOsType(os);
2452: //}
2453: setOsType(response);
2454: } else {
2455: setOsType("UNIX");
2456: }
2457:
2458: return response;
2459: }
2460:
2461: /**
2462: * Set mode to Stream.
2463: * Used internally.
2464: */
2465: public void modeStream() {
2466: if (useStream && !modeStreamSet) {
2467: String ret = mode(STREAM);
2468:
2469: if ((ret != null) && ret.startsWith(NEGATIVE)) {
2470: useStream = false;
2471: } else {
2472: modeStreamSet = true;
2473: }
2474: }
2475: }
2476:
2477: /**
2478: * Unsupported at this time.
2479: */
2480: public void modeBlocked() {
2481: if (useBlocked) {
2482: if (mode(BLOCKED).startsWith(NEGATIVE)) {
2483: useBlocked = false;
2484: }
2485: }
2486: }
2487:
2488: /*
2489: * Unsupported at this time.
2490: */
2491: public void modeCompressed() {
2492: if (useCompressed) {
2493: if (mode(COMPRESSED).startsWith(NEGATIVE)) {
2494: useCompressed = false;
2495: }
2496: }
2497: }
2498:
2499: /**
2500: * Set mode manually.
2501: *
2502: * @param code The mode code wanted, I, A, L8 for example
2503: * @return The server's response to the request
2504: */
2505: public String mode(String code) {
2506: jcon.send(MODE + " " + code);
2507:
2508: String ret = "";
2509:
2510: try {
2511: ret = getLine(POSITIVE);//FTP200_OK);
2512: } catch (Exception ex) {
2513: ex.printStackTrace();
2514: }
2515:
2516: return ret;
2517: }
2518:
2519: /**
2520: * Return the host used.
2521: *
2522: * @return The remote host of this connection
2523: */
2524: public String getHost() {
2525: return host;
2526: }
2527:
2528: /**
2529: * Return the username.
2530: *
2531: * @return The username used by this connection
2532: */
2533: public String getUsername() {
2534: return username;
2535: }
2536:
2537: /**
2538: * Return the password.
2539: *
2540: * @return The password used by this connection
2541: */
2542: public String getPassword() {
2543: return password;
2544: }
2545:
2546: /**
2547: * Return the DataConnection.
2548: * Should be necessary only for complex actions.
2549: *
2550: * @return The DataConnection object currently used by this conenction
2551: */
2552: public DataConnection getDataConnection() {
2553: return dcon;
2554: }
2555:
2556: /**
2557: * Add a ConnectionListener.
2558: * The Listener is notified about transfers and the connection state.
2559: * @param l A ConnectionListener object
2560: */
2561: public void addConnectionListener(ConnectionListener l) {
2562: listeners.add(l);
2563: }
2564:
2565: /**
2566: * Add a Vector of ConnectionListeners.
2567: * Each Listener is notified about transfers and the connection state.
2568: *
2569: * @param l A Vector containig ConnectionListener objects
2570: */
2571: public void setConnectionListeners(Vector l) {
2572: listeners = l;
2573: }
2574:
2575: /**
2576: * Remote directory has changed.
2577: *
2578: * @param con The FtpConnection calling the event
2579: */
2580: public void fireDirectoryUpdate(FtpConnection con) {
2581: if (listeners == null) {
2582: return;
2583: } else {
2584: for (int i = 0; i < listeners.size(); i++) {
2585: ((ConnectionListener) listeners.elementAt(i))
2586: .updateRemoteDirectory(con);
2587: }
2588: }
2589: }
2590:
2591: /**
2592: * Progress update.
2593: * The transfer is active and makes progress, so a signal is send
2594: * each few kb.
2595: *
2596: * @param file The file transferred
2597: * @param type the type of event, DataConnection.GETDIR for example
2598: * @param bytes The number of bytes transferred so far
2599: */
2600: public void fireProgressUpdate(String file, String type, int bytes) {
2601: //System.out.println(listener);
2602: if (listeners == null) {
2603: return;
2604: } else {
2605: for (int i = 0; i < listeners.size(); i++) {
2606: ConnectionListener listener = (ConnectionListener) listeners
2607: .elementAt(i);
2608:
2609: if (shortProgress && Settings.shortProgress) {
2610: if (type.startsWith(DataConnection.DFINISHED)) {
2611: listener.updateProgress(baseFile,
2612: DataConnection.DFINISHED + ":"
2613: + fileCount, bytes);
2614: } else if (isDirUpload) {
2615: listener
2616: .updateProgress(baseFile,
2617: DataConnection.PUTDIR + ":"
2618: + fileCount, bytes);
2619: } else {
2620: listener
2621: .updateProgress(baseFile,
2622: DataConnection.GETDIR + ":"
2623: + fileCount, bytes);
2624: }
2625: } else {
2626: listener.updateProgress(file, type, bytes);
2627: }
2628: }
2629: }
2630: }
2631:
2632: /**
2633: * Connection is there and user logged in
2634: *
2635: * @param con The FtpConnection calling the event
2636: */
2637: public void fireConnectionInitialized(FtpConnection con) {
2638: if (listeners == null) {
2639: return;
2640: } else {
2641: for (int i = 0; i < listeners.size(); i++) {
2642: ((ConnectionListener) listeners.elementAt(i))
2643: .connectionInitialized(con);
2644: }
2645: }
2646: }
2647:
2648: /**
2649: * We are not logged in for some reason
2650: *
2651: * @param con The FtpConnection calling the event
2652: * @param why The login() response code
2653: */
2654: public void fireConnectionFailed(FtpConnection con, String why) {
2655: if (listeners == null) {
2656: return;
2657: } else {
2658: for (int i = 0; i < listeners.size(); i++) {
2659: ((ConnectionListener) listeners.elementAt(i))
2660: .connectionFailed(con, why);
2661: }
2662: }
2663: }
2664:
2665: /**
2666: * Transfer is done
2667: *
2668: * @param con The FtpConnection calling the event
2669: */
2670: public void fireActionFinished(FtpConnection con) {
2671: if (listeners == null) {
2672: return;
2673: } else {
2674: for (int i = 0; i < listeners.size(); i++) {
2675: ((ConnectionListener) listeners.elementAt(i))
2676: .actionFinished(con);
2677: }
2678: }
2679: }
2680:
2681: /**
2682: * Return the ConnectionHandler.
2683: *
2684: * @return The connection handler of this instance
2685: */
2686: public ConnectionHandler getConnectionHandler() {
2687: return handler;
2688: }
2689:
2690: /**
2691: * Set the ConnectionHandler.
2692: *
2693: * @param h The connection handler that is to be used by this connection
2694: */
2695: public void setConnectionHandler(ConnectionHandler h) {
2696: handler = h;
2697: }
2698:
2699: /**
2700: * Get the last FtpTransfer object spawned.
2701: *
2702: */
2703: public FtpTransfer getLastInitiatedTransfer() {
2704: return lastTransfer;
2705: }
2706:
2707: /**
2708: * Abort the last spawned transfer.
2709: *
2710: */
2711: public void abortTransfer() {
2712: try {
2713: DataConnection dcon = lastTransfer.getDataConnection();
2714:
2715: if (dcon == null) {
2716: Log.out("nothing to abort");
2717:
2718: return;
2719: }
2720:
2721: dcon.getCon().work = false;
2722: dcon.sock.close();
2723: } catch (Exception ex) {
2724: Log.debug("Exception during abort: " + ex.toString());
2725: ex.printStackTrace();
2726: }
2727: }
2728:
2729: public Date[] sortDates() {
2730: if (dateVector.size() > 0) {
2731: return (Date[]) dateVector.toArray();
2732: } else {
2733: return null;
2734: }
2735: }
2736:
2737: public String getCRLF() {
2738: return crlf;
2739: }
2740:
2741: public BufferedReader getIn() {
2742: return in;
2743: }
2744:
2745: public void setIn(BufferedReader in) {
2746: this .in = in;
2747: }
2748:
2749: public BufferedReader getCommandInputReader() {
2750: return jcon.getIn();
2751: }
2752:
2753: public OutputStream getCommandOutputStream() {
2754: return jcon.getOut();
2755: }
2756:
2757: }
|