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.gui.base;
0017:
0018: import java.awt.BorderLayout;
0019: import java.awt.Cursor;
0020: import java.awt.FlowLayout;
0021: import java.awt.Font;
0022: import java.awt.Insets;
0023: import java.awt.event.ActionEvent;
0024: import java.awt.event.ActionListener;
0025: import java.awt.event.KeyEvent;
0026: import java.awt.event.KeyListener;
0027: import java.awt.event.MouseAdapter;
0028: import java.awt.event.MouseEvent;
0029: import java.awt.event.MouseListener;
0030: import java.io.File;
0031: import java.io.FileInputStream;
0032: import java.io.FileNotFoundException;
0033: import java.io.PrintStream;
0034: import java.lang.reflect.Array;
0035: import java.util.Date;
0036:
0037: import javax.swing.DefaultListModel;
0038: import javax.swing.ImageIcon;
0039: import javax.swing.JComboBox;
0040: import javax.swing.JEditorPane;
0041: import javax.swing.JLabel;
0042: import javax.swing.JList;
0043: import javax.swing.JMenuItem;
0044: import javax.swing.JOptionPane;
0045: import javax.swing.JPanel;
0046: import javax.swing.JPopupMenu;
0047: import javax.swing.JScrollPane;
0048: import javax.swing.JTextArea;
0049: import javax.swing.JToolBar;
0050: import javax.swing.SwingUtilities;
0051: import javax.swing.event.ListSelectionListener;
0052:
0053: import net.sf.jftp.JFtp;
0054: import net.sf.jftp.config.SaveSet;
0055: import net.sf.jftp.config.Settings;
0056: import net.sf.jftp.gui.base.dir.DirCanvas;
0057: import net.sf.jftp.gui.base.dir.DirCellRenderer;
0058: import net.sf.jftp.gui.base.dir.DirComponent;
0059: import net.sf.jftp.gui.base.dir.DirEntry;
0060: import net.sf.jftp.gui.base.dir.DirLister;
0061: import net.sf.jftp.gui.base.dir.DirPanel;
0062: import net.sf.jftp.gui.base.dir.TableUtils;
0063: import net.sf.jftp.gui.framework.HFrame;
0064: import net.sf.jftp.gui.framework.HImage;
0065: import net.sf.jftp.gui.framework.HImageButton;
0066: import net.sf.jftp.gui.tasks.Creator;
0067: import net.sf.jftp.gui.tasks.Displayer;
0068: import net.sf.jftp.gui.tasks.PathChanger;
0069: import net.sf.jftp.gui.tasks.RemoteCommand;
0070: import net.sf.jftp.net.BasicConnection;
0071: import net.sf.jftp.net.ConnectionListener;
0072: import net.sf.jftp.net.FilesystemConnection;
0073: import net.sf.jftp.net.FtpConnection;
0074: import net.sf.jftp.net.SftpConnection;
0075: import net.sf.jftp.net.SmbConnection;
0076: import net.sf.jftp.system.LocalIO;
0077: import net.sf.jftp.system.StringUtils;
0078: import net.sf.jftp.system.UpdateDaemon;
0079: import net.sf.jftp.system.logging.Log;
0080: import net.sf.jftp.tools.Shell;
0081:
0082: public class RemoteDir extends DirComponent implements
0083: ListSelectionListener, ActionListener, ConnectionListener,
0084: KeyListener {
0085: //HImageButton openButton;
0086: static final String deleteString = "rm";
0087: static final String mkdirString = "mkdir";
0088: static final String refreshString = "fresh";
0089: static final String cdString = "cd";
0090: static final String cmdString = "cmd";
0091: static final String downloadString = "<-";
0092: static final String uploadString = "->";
0093: static final String queueString = "que";
0094: static final String cdUpString = "cdUp";
0095: static final String rnString = "rn";
0096: HImageButton deleteButton;
0097: HImageButton mkdirButton;
0098: HImageButton cmdButton;
0099: HImageButton refreshButton;
0100: HImageButton cdButton;
0101: HImageButton uploadButton;
0102: HImageButton downloadButton;
0103: HImageButton queueButton;
0104: HImageButton cdUpButton;
0105: HImageButton rnButton;
0106:
0107: //static final String openString = "open";
0108: private DirCanvas label = new DirCanvas(this );
0109: private boolean pathChanged = true;
0110: private boolean firstGui = true;
0111: private int pos = 0;
0112: private JPanel p = new JPanel();
0113: private JToolBar buttonPanel = new JToolBar() {
0114: public Insets getInsets() {
0115: return new Insets(0, 0, 0, 0);
0116: }
0117: };
0118:
0119: //private JPanel buttonPanel = new JPanel();
0120: private JToolBar currDirPanel = new JToolBar() {
0121: public Insets getInsets() {
0122: return new Insets(0, 0, 0, 0);
0123: }
0124: };
0125:
0126: private DefaultListModel jlm;
0127: private JScrollPane jsp = new JScrollPane(jl);
0128: private int tmpindex = -1;
0129: private HImageButton list = new HImageButton(Settings.listImage,
0130: "list", "Show remote listing...", this );
0131: private HImageButton transferType = new HImageButton(
0132: Settings.typeImage, "type", "Toggle transfer type...", this );
0133: private JPopupMenu popupMenu = new JPopupMenu();
0134: private JMenuItem props = new JMenuItem("Properties");
0135: private DirEntry currentPopup = null;
0136: private String sortMode = null;
0137: String[] sortTypes = new String[] { "Normal", "Reverse", "Size",
0138: "Size/Re" };
0139: private JComboBox sorter = new JComboBox(sortTypes);
0140: private boolean dateEnabled = false;
0141:
0142: /**
0143: * RemoteDir constructor.
0144: */
0145: public RemoteDir() {
0146: type = "remote";
0147: con = new FilesystemConnection();
0148: con.addConnectionListener(this );
0149:
0150: if (!con.chdir("/")) {
0151: con.chdir("C:\\");
0152: }
0153:
0154: setDate();
0155: }
0156:
0157: /**
0158: * RemoteDir constructor.
0159: */
0160: public RemoteDir(String path) {
0161: type = "remote";
0162: this .path = path;
0163: con = new FilesystemConnection();
0164: con.addConnectionListener(this );
0165: con.chdir(path);
0166:
0167: setDate();
0168: }
0169:
0170: /**
0171: * Creates the gui and adds the MouseListener etc.
0172: */
0173: public void gui_init() {
0174: setLayout(new BorderLayout());
0175: currDirPanel.setFloatable(false);
0176: buttonPanel.setFloatable(false);
0177:
0178: FlowLayout f = new FlowLayout(FlowLayout.LEFT);
0179: f.setHgap(1);
0180: f.setVgap(2);
0181:
0182: buttonPanel.setLayout(f);
0183: buttonPanel.setMargin(new Insets(0, 0, 0, 0));
0184:
0185: props.addActionListener(this );
0186: popupMenu.add(props);
0187:
0188: rnButton = new HImageButton(Settings.textFileImage, rnString,
0189: "Rename selected file or directory", this );
0190: rnButton.setToolTipText("Rename selected");
0191:
0192: list.setToolTipText("Show remote listing...");
0193: transferType.setToolTipText("Toggle transfer type...");
0194:
0195: deleteButton = new HImageButton(Settings.deleteImage,
0196: deleteString, "Delete selected", this );
0197: deleteButton.setToolTipText("Delete selected");
0198:
0199: mkdirButton = new HImageButton(Settings.mkdirImage,
0200: mkdirString, "Create a new directory", this );
0201: mkdirButton.setToolTipText("Create directory");
0202:
0203: refreshButton = new HImageButton(Settings.refreshImage,
0204: refreshString, "Refresh current directory", this );
0205: refreshButton.setToolTipText("Refresh directory");
0206: refreshButton.setRolloverIcon(new ImageIcon(HImage.getImage(
0207: this , Settings.refreshImage2)));
0208: refreshButton.setRolloverEnabled(true);
0209:
0210: cdButton = new HImageButton(Settings.cdImage, cdString,
0211: "Change directory", this );
0212: cdButton.setToolTipText("Change directory");
0213:
0214: cmdButton = new HImageButton(Settings.cmdImage, cmdString,
0215: "Execute remote command", this );
0216: cmdButton.setToolTipText("Execute remote command");
0217:
0218: downloadButton = new HImageButton(Settings.downloadImage,
0219: downloadString, "Download selected", this );
0220: downloadButton.setToolTipText("Download selected");
0221:
0222: queueButton = new HImageButton(Settings.downloadImage,
0223: queueString, "Queue selected", this );
0224: queueButton.setToolTipText("Queue selected");
0225:
0226: cdUpButton = new HImageButton(Settings.cdUpImage, cdUpString,
0227: "Go to Parent Directory", this );
0228: cdUpButton.setToolTipText("Go to Parent Directory");
0229:
0230: //openButton = new HImageButton(Settings.openImage,openString,"Connect to server",this);
0231: //openButton.setToolTipText("Connect");
0232: setLabel();
0233: label.setSize(getSize().width - 10, 24);
0234: currDirPanel.add(label);
0235: currDirPanel.setSize(getSize().width - 10, 32);
0236: label.setSize(getSize().width - 20, 24);
0237:
0238: p.setLayout(new BorderLayout());
0239: p.add("North", currDirPanel);
0240:
0241: buttonPanel.add(downloadButton);
0242:
0243: //buttonPanel.add(new JLabel(" "));
0244: buttonPanel.add(queueButton);
0245:
0246: buttonPanel.add(new JLabel(" "));
0247:
0248: //buttonPanel.add(openButton);
0249: //buttonPanel.add(new JLabel(" "));
0250: buttonPanel.add(refreshButton);
0251: buttonPanel.add(new JLabel(" "));
0252: buttonPanel.add(rnButton);
0253: buttonPanel.add(mkdirButton);
0254: buttonPanel.add(cdButton);
0255: buttonPanel.add(deleteButton);
0256: buttonPanel.add(cdUpButton);
0257: buttonPanel.add(new JLabel(" "));
0258:
0259: buttonPanel.add(cmdButton);
0260: buttonPanel.add(list);
0261: buttonPanel.add(transferType);
0262:
0263: //buttonPanel.add(new JLabel(" "));
0264: buttonPanel.add(sorter);
0265:
0266: buttonPanel.setVisible(true);
0267:
0268: buttonPanel.setSize(getSize().width - 10, 32);
0269:
0270: p.add("West", buttonPanel);
0271: add("North", p);
0272:
0273: sorter.addActionListener(this );
0274:
0275: //setDirList(true);
0276: jlm = new DefaultListModel();
0277: jl = new JList(jlm);
0278: jl.setCellRenderer(new DirCellRenderer());
0279: jl.setVisibleRowCount(Settings.visibleFileRows);
0280: jl.setDropTarget(JFtp.statusP.jftp.dropTarget);
0281:
0282: // add this becaus we need to fetch only doubleclicks
0283: MouseListener mouseListener = new MouseAdapter() {
0284: public void mousePressed(MouseEvent e) {
0285: if (JFtp.uiBlocked) {
0286: return;
0287: }
0288:
0289: if (e.isPopupTrigger()
0290: || SwingUtilities.isRightMouseButton(e)) {
0291: int index = jl.getSelectedIndex() - 1;
0292:
0293: if (index < -1) {
0294: return;
0295: }
0296:
0297: String tgt = (String) jl.getSelectedValue()
0298: .toString();
0299:
0300: if (index < 0) {
0301: } else if ((dirEntry == null)
0302: || (dirEntry.length < index)
0303: || (dirEntry[index] == null)) {
0304: return;
0305: } else {
0306: currentPopup = dirEntry[index];
0307: popupMenu.show(e.getComponent(), e.getX(), e
0308: .getY());
0309: }
0310: }
0311: }
0312:
0313: public void mouseClicked(MouseEvent e) {
0314: if (JFtp.uiBlocked) {
0315: return;
0316: }
0317:
0318: if (Settings.getUseJTableLayout()) {
0319: TableUtils.copyTableSelectionsToJList(jl, table);
0320: }
0321:
0322: //System.out.println("DirEntryListener::");
0323: if (e.getClickCount() == 2) {
0324: //System.out.println("2xList selection: "+jl.getSelectedValue().toString());
0325: int index = jl.getSelectedIndex() - 1;
0326:
0327: // mousewheel bugfix
0328: if (index < -1) {
0329: return;
0330: }
0331:
0332: String tgt = (String) jl.getSelectedValue()
0333: .toString();
0334:
0335: if (index < 0) {
0336: if (JFtp.mainFrame != null) {
0337: JFtp.mainFrame
0338: .setCursor(Cursor.WAIT_CURSOR);
0339: }
0340:
0341: con.chdir(path + tgt);
0342:
0343: if (JFtp.mainFrame != null) {
0344: JFtp.mainFrame
0345: .setCursor(Cursor.DEFAULT_CURSOR);
0346: }
0347: } else if ((dirEntry == null)
0348: || (dirEntry.length < index)
0349: || (dirEntry[index] == null)) {
0350: return;
0351: } else if (dirEntry[index].isDirectory()) {
0352: con.chdir(path + tgt);
0353: } else if (dirEntry[index].isLink()) {
0354: if (!con.chdir(path + tgt)) {
0355: showContentWindow(path
0356: + dirEntry[index].toString(),
0357: dirEntry[index]);
0358:
0359: //blockedTransfer(index);
0360: }
0361: } else {
0362: showContentWindow(path
0363: + dirEntry[index].toString(),
0364: dirEntry[index]);
0365:
0366: //blockedTransfer(index);
0367: }
0368: }
0369: }
0370: };
0371:
0372: if (Settings.newTableGui) {
0373: jsp = new JScrollPane(table);
0374: table.getSelectionModel().addListSelectionListener(this );
0375: table.addMouseListener(mouseListener);
0376: } else {
0377: jsp = new JScrollPane(jl);
0378: jl.addListSelectionListener(this );
0379: jl.addKeyListener(this );
0380: jl.addMouseListener(mouseListener);
0381: jl.requestFocus();
0382: }
0383:
0384: jsp.setSize(getSize().width - 20, getSize().height - 72);
0385: add("Center", jsp);
0386: jsp.setVisible(true);
0387:
0388: TableUtils.tryToEnableRowSorting(table);
0389:
0390: if (Settings.IS_JAVA_1_6) {
0391: //sorter.setVisible(false);
0392: buttonPanel.remove(sorter);
0393: }
0394:
0395: setVisible(true);
0396: }
0397:
0398: public void setViewPort() {
0399: }
0400:
0401: private void setLabel() {
0402: if (con instanceof FilesystemConnection) {
0403: label.setText("Filesystem: " + StringUtils.cutPath(path));
0404: } else if (con instanceof FtpConnection) {
0405: label.setText("Ftp: " + StringUtils.cutPath(path));
0406: } else if (con instanceof SftpConnection) {
0407: label.setText("Sftp: " + StringUtils.cutPath(path));
0408: } else {
0409: label.setText(StringUtils.cutPath(path));
0410: }
0411: }
0412:
0413: /**
0414: * Part of a gui refresh.
0415: * There's no need to call this by hand.
0416: */
0417: public void gui(boolean fakeInit) {
0418: if (firstGui) {
0419: gui_init();
0420: firstGui = false;
0421: }
0422:
0423: setLabel();
0424:
0425: if (con instanceof FtpConnection) {
0426: list.show();
0427: cmdButton.show();
0428: transferType.show();
0429: } else {
0430: list.hide();
0431: cmdButton.hide();
0432: transferType.hide();
0433: }
0434:
0435: if (!fakeInit) {
0436: setDirList(false);
0437: }
0438:
0439: //TODO Log.debug("invalidate()");
0440: invalidate();
0441: validate();
0442:
0443: //TODO .debug("validated.");
0444: }
0445:
0446: /**
0447: * List directory and create/update the whole file list.
0448: * There's no need to call this by hand.
0449: */
0450: public void setDirList(boolean fakeInit) {
0451: jlm = new DefaultListModel();
0452:
0453: DirEntry dwn = new DirEntry("..", this );
0454: dwn.setDirectory();
0455: jlm.addElement(dwn);
0456:
0457: if (!fakeInit) {
0458: if (pathChanged) {
0459: pathChanged = false;
0460:
0461: //TODO .debug("before DirLister");
0462: DirLister dir = new DirLister(con, sortMode);
0463:
0464: while (!dir.finished) {
0465: LocalIO.pause(10);
0466: }
0467:
0468: if (dir.isOk()) {
0469: //TODO .debug("dir is ok");
0470: length = dir.getLength();
0471: dirEntry = new DirEntry[length];
0472: files = dir.list();
0473:
0474: String[] fSize = dir.sList();
0475: int[] perms = dir.getPermissions();
0476:
0477: // --------- sorting aphabetically ------------
0478: // is now in DirLister
0479:
0480: /*
0481: if(Settings.sortDir)
0482: {
0483: String[] tmpx = new String[length];
0484:
0485: //if(fSize != null) System.out.println(":"+length+":"+fSize.length+":"+files.length);
0486: int pLength = length;
0487:
0488: if(perms != null)
0489: {
0490: pLength = perms.length;
0491: }
0492:
0493: //System.out.println(files.length + ":" + fSize.length+":"+ pLength + ":"+ length);
0494: if((fSize.length != files.length) ||
0495: (pLength != files.length) ||
0496: (length != files.length))
0497: {
0498: System.out.println("Sort mismatch - hopefully ignoring it...");
0499: }
0500:
0501: for(int x = 0; x < length; x++)
0502: {
0503: if(perms != null)
0504: {
0505: tmpx[x] = files[x] + "@@@" + fSize[x] + "@@@" +
0506: perms[x];
0507: }
0508: else
0509: {
0510: Log.out("permissions are skipped");
0511: tmpx[x] = files[x] + "@@@" + fSize[x];
0512: }
0513: }
0514:
0515: LocalIO.sortStrings(tmpx);
0516:
0517: for(int y = 0; y < length; y++)
0518: {
0519: files[y] = tmpx[y].substring(0,
0520: tmpx[y].indexOf("@@@"));
0521:
0522: String tmp = tmpx[y].substring(tmpx[y].indexOf("@@@") +
0523: 3);
0524:
0525: if(tmp.indexOf("@@@") > 0)
0526: {
0527: fSize[y] = tmp.substring(0,
0528: tmp.lastIndexOf("@@@"));
0529: }
0530: else
0531: {
0532: fSize[y] = tmp;
0533: }
0534:
0535: if(perms != null)
0536: {
0537: perms[y] = Integer.parseInt(tmpx[y].substring(tmpx[y].lastIndexOf("@@@") +
0538: 3));
0539: }
0540: }
0541: }
0542: */
0543:
0544: // ----------- end sorting --------------------
0545: for (int i = 0; i < length; i++) {
0546: //System.out.println(files[i]);
0547: if ((files == null) || (files[i] == null)) {
0548: //System.out.println("Critical error, files or files[i] is null!\nPlease report when and how this happened...");
0549: System.out
0550: .println("skipping setDirList, files or files[i] is null!");
0551:
0552: return;
0553:
0554: //System.exit(0);
0555: }
0556:
0557: //Log.debug("adding: " + files[i]);
0558: dirEntry[i] = new DirEntry(files[i], this );
0559:
0560: if (dirEntry[i] == null) {
0561: System.out
0562: .println("\nskipping setDirList, dirEntry[i] is null!");
0563:
0564: return;
0565: }
0566:
0567: if (dirEntry[i].file == null) {
0568: System.out
0569: .println("\nskipping setDirList, dirEntry[i].file is null!");
0570:
0571: return;
0572: }
0573:
0574: if (perms != null) {
0575: dirEntry[i].setPermission(perms[i]);
0576: }
0577:
0578: if (fSize[i].startsWith("@")) {
0579: fSize[i] = fSize[i].substring(1);
0580: }
0581:
0582: dirEntry[i].setFileSize(Long
0583: .parseLong(fSize[i]));
0584:
0585: if (dirEntry[i].file.endsWith("/")) {
0586: dirEntry[i].setDirectory();
0587: } else {
0588: dirEntry[i].setFile();
0589: }
0590:
0591: if (dirEntry[i].file.endsWith("###")) {
0592: dirEntry[i].setLink();
0593: }
0594:
0595: //------ date parser -------
0596: Object[] d = dir.getDates();
0597:
0598: if (d != null) {
0599: dirEntry[i].setDate((Date) d[i]);
0600: }
0601:
0602: //--------------------------
0603: jlm.addElement(dirEntry[i]);
0604: }
0605: } else {
0606: Log.debug("Not a directory: " + path);
0607: }
0608: }
0609:
0610: //System.out.println("length: "+dirEntry.length);
0611: }
0612:
0613: jl.setModel(jlm);
0614: jl.grabFocus();
0615: jl.setSelectedIndex(0);
0616:
0617: //Log.debug("ListModel set.");
0618: //System.out.print("x");
0619: //new Exception().printStackTrace();
0620: //System.out.println("\n\n\n");
0621:
0622: update();
0623: }
0624:
0625: /**
0626: * Handles the user events if the ui is unlocked
0627: */
0628: public void actionPerformed(ActionEvent e) {
0629: if (JFtp.uiBlocked) {
0630: return;
0631: }
0632:
0633: if (e.getActionCommand().equals("rm")) {
0634: lock(false);
0635:
0636: if (Settings.getAskToDelete()) {
0637: if (!UITool.askToDelete(this )) {
0638: unlock(false);
0639:
0640: return;
0641: }
0642: }
0643:
0644: for (int i = 0; i < length; i++) {
0645: if (dirEntry[i].selected) {
0646: con.removeFileOrDir(dirEntry[i].file);
0647: }
0648: }
0649:
0650: unlock(false);
0651: fresh();
0652: } else if (e.getActionCommand().equals("mkdir")) {
0653: Creator c = new Creator("Create:", con);
0654:
0655: //TODO: do we need this on events? UpdateDaemon.updateRemoteDirGUI();
0656: //fresh();
0657: } else if (e.getActionCommand().equals("cmd")) {
0658: if (!(con instanceof FtpConnection)) {
0659: Log.debug("This feature is for ftp only.");
0660:
0661: return;
0662: }
0663:
0664: int opt = JOptionPane
0665: .showOptionDialog(
0666: this ,
0667: "Would you like to type one command or to open a shell?",
0668: "Question", JOptionPane.DEFAULT_OPTION,
0669: JOptionPane.QUESTION_MESSAGE,
0670: new ImageIcon(HImage.getImage(this ,
0671: Settings.helpImage)), new String[] {
0672: "Shell", "Command", "Cancel" },
0673: "Command");
0674:
0675: if (opt == 1) {
0676: RemoteCommand rc = new RemoteCommand();
0677: } else if (opt == 0) {
0678: FtpConnection conn = (FtpConnection) con;
0679: Shell s = new Shell(conn.getCommandInputReader(), conn
0680: .getCommandOutputStream());
0681: }
0682:
0683: //fresh();
0684: } else if (e.getActionCommand().equals("cd")) {
0685: PathChanger pthc = new PathChanger("remote");
0686:
0687: //fresh();
0688: //String tmp = UITool.getPathFromDialog();
0689: //setPath(tmp);
0690: } else if (e.getActionCommand().equals("fresh")) {
0691: fresh();
0692: } else if (e.getActionCommand().equals("->")) {
0693: blockedTransfer(-2);
0694: } else if (e.getActionCommand().equals("<-")) {
0695: blockedTransfer(-2);
0696: } else if (e.getActionCommand().equals("list")) {
0697: try {
0698: if (!(con instanceof FtpConnection)) {
0699: Log.debug("Can only list FtpConnection output!");
0700: }
0701:
0702: PrintStream out = new PrintStream(Settings.ls_out);
0703: for (int i = 0; i < ((FtpConnection) con).currentListing
0704: .size(); i++) {
0705: out.println(((FtpConnection) con).currentListing
0706: .get(i));
0707: }
0708: out.flush();
0709: out.close();
0710:
0711: java.net.URL url = new java.io.File(Settings.ls_out)
0712: .toURL();
0713: Displayer d = new Displayer(url, new Font("monospaced",
0714: Font.PLAIN, 11));
0715: JFtp.desktop
0716: .add(d, new Integer(Integer.MAX_VALUE - 13));
0717: } catch (java.net.MalformedURLException ex) {
0718: ex.printStackTrace();
0719: Log.debug("ERROR: Malformed URL!");
0720: } catch (FileNotFoundException ex2) {
0721: ex2.printStackTrace();
0722: Log.debug("ERROR: File not found!");
0723: }
0724: } else if (e.getActionCommand().equals("type")
0725: && (!JFtp.uiBlocked)) {
0726: if (!(con instanceof FtpConnection)) {
0727: Log
0728: .debug("You can only set the transfer type for ftp connections.");
0729:
0730: return;
0731: }
0732:
0733: FtpConnection c = (FtpConnection) con;
0734: String t = c.getTypeNow();
0735: boolean ret = false;
0736:
0737: if (t.equals(FtpConnection.ASCII)) {
0738: ret = c.type(FtpConnection.BINARY);
0739: } else if (t.equals(FtpConnection.BINARY)) {
0740: ret = c.type(FtpConnection.EBCDIC);
0741: }
0742:
0743: if (t.equals(FtpConnection.EBCDIC)
0744: || (!ret && !t.equals(FtpConnection.L8))) {
0745: ret = c.type(FtpConnection.L8);
0746: }
0747:
0748: if (!ret) {
0749: c.type(FtpConnection.ASCII);
0750: Log
0751: .debug("Warning: type should be \"I\" if you want to transfer binary files!");
0752: }
0753:
0754: Log.debug("Type is now " + c.getTypeNow());
0755: }
0756:
0757: else if (e.getActionCommand().equals("que")) /*&& (!JFtp.uiBlocked))*/
0758: {
0759: if (!(con instanceof FtpConnection)) {
0760: Log.debug("Queue supported only for FTP");
0761:
0762: return;
0763: }
0764:
0765: Object[] o = jl.getSelectedValues();
0766: DirEntry[] tmp = new DirEntry[Array.getLength(o)];
0767:
0768: for (int i = 0; i < Array.getLength(o); i++) {
0769: tmp[i] = (DirEntry) o[i];
0770: JFtp.dQueue.addFtp(tmp[i].toString());
0771: }
0772: } else if (e.getSource() == props) {
0773: JFtp.statusP.jftp.clearLog();
0774:
0775: int x = currentPopup.getPermission();
0776: String tmp;
0777:
0778: if (x == FtpConnection.R) {
0779: tmp = "read only";
0780: } else if (x == FtpConnection.W) {
0781: tmp = "read/write";
0782: } else if (x == FtpConnection.DENIED) {
0783: tmp = "denied";
0784: } else {
0785: tmp = "undefined";
0786: }
0787:
0788: String msg = "File: " + currentPopup.toString() + "\n"
0789: + " Size: " + currentPopup.getFileSize()
0790: + " raw size: " + currentPopup.getRawSize() + "\n"
0791: + " Symlink: " + currentPopup.isLink() + "\n"
0792: + " Directory: " + currentPopup.isDirectory()
0793: + "\n" + " Permission: " + tmp + "\n";
0794: Log.debug(msg);
0795: } else if (e.getSource() == sorter) {
0796: sortMode = (String) sorter.getSelectedItem();
0797:
0798: if (sortMode.equals("Date")) {
0799: Settings.showDateNoSize = true;
0800: } else {
0801: Settings.showDateNoSize = false;
0802: }
0803:
0804: fresh();
0805: } else if (e.getActionCommand().equals("cdUp")) {
0806: JFtp.remoteDir.getCon().chdir("..");
0807: } else if (e.getActionCommand().equals("rn")) {
0808: Object[] target = jl.getSelectedValues();
0809:
0810: if ((target == null) || (target.length == 0)) {
0811: Log.debug("No file selected");
0812:
0813: return;
0814: } else if (target.length > 1) {
0815: Log.debug("Too many files selected");
0816:
0817: return;
0818: }
0819:
0820: String val = JOptionPane.showInternalInputDialog(this ,
0821: "Choose a name...");
0822:
0823: if (val != null) {
0824: if (!con.rename(target[0].toString(), val)) {
0825: Log.debug("Rename failed.");
0826: } else {
0827: Log.debug("Successfully renamed.");
0828: fresh();
0829: }
0830: }
0831: }
0832: }
0833:
0834: /**
0835: * Initiate a tranfer with ui locking enabled
0836: */
0837: public synchronized void blockedTransfer(int index) {
0838: tmpindex = index;
0839:
0840: Runnable r = new Runnable() {
0841: public void run() {
0842: boolean block = !Settings.getEnableMultiThreading();
0843:
0844: if (!(con instanceof FtpConnection)) {
0845: block = true;
0846: }
0847:
0848: if (block) {
0849: lock(false);
0850: }
0851:
0852: transfer(tmpindex);
0853:
0854: if (block) {
0855: JFtp.localDir.fresh();
0856: unlock(false);
0857: }
0858: }
0859: };
0860:
0861: Thread t = new Thread(r);
0862: t.start();
0863: }
0864:
0865: /**
0866: * Lock the gui.
0867: */
0868: public void lock(boolean first) {
0869: JFtp.uiBlocked = true;
0870: jl.setEnabled(false);
0871:
0872: if (!first) {
0873: JFtp.localDir.lock(true);
0874: }
0875:
0876: Log.out("ui locked.");
0877: }
0878:
0879: /**
0880: * Unlock the gui.
0881: */
0882: public void unlock(boolean first) {
0883: JFtp.uiBlocked = false;
0884: jl.setEnabled(true);
0885:
0886: if (!first) {
0887: JFtp.localDir.unlock(true);
0888: }
0889:
0890: Log.out("ui unlocked.");
0891: }
0892:
0893: /**
0894: * Do a hard UI refresh - do no longe call this directly, use
0895: * safeUpdate() instead if possible.
0896: */
0897: public void fresh() {
0898: Log.out("fresh() called.");
0899:
0900: Cursor x = null;
0901:
0902: if (JFtp.mainFrame != null) {
0903: x = JFtp.mainFrame.getCursor();
0904: JFtp.mainFrame.setCursor(Cursor.WAIT_CURSOR);
0905: }
0906:
0907: //TODO .debug("fresh()");
0908: String i = "";
0909: int idx = jl.getSelectedIndex();
0910:
0911: if (idx >= 0) {
0912: Object o = jl.getSelectedValue();
0913:
0914: if (o != null) {
0915: i = o.toString();
0916: }
0917: }
0918:
0919: con.chdir(path);
0920:
0921: if ((idx >= 0) && (idx < jl.getModel().getSize())) {
0922: if (jl.getModel().getElementAt(idx).toString().equals(i)) {
0923: jl.setSelectedIndex(idx);
0924: } else {
0925: jl.setSelectedIndex(0);
0926: }
0927: }
0928:
0929: update();
0930:
0931: if ((JFtp.mainFrame != null)
0932: && (x.getType() != Cursor.WAIT_CURSOR)) {
0933: JFtp.mainFrame.setCursor(Cursor.DEFAULT_CURSOR);
0934: }
0935: }
0936:
0937: /**
0938: * Called by FtpConnection, DownloadList is updated from here
0939: */
0940: public void updateProgress(String file, String type, long bytes) {
0941: if ((dList == null) || (dirEntry == null)) {
0942: return;
0943: }
0944:
0945: boolean flag = false;
0946:
0947: if (file.endsWith("/") && (file.length() > 1)) {
0948: flag = true;
0949: file = file.substring(0, file.lastIndexOf("/"));
0950: }
0951:
0952: file = file.substring(file.lastIndexOf("/") + 1);
0953:
0954: if (flag) {
0955: file = file + "/";
0956: }
0957:
0958: long s = 0;
0959:
0960: if (JFtp.dList.sizeCache.containsKey(file)) {
0961: s = ((Long) JFtp.dList.sizeCache.get(file)).longValue();
0962: } else {
0963: for (int i = 0; i < dirEntry.length; i++) {
0964: if (dirEntry[i] == null) {
0965: continue;
0966: }
0967:
0968: if (dirEntry[i].toString().equals(file)) {
0969: s = dirEntry[i].getRawSize();
0970: JFtp.dList.sizeCache.put(file, new Long(s));
0971:
0972: break;
0973: }
0974: }
0975:
0976: if (s <= 0) {
0977: File f = new File(JFtp.localDir.getPath() + file);
0978:
0979: if (f.exists()) {
0980: s = f.length();
0981: }
0982: }
0983: }
0984:
0985: dList.updateList(file, type, bytes, s);
0986: }
0987:
0988: /**
0989: * Called by FtpConnection
0990: */
0991: public void connectionInitialized(BasicConnection con) {
0992: if (con == null) {
0993: return;
0994: }
0995:
0996: setDate();
0997:
0998: Log.out("remote connection initialized");
0999: }
1000:
1001: /**
1002: * Called by FtpConnection
1003: */
1004: public void connectionFailed(BasicConnection con, String reason) {
1005: Log.out("remote connection failed");
1006:
1007: if ((Integer.parseInt(reason) == FtpConnection.OFFLINE)
1008: && Settings.reconnect) {
1009: return;
1010: }
1011:
1012: //this.con = con;
1013: HFrame h = new HFrame();
1014: h.getContentPane().setLayout(new BorderLayout(10, 10));
1015: h.setTitle("Connection failed!");
1016: h.setLocation(150, 200);
1017:
1018: JTextArea text = new JTextArea();
1019: h.getContentPane().add("Center", text);
1020: text.setText(" ---------------- Output -----------------\n"
1021: + JFtp.log.getText());
1022: JFtp.log.setText("");
1023: text.setEditable(false);
1024: h.pack();
1025: h.show();
1026: }
1027:
1028: private void setDate() {
1029: if (!(con instanceof FtpConnection)
1030: && !(con instanceof FilesystemConnection)) {
1031: try {
1032: sorter.removeItem("Date");
1033: } catch (Exception ex) {
1034: }
1035:
1036: dateEnabled = false;
1037:
1038: return;
1039: }
1040:
1041: //Log.debug(">>> date gui init");
1042: if ((con instanceof FtpConnection)
1043: && (((FtpConnection) con).dateVector.size() > 0)) {
1044: if (!dateEnabled) {
1045: sorter.addItem("Date");
1046: dateEnabled = true;
1047: UpdateDaemon.updateRemoteDirGUI();
1048: }
1049: } else if ((con instanceof FilesystemConnection)
1050: && (((FilesystemConnection) con).dateVector.size() > 0)) {
1051: if (!dateEnabled) {
1052: sorter.addItem("Date");
1053: dateEnabled = true;
1054: UpdateDaemon.updateRemoteDirGUI();
1055: }
1056: } else {
1057: if (dateEnabled) {
1058: try {
1059: sorter.removeItem("Date");
1060: dateEnabled = false;
1061: Settings.showDateNoSize = false;
1062: UpdateDaemon.updateRemoteDirGUI();
1063: } catch (Exception ex) {
1064: }
1065: }
1066: }
1067: }
1068:
1069: /**
1070: * Called by FtpConnection
1071: */
1072: public void updateRemoteDirectory(BasicConnection c) {
1073: //TODO Log.debug("updateRemoteDirectory()");
1074: if (con == null) {
1075: return;
1076: }
1077:
1078: if ((c != con) && !c.hasUploaded
1079: && con instanceof FtpConnection) {
1080: //System.out.println("Skipping connection: " + con.getCachedPWD() + " : " + JFtp.remoteDir.path);
1081: return;
1082: }
1083:
1084: //Log.out(">>> update remote dir");
1085: setDate();
1086:
1087: if (con instanceof FtpConnection) {
1088: path = ((FtpConnection) con).getCachedPWD();
1089: } else if (con instanceof SmbConnection
1090: && !path.startsWith("smb://")) {
1091: path = c.getPWD();
1092: } else {
1093: path = con.getPWD();
1094: }
1095:
1096: //System.out.println("path: "+path +":"+ con +":" +con.getPWD() +":"+c+":" +c.getPWD());
1097: if ((c != null) && (c instanceof FtpConnection)) {
1098: FtpConnection con = (FtpConnection) c;
1099:
1100: String tmp = con.getCachedPWD();
1101: SaveSet s = new SaveSet(Settings.login_def, con.getHost(),
1102: con.getUsername(), con.getPassword(), Integer
1103: .toString(con.getPort()), tmp, con
1104: .getLocalPath());
1105: } else if ((c != null) && (c instanceof FilesystemConnection)) {
1106: JFtp.localDir.getCon().setLocalPath(path);
1107: }
1108:
1109: //TODO .debug("before gui()");
1110: //Log.debug(c.toString());
1111: pathChanged = true;
1112: gui(false);
1113:
1114: UpdateDaemon.updateLog();
1115:
1116: //JFtp.statusP.jftp.ensureLogging();
1117: //TODO .debug("after gui()");
1118: }
1119:
1120: /**
1121: * Transfers all selected files
1122: */
1123: public synchronized void transfer() {
1124: boolean[] bFileSelected = new boolean[dirEntry.length + 1];
1125: DirEntry[] cacheEntry = new DirEntry[dirEntry.length];
1126: System.arraycopy(dirEntry, 0, cacheEntry, 0, cacheEntry.length);
1127:
1128: for (int i = 0; i < dirEntry.length; i++) {
1129: bFileSelected[i] = cacheEntry[i].selected;
1130:
1131: if (!cacheEntry[i].equals(dirEntry[i])) {
1132: Log.out("mismatch");
1133: }
1134: }
1135:
1136: for (int i = 0; i < cacheEntry.length; i++) {
1137: if (bFileSelected[i]) {
1138: startTransfer(cacheEntry[i]);
1139: }
1140: }
1141: }
1142:
1143: /**
1144: * Start a file transfer.
1145: * Depending on the local and remote connection types some things like
1146: * local working directory have to be set, resuming may have to be checked etc.
1147: * As with ftp to ftp transfers the action used to download a file might actually be
1148: * an upload.
1149: *
1150: * WARNING: If you do anything here, please check LocalDir.startTransfer(), too!
1151: */
1152: public void startTransfer(DirEntry entry) {
1153: if (con instanceof FtpConnection
1154: && JFtp.localDir.getCon() instanceof FtpConnection) {
1155: if (entry.isDirectory()) {
1156: Log
1157: .debug("Directory transfer between remote connections is not supported yet!");
1158:
1159: return;
1160: }
1161:
1162: Log.out("direct ftp transfer started (download)");
1163: ((FtpConnection) JFtp.localDir.getCon()).upload(entry.file,
1164: ((FtpConnection) JFtp.remoteDir.getCon())
1165: .getDownloadInputStream(path + entry.file));
1166: } else if (con instanceof FtpConnection
1167: && JFtp.localDir.getCon() instanceof FilesystemConnection) {
1168: // local: file, remote: ftp
1169: int status = checkForExistingFile(entry);
1170:
1171: if (status >= 0) {
1172: //--------------------------------------------
1173: // dirty bugfix for sizes that would be
1174: // messed up otherwise
1175:
1176: /*
1177: boolean flag = false;
1178: String file = entry.file;
1179:
1180: if(file.endsWith("/") && (file.length() > 1))
1181: {
1182: flag = true;
1183: file = file.substring(0, file.lastIndexOf("/"));
1184: }
1185:
1186: file = file.substring(file.lastIndexOf("/") + 1);
1187:
1188: if(flag)
1189: {
1190: file = file + "/";
1191: } */
1192: long s = entry.getRawSize();
1193: JFtp.dList.sizeCache.put(entry.file, new Long(s));
1194:
1195: // ---------------------------------
1196: if ((entry.getRawSize() < Settings.smallSize)
1197: && !entry.isDirectory()) {
1198: con.download(entry.file);
1199: } else {
1200: con.handleDownload(path + entry.file);
1201: }
1202: }
1203: } else if (con instanceof FilesystemConnection
1204: && JFtp.localDir.getCon() instanceof FtpConnection) {
1205: try {
1206: File f = new File(path + entry.file);
1207: FileInputStream in = new FileInputStream(f);
1208: JFtp.localDir.getCon().setLocalPath(path);
1209: Log.debug(JFtp.localDir.getCon().getPWD());
1210: ((FtpConnection) JFtp.localDir.getCon()).upload(
1211: entry.file, in);
1212: } catch (FileNotFoundException ex) {
1213: Log
1214: .debug("Error: File not found: " + path
1215: + entry.file);
1216: }
1217: } else if (con instanceof FilesystemConnection
1218: && JFtp.localDir.getCon() instanceof FilesystemConnection) {
1219: con.download(path + entry.file);
1220: JFtp.localDir.actionPerformed(con, "");
1221: } else if (JFtp.localDir.getCon() instanceof FilesystemConnection) {
1222: // local: file, remote: smb, sftp, nfs
1223: con.handleDownload(entry.file);
1224: JFtp.localDir.actionPerformed(con, "");
1225: } else {
1226: if (entry.isDirectory()) {
1227: Log
1228: .debug("Directory transfer between remote connections is not supported yet!");
1229:
1230: return;
1231: }
1232:
1233: Log.out("direct transfer started (download)");
1234: JFtp.localDir.getCon().upload(
1235: entry.file,
1236: JFtp.remoteDir.getCon().getDownloadInputStream(
1237: path + entry.file));
1238: JFtp.localDir.actionPerformed(con, "FRESH");
1239: }
1240: }
1241:
1242: /**
1243: * Transfers single file, or all selected files if index is -1
1244: */
1245: public void transfer(int i) {
1246: if (i == -2) {
1247: transfer();
1248:
1249: return;
1250: } else if (dirEntry[i].selected) {
1251: startTransfer(dirEntry[i]);
1252: }
1253: }
1254:
1255: /**
1256: * Ask for resuming or overwrite if a local file does already exist for a download
1257: */
1258: private int checkForExistingFile(DirEntry dirEntry) {
1259: File f = new File(JFtp.localDir.getPath() + dirEntry.file);
1260:
1261: if (f.exists() && Settings.enableResuming
1262: && Settings.askToResume) {
1263: ResumeDialog r = new ResumeDialog(dirEntry); // ResumeDialog handels the rest
1264:
1265: return -1;
1266: }
1267:
1268: return 1;
1269: }
1270:
1271: /**
1272: * Called by FtpConnection
1273: */
1274: public void actionFinished(BasicConnection c) {
1275: JFtp.localDir.actionPerformed(c, "LOWFRESH");
1276:
1277: if (c instanceof FtpConnection) {
1278: if (((FtpConnection) c).hasUploaded) {
1279: Log.out("actionFinished called by upload: " + c);
1280:
1281: //fresh();
1282: UpdateDaemon.updateRemoteDir();
1283: }
1284:
1285: Log.out("actionFinished called by download: " + c);
1286: } else {
1287: Log.out("actionFinished called by: " + c);
1288:
1289: //fresh();
1290: UpdateDaemon.updateRemoteDir();
1291: }
1292:
1293: //JFtp.statusP.jftp.ensureLogging();
1294: UpdateDaemon.updateLog();
1295: }
1296:
1297: /**
1298: * Called by FtpConnection
1299: */
1300: public void actionPerformed(Object target, String msg) {
1301: if (msg.equals(type)) {
1302: UpdateDaemon.updateRemoteDirGUI();
1303:
1304: //gui(true);
1305: //updateRemoteDirectory(con);
1306: } else if (msg.equals("FRESH")) {
1307: UpdateDaemon.updateRemoteDir();
1308:
1309: //fresh();
1310: }
1311:
1312: //Log.out("actionPerformed called.");
1313: //JFtp.statusP.jftp.ensureLogging();
1314: UpdateDaemon.updateLog();
1315: }
1316:
1317: /**
1318: * Mime type handler for doubleclicks on files
1319: */
1320: public void showContentWindow(String url, DirEntry d) {
1321: try {
1322: if (d.getRawSize() > 200000) {
1323: Log
1324: .debug("File is too big - 200kb is the maximum, sorry.");
1325:
1326: return;
1327: }
1328:
1329: String path = JFtp.localDir.getPath();
1330:
1331: if (!path.endsWith("/")) {
1332: path = path + "/";
1333: }
1334:
1335: if (!new File(path + StringUtils.getFile(url)).exists()) {
1336: con.download(url);
1337: } else {
1338: Log
1339: .debug("\nRemote file must be downloaded to be viewed and\n"
1340: + " you already have a local copy present, pleasen rename it\n"
1341: + " and try again.");
1342:
1343: return;
1344: }
1345:
1346: File file = new File(JFtp.localDir.getPath()
1347: + StringUtils.getFile(url));
1348:
1349: if (!file.exists()) {
1350: Log.debug("File not found: " + JFtp.localDir.getPath()
1351: + StringUtils.getFile(url));
1352: }
1353:
1354: HFrame f = new HFrame();
1355: f.setTitle(url);
1356:
1357: JEditorPane pane = new JEditorPane("file://"
1358: + file.getAbsolutePath());
1359:
1360: if (!pane.getEditorKit().getContentType().equals(
1361: "text/html")
1362: && !pane.getEditorKit().getContentType().equals(
1363: "text/rtf")) {
1364: if (!pane.getEditorKit().getContentType().equals(
1365: "text/plain")) {
1366: Log
1367: .debug("Nothing to do with this filetype - use the buttons if you want to transfer files.");
1368:
1369: return;
1370: }
1371:
1372: pane.setEditable(false);
1373: }
1374:
1375: JScrollPane jsp = new JScrollPane(pane);
1376:
1377: f.getContentPane().setLayout(new BorderLayout());
1378: f.getContentPane().add("Center", jsp);
1379: f.setModal(false);
1380: f.setLocation(100, 100);
1381: f.setSize(600, 400);
1382:
1383: //f.pack();
1384: f.show();
1385:
1386: dList.fresh();
1387: JFtp.localDir.getCon().removeFileOrDir(
1388: StringUtils.getFile(url));
1389: JFtp.localDir.fresh();
1390: } catch (Exception ex) {
1391: Log.debug("File error: " + ex);
1392: }
1393: }
1394:
1395: public void keyPressed(KeyEvent e) {
1396: if (e.getKeyCode() == KeyEvent.VK_ENTER) {
1397: Object o = jl.getSelectedValue();
1398:
1399: if (o == null) {
1400: return;
1401: }
1402:
1403: String tmp = ((DirEntry) o).toString();
1404:
1405: if (tmp.endsWith("/")) {
1406: con.chdir(tmp);
1407: } else {
1408: showContentWindow(path + tmp, (DirEntry) o);
1409: }
1410: } else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
1411: int x = ((DirPanel) JFtp.localDir).jl.getSelectedIndex();
1412:
1413: if (x == -1) {
1414: x = 0;
1415: }
1416:
1417: ((DirPanel) JFtp.localDir).jl.grabFocus();
1418: ((DirPanel) JFtp.localDir).jl.setSelectedIndex(x);
1419: }
1420: }
1421:
1422: public void keyReleased(KeyEvent e) {
1423: }
1424:
1425: public void keyTyped(KeyEvent e) {
1426: }
1427: }
|