Filewatcher File Search
FTP Search
  
Directory (beta)
  
Content Search (beta)
   
pkg://j2ssh-0.2.7-1jpp.src.rpm:2192702/j2ssh-0.2.7-src.tar.gz  info  downloads

j2ssh/ 40755      0      0           0  7765076374   7146 5ustar     0      0 j2ssh/src/ 40755      0      0           0  7765076374   7735 5ustar     0      0 j2ssh/src/com/ 40755      0      0           0  7763376516  10512 5ustar     0      0 j2ssh/src/com/sshtools/ 40755      0      0           0  7763376516  12370 5ustar     0      0 j2ssh/src/com/sshtools/daemon/ 40755      0      0           0  7763376516  13633 5ustar     0      0 j2ssh/src/com/sshtools/daemon/vfs/ 40755      0      0           0  7763376516  14431 5ustar     0      0 j2ssh/src/com/sshtools/daemon/util/ 40755      0      0           0  7763376516  14610 5ustar     0      0 j2ssh/src/com/sshtools/daemon/transport/ 40755      0      0           0  7763376516  15667 5ustar     0      0 j2ssh/src/com/sshtools/daemon/terminal/ 40755      0      0           0  7763376516  15446 5ustar     0      0 j2ssh/src/com/sshtools/daemon/subsystem/ 40755      0      0           0  7763376516  15671 5ustar     0      0 j2ssh/src/com/sshtools/daemon/sftp/ 40755      0      0           0  7763376516  14607 5ustar     0      0 j2ssh/src/com/sshtools/daemon/session/ 40755      0      0           0  7763376516  15316 5ustar     0      0 j2ssh/src/com/sshtools/daemon/scp/ 40755      0      0           0  7763376516  14420 5ustar     0      0 j2ssh/src/com/sshtools/daemon/platform/ 40755      0      0           0  7763376516  15457 5ustar     0      0 j2ssh/src/com/sshtools/daemon/forwarding/ 40755      0      0           0  7763376516  15775 5ustar     0      0 j2ssh/src/com/sshtools/daemon/configuration/ 40755      0      0           0  7763376516  16502 5ustar     0      0 j2ssh/src/com/sshtools/daemon/authentication/ 40755      0      0           0  7763376516  16652 5ustar     0      0 j2ssh/src/com/sshtools/common/ 40755      0      0           0  7763376520  13653 5ustar     0      0 j2ssh/src/com/sshtools/common/util/ 40755      0      0           0  7763376520  14630 5ustar     0      0 j2ssh/src/com/sshtools/common/ui/ 40755      0      0           0  7763376520  14270 5ustar     0      0 j2ssh/src/com/sshtools/common/mru/ 40755      0      0           0  7763376520  14456 5ustar     0      0 j2ssh/src/com/sshtools/common/keygen/ 40755      0      0           0  7763376520  15135 5ustar     0      0 j2ssh/src/com/sshtools/common/hosts/ 40755      0      0           0  7763376520  15013 5ustar     0      0 j2ssh/src/com/sshtools/common/configuration/ 40755      0      0           0  7763376520  16522 5ustar     0      0 j2ssh/src/com/sshtools/common/automate/ 40755      0      0           0  7763376520  15472 5ustar     0      0 j2ssh/src/com/sshtools/common/authentication/ 40755      0      0           0  7763376520  16672 5ustar     0      0 j2ssh/src/com/sshtools/ant/ 40755      0      0           0  7763376520  13145 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/ 40755      0      0           0  7763376520  13414 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/util/ 40755      0      0           0  7763376520  14371 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/transport/ 40755      0      0           0  7763376520  15450 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/transport/publickey/ 40755      0      0           0  7763376520  17437 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/transport/publickey/rsa/ 40755      0      0           0  7763376520  20224 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/transport/publickey/dsa/ 40755      0      0           0  7763376522  20210 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/transport/kex/ 40755      0      0           0  7763376522  16241 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/transport/hmac/ 40755      0      0           0  7763376522  16362 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/transport/compression/ 40755      0      0           0  7763376522  20013 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/transport/cipher/ 40755      0      0           0  7763376522  16724 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/subsystem/ 40755      0      0           0  7763376522  15454 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/sftp/ 40755      0      0           0  7763376522  14372 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/session/ 40755      0      0           0  7763376522  15101 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/openssh/ 40755      0      0           0  7763376522  15075 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/net/ 40755      0      0           0  7763376522  14204 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/io/ 40755      0      0           0  7763376522  14025 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/forwarding/ 40755      0      0           0  7763376522  15560 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/connection/ 40755      0      0           0  7763376522  15555 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/configuration/ 40755      0      0           0  7763376522  16265 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/authentication/ 40755      0      0           0  7763376522  16435 5ustar     0      0 j2ssh/src/com/sshtools/j2ssh/agent/ 40755      0      0           0  7763376524  14516 5ustar     0      0 j2ssh/conf/ 40755      0      0           0  7765076376  10075 5ustar     0      0 j2ssh/lib/ 40755      0      0           0  7765076376   7716 5ustar     0      0 j2ssh/examples/ 40755      0      0           0  7765076376  10766 5ustar     0      0 j2ssh/src/com/sshtools/daemon/SshDaemon.java100644      0      0       12101  7765072224  16456 0ustar     0      0 /*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
 *
 *  Contributions made by:
 *
 *  Brett Smith
 *  Richard Pernavas
 *  Erwin Bolwidt
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  License document supplied with your distribution for more details.
 *
 */
package com.sshtools.daemon;

import com.sshtools.common.configuration.*;

import com.sshtools.daemon.configuration.*;
import com.sshtools.daemon.forwarding.*;
import com.sshtools.daemon.session.*;

import com.sshtools.j2ssh.configuration.*;
import com.sshtools.j2ssh.connection.*;

import org.apache.commons.logging.*;

import java.io.*;

import java.net.*;


/**
 *
 *
 * @author $author$
 * @version $Revision: 1.17 $
 */
public class SshDaemon {
    private static Log log = LogFactory.getLog(SshDaemon.class);

    /**
 *
 *
 * @param args
 */
    public static void main(String[] args) {
        try {
            XmlServerConfigurationContext context = new XmlServerConfigurationContext();
            context.setServerConfigurationResource(ConfigurationLoader.checkAndGetProperty(
                    "sshtools.server", "server.xml"));
            context.setPlatformConfigurationResource(System.getProperty(
                    "sshtools.platform", "platform.xml"));
            ConfigurationLoader.initialize(false, context);

            XmlConfigurationContext context2 = new XmlConfigurationContext();
            context2.setFailOnError(false);
            context2.setAPIConfigurationResource(ConfigurationLoader.checkAndGetProperty(
                    "sshtools.config", "sshtools.xml"));
            context2.setAutomationConfigurationResource(ConfigurationLoader.checkAndGetProperty(
                    "sshtools.automate", "automation.xml"));
            ConfigurationLoader.initialize(false, context2);

            if (args.length > 0) {
                if (args[0].equals("-start")) {
                    start();
                } else if (args[0].equals("-stop")) {
                    if (args.length > 1) {
                        stop(args[1]);
                    } else {
                        stop("The framework daemon is shutting down");
                    }
                } else {
                    System.out.println("Usage: SshDaemon [-start|-stop]");
                }
            } else {
                System.out.println("Usage: SshDaemon [-start|-stop]");
            }
        } catch (Exception e) {
            log.error("The server failed to process the " +
                ((args.length > 0) ? args[0] : "") + " command", e);
        }
    }

    /**
 *
 *
 * @throws IOException
 */
    public static void start() throws IOException {
        // We need at least one host key
        SshServer server = new SshServer() {
                public void configureServices(ConnectionProtocol connection)
                    throws IOException {
                    connection.addChannelFactory(SessionChannelFactory.SESSION_CHANNEL,
                        new SessionChannelFactory());

                    if (ConfigurationLoader.isConfigurationAvailable(
                                ServerConfiguration.class)) {
                        if (((ServerConfiguration) ConfigurationLoader.getConfiguration(
                                    ServerConfiguration.class)).getAllowTcpForwarding()) {
                            ForwardingServer forwarding = new ForwardingServer(connection);
                        }
                    }
                }

                public void shutdown(String msg) {
                    // Disconnect all sessions
                }
            };

        server.startServer();
    }

    /**
 *
 *
 * @param msg
 *
 * @throws IOException
 */
    public static void stop(String msg) throws IOException {
        try {
            Socket socket = new Socket(InetAddress.getLocalHost(),
                    ((ServerConfiguration) ConfigurationLoader.getConfiguration(
                        ServerConfiguration.class)).getCommandPort());

            // Write the command id
            socket.getOutputStream().write(0x3a);

            // Write the length of the message (max 255)
            int len = (msg.length() <= 255) ? msg.length() : 255;
            socket.getOutputStream().write(len);

            // Write the message
            if (len > 0) {
                socket.getOutputStream().write(msg.substring(0, len).getBytes());
            }

            socket.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}
j2ssh/src/com/sshtools/daemon/SshServer.java100644      0      0       30053  7765072224  16527 0ustar     0      0 /*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
 *
 *  Contributions made by:
 *
 *  Brett Smith
 *  Richard Pernavas
 *  Erwin Bolwidt
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  License document supplied with your distribution for more details.
 *
 */
package com.sshtools.daemon;

import com.sshtools.daemon.authentication.*;
import com.sshtools.daemon.configuration.*;
import com.sshtools.daemon.transport.*;

import com.sshtools.j2ssh.*;
import com.sshtools.j2ssh.configuration.*;
import com.sshtools.j2ssh.connection.*;
import com.sshtools.j2ssh.net.*;
import com.sshtools.j2ssh.transport.*;
import com.sshtools.j2ssh.util.*;

import org.apache.commons.logging.*;

import java.io.*;

import java.net.*;

import java.util.*;


/**
 *
 *
 * @author $author$
 * @version $Revision: 1.18 $
 */
public abstract class SshServer {
    private static Log log = LogFactory.getLog(SshServer.class);
    private ConnectionListener listener = null;
    private ServerSocket server = null;
    private boolean shutdown = false;
    private ServerSocket commandServerSocket;

    /**  */
    protected List activeConnections = new Vector();
    Thread thread;

    /**
 * Creates a new SshServer object.
 *
 * @throws IOException
 * @throws SshException
 */
    public SshServer() throws IOException {
        String serverId = System.getProperty("sshtools.serverid");

        if (serverId != null) {
            TransportProtocolServer.SOFTWARE_VERSION_COMMENTS = serverId;
        }

        if (!ConfigurationLoader.isConfigurationAvailable(
                    ServerConfiguration.class)) {
            throw new SshException("Server configuration not available!");
        }

        if (!ConfigurationLoader.isConfigurationAvailable(
                    PlatformConfiguration.class)) {
            throw new SshException("Platform configuration not available");
        }

        if (((ServerConfiguration) ConfigurationLoader.getConfiguration(
                    ServerConfiguration.class)).getServerHostKeys().size() <= 0) {
            throw new SshException(
                "Server cannot start because there are no server host keys available");
        }
    }

    /**
 *
 *
 * @throws IOException
 */
    public void startServer() throws IOException {
        log.info("Starting server");
        shutdown = false;
        startServerSocket();
        thread = new Thread(new Runnable() {
                    public void run() {
                        try {
                            startCommandSocket();
                        } catch (IOException ex) {
                            log.info("Failed to start command socket", ex);

                            try {
                                stopServer("The command socket failed to start");
                            } catch (IOException ex1) {
                            }
                        }
                    }
                });
        thread.start();

        try {
            thread.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
 *
 *
 * @param command
 * @param client
 *
 * @throws IOException
 */
    protected void processCommand(int command, Socket client)
        throws IOException {
        if (command == 0x3a) {
            int len = client.getInputStream().read();
            byte[] msg = new byte[len];
            client.getInputStream().read(msg);
            stopServer(new String(msg));
        }
    }

    /**
 *
 *
 * @throws IOException
 */
    protected void startCommandSocket() throws IOException {
        try {
            commandServerSocket = new ServerSocket(((ServerConfiguration) ConfigurationLoader.getConfiguration(
                        ServerConfiguration.class)).getCommandPort(), 50,
                    InetAddress.getLocalHost());

            Socket client;

            while ((client = commandServerSocket.accept()) != null) {
                log.info("Command request received");

                // Read and process the command
                processCommand(client.getInputStream().read(), client);
                client.close();

                if (shutdown) {
                    break;
                }
            }

            commandServerSocket.close();
        } catch (Exception e) {
            if (!shutdown) {
                log.fatal("The command socket failed", e);
            }
        }
    }

    /**
 *
 *
 * @throws IOException
 */
    protected void startServerSocket() throws IOException {
        listener = new ConnectionListener(((ServerConfiguration) ConfigurationLoader.getConfiguration(
                    ServerConfiguration.class)).getListenAddress(),
                ((ServerConfiguration) ConfigurationLoader.getConfiguration(
                    ServerConfiguration.class)).getPort());
        listener.start();
    }

    /**
 *
 *
 * @param msg
 *
 * @throws IOException
 */
    public void stopServer(String msg) throws IOException {
        log.info("Shutting down server");
        shutdown = true;
        log.debug(msg);
        shutdown(msg);
        listener.stop();
        log.debug("Stopping command server");

        try {
            if (commandServerSocket != null) {
                commandServerSocket.close();
            }
        } catch (IOException ioe) {
            log.error(ioe);
        }
    }

    /**
 *
 *
 * @param msg
 */
    protected abstract void shutdown(String msg);

    /**
 *
 *
 * @param connection
 *
 * @throws IOException
 */
    protected abstract void configureServices(ConnectionProtocol connection)
        throws IOException;

    /**
 *
 *
 * @param socket
 *
 * @throws IOException
 */
    protected void refuseSession(Socket socket) throws IOException {
        TransportProtocolServer transport = new TransportProtocolServer(true);
        transport.startTransportProtocol(new ConnectedSocketTransportProvider(
                socket), new SshConnectionProperties());
    }

    /**
 *
 *
 * @param socket
 *
 * @return
 *
 * @throws IOException
 */
    protected TransportProtocolServer createSession(Socket socket)
        throws IOException {
        log.debug("Initializing connection");

        InetAddress address = socket.getInetAddress();

        /*( (InetSocketAddress) socket
     .getRemoteSocketAddress()).getAddress();*/
        log.debug("Remote Hostname: " + address.getHostName());
        log.debug("Remote IP: " + address.getHostAddress());

        TransportProtocolServer transport = new TransportProtocolServer();

        // Create the Authentication Protocol
        AuthenticationProtocolServer authentication = new AuthenticationProtocolServer();

        // Create the Connection Protocol
        ConnectionProtocol connection = new ConnectionProtocol();

        // Configure the connections services
        configureServices(connection);

        // Allow the Connection Protocol to be accepted by the Authentication Protocol
        authentication.acceptService(connection);

        // Allow the Authentication Protocol to be accepted by the Transport Protocol
        transport.acceptService(authentication);
        transport.startTransportProtocol(new ConnectedSocketTransportProvider(
                socket), new SshConnectionProperties());

        return transport;
    }

    class ConnectionListener implements Runnable {
        private Log log = LogFactory.getLog(ConnectionListener.class);
        private ServerSocket server;
        private String listenAddress;
        private Thread thread;
        private int maxConnections;
        private int port;
        private StartStopState state = new StartStopState(StartStopState.STOPPED);

        public ConnectionListener(String listenAddress, int port) {
            this.port = port;
            this.listenAddress = listenAddress;
        }

        public void run() {
            try {
                log.debug("Starting connection listener thread");
                state.setValue(StartStopState.STARTED);
                server = new ServerSocket(port);

                Socket socket;
                maxConnections = ((ServerConfiguration) ConfigurationLoader.getConfiguration(ServerConfiguration.class)).getMaxConnections();

                boolean refuse = false;
                TransportProtocolEventHandler eventHandler = new TransportProtocolEventAdapter() {
                        public void onDisconnect(TransportProtocol transport) {
                            // Remove from our active channels list only if
                            // were still connected (the thread cleans up
                            // when were exiting so this is to avoid any concurrent
                            // modification problems
                            if (state.getValue() != StartStopState.STOPPED) {
                                synchronized (activeConnections) {
                                    log.info(transport.getUnderlyingProviderDetail() +
                                        " connection closed");
                                    activeConnections.remove(transport);
                                }
                            }
                        }
                    };

                try {
                    while (((socket = server.accept()) != null) &&
                            (state.getValue() == StartStopState.STARTED)) {
                        log.debug("New connection requested");

                        if (maxConnections < activeConnections.size()) {
                            refuseSession(socket);
                        } else {
                            TransportProtocolServer transport = createSession(socket);
                            log.info("Monitoring active session from " +
                                socket.getInetAddress().getHostName());

                            synchronized (activeConnections) {
                                activeConnections.add(transport);
                            }

                            transport.addEventHandler(eventHandler);
                        }
                    }
                } catch (IOException ex) {
                    if (state.getValue() != StartStopState.STOPPED) {
                        log.info("The server was shutdown unexpectedly", ex);
                    }
                }

                state.setValue(StartStopState.STOPPED);

                // Closing all connections
                log.info("Disconnecting active sessions");

                for (Iterator it = activeConnections.iterator(); it.hasNext();) {
                    ((TransportProtocolServer) it.next()).disconnect(
                        "The server is shuting down");
                }

                listener = null;
                log.info("Exiting connection listener thread");
            } catch (IOException ex) {
                log.info("The server thread failed", ex);
            } finally {
                thread = null;
            }

            // brett
            //      System.exit(0);
        }

        public void start() {
            thread = new SshThread(this, "Connection listener", true);
            thread.start();
        }

        public void stop() {
            try {
                state.setValue(StartStopState.STOPPED);
                server.close();

                if (thread != null) {
                    thread.interrupt();
                }
            } catch (IOException ioe) {
                log.warn("The listening socket reported an error during shutdown",
                    ioe);
            }
        }
    }
}
j2ssh/src/com/sshtools/daemon/vfs/VFSMount.java100644      0      0        5377  7765072224  17055 0ustar     0      0 /*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
 *
 *  Contributions made by:
 *
 *  Brett Smith
 *  Richard Pernavas
 *  Erwin Bolwidt
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  License document supplied with your distribution for more details.
 *
 */
package com.sshtools.daemon.vfs;

import com.sshtools.j2ssh.configuration.*;

import java.io.*;

import java.util.*;


/**
 *
 *
 * @author $author$
 * @version $Revision: 1.12 $
 */
public class VFSMount {
    private String mount;
    private String path;
    private HashMap acl = new HashMap();
    private boolean isroot = false;

    /**
 * Creates a new VFSMount object.
 *
 * @param mount
 * @param path
 *
 * @throws IOException
 */
    public VFSMount(String mount, String path) throws IOException {
        path.replace('\\', '/');

        // Replace any tokens
        int index = path.indexOf("%HOME%");

        if (index >= 0) {
            path = ((index > 0) ? path.substring(0, index) : "") +
                ConfigurationLoader.getHomeDirectory() +
                (((index + 6) < (path.length() - 1))
                ? path.substring(index +
                    ((path.charAt(index + 6) == '/') ? 7 : 6)) : "");
        }

        File f = new File(path);

        if (!f.exists()) {
            f.mkdirs();
        }

        if (!mount.trim().startsWith("/")) {
            this.mount = "/" + mount.trim();
        } else {
            this.mount = mount.trim();
        }

        this.path = f.getCanonicalPath();
    }

    /**
 *
 *
 * @return
 */
    public boolean isRoot() {
        return isroot;
    }

    /**
 *
 *
 * @param isroot
 */
    public void setRoot(boolean isroot) {
        this.isroot = isroot;
    }

    /**
 *
 *
 * @param permissions
 */
    public void setPermissions(VFSPermission permissions) {
        acl.put(permissions.getName(), permissions);
    }

    /**
 *
 *
 * @return
 */
    public String getPath() {
        return path.replace('\\', '/');
    }

    /**
 *
 *
 * @return
 */
    public String getMount() {
        return mount;
    }

    /**
 *
 *
 * @return
 */
    public Map getPermissions() {
        return acl;
    }
}
j2ssh/src/com/sshtools/daemon/vfs/VFSPermissionHandler.java100644      0      0        3007  7765072224  21365 0ustar     0      0 /*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
 *
 *  Contributions made by:
 *
 *  Brett Smith
 *  Richard Pernavas
 *  Erwin Bolwidt
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  License document supplied with your distribution for more details.
 *
 */
package com.sshtools.daemon.vfs;

import com.sshtools.daemon.platform.*;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2003</p>
 * <p>Company: </p>
 * @author Lee David Painter
 * @version $Id: VFSPermissionHandler.java,v 1.6 2003/09/11 15:37:07 martianx Exp $
 */
import java.io.*;


public interface VFSPermissionHandler {
    public void verifyPermissions(String username, String path,
        String permissions)
        throws PermissionDeniedException, FileNotFoundException, IOException;

    public String getVFSHomeDirectory(String username)
        throws FileNotFoundException;
}
j2ssh/src/com/sshtools/daemon/vfs/VFSPermission.java100644      0      0        6022  7765072224  20067 0ustar     0      0 /*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
 *
 *  Contributions made by:
 *
 *  Brett Smith
 *  Richard Pernavas
 *  Erwin Bolwidt
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  License document supplied with your distribution for more details.
 *
 */
package com.sshtools.daemon.vfs;


/**
 *
 *
 * @author $author$
 * @version $Revision: 1.12 $
 */
public class VFSPermission {
    private boolean canRead;
    private boolean canWrite;
    private boolean canExecute;
    private String name;

    /**
 * Creates a new VFSPermission object.
 *
 * @param name
 * @param permissions
 */
    public VFSPermission(String name, String permissions) {
        this.name = name;
        setPermissions(permissions);
    }

    /**
 * Creates a new VFSPermission object.
 *
 * @param name
 */
    public VFSPermission(String name) {
        this.name = name;
        setPermissions("rwx");
    }

    /**
 *
 *
 * @return
 */
    public String getName() {
        return name;
    }

    /**
 *
 *
 * @param permissions
 */
    public void setPermissions(String permissions) {
        canRead = false;
        canWrite = false;
        canExecute = false;

        for (int i = 0; i < permissions.length(); i++) {
            switch (permissions.charAt(i)) {
            case 'r': {
                canRead = true;

                break;
            }

            case 'w': {
                canWrite = true;

                break;
            }

            case 'x': {
                canExecute = true;

                break;
            }
            }
        }
    }

    /**
 *
 *
 * @return
 */
    public String getPermissions() {
        return (canRead ? "r" : "") + (canWrite ? "w" : "") +
        (canExecute ? "x" : "");
    }

    /**
 *
 *
 * @param permissions
 *
 * @return
 */
    public boolean verifyPermissions(String permissions) {
        String tmp = getPermissions();
        String ch;

        for (int i = 0; i < permissions.length(); i++) {
            ch = permissions.substring(i, 1);

            if (tmp.indexOf(ch) == -1) {
                return false;
            }
        }

        return true;
    }

    /**
 *
 *
 * @return
 */
    public boolean canRead() {
        return canRead;
    }

    /**
 *
 *
 * @return
 */
    public boolean canWrite() {
        return canWrite;
    }

    /**
 *
 *
 * @return
 */
    public boolean canExecute() {
        return canExecute;
    }
}
j2ssh/src/com/sshtools/daemon/vfs/VirtualFileSystem.java100644      0      0      110717  7765072224  21062 0ustar     0      0 /*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
 *
 *  Contributions made by:
 *
 *  Brett Smith
 *  Richard Pernavas
 *  Erwin Bolwidt
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  License document supplied with your distribution for more details.
 *
 */
package com.sshtools.daemon.vfs;

import com.sshtools.daemon.configuration.PlatformConfiguration;
import com.sshtools.daemon.platform.InvalidHandleException;
import com.sshtools.daemon.platform.NativeAuthenticationProvider;
import com.sshtools.daemon.platform.NativeFileSystemProvider;
import com.sshtools.daemon.platform.PermissionDeniedException;
import com.sshtools.daemon.platform.UnsupportedFileOperationException;

import com.sshtools.j2ssh.SshThread;
import com.sshtools.j2ssh.configuration.ConfigurationException;
import com.sshtools.j2ssh.configuration.ConfigurationLoader;
import com.sshtools.j2ssh.io.UnsignedInteger32;
import com.sshtools.j2ssh.io.UnsignedInteger64;
import com.sshtools.j2ssh.sftp.FileAttributes;
import com.sshtools.j2ssh.sftp.SftpFile;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


/**
 *
 *
 * @author $author$
 * @version $Revision: 1.32 $
 */
public class VirtualFileSystem extends NativeFileSystemProvider {
    private static String USER_HOME = "/home/";
    private static Map vfsmounts;
    private static VFSMount vfsroot;
    private static Log log = LogFactory.getLog(VirtualFileSystem.class);
    private static VFSPermissionHandler permissionHandler = null;

    static {
        try {
            vfsmounts = ((PlatformConfiguration) ConfigurationLoader.getConfiguration(PlatformConfiguration.class)).getVFSMounts();
            vfsroot = ((PlatformConfiguration) ConfigurationLoader.getConfiguration(PlatformConfiguration.class)).getVFSRoot();
        } catch (ConfigurationException ex) {
            log.error("Failed to initialize the Virtual File System", ex);
        }
    }

    private Map openFiles = new HashMap();

    /**
 * Creates a new VirtualFileSystem object.
 *
 * @throws IOException
 */
    public VirtualFileSystem() throws IOException {
        if (!ConfigurationLoader.isConfigurationAvailable(
                    PlatformConfiguration.class)) {
            throw new IOException("No valid platform configuration available");
        }
    }

    public static void setPermissionHandler(
        VFSPermissionHandler permissionHandler) {
        VirtualFileSystem.permissionHandler = permissionHandler;
    }

    private static String getVFSHomeDirectory(String username)
        throws FileNotFoundException {
        if (permissionHandler != null) {
            return permissionHandler.getVFSHomeDirectory(username);
        } else {
            return USER_HOME + username;
        }
    }

    private static String getNFSHomeDirectory() throws FileNotFoundException {
        try {
            if (Thread.currentThread() instanceof SshThread &&
                    SshThread.hasUserContext()) {
                NativeAuthenticationProvider nap = NativeAuthenticationProvider.getInstance();

                return nap.getHomeDirectory(SshThread.getCurrentThreadUser());
            } else {
                throw new FileNotFoundException("There is no user logged in");
            }
        } catch (IOException e) {
            throw new FileNotFoundException(e.getMessage());
        }
    }

    /**
 *
 *
 * @param str
 * @param with
 *
 * @return
 */
    public static boolean startsWithIgnoreCase(String str, String with) {
        return str.substring(0,
            (with.length() > str.length()) ? str.length() : with.length())
                  .equalsIgnoreCase(with);
    }

    /**
 *
 *
 * @param nfspath
 *
 * @return
 *
 * @throws FileNotFoundException
 */
    public static String translateNFSPath(String nfspath)
        throws FileNotFoundException {
        nfspath = nfspath.replace('\\', '/');

        // ./ means home
        if (nfspath.startsWith("./")) {
            nfspath = nfspath.substring(2);
        }

        //if (startsWithIgnoreCase(nfspath, nfshome)) {
        try {
            String nfshome = getNFSHomeDirectory().replace('\\', '/');
            nfshome = translateCanonicalPath(nfshome, nfshome);

            String vfshome = getVFSHomeDirectory(SshThread.getCurrentThreadUser());

            // First check for the userhome
            log.debug("NFSPath=" + nfspath);
            log.debug("NFSHome=" + nfshome);
            nfspath = translateCanonicalPath(nfspath, nfshome);

            int idx = nfspath.indexOf(nfshome);

            return vfshome + nfspath.substring(nfshome.length());

            //            StringBuffer buf = new StringBuffer(nfspath);
            //            buf = buf.replace(idx, idx + nfshome.length(), vfshome);
            //            return buf.toString(); /*nfspath.replaceFirst(nfshome, vfshome);*/
            //}
        } catch (FileNotFoundException ex) { /* Ignore as we will try other mounts */
        }

        // Now lets translate from the available mounts
        Iterator it = vfsmounts.entrySet().iterator();
        Map.Entry entry;
        String mount;
        String path;
        VFSMount m;

        while (it.hasNext()) {
            entry = (Map.Entry) it.next();
            mount = (String) entry.getKey();
            m = (VFSMount) entry.getValue();
            path = m.getPath();
            log.debug(m.getMount() + "=" + m.getPath());

            // if (startsWithIgnoreCase(nfspath, path)) {
            try {
                nfspath = translateCanonicalPath(nfspath, path);

                int idx = nfspath.indexOf(path);
                StringBuffer buf = new StringBuffer(nfspath);
                buf = buf.replace(idx, idx + path.length(), mount);

                return buf.toString();
            } catch (FileNotFoundException ex) {
                /* Ingore as we will try other mounts */
            }

            // }
        }

        // if (startsWithIgnoreCase(nfspath, vfsroot.getPath())) {
        log.debug("VFSRoot=" + vfsroot.getPath());
        nfspath = translateCanonicalPath(nfspath, vfsroot.getPath());
        path = nfspath.substring(vfsroot.getPath().length()); //replaceFirst(vfsroot.getPath(), "");

        return (path.startsWith("/") ? path : ("/" + path));

        //  } else {
        //      throw new FileNotFoundException(nfspath + " could not be found");
        //  }
    }

    private static VFSMount getMount(String vfspath)
        throws FileNotFoundException, IOException {
        String vfshome = getVFSHomeDirectory(SshThread.getCurrentThreadUser());
        VFSMount m;

        if (vfspath.startsWith("/")) {
            if (vfspath.startsWith(vfshome)) {
                m = new VFSMount(vfshome, getNFSHomeDirectory());
                m.setPermissions(new VFSPermission(
                        SshThread.getCurrentThreadUser(), "rwx"));

                return m;
            } else {
                Iterator it = vfsmounts.entrySet().iterator();
                Map.Entry entry;
                String mount;

                while (it.hasNext()) {
                    entry = (Map.Entry) it.next();
                    mount = (String) entry.getKey();

                    if (vfspath.startsWith(mount)) {
                        return (VFSMount) entry.getValue();
                    }
                }

                if (vfsroot != null) {
                    return vfsroot;
                } else {
                    throw new FileNotFoundException("The path was not found");
                }
            }
        } else {
            m = new VFSMount(vfshome, getNFSHomeDirectory());
            m.setPermissions(new VFSPermission(vfshome.substring(
                        vfshome.lastIndexOf("/")), "rwx"));

            return m;
        }
    }

    /**
 *
 *
 * @param vfspath
 *
 * @return
 *
 * @throws FileNotFoundException
 */
    public static String translateVFSPath(String vfspath)
        throws FileNotFoundException {
        return translateVFSPath(vfspath, null);
    }

    public static String translateVFSPath(String vfspath, String vfscwd)
        throws FileNotFoundException {
        // Translate any backslashes for sanity
        vfspath = vfspath.replace('\\', '/').trim();

        try {
            if (!vfspath.startsWith("/")) {
                // Work out the path using the current directory
                String path = (((vfscwd == null) || vfscwd.trim().equals(""))
                    ? getVFSHomeDirectory(SshThread.getCurrentThreadUser())
                    : vfscwd);
                vfspath = path + (path.endsWith("/") ? "" : "/") + vfspath;
            }

            String nfshome = getNFSHomeDirectory().replace('\\', '/');
            String vfshome = getVFSHomeDirectory(SshThread.getCurrentThreadUser());

            if (vfspath.startsWith(vfshome)) {
                // Return the canonicalized system dependent path
                if (vfspath.length() > vfshome.length()) {
                    return translateCanonicalPath(nfshome +
                        (nfshome.endsWith("/") ? "" : "/") +
                        vfspath.substring(vfshome.length() + 1), nfshome);
                } else {
                    return translateCanonicalPath(nfshome, nfshome);
                }
            }
        } catch (FileNotFoundException ex) {
            // Ignore since we dont always need to be running as a user
        }

        // The path does not refer to the absolute USER_HOME
        // so we will look up using the platform.xml VFS mounts
        Iterator it = vfsmounts.entrySet().iterator();
        Map.Entry entry;
        String mount;
        String path;
        VFSMount m;

        while (it.hasNext()) {
            entry = (Map.Entry) it.next();
            mount = (String) entry.getKey();
            m = (VFSMount) entry.getValue();
            path = m.getPath();

            if (vfspath.startsWith(mount)) {
                // Lets translate the path, making sure we do not move outside
                // vfs with ..
                String str = path + vfspath.substring(mount.length());

                // vfspath.replaceFirst(mount,
                //        path)
                return translateCanonicalPath(str, path);
            }
        }

        // If we reached here then the VFS path did not refer to an optional mount
        // or the users home directory, so lets attempt to use the VFS root is there
        // is one defined
        if (vfsroot != null) {
            path = vfsroot.getPath() +
                (vfsroot.getPath().endsWith("/") ? vfspath.substring(1) : vfspath);

            return translateCanonicalPath(path, vfsroot.getPath());
        } else {
            throw new FileNotFoundException("The file could not be found");
        }
    }

    /*else {
  try {
    String nfshome = (nfscwd == null || nfscwd.trim().equals("") ? getNFSHomeDirectory() : nfscwd);
    String path = nfshome + (nfshome.endsWith("/") ? "" : "/") + vfspath;
    return translateCanonicalPath(path, nfshome);
  }
  catch (FileNotFoundException ex1) {
    throw new FileNotFoundException(
     "Only fully qualified VFS paths can be translated outside of a user context");
  }
  /*  String path = nfshome + (nfshome.endsWith("/") ? "" : "/")
         + vfspath;
     return translateCanonicalPath(path, nfshome);*/

    //}

    /**
 *
 *
 * @param path
 * @param securemount
 *
 * @return
 *
 * @throws FileNotFoundException
 */
    public static String translateCanonicalPath(String path, String securemount)
        throws FileNotFoundException {
        try {
            log.debug("Translating for canonical path " + path +
                " against secure mount " + securemount);

            File f = new File(path);
            String canonical = f.getCanonicalPath().replace('\\', '/');
            File f2 = new File(securemount);
            String canonical2 = f2.getCanonicalPath().replace('\\', '/');

            // Verify that the canonical path does not exit out of the mount
            if (canonical.startsWith(canonical2)) {
                return canonical;
            } else {
                throw new FileNotFoundException(path + " could not be found");
            }
        } catch (IOException ex) {
            throw new FileNotFoundException(path + " could not be found");
        }
    }

    /**
 *
 *
 * @param path
 *
 * @return
 *
 * @throws PermissionDeniedException
 * @throws FileNotFoundException
 * @throws IOException
 */
    public boolean makeDirectory(String path)
        throws PermissionDeniedException, FileNotFoundException, IOException {
        //    String realPath = path;
        path = VirtualFileSystem.translateVFSPath(path);

        File f = new File(path);
        verifyPermissions(SshThread.getCurrentThreadUser(), path, "rw");
        log.debug("Creating directory " + f.getAbsolutePath());

        return f.mkdir();
    }

    /**
 *
 *
 * @param path
 *
 * @return
 *
 * @throws FileNotFoundException
 * @throws IOException
 */
    public VFSPermission getVFSPermission(String path)
        throws FileNotFoundException, IOException {
        VFSMount mount = getMount(translateNFSPath(path));

        if (mount.getPermissions().containsKey(SshThread.getCurrentThreadUser())) {
            return (VFSPermission) mount.getPermissions().get(SshThread.getCurrentThreadUser());
        } else {
            return (VFSPermission) mount.getPermissions().get("default");
        }
    }

    /**
 *
 *
 * @param handle
 *
 * @return
 *
 * @throws IOException
 * @throws InvalidHandleException
 */
    public FileAttributes getFileAttributes(byte[] handle)
        throws IOException, InvalidHandleException {
        String shandle = new String(handle);

        if (openFiles.containsKey(shandle)) {
            Object obj = openFiles.get(shandle);
            File f;

            if (obj instanceof OpenFile) {
                f = ((OpenFile) obj).getFile();
            } else if (obj instanceof OpenDirectory) {
                f = ((OpenDirectory) obj).getFile();
            } else {
                throw new IOException("Unexpected open file handle");
            }

            VFSPermission permissions = getVFSPermission(f.getAbsolutePath());

            if (permissions == null) {
                throw new IOException("No default permissions set");
            }

            FileAttributes attrs = new FileAttributes();
            attrs.setSize(new UnsignedInteger64(String.valueOf(f.length())));
            attrs.setTimes(new UnsignedInteger32(f.lastModified() / 1000),
                new UnsignedInteger32(f.lastModified() / 1000));

            boolean canExec = true;

            try {
                if (System.getSecurityManager() != null) {
                    System.getSecurityManager().checkExec(f.getCanonicalPath());
                }
            } catch (SecurityException ex1) {
                canExec = false;
            }

            attrs.setPermissions((((f.canRead() && permissions.canRead()) ? "r"
                                                                          : "-") +
                ((f.canWrite() && permissions.canWrite()) ? "w" : "-") +
                ((canExec && permissions.canExecute()) ? "x" : "-")));
            attrs.setPermissions(new UnsignedInteger32(attrs.getPermissions()
                                                            .longValue() |
                    (f.isDirectory() ? FileAttributes.S_IFDIR
                                     : FileAttributes.S_IFREG)));

            return attrs;
        } else {
            throw new InvalidHandleException("The handle is invalid");
        }
    }

    /**
 *
 *
 * @param path
 *
 * @return
 *
 * @throws IOException
 * @throws FileNotFoundException
 */
    public FileAttributes getFileAttributes(String path)
        throws IOException, FileNotFoundException {
        log.debug("Getting file attributes for " + path);
        path = translateVFSPath(path);

        // Look up the VFS mount attributes
        File f = new File(path);
        path = f.getCanonicalPath();

        if (!f.exists()) {
            throw new FileNotFoundException(path + " doesn't exist");
        }

        VFSPermission permissions = getVFSPermission(path);

        if (permissions == null) {
            throw new IOException("No default permissions set");
        }

        FileAttributes attrs = new FileAttributes();
        attrs.setSize(new UnsignedInteger64(String.valueOf(f.length())));
        attrs.setTimes(new UnsignedInteger32(f.lastModified() / 1000),
            new UnsignedInteger32(f.lastModified() / 1000));

        boolean canExec = true;

        try {
            if (System.getSecurityManager() != null) {
                System.getSecurityManager().checkExec(f.getCanonicalPath());
            }
        } catch (SecurityException ex1) {
            canExec = false;
        }

        attrs.setPermissions((((f.canRead() && permissions.canRead()) ? "r" : "-") +
            ((f.canWrite() && permissions.canWrite()) ? "w" : "-") +
            ((canExec && permissions.canExecute()) ? "x" : "-")));
        attrs.setPermissions(new UnsignedInteger32(attrs.getPermissions()
                                                        .longValue() |
                (f.isDirectory() ? FileAttributes.S_IFDIR : FileAttributes.S_IFREG)));

        return attrs;
    }

    /**
 *
 *
 * @param path
 *
 * @return
 *
 * @throws PermissionDeniedException
 * @throws FileNotFoundException
 * @throws IOException
 */
    public byte[] openDirectory(String path)
        throws PermissionDeniedException, FileNotFoundException, IOException {
        String realPath = path;
        path = VirtualFileSystem.translateVFSPath(path);

        File f = new File(path);
        verifyPermissions(SshThread.getCurrentThreadUser(), path, "r");

        if (f.exists()) {
            if (f.isDirectory()) {
                openFiles.put(f.toString(), new OpenDirectory(realPath, path, f));

                return f.toString().getBytes("US-ASCII");
            } else {
                throw new IOException(translateNFSPath(path) +
                    " is not a directory");
            }
        } else {
            throw new FileNotFoundException(translateNFSPath(path) +
                " does not exist");
        }
    }

    /**
 *
 *
 * @param handle
 *
 * @return
 *
 * @throws InvalidHandleException
 * @throws EOFException
 * @throws IOException
 */
    public SftpFile[] readDirectory(byte[] handle)
        throws InvalidHandleException, EOFException, IOException {
        String shandle = new String(handle);

        if (openFiles.containsKey(shandle)) {
            Object obj = openFiles.get(shandle);

            if (obj instanceof OpenDirectory) {
                OpenDirectory dir = (OpenDirectory) obj;
                int pos = dir.getPosition();
                File[] children = dir.getChildren();

                if (children == null) {
                    throw new IOException("Permission denined.");
                }

                int count = ((children.length - pos) < 100)
                    ? (children.length - pos) : 100;

                if (count > 0) {
                    SftpFile[] files = new SftpFile[count];

                    for (int i = 0; i < files.length; i++) {
                        File f = children[pos + i];
                        String absolutePath = dir.realPath + "/" + f.getName();
                        SftpFile sftpfile = new SftpFile(f.getName(),
                                getFileAttributes(absolutePath));
                        files[i] = sftpfile;
                    }

                    dir.readpos = pos + files.length;

                    return files;
                } else {
                    throw new EOFException("There are no more files");
                }
            } else {
                throw new InvalidHandleException(
                    "Handle is not an open directory");
            }
        } else {
            throw new InvalidHandleException("The handle is invalid");
        }
    }

    /**
 *
 *
 * @param path
 * @param flags
 * @param attrs
 *
 * @return
 *
 * @throws PermissionDeniedException
 * @throws FileNotFoundException
 * @throws IOException
 */
    public byte[] openFile(String path, UnsignedInteger32 flags,
        FileAttributes attrs)
        throws PermissionDeniedException, FileNotFoundException, IOException {
        path = VirtualFileSystem.translateVFSPath(path);

        File f = new File(path);
        verifyPermissions(SshThread.getCurrentThreadUser(), path, "r");

        // Check if the file does not exist and process according to flags
        if (!f.exists()) {
            if ((flags.intValue() & NativeFileSystemProvider.OPEN_CREATE) == NativeFileSystemProvider.OPEN_CREATE) {
                // The file does not exist and the create flag is present so lets create it
                if (!f.createNewFile()) {
                    throw new IOException(translateNFSPath(path) +
                        " could not be created");
                }
            } else {
                // The file does not exist and no create flag present
                throw new FileNotFoundException(translateNFSPath(path) +
                    " does not exist");
            }
        } else {
            if (((flags.intValue() & NativeFileSystemProvider.OPEN_CREATE) == NativeFileSystemProvider.OPEN_CREATE) &&
                    ((flags.intValue() &
                    NativeFileSystemProvider.OPEN_EXCLUSIVE) == NativeFileSystemProvider.OPEN_EXCLUSIVE)) {
                // The file exists but the EXCL flag is set which requires that the
                // file should not exist prior to creation, so throw a status exception
                throw new IOException(translateNFSPath(path) +
                    " already exists");
            }
        }

        // The file now exists so open the file according to the flags yb building the relevant
        // flags for the RandomAccessFile class
        String mode = "r" +
            (((flags.intValue() & NativeFileSystemProvider.OPEN_WRITE) == NativeFileSystemProvider.OPEN_WRITE)
            ? "ws" : "");
        RandomAccessFile raf = new RandomAccessFile(f, mode);

        // Determine whether we need to truncate the file
        if (((flags.intValue() & NativeFileSystemProvider.OPEN_CREATE) == NativeFileSystemProvider.OPEN_CREATE) &&
                ((flags.intValue() & NativeFileSystemProvider.OPEN_TRUNCATE) == NativeFileSystemProvider.OPEN_TRUNCATE)) {
            // Set the length to zero
            raf.setLength(0);
        }

        // Record the open file
        openFiles.put(raf.toString(), new OpenFile(f, raf, flags));

        // Return the handle
        return raf.toString().getBytes("US-ASCII");
    }

    /**
 *
 *
 * @param handle
 * @param offset
 * @param len
 *
 * @return
 *
 * @throws InvalidHandleException
 * @throws EOFException
 * @throws IOException
 */
    public byte[] readFile(byte[] handle, UnsignedInteger64 offset,
        UnsignedInteger32 len)
        throws InvalidHandleException, EOFException, IOException {
        String shandle = new String(handle);

        if (openFiles.containsKey(shandle)) {
            Object obj = openFiles.get(shandle);

            if (obj instanceof OpenFile) {
                OpenFile file = (OpenFile) obj;

                if ((file.getFlags().intValue() &
                        NativeFileSystemProvider.OPEN_READ) == NativeFileSystemProvider.OPEN_READ) {
                    byte[] buf = new byte[len.intValue()];

                    if (file.getRandomAccessFile().getFilePointer() != offset.longValue()) {
                        file.getRandomAccessFile().seek(offset.longValue());
                    }

                    int read = file.getRandomAccessFile().read(buf);

                    if (read >= 0) {
                        if (read == buf.length) {
                            return buf;
                        } else {
                            byte[] tmp = new byte[read];
                            System.arraycopy(buf, 0, tmp, 0, read);

                            return tmp;
                        }
                    } else {
                        throw new EOFException("The file is EOF");
                    }
                } else {
                    throw new InvalidHandleException(
                        "The file handle was not opened for reading");
                }
            } else {
                throw new InvalidHandleException("Handle is not an open file");
            }
        } else {
            throw new InvalidHandleException("The handle is invalid");
        }
    }

    /**
 *
 *
 * @param handle
 * @param offset
 * @param data
 * @param off
 * @param len
 *
 * @throws InvalidHandleException
 * @throws IOException
 */
    public void writeFile(byte[] handle, UnsignedInteger64 offset, byte[] data,
        int off, int len) throws InvalidHandleException, IOException {
        String shandle = new String(handle);

        if (openFiles.containsKey(shandle)) {
            Object obj = openFiles.get(shandle);

            if (obj instanceof OpenFile) {
                OpenFile file = (OpenFile) obj;

                if ((file.getFlags().intValue() &
                        NativeFileSystemProvider.OPEN_WRITE) == NativeFileSystemProvider.OPEN_WRITE) {
                    if ((file.getFlags().intValue() &
                            NativeFileSystemProvider.OPEN_APPEND) == NativeFileSystemProvider.OPEN_APPEND) {
                        // Force the data to be written to the end of the file by seeking to the end
                        file.getRandomAccessFile().seek(file.getRandomAccessFile()
                                                            .length());
                    } else if (file.getRandomAccessFile().getFilePointer() != offset.longValue()) {
                        // Move the file pointer if its not in the write place
                        file.getRandomAccessFile().seek(offset.longValue());
                    }

                    file.getRandomAccessFile().write(data, off, len);
                } else {
                    throw new InvalidHandleException(
                        "The file was not opened for writing");
                }
            } else {
                throw new InvalidHandleException("Handle is not an open file");
            }
        } else {
            throw new InvalidHandleException("The handle is invalid");
        }
    }

    /**
 *
 *
 * @param handle
 *
 * @throws InvalidHandleException
 * @throws IOException
 */
    public void closeFile(byte[] handle)
        throws InvalidHandleException, IOException {
        String shandle = new String(handle);

        if (openFiles.containsKey(shandle)) {
            Object obj = openFiles.get(shandle);

            if (obj instanceof OpenDirectory) {
                openFiles.remove(shandle);
            } else if (obj instanceof OpenFile) {
                ((OpenFile) obj).getRandomAccessFile().close();
                openFiles.remove(shandle);
            } else {
                throw new InvalidHandleException("Internal server error");
            }
        } else {
            throw new InvalidHandleException("The handle is invalid");
        }
    }

    /**
 *
 *
 * @param path
 *
 * @throws PermissionDeniedException
 * @throws IOException
 * @throws FileNotFoundException
 */
    public void removeFile(String path)
        throws PermissionDeniedException, IOException, FileNotFoundException {
        path = VirtualFileSystem.translateVFSPath(path);

        File f = new File(path);

        if (f.exists()) {
            try {
                if (f.isFile()) {
                    if (!f.delete()) {
                        throw new IOException("Failed to delete " +
                            translateNFSPath(path));
                    }
                } else {
                    throw new IOException(translateNFSPath(path) +
                        " is a directory, use remove directory command to remove");
                }
            } catch (SecurityException se) {
                throw new PermissionDeniedException("Permission denied");
            }
        } else {
            throw new FileNotFoundException(translateNFSPath(path) +
                " does not exist");
        }
    }

    /**
 *
 *
 * @param oldpath
 * @param newpath
 *
 * @throws PermissionDeniedException
 * @throws FileNotFoundException
 * @throws IOException
 */
    public void renameFile(String oldpath, String newpath)
        throws PermissionDeniedException, FileNotFoundException, IOException {
        oldpath = VirtualFileSystem.translateVFSPath(oldpath);
        newpath = VirtualFileSystem.translateVFSPath(newpath);

        File f = new File(oldpath);
        verifyPermissions(SshThread.getCurrentThreadUser(), oldpath, "rw");
        verifyPermissions(SshThread.getCurrentThreadUser(), newpath, "rw");

        if (f.exists()) {
            File f2 = new File(newpath);

            if (!f2.exists()) {
                if (!f.renameTo(f2)) {
                    throw new IOException("Failed to rename file " +
                        translateNFSPath(oldpath));
                }
            } else {
                throw new IOException(translateNFSPath(newpath) +
                    " already exists");
            }
        } else {
            throw new FileNotFoundException(translateNFSPath(oldpath) +
                " does not exist");
        }
    }

    /**
 *
 *
 * @param path
 *
 * @throws PermissionDeniedException
 * @throws FileNotFoundException
 * @throws IOException
 */
    public void removeDirectory(String path)
        throws PermissionDeniedException, FileNotFoundException, IOException {
        path = VirtualFileSystem.translateVFSPath(path);

        File f = new File(path);
        verifyPermissions(SshThread.getCurrentThreadUser(), path, "rw");

        if (f.isDirectory()) {
            if (f.exists()) {
                if (f.listFiles().length == 0) {
                    if (!f.delete()) {
                        throw new IOException("Failed to remove directory " +
                            translateNFSPath(path));
                    }
                } else {
                    throw new IOException(translateNFSPath(path) +
                        " is not an empty directory");
                }
            } else {
                throw new FileNotFoundException(translateNFSPath(path) +
                    " does not exist");
            }
        } else {
            throw new IOException(translateNFSPath(path) +
                " is not a directory");
        }
    }

    /**
 *
 *
 * @param path
 * @param attrs
 *
 * @throws PermissionDeniedException
 * @throws IOException
 * @throws FileNotFoundException
 */
    public void setFileAttributes(String path, FileAttributes attrs)
        throws PermissionDeniedException, IOException, FileNotFoundException {
        // Since we cannot really set permissions, this should be ignored as we
        // do not want applications to fail.

        /*String realPath = VirtualFileSystem.translateVFSPath(path);
     throw new PermissionDeniedException(
    "Cannot set file attributes using virtual file system for file "
    + realPath);*/
    }

    /**
 *
 *
 * @param handle
 * @param attrs
 *
 * @throws PermissionDeniedException
 * @throws IOException
 * @throws InvalidHandleException
 */
    public void setFileAttributes(byte[] handle, FileAttributes attrs)
        throws PermissionDeniedException, IOException, InvalidHandleException {
    }

    /**
 *
 *
 * @param path
 *
 * @return
 *
 * @throws UnsupportedFileOperationException
 * @throws FileNotFoundException
 * @throws IOException
 * @throws PermissionDeniedException
 */
    public SftpFile readSymbolicLink(String path)
        throws UnsupportedFileOperationException, FileNotFoundException, 
            IOException, PermissionDeniedException {
        throw new UnsupportedFileOperationException(
            "Symbolic links are not supported by the Virtual File System");
    }

    /**
 *
 *
 * @param link
 * @param target
 *
 * @throws UnsupportedFileOperationException
 * @throws FileNotFoundException
 * @throws IOException
 * @throws PermissionDeniedException
 */
    public void createSymbolicLink(String link, String target)
        throws UnsupportedFileOperationException, FileNotFoundException, 
            IOException, PermissionDeniedException {
        throw new UnsupportedFileOperationException(
            "Symbolic links are not supported by the Virtual File System");
    }

    /**
 *
 *
 * @param path
 *
 * @return
 *
 * @throws IOException
 */
    public boolean fileExists(String path) throws IOException {
        File f = new File(VirtualFileSystem.translateVFSPath(path));

        return f.exists();
    }

    public String getDefaultPath(String username) throws FileNotFoundException {
        return getVFSHomeDirectory(username);
    }

    /**
 *
 *
 * @param path
 *
 * @return
 *
 * @throws IOException
 * @throws FileNotFoundException
 */
    public String getCanonicalPath(String path)
        throws IOException, FileNotFoundException {
        File f = new File(VirtualFileSystem.translateVFSPath(path));

        return f.getCanonicalPath();
    }

    /**
 *
 *
 * @param path
 *
 * @return
 *
 * @throws FileNotFoundException
 */
    public String getRealPath(String path) throws FileNotFoundException {
        log.debug("Get real path for '" + path + "'");
        path = VirtualFileSystem.translateVFSPath(path);
        log.debug("Translated VFS is '" + path + "'");
        path = VirtualFileSystem.translateNFSPath(path);
        log.debug("Translated NFS is '" + path + "'");

        return path;
    }

    /**
 *
 *
 * @param username
 * @param path
 * @param permissions
 *
 * @throws PermissionDeniedException
 * @throws FileNotFoundException
 * @throws IOException
 */
    public void verifyPermissions(String username, String path,
        String permissions)
        throws PermissionDeniedException, FileNotFoundException, IOException {
        String vfspath = translateNFSPath(path);

        if (permissionHandler == null) {
            VFSMount mount = getMount(vfspath);
            VFSPermission perm;

            if (mount.getPermissions().containsKey(SshThread.getCurrentThreadUser())) {
                perm = (VFSPermission) mount.getPermissions().get(SshThread.getCurrentThreadUser());
            } else if (mount.getPermissions().containsKey("default")) {
                perm = (VFSPermission) mount.getPermissions().get("default");
            } else {
                throw new PermissionDeniedException(
                    "No permissions set for mount");
            }

            if (!perm.verifyPermissions(permissions)) {
                throw new PermissionDeniedException("Permission denied for " +
                    translateNFSPath(path));
            }
        } else {
            permissionHandler.verifyPermissions(username, path, permissions);
        }
    }

    class OpenFile {
        File f;
        RandomAccessFile raf;
        UnsignedInteger32 flags;

        public OpenFile(File f, RandomAccessFile raf, UnsignedInteger32 flags) {
            this.f = f;
            this.raf = raf;
            this.flags = flags;
        }

        public File getFile() {
            return f;
        }

        public RandomAccessFile getRandomAccessFile() {
            return raf;
        }

        public UnsignedInteger32 getFlags() {
            return flags;
        }
    }

    class OpenDirectory {
        File f;
        File[] children;
        int readpos = 0;
        String path;
        String realPath;

        public OpenDirectory(String realPath, String path, File f) {
            this.path = path;
            this.realPath = realPath;
            this.f = f;
            this.children = f.listFiles();
        }

        public File getFile() {
            return f;
        }

        public File[] getChildren() {
            return children;
        }

        public int getPosition() {
            return readpos;
        }

        public void setPosition(int readpos) {
            this.readpos = readpos;
        }
    }
}
j2ssh/src/com/sshtools/daemon/util/StringScanner.java100644      0      0       16661  7765072224  20351 0ustar     0      0 /*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
 *
 *  Contributions made by:
 *
 *  Brett Smith
 *  Richard Pernavas
 *  Erwin Bolwidt
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  License document supplied with your distribution for more details.
 *
 */

// ===========================================================================
// CONTENT  : CLASS StringScanner
// AUTHOR   : Manfred Duchrow
// VERSION  : 1.1 - 29/09/2002
// HISTORY  :
//  11/07/2001  duma  CREATED
//	29/09/2002	duma	added		-> endReached(), endNotReached()
//
// Copyright (c) 2001-2002, by Manfred Duchrow. All rights reserved.
// ===========================================================================
package com.sshtools.daemon.util;


// ===========================================================================
// IMPORTS
// ===========================================================================

/**
 * Simple scanner that allows to navigate over the characters of a string.
 *
 * @author Manfred Duchrow
 * @version 1.1
 */
public class StringScanner {
    // =========================================================================
    // CONSTANTS
    // =========================================================================

    /**  */
    public static final char END_REACHED = (char) -1;

    // =========================================================================
    // INSTANCE VARIABLES
    // =========================================================================

    /**  */
    protected int length = 0;

    /**  */
    protected int position = 0;

    /**  */
    protected int pos_marker = 0;

    /**  */
    protected char[] buffer = null;

    // -------------------------------------------------------------------------
    // =========================================================================
    // CONSTRUCTORS
    // =========================================================================

    /**
 * Initialize the new instance with the string that should be scanned.
 *
 * @param stringToScan
 */
    public StringScanner(String stringToScan) {
        super();
        length = stringToScan.length();
        buffer = new char[length];
        stringToScan.getChars(0, length, buffer, 0);
    }

    // StringScanner()
    // =========================================================================
    // PUBLIC CLASS METHODS
    // =========================================================================

    /**
 * Returns true, if the given character indicates that the end of the
 * scanned string is reached.
 *
 * @param character
 *
 * @return
 */
    public boolean endReached(char character) {
        return (character == END_REACHED);
    }

    // endReached()
    // -------------------------------------------------------------------------

    /**
 * Returns true, if the given character does <b>not</b> indicate that the
 * end of the scanned string si reached.
 *
 * @param character
 *
 * @return
 */
    public boolean endNotReached(char character) {
        return (!endReached(character));
    }

    // endNotReached()
    // =========================================================================
    // PUBLIC INSTANCE METHODS
    // =========================================================================

    /**
 * Returns the string the scanner was initialized with
 *
 * @return
 */
    public String toString() {
        return new String(buffer);
    }

    // toString()
    // -------------------------------------------------------------------------

    /**
 * Moves the position pointer count characters. positive values move
 * forwards, negative backwards. The position never becomes negative !
 *
 * @param count
 */
    public void skip(int count) {
        position += count;

        if (position < 0) {
            position = 0;
        }
    }

    // skip()
    // -------------------------------------------------------------------------

    /**
 * Returns the character at the current position without changing the
 * position, that is subsequent calls to this method return always the
 * same character.
 *
 * @return
 */
    public char peek() {
        return ((position < length()) ? buffer[position] : END_REACHED);
    }

    // skip()
    // -------------------------------------------------------------------------

    /**
 * Returns the character at the current position and increments the
 * position afterwards by 1.
 *
 * @return
 */
    public char nextChar() {
        char next = this.peek();

        if (endNotReached(next)) {
            this.skip(1);
        }

        return next;
    }

    // nextChar()
    // -------------------------------------------------------------------------

    /**
 * Returns true, if the scanner has reached the end and a further
 * invocation  of nextChar() would return the END_REACHED character.
 *
 * @return
 */
    public boolean atEnd() {
        return (endReached(this.peek()));
    }

    // atEnd()
    // -------------------------------------------------------------------------

    /**
 * Returns true, if the scanner has not yet reached the end.
 *
 * @return
 */
    public boolean hasNext() {
        return !this.atEnd();
    }

    // hasNext()
    // -------------------------------------------------------------------------

    /**
 * Returns the next character that is no whitespace and leaves the position
 * pointer one character after the returned one.
 *
 * @return
 */
    public char nextNoneWhitespaceChar() {
        char next = this.nextChar();

        while ((endNotReached(next)) && (Character.isWhitespace(next))) {
            next = this.nextChar();
        }

        return next;
    }

    // nextNoneWhitespaceChar()
    // -------------------------------------------------------------------------

    /**
 * Returns the current position in the string
 *
 * @return
 */
    public int getPosition() {
        return position;
    }

    // getPosition()
    // -------------------------------------------------------------------------

    /**
 * Remembers the current position for later use with restorePosition()
 */
    public void markPosition() {
        pos_marker = position;
    }

    // markPosition()
    // -------------------------------------------------------------------------

    /**
 * Restores the position to the value of the latest markPosition() call
 */
    public void restorePosition() {
        this.setPosition(pos_marker);
    }

    // restorePosition()

    /**
 *
 *
 * @return
 */
    protected int length() {
        return length;
    }

    // length()
    // -------------------------------------------------------------------------
    protected void setPosition(int pos) {
        if ((pos >= 0) && (pos <= this.length())) {
            position = pos;
        }
    }

    // setPosition()
    // -------------------------------------------------------------------------
}


// class StringScanner
j2ssh/src/com/sshtools/daemon/util/StringExaminer.java100644      0      0       20012  7765072224  20511 0ustar     0      0 /*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
 *
 *  Contributions made by:
 *
 *  Brett Smith
 *  Richard Pernavas
 *  Erwin Bolwidt
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  License document supplied with your distribution for more details.
 *
 */

// ===========================================================================
// CONTENT  : CLASS StringExaminer
// AUTHOR   : Manfred Duchrow
// VERSION  : 1.0 - 29/09/2002
// HISTORY  :
//  29/09/2002  duma  CREATED
//
// Copyright (c) 2002, by Manfred Duchrow. All rights reserved.
// ===========================================================================
package com.sshtools.daemon.util;


// ===========================================================================
// IMPORTS
// ===========================================================================

/**
 * As a subclass of StringScanner this class allows more advanced navigation
 * over the underlying string.    <br>
 * That includes moving to positions of specific substrings etc.
 *
 * @author Manfred Duchrow
 * @version $Id: StringExaminer.java,v 1.7 2003/09/11 15:37:07 martianx Exp $
 */
public class StringExaminer extends StringScanner {
    // =========================================================================
    // CONSTANTS
    // =========================================================================
    // =========================================================================
    // INSTANCE VARIABLES
    // =========================================================================
    private boolean ignoreCase = false;

    // =========================================================================
    // CLASS METHODS
    // =========================================================================
    // =========================================================================
    // CONSTRUCTORS
    // =========================================================================

    /**
 * Initialize the new instance with the string to examine.   <br>
 * The string will be treated case-sensitive.
 *
 * @param stringToExamine The string that should be examined
 */
    public StringExaminer(String stringToExamine) {
        this(stringToExamine, false);
    }

    // StringExaminer()
    // -------------------------------------------------------------------------

    /**
 * Initialize the new instance with the string to examine.
 *
 * @param stringToExamine The string that should be examined
 * @param ignoreCase Specified whether or not treating the string case
 *        insensitive
 */
    public StringExaminer(String stringToExamine, boolean ignoreCase) {
        super(stringToExamine);
        this.ignoreCase(ignoreCase);
    }

    // StringExaminer()

    /**
 *
 *
 * @return
 */
    protected boolean ignoreCase() {
        return ignoreCase;
    }

    /**
 *
 *
 * @param newValue
 */
    protected void ignoreCase(boolean newValue) {
        ignoreCase = newValue;
    }

    // -------------------------------------------------------------------------
    // =========================================================================
    // PUBLIC INSTANCE METHODS
    // =========================================================================

    /**
 * Increments the position pointer up to the last character that matched
 * the character sequence in the given matchString. Returns true, if the
 * matchString was found, otherwise false.
 *
 * <p>
 * If the matchString was found, the next invocation of method nextChar()
 * returns the first character after that matchString.
 * </p>
 *
 * @param matchString The string to look up
 *
 * @return
 */
    public boolean skipAfter(String matchString) {
        char ch = '-';
        char matchChar = ' ';
        boolean found = false;
        int index = 0;

        if ((matchString == null) || (matchString.length() == 0)) {
            return false;
        }

        ch = this.nextChar();

        while ((endNotReached(ch)) && (!found)) {
            matchChar = matchString.charAt(index);

            if (this.charsAreEqual(ch, matchChar)) {
                index++;

                if (index >= matchString.length()) { // whole matchString checked ?
                    found = true;
                } else {
                    ch = this.nextChar();
                }
            } else {
                if (index == 0) {
                    ch = this.nextChar();
                } else {
                    index = 0;
                }
            }
        }

        return found;
    }

    // skipAfter()
    // -------------------------------------------------------------------------

    /**
 * Increments the position pointer up to the first character before the
 * character sequence in the given matchString. Returns true, if the
 * matchString was found, otherwise false.
 *
 * <p>
 * If the matchString was found, the next invocation of method nextChar()
 * returns the first character of that matchString from the position where
 * it was found inside the examined string.
 * </p>
 *
 * @param matchString The string to look up
 *
 * @return
 */
    public boolean skipBefore(String matchString) {
        boolean found;
        found = this.skipAfter(matchString);

        if (found) {
            this.skip(0 - matchString.length());
        }

        return found;
    }

    // skipBefore()
    // -------------------------------------------------------------------------

    /**
 * Returns the a string containing all characters from the current position
 * up to the end of the examined string.   <br>
 * The character position of the examiner is not changed by this method.
 *
 * @return
 */
    public String peekUpToEnd() {
        return this.upToEnd(true);
    }

    // peekUpToEnd()
    // -------------------------------------------------------------------------

    /**
 * Returns the a string containing all characters from the current position
 * up to the end of the examined string.   <br>
 * The character position is put to the end by this method. That means the
 * next invocation of nextChar() returns END_REACHED.
 *
 * @return
 */
    public String upToEnd() {
        return this.upToEnd(false);
    }

    // upToEnd()

    /**
 *
 *
 * @param char1
 * @param char2
 *
 * @return
 */
    protected boolean charsAreEqual(char char1, char char2) {
        return (this.ignoreCase())
        ? (Character.toUpperCase(char1) == Character.toUpperCase(char2))
        : (char1 == char2);
    }

    // charsAreEqual()
    // -------------------------------------------------------------------------

    /**
 * Returns the a string containing all characters from the current position
 * up to the end of the examined string.   <br>
 * Depending on the peek flag the character position of the examiner  is
 * unchanged (true) after calling this method or points behind the strings
 * last character.
 *
 * @param peek
 *
 * @return
 */
    protected String upToEnd(boolean peek) {
        char result = '-';
        int lastPosition = 0;
        StringBuffer buffer = new StringBuffer(100);
        lastPosition = this.getPosition();
        result = this.nextChar();

        while (endNotReached(result)) {
            buffer.append(result);
            result = this.nextChar();
        }

        if (peek) {
            this.setPosition(lastPosition);
        }

        return buffer.toString();
    }

    // upToEnd()
    // -------------------------------------------------------------------------
}


// class StringExaminer
j2ssh/src/com/sshtools/daemon/util/StringPattern.java100644      0      0       43151  7765072224  20367 0ustar     0      0 /*
 *  SSHTools - Java SSH2 API
 *
 *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
 *
 *  Contributions made by:
 *
 *  Brett Smith
 *  Richard Pernavas
 *  Erwin Bolwidt
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  You may also distribute it and/or modify it under the terms of the
 *  Apache style J2SSH Software License. A copy of which should have
 *  been provided with the distribution.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  License document supplied with your distribution for more details.
 *
 */

// ===========================================================================
// CONTENT  : CLASS StringPattern
// AUTHOR   : Manfred Duchrow
// VERSION  : 1.7 - 13/02/2003
// HISTORY  :
//  24/01/2000  duma  CREATED
//  08/01/2002  duma  bugfix  -> Handle *xxx (equal characters after star) correctly
//  16/01/2002  duma  changed -> Implements Serializable
//	06/07/2002	duma	bugfix	-> Couldn't match "London" on "L*n"
//	19/09/2002	duma	bugfix	-> Couldn't match "MA_DR_HRBLUB" on "*_HR*"
//	19/09/2002	duma	changed	-> Using now StringExaminer instead of CharacterIterator
//	29/09/2002	duma	changed	-> Refactored: Using StringExaminer instead of StringScanner
//	26/12/2002	duma	changed	-> Comment of matches() was wrong / new hasWildcard()
//	13/02/2003	duma	added		-> setDigitWildcardChar()
//
// Copyright (c) 2000-2003, by Manfred Duchrow. All rights reserved.
// ===========================================================================
package com.sshtools.daemon.util;


// ===========================================================================
// IMPORTS
// ===========================================================================
import java.io.*;


/**
 * This class provides services for checking strings against string-patterns.
 * Currently it supports the wildcards<br>
 * '' for any number of any character and <br>
 * '?' for any one character. The API is very simple:<br>
 * <br>
 * There are only the two class methods <i>match()</i> and
 * <i>matchIgnoreCase()</i>. <br>
 * Example: <br>
 * StringPattern.match( 'Hello World", "H W" ) ;  --> evaluates to true  <br>
 * StringPattern.matchIgnoreCase( 'StringPattern", "str???pat" ) ;  -->
 * evaluates to true  <br>
 *
 * @author Manfred Duchrow
 * @version 1.7
 */
public class StringPattern implements Serializable {
    // =========================================================================
    // CONSTANTS
    // =========================================================================

    /**  */
    protected final static String MULTI_WILDCARD = "*";

    /**  */
    protected final static char MULTICHAR_WILDCARD = '*';

    /**  */
    protected final static char SINGLECHAR_WILDCARD = '?';

    // =========================================================================
    // INSTANCE VARIABLES
    // =========================================================================
    private boolean ignoreCase = false;
    private String pattern = null;

    // -------------------------------------------------------------------------
    private Character digitWildcard = null;

    // -------------------------------------------------------------------------
    // =========================================================================
    // CONSTRUCTORS
    // =========================================================================

    /**
 * Initializes the new instance with the string pattern and the selecteion,
 * if case should be ignored when comparing characters.
 *
 * @param pattern The pattern to check against ( May contain '' and '?'
 *        wildcards )
 * @param ignoreCase Definition, if case sensitive character comparison or
 *        not.
 */
    public StringPattern(String pattern, boolean ignoreCase) {
        this.setPattern(pattern);
        this.setIgnoreCase(ignoreCase);
    }

    // StringPattern()
    // -------------------------------------------------------------------------

    /**
 * Initializes the new instance with the string pattern. The default is
 * case sensitive checking.
 *
 * @param pattern The pattern to check against ( May contain '' and '?'
 *        wildcards )
 */
    public StringPattern(String pattern) {
        this(pattern, false);
    }

    // StringPattern()
    // -------------------------------------------------------------------------

    /**
 * Initializes the new instance with the string pattern and a digit
 * wildcard  character. The default is case sensitive checking.
 *
 * @param pattern The pattern to check against ( May contain '', '?'
 *        wildcards and the digit wildcard )
 * @param digitWildcard A wildcard character that stands as placeholder for
 *        digits
 */
    public StringPattern(String pattern, char digitWildcard) {
        this(pattern, false, digitWildcard);
    }

    // StringPattern()
    // -------------------------------------------------------------------------

    /**
 * Initializes the new instance with the string pattern and the selecteion,
 * if case should be ignored when comparing characters plus a wildcard
 * character for digits.
 *
 * @param pattern The pattern to check against ( May contain '' and '?'
 *        wildcards )
 * @param ignoreCase Definition, if case sensitive character comparison or
 *        not.
 * @param digitWildcard A wildcard character that stands as placeholder for
 *        digits
 */
    public StringPattern(String pattern, boolean ignoreCase, char digitWildcard) {
        this.setPattern(pattern);
        this.setIgnoreCase(ignoreCase);
        this.setDigitWildcardChar(digitWildcard);
    }

    // StringPattern()

    /**
 * Returns whether or not the pattern matching ignores upper and lower case
 *
 * @return
 */
    public boolean getIgnoreCase() {
        return ignoreCase;
    }

    /**
 * Sets whether the pattern matching should ignore case or not
 *
 * @param newValue
 */
    public void setIgnoreCase(boolean newValue) {
        ignoreCase = newValue;
    }

    /**
 * Returns the pattern as string.
 *
 * @return
 */
    public String getPattern() {
        return pattern;
    }

    /**
 * Sets the pattern to a new value
 *
 * @param newValue
 */
    public void setPattern(String newValue) {
        pattern = newValue;
    }

    /**
 *
 *
 * @return
 */
    protected Character digitWildcard() {
        return digitWildcard;
    }

    /**
 *
 *
 * @param newValue
 */
    protected void digitWildcard(Character newValue) {
        digitWildcard = newValue;
    }

    // =========================================================================
    // CLASS METHODS
    // =========================================================================

    /**
 * Returns true, if the given probe string matches the given pattern.  <br>
 * The character comparison is done case sensitive.
 *
 * @param probe The string to check against the pattern.
 * @param pattern The patter, that probably contains wildcards ( '' or '?'
 *        )
 *
 * @return
 */
    public static boolean match(String probe, String pattern) {
        StringPattern stringPattern = new StringPattern(pattern, false);

        return (stringPattern.matches(probe));
    }

    // match()
    // -------------------------------------------------------------------------

    /**
 * Returns true, if the given probe string matches the given pattern.  <br>
 * The character comparison is done ignoring upper/lower-case.
 *
 * @param probe The string to check against the pattern.
 * @param pattern The patter, that probably contains wildcards ( '' or '?'
 *        )
 *
 * @return
 */
    public static boolean matchIgnoreCase(String probe, String pattern) {
        StringPattern stringPattern = new StringPattern(pattern, true);

        return (stringPattern.matches(probe));
    }

    // matchIgnoreCase()
    // -------------------------------------------------------------------------
    // =========================================================================
    // PUBLIC INSTANCE METHODS
    // =========================================================================

    /**
 * Tests if a specified string matches the pattern.
 *
 * @param probe The string to compare to the pattern
 *
 * @return true if and only if the probe matches the pattern, false
 *         otherwise.
 */
    public boolean matches(String probe) {
        StringExaminer patternIterator = null;
        StringExaminer probeIterator = null;
        char patternCh = '-';
        char probeCh = '-';
        String newPattern = null;
        String subPattern = null;
        int charIndex = 0;

        if (probe == null) {
            return false;
        }

        if (probe.length() == 0) {
            return false;
        }

        patternIterator = this.newExaminer(this.getPattern());
        probeIterator = this.newExaminer(probe);
        probeCh = probeIterator.nextChar();
        patternCh = this.getPatternChar(patternIterator, probeCh);

        while ((this.endNotReached(patternCh)) &&
                (this.endNotReached(probeCh))) {
            if (patternCh == MULTICHAR_WILDCARD) {
                patternCh = this.skipWildcards(patternIterator);

                if (this.endReached(patternCh)) {
                    return true; // No more characters after multi wildcard - So everything matches
                } else {
                    patternIterator.skip(-1);
                    newPattern = this.upToEnd(patternIterator);
                    charIndex = newPattern.indexOf(MULTICHAR_WILDCARD);

                    if (charIndex >= 0) {
                        subPattern = newPattern.substring(0, charIndex);

                        if (this.skipAfter(probeIterator, subPattern)) {
                            patternIterator = this.newExaminer(newPattern.substring(
                                        charIndex));
                            patternCh = probeCh;
                        } else {
                            return false;
                        }
                    } else {
                        probeIterator.skip(-1);

                        return this.matchReverse(newPattern, probeIterator);
                    }
                }
            }

            if (this.charsAreEqual(probeCh, patternCh)) {
                if (this.endNotReached(patternCh)) {
                    probeCh = probeIterator.nextChar();
                    patternCh = this.getPatternChar(patternIterator, probeCh);
                }
            } else {
                if (patternCh != MULTICHAR_WILDCARD) {
                    return false; // character is not matching - return immediately
                }
            }
        }

        // while()
        return ((this.endReached(patternCh)) && (this.endReached(probeCh)));
    }

    // matches()
    // -------------------------------------------------------------------------

    /**
 * Returns the pattern string.
 *
 * @see java.lang.Object#toString()
 */
    public String toString() {
        if (this.getPattern() == null) {
            return super.toString();
        } else {
            return this.getPattern();
        }
    }

    // toString()
    // -------------------------------------------------------------------------

    /**
 * Returns true if the pattern contains any '' or '?' wildcard character.
 *
 * @return
 */
    public boolean hasWildcard() {
        if (this.getPattern() == null) {
            return false;
        }

        if (this.hasDigitWildcard()) {
            if (this.getPattern().indexOf(this.digitWildcardChar()) >= 0) {
                return true;
            }
        }

        return (this.getPattern().indexOf(MULTI_WILDCARD) >= 0) ||
        (this.getPattern().indexOf(SINGLECHAR_WILDCARD) >= 0);
    }

    // hasWildcard()
    // -------------------------------------------------------------------------

    /**
 * Sets the given character as a wildcard character in this pattern to
 * match only digits ('0'-'9').   <br>
 *
 * @param digitWildcard The placeholder character for digits
 */
    public void setDigitWildcardChar(char digitWildcard) {
        if (digitWildcard <= 0) {
            this.digitWildcard(null);
        } else {
            this.digitWildcard(new Character(digitWildcard));
        }
    }

    // setDigitWildcardChar()

    /**
 *
 *
 * @return
 */
    protected boolean hasDigitWildcard() {
        return this.digitWildcard() != null;
    }

    // hasDigitWildcard()
    // -------------------------------------------------------------------------
    protected char digitWildcardChar() {
        if (this.hasDigitWildcard()) {
            return this.digitWildcard().charValue();
        } else {
            return '\0';
        }
    }

    // digitWildcardChar()
    // -------------------------------------------------------------------------

    /**
 * Moves the iterator position to the next character that is no wildcard.
 * Doesn't skip digit wildcards !
 *
 * @param iterator
 *
 * @return
 */
    protected char skipWildcards(StringExaminer iterator) {
        char result = '-';

        do {
            result = iterator.nextChar();
        } while ((result == MULTICHAR_WILDCARD) ||
                (result == SINGLECHAR_WILDCARD));

        return result;
    }

    // skipWildcards()
    // -------------------------------------------------------------------------

    /**
 * Increments the given iterator up to the last character that matched the
 * character sequence in the given matchString. Returns true, if the
 * matchString was found, otherwise false.
 *
 * @param examiner
 * @param matchString The string to be found (must not contain )
 *
 * @return
 */
    protected boolean skipAfter(StringExaminer examiner, String matchString) {
        // Do not use the method of StringExaminer anymore, because digit wildcard
        // support is in