From 063284837c8c366e5502b1b0264b8eb807b61732 Mon Sep 17 00:00:00 2001
From: Joe Robinson
+ *
+ * @author Daniel F. Savarese
+ * @see DatagramSocketFactory
+ ***/
+
+public abstract class DatagramSocketClient
+{
+ /***
+ * The default DatagramSocketFactory shared by all DatagramSocketClient
+ * instances.
+ ***/
+ private static final DatagramSocketFactory __DEFAULT_SOCKET_FACTORY =
+ new DefaultDatagramSocketFactory();
+
+ /*** The timeout to use after opening a socket. ***/
+ protected int _timeout_;
+
+ /*** The datagram socket used for the connection. ***/
+ protected DatagramSocket _socket_;
+
+ /***
+ * A status variable indicating if the client's socket is currently open.
+ ***/
+ protected boolean _isOpen_;
+
+ /*** The datagram socket's DatagramSocketFactory. ***/
+ protected DatagramSocketFactory _socketFactory_;
+
+ /***
+ * Default constructor for DatagramSocketClient. Initializes
+ * _socket_ to null, _timeout_ to 0, and _isOpen_ to false.
+ ***/
+ public DatagramSocketClient()
+ {
+ _socket_ = null;
+ _timeout_ = 0;
+ _isOpen_ = false;
+ _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
+ }
+
+
+ /***
+ * Opens a DatagramSocket on the local host at the first available port.
+ * Also sets the timeout on the socket to the default timeout set
+ * by {@link #setDefaultTimeout setDefaultTimeout() }.
+ *
+ * _isOpen_ is set to true after calling this method and _socket_
+ * is set to the newly opened socket.
+ *
+ * @exception SocketException If the socket could not be opened or the
+ * timeout could not be set.
+ ***/
+ public void open() throws SocketException
+ {
+ _socket_ = _socketFactory_.createDatagramSocket();
+ _socket_.setSoTimeout(_timeout_);
+ _isOpen_ = true;
+ }
+
+
+ /***
+ * Opens a DatagramSocket on the local host at a specified port.
+ * Also sets the timeout on the socket to the default timeout set
+ * by {@link #setDefaultTimeout setDefaultTimeout() }.
+ *
+ * _isOpen_ is set to true after calling this method and _socket_
+ * is set to the newly opened socket.
+ *
+ * @param port The port to use for the socket.
+ * @exception SocketException If the socket could not be opened or the
+ * timeout could not be set.
+ ***/
+ public void open(int port) throws SocketException
+ {
+ _socket_ = _socketFactory_.createDatagramSocket(port);
+ _socket_.setSoTimeout(_timeout_);
+ _isOpen_ = true;
+ }
+
+
+ /***
+ * Opens a DatagramSocket at the specified address on the local host
+ * at a specified port.
+ * Also sets the timeout on the socket to the default timeout set
+ * by {@link #setDefaultTimeout setDefaultTimeout() }.
+ *
+ * _isOpen_ is set to true after calling this method and _socket_
+ * is set to the newly opened socket.
+ *
+ * @param port The port to use for the socket.
+ * @param laddr The local address to use.
+ * @exception SocketException If the socket could not be opened or the
+ * timeout could not be set.
+ ***/
+ public void open(int port, InetAddress laddr) throws SocketException
+ {
+ _socket_ = _socketFactory_.createDatagramSocket(port, laddr);
+ _socket_.setSoTimeout(_timeout_);
+ _isOpen_ = true;
+ }
+
+
+
+ /***
+ * Closes the DatagramSocket used for the connection.
+ * You should call this method after you've finished using the class
+ * instance and also before you call {@link #open open() }
+ * again. _isOpen_ is set to false and _socket_ is set to null.
+ * If you call this method when the client socket is not open,
+ * a NullPointerException is thrown.
+ ***/
+ public void close()
+ {
+ _socket_.close();
+ _socket_ = null;
+ _isOpen_ = false;
+ }
+
+
+ /***
+ * Returns true if the client has a currently open socket.
+ *
+ * @return True if the client has a curerntly open socket, false otherwise.
+ ***/
+ public boolean isOpen()
+ {
+ return _isOpen_;
+ }
+
+
+ /***
+ * Set the default timeout in milliseconds to use when opening a socket.
+ * After a call to open, the timeout for the socket is set using this value.
+ * This method should be used prior to a call to {@link #open open()}
+ * and should not be confused with {@link #setSoTimeout setSoTimeout()}
+ * which operates on the currently open socket. _timeout_ contains
+ * the new timeout value.
+ *
+ * @param timeout The timeout in milliseconds to use for the datagram socket
+ * connection.
+ ***/
+ public void setDefaultTimeout(int timeout)
+ {
+ _timeout_ = timeout;
+ }
+
+
+ /***
+ * Returns the default timeout in milliseconds that is used when
+ * opening a socket.
+ *
+ * @return The default timeout in milliseconds that is used when
+ * opening a socket.
+ ***/
+ public int getDefaultTimeout()
+ {
+ return _timeout_;
+ }
+
+
+ /***
+ * Set the timeout in milliseconds of a currently open connection.
+ * Only call this method after a connection has been opened
+ * by {@link #open open()}.
+ *
+ * @param timeout The timeout in milliseconds to use for the currently
+ * open datagram socket connection.
+ ***/
+ public void setSoTimeout(int timeout) throws SocketException
+ {
+ _socket_.setSoTimeout(timeout);
+ }
+
+
+ /***
+ * Returns the timeout in milliseconds of the currently opened socket.
+ * If you call this method when the client socket is not open,
+ * a NullPointerException is thrown.
+ *
+ * @return The timeout in milliseconds of the currently opened socket.
+ ***/
+ public int getSoTimeout() throws SocketException
+ {
+ return _socket_.getSoTimeout();
+ }
+
+
+ /***
+ * Returns the port number of the open socket on the local host used
+ * for the connection. If you call this method when the client socket
+ * is not open, a NullPointerException is thrown.
+ *
+ * @return The port number of the open socket on the local host used
+ * for the connection.
+ ***/
+ public int getLocalPort()
+ {
+ return _socket_.getLocalPort();
+ }
+
+
+ /***
+ * Returns the local address to which the client's socket is bound.
+ * If you call this method when the client socket is not open, a
+ * NullPointerException is thrown.
+ *
+ * @return The local address to which the client's socket is bound.
+ ***/
+ public InetAddress getLocalAddress()
+ {
+ return _socket_.getLocalAddress();
+ }
+
+
+ /***
+ * Sets the DatagramSocketFactory used by the DatagramSocketClient
+ * to open DatagramSockets. If the factory value is null, then a default
+ * factory is used (only do this to reset the factory after having
+ * previously altered it).
+ *
+ * @param factory The new DatagramSocketFactory the DatagramSocketClient
+ * should use.
+ ***/
+ public void setDatagramSocketFactory(DatagramSocketFactory factory)
+ {
+ if (factory == null)
+ _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
+ else
+ _socketFactory_ = factory;
+ }
+}
diff --git a/org/apache/commons/net/DatagramSocketFactory.java b/org/apache/commons/net/DatagramSocketFactory.java
new file mode 100644
index 0000000..c152eb2
--- /dev/null
+++ b/org/apache/commons/net/DatagramSocketFactory.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+
+/***
+ * The DatagramSocketFactory interface provides a means for the
+ * programmer to control the creation of datagram sockets and
+ * provide his own DatagramSocket implementations for use by all
+ * classes derived from
+ * {@link org.apache.commons.net.DatagramSocketClient}
+ * .
+ * This allows you to provide your own DatagramSocket implementations and
+ * to perform security checks or browser capability requests before
+ * creating a DatagramSocket.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public interface DatagramSocketFactory
+{
+
+ /***
+ * Creates a DatagramSocket on the local host at the first available port.
+ *
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket() throws SocketException;
+
+ /***
+ * Creates a DatagramSocket on the local host at a specified port.
+ *
+ * @param port The port to use for the socket.
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket(int port) throws SocketException;
+
+ /***
+ * Creates a DatagramSocket at the specified address on the local host
+ * at a specified port.
+ *
+ * @param port The port to use for the socket.
+ * @param laddr The local address to use.
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket(int port, InetAddress laddr)
+ throws SocketException;
+}
diff --git a/org/apache/commons/net/DefaultDatagramSocketFactory.java b/org/apache/commons/net/DefaultDatagramSocketFactory.java
new file mode 100644
index 0000000..3983fcb
--- /dev/null
+++ b/org/apache/commons/net/DefaultDatagramSocketFactory.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+
+/***
+ * DefaultDatagramSocketFactory implements the DatagramSocketFactory
+ * interface by simply wrapping the java.net.DatagramSocket
+ * constructors. It is the default DatagramSocketFactory used by
+ * {@link org.apache.commons.net.DatagramSocketClient}
+ * implementations.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see DatagramSocketFactory
+ * @see DatagramSocketClient
+ * @see DatagramSocketClient#setDatagramSocketFactory
+ ***/
+
+public class DefaultDatagramSocketFactory implements DatagramSocketFactory
+{
+
+ /***
+ * Creates a DatagramSocket on the local host at the first available port.
+ *
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket() throws SocketException
+ {
+ return new DatagramSocket();
+ }
+
+ /***
+ * Creates a DatagramSocket on the local host at a specified port.
+ *
+ * @param port The port to use for the socket.
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket(int port) throws SocketException
+ {
+ return new DatagramSocket(port);
+ }
+
+ /***
+ * Creates a DatagramSocket at the specified address on the local host
+ * at a specified port.
+ *
+ * @param port The port to use for the socket.
+ * @param laddr The local address to use.
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket(int port, InetAddress laddr)
+ throws SocketException
+ {
+ return new DatagramSocket(port, laddr);
+ }
+}
diff --git a/org/apache/commons/net/DefaultSocketFactory.java b/org/apache/commons/net/DefaultSocketFactory.java
new file mode 100644
index 0000000..e809f84
--- /dev/null
+++ b/org/apache/commons/net/DefaultSocketFactory.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import javax.net.SocketFactory;
+
+/***
+ * DefaultSocketFactory implements the SocketFactory interface by
+ * simply wrapping the java.net.Socket and java.net.ServerSocket
+ * constructors. It is the default SocketFactory used by
+ * {@link org.apache.commons.net.SocketClient}
+ * implementations.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SocketFactory
+ * @see SocketClient
+ * @see SocketClient#setSocketFactory
+ ***/
+
+public class DefaultSocketFactory extends SocketFactory
+{
+
+ /***
+ * Creates a Socket connected to the given host and port.
+ *
+ * @param host The hostname to connect to.
+ * @param port The port to connect to.
+ * @return A Socket connected to the given host and port.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ * @exception IOException If an I/O error occurs while creating the Socket.
+ ***/
+ @Override
+ public Socket createSocket(String host, int port)
+ throws UnknownHostException, IOException
+ {
+ return new Socket(host, port);
+ }
+
+ /***
+ * Creates a Socket connected to the given host and port.
+ *
+ * @param address The address of the host to connect to.
+ * @param port The port to connect to.
+ * @return A Socket connected to the given host and port.
+ * @exception IOException If an I/O error occurs while creating the Socket.
+ ***/
+ @Override
+ public Socket createSocket(InetAddress address, int port)
+ throws IOException
+ {
+ return new Socket(address, port);
+ }
+
+ /***
+ * Creates a Socket connected to the given host and port and
+ * originating from the specified local address and port.
+ *
+ * @param host The hostname to connect to.
+ * @param port The port to connect to.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
+ * @return A Socket connected to the given host and port.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ * @exception IOException If an I/O error occurs while creating the Socket.
+ ***/
+ @Override
+ public Socket createSocket(String host, int port,
+ InetAddress localAddr, int localPort)
+ throws UnknownHostException, IOException
+ {
+ return new Socket(host, port, localAddr, localPort);
+ }
+
+ /***
+ * Creates a Socket connected to the given host and port and
+ * originating from the specified local address and port.
+ *
+ * @param address The address of the host to connect to.
+ * @param port The port to connect to.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
+ * @return A Socket connected to the given host and port.
+ * @exception IOException If an I/O error occurs while creating the Socket.
+ ***/
+ @Override
+ public Socket createSocket(InetAddress address, int port,
+ InetAddress localAddr, int localPort)
+ throws IOException
+ {
+ return new Socket(address, port, localAddr, localPort);
+ }
+
+ /***
+ * Creates a ServerSocket bound to a specified port. A port
+ * of 0 will create the ServerSocket on a system-determined free port.
+ *
+ * @param port The port on which to listen, or 0 to use any free port.
+ * @return A ServerSocket that will listen on a specified port.
+ * @exception IOException If an I/O error occurs while creating
+ * the ServerSocket.
+ ***/
+ public ServerSocket createServerSocket(int port) throws IOException
+ {
+ return new ServerSocket(port);
+ }
+
+ /***
+ * Creates a ServerSocket bound to a specified port with a given
+ * maximum queue length for incoming connections. A port of 0 will
+ * create the ServerSocket on a system-determined free port.
+ *
+ * @param port The port on which to listen, or 0 to use any free port.
+ * @param backlog The maximum length of the queue for incoming connections.
+ * @return A ServerSocket that will listen on a specified port.
+ * @exception IOException If an I/O error occurs while creating
+ * the ServerSocket.
+ ***/
+ public ServerSocket createServerSocket(int port, int backlog)
+ throws IOException
+ {
+ return new ServerSocket(port, backlog);
+ }
+
+ /***
+ * Creates a ServerSocket bound to a specified port on a given local
+ * address with a given maximum queue length for incoming connections.
+ * A port of 0 will
+ * create the ServerSocket on a system-determined free port.
+ *
+ * @param port The port on which to listen, or 0 to use any free port.
+ * @param backlog The maximum length of the queue for incoming connections.
+ * @param bindAddr The local address to which the ServerSocket should bind.
+ * @return A ServerSocket that will listen on a specified port.
+ * @exception IOException If an I/O error occurs while creating
+ * the ServerSocket.
+ ***/
+ public ServerSocket createServerSocket(int port, int backlog,
+ InetAddress bindAddr)
+ throws IOException
+ {
+ return new ServerSocket(port, backlog, bindAddr);
+ }
+}
diff --git a/org/apache/commons/net/MalformedServerReplyException.class b/org/apache/commons/net/MalformedServerReplyException.class
new file mode 100644
index 0000000..6b04dd8
Binary files /dev/null and b/org/apache/commons/net/MalformedServerReplyException.class differ
diff --git a/org/apache/commons/net/MalformedServerReplyException.java b/org/apache/commons/net/MalformedServerReplyException.java
new file mode 100644
index 0000000..3cad5f0
--- /dev/null
+++ b/org/apache/commons/net/MalformedServerReplyException.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.io.IOException;
+
+/***
+ * This exception is used to indicate that the reply from a server
+ * could not be interpreted. Most of the NetComponents classes attempt
+ * to be as lenient as possible when receiving server replies. Many
+ * server implementations deviate from IETF protocol specifications, making
+ * it necessary to be as flexible as possible. However, there will be
+ * certain situations where it is not possible to continue an operation
+ * because the server reply could not be interpreted in a meaningful manner.
+ * In these cases, a MalformedServerReplyException should be thrown.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public class MalformedServerReplyException extends IOException
+{
+
+ /*** Constructs a MalformedServerReplyException with no message ***/
+ public MalformedServerReplyException()
+ {
+ super();
+ }
+
+ /***
+ * Constructs a MalformedServerReplyException with a specified message.
+ *
+ * @param message The message explaining the reason for the exception.
+ ***/
+ public MalformedServerReplyException(String message)
+ {
+ super(message);
+ }
+
+}
diff --git a/org/apache/commons/net/PrintCommandListener.java b/org/apache/commons/net/PrintCommandListener.java
new file mode 100644
index 0000000..d8e7a68
--- /dev/null
+++ b/org/apache/commons/net/PrintCommandListener.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.io.PrintWriter;
+import org.apache.commons.net.ProtocolCommandEvent;
+import org.apache.commons.net.ProtocolCommandListener;
+
+/***
+ * This is a support class for some of the example programs. It is
+ * a sample implementation of the ProtocolCommandListener interface
+ * which just prints out to a specified stream all command/reply traffic.
+ *
+ *
+ * @since 2.0
+ ***/
+
+public class PrintCommandListener implements ProtocolCommandListener
+{
+ private PrintWriter __writer;
+
+ public PrintCommandListener(PrintWriter writer)
+ {
+ __writer = writer;
+ }
+
+ public void protocolCommandSent(ProtocolCommandEvent event)
+ {
+ __writer.print(event.getMessage());
+ __writer.flush();
+ }
+
+ public void protocolReplyReceived(ProtocolCommandEvent event)
+ {
+ __writer.print(event.getMessage());
+ __writer.flush();
+ }
+}
+
diff --git a/org/apache/commons/net/ProtocolCommandEvent.class b/org/apache/commons/net/ProtocolCommandEvent.class
new file mode 100644
index 0000000..e558b69
Binary files /dev/null and b/org/apache/commons/net/ProtocolCommandEvent.class differ
diff --git a/org/apache/commons/net/ProtocolCommandEvent.java b/org/apache/commons/net/ProtocolCommandEvent.java
new file mode 100644
index 0000000..8977c03
--- /dev/null
+++ b/org/apache/commons/net/ProtocolCommandEvent.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+import java.util.EventObject;
+
+/***
+ * There exists a large class of IETF protocols that work by sending an
+ * ASCII text command and arguments to a server, and then receiving an
+ * ASCII text reply. For debugging and other purposes, it is extremely
+ * useful to log or keep track of the contents of the protocol messages.
+ * The ProtocolCommandEvent class coupled with the
+ * {@link org.apache.commons.net.ProtocolCommandListener}
+ * interface facilitate this process.
+ *
+ *
+ * @see ProtocolCommandListener
+ * @see ProtocolCommandSupport
+ * @author Daniel F. Savarese
+ ***/
+
+public class ProtocolCommandEvent extends EventObject
+{
+ private int __replyCode;
+ private boolean __isCommand;
+ private String __message, __command;
+
+ /***
+ * Creates a ProtocolCommandEvent signalling a command was sent to
+ * the server. ProtocolCommandEvents created with this constructor
+ * should only be sent after a command has been sent, but before the
+ * reply has been received.
+ *
+ * @param source The source of the event.
+ * @param command The string representation of the command type sent, not
+ * including the arguments (e.g., "STAT" or "GET").
+ * @param message The entire command string verbatim as sent to the server,
+ * including all arguments.
+ ***/
+ public ProtocolCommandEvent(Object source, String command, String message)
+ {
+ super(source);
+ __replyCode = 0;
+ __message = message;
+ __isCommand = true;
+ __command = command;
+ }
+
+
+ /***
+ * Creates a ProtocolCommandEvent signalling a reply to a command was
+ * received. ProtocolCommandEvents created with this constructor
+ * should only be sent after a complete command reply has been received
+ * fromt a server.
+ *
+ * @param source The source of the event.
+ * @param replyCode The integer code indicating the natureof the reply.
+ * This will be the protocol integer value for protocols
+ * that use integer reply codes, or the reply class constant
+ * corresponding to the reply for protocols like POP3 that use
+ * strings like OK rather than integer codes (i.e., POP3Repy.OK).
+ * @param message The entire reply as received from the server.
+ ***/
+ public ProtocolCommandEvent(Object source, int replyCode, String message)
+ {
+ super(source);
+ __replyCode = replyCode;
+ __message = message;
+ __isCommand = false;
+ __command = null;
+ }
+
+ /***
+ * Returns the string representation of the command type sent (e.g., "STAT"
+ * or "GET"). If the ProtocolCommandEvent is a reply event, then null
+ * is returned.
+ *
+ * @return The string representation of the command type sent, or null
+ * if this is a reply event.
+ ***/
+ public String getCommand()
+ {
+ return __command;
+ }
+
+
+ /***
+ * Returns the reply code of the received server reply. Undefined if
+ * this is not a reply event.
+ *
+ * @return The reply code of the received server reply. Undefined if
+ * not a reply event.
+ ***/
+ public int getReplyCode()
+ {
+ return __replyCode;
+ }
+
+ /***
+ * Returns true if the ProtocolCommandEvent was generated as a result
+ * of sending a command.
+ *
+ * @return true If the ProtocolCommandEvent was generated as a result
+ * of sending a command. False otherwise.
+ ***/
+ public boolean isCommand()
+ {
+ return __isCommand;
+ }
+
+ /***
+ * Returns true if the ProtocolCommandEvent was generated as a result
+ * of receiving a reply.
+ *
+ * @return true If the ProtocolCommandEvent was generated as a result
+ * of receiving a reply. False otherwise.
+ ***/
+ public boolean isReply()
+ {
+ return !isCommand();
+ }
+
+ /***
+ * Returns the entire message sent to or received from the server.
+ *
+ * @return The entire message sent to or received from the server.
+ ***/
+ public String getMessage()
+ {
+ return __message;
+ }
+}
diff --git a/org/apache/commons/net/ProtocolCommandListener.class b/org/apache/commons/net/ProtocolCommandListener.class
new file mode 100644
index 0000000..54d6a46
Binary files /dev/null and b/org/apache/commons/net/ProtocolCommandListener.class differ
diff --git a/org/apache/commons/net/ProtocolCommandListener.java b/org/apache/commons/net/ProtocolCommandListener.java
new file mode 100644
index 0000000..8089926
--- /dev/null
+++ b/org/apache/commons/net/ProtocolCommandListener.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+import java.util.EventListener;
+
+/***
+ * There exists a large class of IETF protocols that work by sending an
+ * ASCII text command and arguments to a server, and then receiving an
+ * ASCII text reply. For debugging and other purposes, it is extremely
+ * useful to log or keep track of the contents of the protocol messages.
+ * The ProtocolCommandListener interface coupled with the
+ * {@link ProtocolCommandEvent} class facilitate this process.
+ *
+ * To receive ProtocolCommandEvents, you merely implement the
+ * ProtocolCommandListener interface and register the class as a listener
+ * with a ProtocolCommandEvent source such as
+ * {@link org.apache.commons.net.ftp.FTPClient}.
+ *
+ *
+ * @see ProtocolCommandEvent
+ * @see ProtocolCommandSupport
+ * @author Daniel F. Savarese
+ ***/
+
+public interface ProtocolCommandListener extends EventListener
+{
+
+ /***
+ * This method is invoked by a ProtocolCommandEvent source after
+ * sending a protocol command to a server.
+ *
+ * @param event The ProtocolCommandEvent fired.
+ ***/
+ public void protocolCommandSent(ProtocolCommandEvent event);
+
+ /***
+ * This method is invoked by a ProtocolCommandEvent source after
+ * receiving a reply from a server.
+ *
+ * @param event The ProtocolCommandEvent fired.
+ ***/
+ public void protocolReplyReceived(ProtocolCommandEvent event);
+
+}
diff --git a/org/apache/commons/net/ProtocolCommandSupport.class b/org/apache/commons/net/ProtocolCommandSupport.class
new file mode 100644
index 0000000..70ee4eb
Binary files /dev/null and b/org/apache/commons/net/ProtocolCommandSupport.class differ
diff --git a/org/apache/commons/net/ProtocolCommandSupport.java b/org/apache/commons/net/ProtocolCommandSupport.java
new file mode 100644
index 0000000..1a51fb6
--- /dev/null
+++ b/org/apache/commons/net/ProtocolCommandSupport.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.io.Serializable;
+import java.util.EventListener;
+
+import org.apache.commons.net.util.ListenerList;
+
+/***
+ * ProtocolCommandSupport is a convenience class for managing a list of
+ * ProtocolCommandListeners and firing ProtocolCommandEvents. You can
+ * simply delegate ProtocolCommandEvent firing and listener
+ * registering/unregistering tasks to this class.
+ *
+ *
+ * @see ProtocolCommandEvent
+ * @see ProtocolCommandListener
+ * @author Daniel F. Savarese
+ ***/
+
+public class ProtocolCommandSupport implements Serializable
+{
+ private Object __source;
+ private ListenerList __listeners;
+
+ /***
+ * Creates a ProtocolCommandSupport instant using the indicated source
+ * as the source of fired ProtocolCommandEvents.
+ *
+ * @param source The source to use for all generated ProtocolCommandEvents.
+ ***/
+ public ProtocolCommandSupport(Object source)
+ {
+ __listeners = new ListenerList();
+ __source = source;
+ }
+
+
+ /***
+ * Fires a ProtocolCommandEvent signalling the sending of a command to all
+ * registered listeners, invoking their
+ * {@link org.apache.commons.net.ProtocolCommandListener#protocolCommandSent protocolCommandSent() }
+ * methods.
+ *
+ * @param command The string representation of the command type sent, not
+ * including the arguments (e.g., "STAT" or "GET").
+ * @param message The entire command string verbatim as sent to the server,
+ * including all arguments.
+ ***/
+ public void fireCommandSent(String command, String message)
+ {
+ ProtocolCommandEvent event;
+
+ event = new ProtocolCommandEvent(__source, command, message);
+
+ for (EventListener listener : __listeners)
+ {
+ ((ProtocolCommandListener)listener).protocolCommandSent(event);
+ }
+ }
+
+ /***
+ * Fires a ProtocolCommandEvent signalling the reception of a command reply
+ * to all registered listeners, invoking their
+ * {@link org.apache.commons.net.ProtocolCommandListener#protocolReplyReceived protocolReplyReceived() }
+ * methods.
+ *
+ * @param replyCode The integer code indicating the natureof the reply.
+ * This will be the protocol integer value for protocols
+ * that use integer reply codes, or the reply class constant
+ * corresponding to the reply for protocols like POP3 that use
+ * strings like OK rather than integer codes (i.e., POP3Repy.OK).
+ * @param message The entire reply as received from the server.
+ ***/
+ public void fireReplyReceived(int replyCode, String message)
+ {
+ ProtocolCommandEvent event;
+ event = new ProtocolCommandEvent(__source, replyCode, message);
+
+ for (EventListener listener : __listeners)
+ {
+ ((ProtocolCommandListener)listener).protocolReplyReceived(event);
+ }
+ }
+
+ /***
+ * Adds a ProtocolCommandListener.
+ *
+ * @param listener The ProtocolCommandListener to add.
+ ***/
+ public void addProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ __listeners.addListener(listener);
+ }
+
+ /***
+ * Removes a ProtocolCommandListener.
+ *
+ * @param listener The ProtocolCommandListener to remove.
+ ***/
+ public void removeProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ __listeners.removeListener(listener);
+ }
+
+
+ /***
+ * Returns the number of ProtocolCommandListeners currently registered.
+ *
+ * @return The number of ProtocolCommandListeners currently registered.
+ ***/
+ public int getListenerCount()
+ {
+ return __listeners.getListenerCount();
+ }
+
+}
+
diff --git a/org/apache/commons/net/SocketClient.class b/org/apache/commons/net/SocketClient.class
new file mode 100644
index 0000000..216f590
Binary files /dev/null and b/org/apache/commons/net/SocketClient.class differ
diff --git a/org/apache/commons/net/SocketClient.java b/org/apache/commons/net/SocketClient.java
new file mode 100644
index 0000000..a5a8ead
--- /dev/null
+++ b/org/apache/commons/net/SocketClient.java
@@ -0,0 +1,586 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+
+import javax.net.ServerSocketFactory;
+import javax.net.SocketFactory;
+
+
+/**
+ * The SocketClient provides the basic operations that are required of
+ * client objects accessing sockets. It is meant to be
+ * subclassed to avoid having to rewrite the same code over and over again
+ * to open a socket, close a socket, set timeouts, etc. Of special note
+ * is the {@link #setSocketFactory setSocketFactory }
+ * method, which allows you to control the type of Socket the SocketClient
+ * creates for initiating network connections. This is especially useful
+ * for adding SSL or proxy support as well as better support for applets. For
+ * example, you could create a
+ * {@link org.apache.commons.net.SocketFactory} that
+ * requests browser security capabilities before creating a socket.
+ * All classes derived from SocketClient should use the
+ * {@link #_socketFactory_ _socketFactory_ } member variable to
+ * create Socket and ServerSocket instances rather than instanting
+ * them by directly invoking a constructor. By honoring this contract
+ * you guarantee that a user will always be able to provide his own
+ * Socket implementations by substituting his own SocketFactory.
+ * @author Daniel F. Savarese
+ * @see SocketFactory
+ */
+public abstract class SocketClient
+{
+ /**
+ * The end of line character sequence used by most IETF protocols. That
+ * is a carriage return followed by a newline: "\r\n"
+ */
+ public static final String NETASCII_EOL = "\r\n";
+
+ /** The default SocketFactory shared by all SocketClient instances. */
+ private static final SocketFactory __DEFAULT_SOCKET_FACTORY =
+ SocketFactory.getDefault();
+
+ private static final ServerSocketFactory __DEFAULT_SERVER_SOCKET_FACTORY =
+ ServerSocketFactory.getDefault();
+
+ /** The timeout to use after opening a socket. */
+ protected int _timeout_;
+
+ /** The socket used for the connection. */
+ protected Socket _socket_;
+
+ /** The default port the client should connect to. */
+ protected int _defaultPort_;
+
+ /** The socket's InputStream. */
+ protected InputStream _input_;
+
+ /** The socket's OutputStream. */
+ protected OutputStream _output_;
+
+ /** The socket's SocketFactory. */
+ protected SocketFactory _socketFactory_;
+
+ /** The socket's ServerSocket Factory. */
+ protected ServerSocketFactory _serverSocketFactory_;
+
+ /** The socket's connect timeout (0 = infinite timeout) */
+ private static final int DEFAULT_CONNECT_TIMEOUT = 0;
+ protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
+
+ /**
+ * Default constructor for SocketClient. Initializes
+ * _socket_ to null, _timeout_ to 0, _defaultPort to 0,
+ * _isConnected_ to false, and _socketFactory_ to a shared instance of
+ * {@link org.apache.commons.net.DefaultSocketFactory}.
+ */
+ public SocketClient()
+ {
+ _socket_ = null;
+ _input_ = null;
+ _output_ = null;
+ _timeout_ = 0;
+ _defaultPort_ = 0;
+ _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
+ _serverSocketFactory_ = __DEFAULT_SERVER_SOCKET_FACTORY;
+ }
+
+
+ /**
+ * Because there are so many connect() methods, the _connectAction_()
+ * method is provided as a means of performing some action immediately
+ * after establishing a connection, rather than reimplementing all
+ * of the connect() methods. The last action performed by every
+ * connect() method after opening a socket is to call this method.
+ *
+ * This method sets the timeout on the just opened socket to the default
+ * timeout set by {@link #setDefaultTimeout setDefaultTimeout() },
+ * sets _input_ and _output_ to the socket's InputStream and OutputStream
+ * respectively, and sets _isConnected_ to true.
+ *
+ * Subclasses overriding this method should start by calling
+ *
+ * @param host The remote host.
+ * @param port The port to connect to on the remote host.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ */
+ public void connect(InetAddress host, int port)
+ throws SocketException, IOException
+ {
+ _socket_ = _socketFactory_.createSocket();
+ _socket_.connect(new InetSocketAddress(host, port), connectTimeout);
+
+ _connectAction_();
+ }
+
+ /**
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the current host at a system assigned port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param hostname The name of the remote host.
+ * @param port The port to connect to on the remote host.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ */
+ public void connect(String hostname, int port)
+ throws SocketException, IOException
+ {
+ _socket_= _socketFactory_.createSocket();
+ _socket_.connect(new InetSocketAddress(hostname, port), connectTimeout);
+
+ _connectAction_();
+ }
+
+
+ /**
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the specified local address and port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param host The remote host.
+ * @param port The port to connect to on the remote host.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ */
+ public void connect(InetAddress host, int port,
+ InetAddress localAddr, int localPort)
+ throws SocketException, IOException
+ {
+ _socket_ = _socketFactory_.createSocket();
+ _socket_.bind(new InetSocketAddress(localAddr, localPort));
+ _socket_.connect(new InetSocketAddress(host, port), connectTimeout);
+
+ _connectAction_();
+ }
+
+
+ /**
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the specified local address and port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param hostname The name of the remote host.
+ * @param port The port to connect to on the remote host.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ */
+ public void connect(String hostname, int port,
+ InetAddress localAddr, int localPort)
+ throws SocketException, IOException
+ {
+ _socket_ =
+ _socketFactory_.createSocket(hostname, port, localAddr, localPort);
+ _connectAction_();
+ }
+
+
+ /**
+ * Opens a Socket connected to a remote host at the current default port
+ * and originating from the current host at a system assigned port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param host The remote host.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ */
+ public void connect(InetAddress host) throws SocketException, IOException
+ {
+ connect(host, _defaultPort_);
+ }
+
+
+ /**
+ * Opens a Socket connected to a remote host at the current default
+ * port and originating from the current host at a system assigned port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param hostname The name of the remote host.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ */
+ public void connect(String hostname) throws SocketException, IOException
+ {
+ connect(hostname, _defaultPort_);
+ }
+
+
+ /**
+ * Disconnects the socket connection.
+ * You should call this method after you've finished using the class
+ * instance and also before you call
+ * {@link #connect connect() }
+ * again. _isConnected_ is set to false, _socket_ is set to null,
+ * _input_ is set to null, and _output_ is set to null.
+ *
+ * @exception IOException If there is an error closing the socket.
+ */
+ public void disconnect() throws IOException
+ {
+ if (_socket_ != null) _socket_.close();
+ if (_input_ != null) _input_.close();
+ if (_output_ != null) _output_.close();
+ if (_socket_ != null) _socket_ = null;
+ _input_ = null;
+ _output_ = null;
+ }
+
+
+ /**
+ * Returns true if the client is currently connected to a server.
+ *
+ * @return True if the client is currently connected to a server,
+ * false otherwise.
+ */
+ public boolean isConnected()
+ {
+ if (_socket_ == null)
+ return false;
+
+ return _socket_.isConnected();
+ }
+
+
+ /**
+ * Sets the default port the SocketClient should connect to when a port
+ * is not specified. The {@link #_defaultPort_ _defaultPort_ }
+ * variable stores this value. If never set, the default port is equal
+ * to zero.
+ *
+ * @param port The default port to set.
+ */
+ public void setDefaultPort(int port)
+ {
+ _defaultPort_ = port;
+ }
+
+ /**
+ * Returns the current value of the default port (stored in
+ * {@link #_defaultPort_ _defaultPort_ }).
+ *
+ * @return The current value of the default port.
+ */
+ public int getDefaultPort()
+ {
+ return _defaultPort_;
+ }
+
+
+ /**
+ * Set the default timeout in milliseconds to use when opening a socket.
+ * This value is only used previous to a call to
+ * {@link #connect connect()}
+ * and should not be confused with {@link #setSoTimeout setSoTimeout()}
+ * which operates on an the currently opened socket. _timeout_ contains
+ * the new timeout value.
+ *
+ * @param timeout The timeout in milliseconds to use for the socket
+ * connection.
+ */
+ public void setDefaultTimeout(int timeout)
+ {
+ _timeout_ = timeout;
+ }
+
+
+ /**
+ * Returns the default timeout in milliseconds that is used when
+ * opening a socket.
+ *
+ * @return The default timeout in milliseconds that is used when
+ * opening a socket.
+ */
+ public int getDefaultTimeout()
+ {
+ return _timeout_;
+ }
+
+
+ /**
+ * Set the timeout in milliseconds of a currently open connection.
+ * Only call this method after a connection has been opened
+ * by {@link #connect connect()}.
+ *
+ * @param timeout The timeout in milliseconds to use for the currently
+ * open socket connection.
+ * @exception SocketException If the operation fails.
+ */
+ public void setSoTimeout(int timeout) throws SocketException
+ {
+ _socket_.setSoTimeout(timeout);
+ }
+
+
+ /**
+ * Set the underlying socket send buffer size.
+ *
+ * @param size The size of the buffer in bytes.
+ * @throws SocketException
+ * @since 2.0
+ */
+ public void setSendBufferSize(int size) throws SocketException {
+ _socket_.setSendBufferSize(size);
+ }
+
+
+ /**
+ * Sets the underlying socket receive buffer size.
+ *
+ * @param size The size of the buffer in bytes.
+ * @throws SocketException
+ * @since 2.0
+ */
+ public void setReceiveBufferSize(int size) throws SocketException {
+ _socket_.setReceiveBufferSize(size);
+ }
+
+
+ /**
+ * Returns the timeout in milliseconds of the currently opened socket.
+ *
+ * @return The timeout in milliseconds of the currently opened socket.
+ * @exception SocketException If the operation fails.
+ */
+ public int getSoTimeout() throws SocketException
+ {
+ return _socket_.getSoTimeout();
+ }
+
+ /**
+ * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the
+ * currently opened socket.
+ *
+ * @param on True if Nagle's algorithm is to be enabled, false if not.
+ * @exception SocketException If the operation fails.
+ */
+ public void setTcpNoDelay(boolean on) throws SocketException
+ {
+ _socket_.setTcpNoDelay(on);
+ }
+
+
+ /**
+ * Returns true if Nagle's algorithm is enabled on the currently opened
+ * socket.
+ *
+ * @return True if Nagle's algorithm is enabled on the currently opened
+ * socket, false otherwise.
+ * @exception SocketException If the operation fails.
+ */
+ public boolean getTcpNoDelay() throws SocketException
+ {
+ return _socket_.getTcpNoDelay();
+ }
+
+
+ /**
+ * Sets the SO_LINGER timeout on the currently opened socket.
+ *
+ * @param on True if linger is to be enabled, false if not.
+ * @param val The linger timeout (in hundredths of a second?)
+ * @exception SocketException If the operation fails.
+ */
+ public void setSoLinger(boolean on, int val) throws SocketException
+ {
+ _socket_.setSoLinger(on, val);
+ }
+
+
+ /**
+ * Returns the current SO_LINGER timeout of the currently opened socket.
+ *
+ * @return The current SO_LINGER timeout. If SO_LINGER is disabled returns
+ * -1.
+ * @exception SocketException If the operation fails.
+ */
+ public int getSoLinger() throws SocketException
+ {
+ return _socket_.getSoLinger();
+ }
+
+
+ /**
+ * Returns the port number of the open socket on the local host used
+ * for the connection.
+ *
+ * @return The port number of the open socket on the local host used
+ * for the connection.
+ */
+ public int getLocalPort()
+ {
+ return _socket_.getLocalPort();
+ }
+
+
+ /**
+ * Returns the local address to which the client's socket is bound.
+ *
+ * @return The local address to which the client's socket is bound.
+ */
+ public InetAddress getLocalAddress()
+ {
+ return _socket_.getLocalAddress();
+ }
+
+ /**
+ * Returns the port number of the remote host to which the client is
+ * connected.
+ *
+ * @return The port number of the remote host to which the client is
+ * connected.
+ */
+ public int getRemotePort()
+ {
+ return _socket_.getPort();
+ }
+
+
+ /**
+ * @return The remote address to which the client is connected.
+ */
+ public InetAddress getRemoteAddress()
+ {
+ return _socket_.getInetAddress();
+ }
+
+
+ /**
+ * Verifies that the remote end of the given socket is connected to the
+ * the same host that the SocketClient is currently connected to. This
+ * is useful for doing a quick security check when a client needs to
+ * accept a connection from a server, such as an FTP data connection or
+ * a BSD R command standard error stream.
+ *
+ * @return True if the remote hosts are the same, false if not.
+ */
+ public boolean verifyRemote(Socket socket)
+ {
+ InetAddress host1, host2;
+
+ host1 = socket.getInetAddress();
+ host2 = getRemoteAddress();
+
+ return host1.equals(host2);
+ }
+
+
+ /**
+ * Sets the SocketFactory used by the SocketClient to open socket
+ * connections. If the factory value is null, then a default
+ * factory is used (only do this to reset the factory after having
+ * previously altered it).
+ *
+ * @param factory The new SocketFactory the SocketClient should use.
+ */
+ public void setSocketFactory(SocketFactory factory)
+ {
+ if (factory == null)
+ _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
+ else
+ _socketFactory_ = factory;
+ }
+
+ /**
+ * Sets the ServerSocketFactory used by the SocketClient to open ServerSocket
+ * connections. If the factory value is null, then a default
+ * factory is used (only do this to reset the factory after having
+ * previously altered it).
+ *
+ * @param factory The new ServerSocketFactory the SocketClient should use.
+ * @since 2.0
+ */
+ public void setServerSocketFactory(ServerSocketFactory factory) {
+ if (factory == null)
+ _serverSocketFactory_ = __DEFAULT_SERVER_SOCKET_FACTORY;
+ else
+ _serverSocketFactory_ = factory;
+ }
+
+ /**
+ * Sets the connection timeout in milliseconds, which will be passed to the {@link Socket} object's
+ * connect() method.
+ * @param connectTimeout The connection timeout to use (in ms)
+ * @since 2.0
+ */
+ public void setConnectTimeout(int connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ }
+
+ /**
+ * Get the underlying socket connection timeout.
+ * @return
+ * @since 2.0
+ */
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+
+
+
+}
+
+
diff --git a/org/apache/commons/net/bsd/RCommandClient.java b/org/apache/commons/net/bsd/RCommandClient.java
new file mode 100644
index 0000000..50cb87a
--- /dev/null
+++ b/org/apache/commons/net/bsd/RCommandClient.java
@@ -0,0 +1,402 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.bsd;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.BindException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+
+import org.apache.commons.net.io.SocketInputStream;
+
+/***
+ * RCommandClient is very similar to
+ * {@link org.apache.commons.net.bsd.RExecClient},
+ * from which it is derived, and implements the rcmd() facility that
+ * first appeared in 4.2BSD Unix. rcmd() is the facility used by the rsh
+ * (rshell) and other commands to execute a command on another machine
+ * from a trusted host without issuing a password. The trust relationship
+ * between two machines is established by the contents of a machine's
+ * /etc/hosts.equiv file and a user's .rhosts file. These files specify
+ * from which hosts and accounts on those hosts rcmd() requests will be
+ * accepted. The only additional measure for establishing trust is that
+ * all client connections must originate from a port between 512 and 1023.
+ * Consequently, there is an upper limit to the number of rcmd connections
+ * that can be running simultaneously. The required ports are reserved
+ * ports on Unix systems, and can only be bound by a
+ * process running with root permissions (to accomplish this rsh, rlogin,
+ * and related commands usualy have the suid bit set). Therefore, on a
+ * Unix system, you will only be able to successfully use the RCommandClient
+ * class if the process runs as root. However, there is no such restriction
+ * on Windows95 and some other systems. The security risks are obvious.
+ * However, when carefully used, rcmd() can be very useful when used behind
+ * a firewall.
+ *
+ * As with virtually all of the client classes in org.apache.commons.net, this
+ * class derives from SocketClient. But it overrides most of its connection
+ * methods so that the local Socket will originate from an acceptable
+ * rshell port. The way to use RCommandClient is to first connect
+ * to the server, call the {@link #rcommand rcommand() } method,
+ * and then
+ * fetch the connection's input, output, and optionally error streams.
+ * Interaction with the remote command is controlled entirely through the
+ * I/O streams. Once you have finished processing the streams, you should
+ * invoke {@link org.apache.commons.net.bsd.RExecClient#disconnect disconnect() }
+ * to clean up properly.
+ *
+ * By default the standard output and standard error streams of the
+ * remote process are transmitted over the same connection, readable
+ * from the input stream returned by
+ * {@link org.apache.commons.net.bsd.RExecClient#getInputStream getInputStream() }
+ * . However, it is
+ * possible to tell the rshd daemon to return the standard error
+ * stream over a separate connection, readable from the input stream
+ * returned by {@link org.apache.commons.net.bsd.RExecClient#getErrorStream getErrorStream() }
+ * . You
+ * can specify that a separate connection should be created for standard
+ * error by setting the boolean
+ *
+ * @author Daniel F. Savarese
+ * @see org.apache.commons.net.SocketClient
+ * @see RExecClient
+ * @see RLoginClient
+ ***/
+
+public class RCommandClient extends RExecClient
+{
+ /***
+ * The default rshell port. Set to 514 in BSD Unix.
+ ***/
+ public static final int DEFAULT_PORT = 514;
+
+ /***
+ * The smallest port number an rcmd client may use. By BSD convention
+ * this number is 512.
+ ***/
+ public static final int MIN_CLIENT_PORT = 512;
+
+ /***
+ * The largest port number an rcmd client may use. By BSD convention
+ * this number is 1023.
+ ***/
+ public static final int MAX_CLIENT_PORT = 1023;
+
+ // Overrides method in RExecClient in order to implement proper
+ // port number limitations.
+ @Override
+ InputStream _createErrorStream() throws IOException
+ {
+ int localPort;
+ ServerSocket server;
+ Socket socket;
+
+ localPort = MAX_CLIENT_PORT;
+ server = null; // Keep compiler from barfing
+
+ for (localPort = MAX_CLIENT_PORT; localPort >= MIN_CLIENT_PORT; --localPort)
+ {
+ try
+ {
+ server = _serverSocketFactory_.createServerSocket(localPort, 1,
+ getLocalAddress());
+ }
+ catch (SocketException e)
+ {
+ continue;
+ }
+ break;
+ }
+
+ if (localPort < MIN_CLIENT_PORT)
+ throw new BindException("All ports in use.");
+
+ _output_.write(Integer.toString(server.getLocalPort()).getBytes());
+ _output_.write('\0');
+ _output_.flush();
+
+ socket = server.accept();
+ server.close();
+
+ if (isRemoteVerificationEnabled() && !verifyRemote(socket))
+ {
+ socket.close();
+ throw new IOException(
+ "Security violation: unexpected connection attempt by " +
+ socket.getInetAddress().getHostAddress());
+ }
+
+ return (new SocketInputStream(socket, socket.getInputStream()));
+ }
+
+ /***
+ * The default RCommandClient constructor. Initializes the
+ * default port to
+ * @param host The remote host.
+ * @param port The port to connect to on the remote host.
+ * @param localAddr The local address to use.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception BindException If all acceptable rshell ports are in use.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ ***/
+ public void connect(InetAddress host, int port, InetAddress localAddr)
+ throws SocketException, BindException, IOException
+ {
+ int localPort;
+
+ localPort = MAX_CLIENT_PORT;
+
+ for (localPort = MAX_CLIENT_PORT; localPort >= MIN_CLIENT_PORT; --localPort)
+ {
+ try
+ {
+ _socket_ =
+ _socketFactory_.createSocket(host, port, localAddr, localPort);
+ }
+ catch (BindException be) {
+ continue;
+ }
+ catch (SocketException e)
+ {
+ continue;
+ }
+ break;
+ }
+
+ if (localPort < MIN_CLIENT_PORT)
+ throw new BindException("All ports in use or insufficient permssion.");
+
+ _connectAction_();
+ }
+
+
+
+ /***
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the current host at a port in a range acceptable
+ * to the BSD rshell daemon.
+ * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param host The remote host.
+ * @param port The port to connect to on the remote host.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception BindException If all acceptable rshell ports are in use.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ ***/
+ @Override
+ public void connect(InetAddress host, int port)
+ throws SocketException, IOException
+ {
+ connect(host, port, InetAddress.getLocalHost());
+ }
+
+
+ /***
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the current host at a port in a range acceptable
+ * to the BSD rshell daemon.
+ * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param hostname The name of the remote host.
+ * @param port The port to connect to on the remote host.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception BindException If all acceptable rshell ports are in use.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ ***/
+ @Override
+ public void connect(String hostname, int port)
+ throws SocketException, IOException
+ {
+ connect(InetAddress.getByName(hostname), port, InetAddress.getLocalHost());
+ }
+
+
+ /***
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the specified local address using a port in a range
+ * acceptable to the BSD rshell daemon.
+ * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param hostname The remote host.
+ * @param port The port to connect to on the remote host.
+ * @param localAddr The local address to use.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception BindException If all acceptable rshell ports are in use.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ ***/
+ public void connect(String hostname, int port, InetAddress localAddr)
+ throws SocketException, IOException
+ {
+ connect(InetAddress.getByName(hostname), port, localAddr);
+ }
+
+
+ /***
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the specified local address and port. The
+ * local port must lie between
+ * @param host The remote host.
+ * @param port The port to connect to on the remote host.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ * @exception IllegalArgumentException If an invalid local port number
+ * is specified.
+ ***/
+ @Override
+ public void connect(InetAddress host, int port,
+ InetAddress localAddr, int localPort)
+ throws SocketException, IOException, IllegalArgumentException
+ {
+ if (localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT)
+ throw new IllegalArgumentException("Invalid port number " + localPort);
+ super.connect(host, port, localAddr, localPort);
+ }
+
+
+ /***
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the specified local address and port. The
+ * local port must lie between
+ * @param hostname The name of the remote host.
+ * @param port The port to connect to on the remote host.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ * @exception IllegalArgumentException If an invalid local port number
+ * is specified.
+ ***/
+ @Override
+ public void connect(String hostname, int port,
+ InetAddress localAddr, int localPort)
+ throws SocketException, IOException, IllegalArgumentException
+ {
+ if (localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT)
+ throw new IllegalArgumentException("Invalid port number " + localPort);
+ super.connect(hostname, port, localAddr, localPort);
+ }
+
+
+ /***
+ * Remotely executes a command through the rshd daemon on the server
+ * to which the RCommandClient is connected. After calling this method,
+ * you may interact with the remote process through its standard input,
+ * output, and error streams. You will typically be able to detect
+ * the termination of the remote process after reaching end of file
+ * on its standard output (accessible through
+ * {@link #getInputStream getInputStream() }. Disconnecting
+ * from the server or closing the process streams before reaching
+ * end of file will not necessarily terminate the remote process.
+ *
+ * If a separate error stream is requested, the remote server will
+ * connect to a local socket opened by RCommandClient, providing an
+ * independent stream through which standard error will be transmitted.
+ * The local socket must originate from a secure port (512 - 1023),
+ * and rcommand() ensures that this will be so.
+ * RCommandClient will also do a simple security check when it accepts a
+ * connection for this error stream. If the connection does not originate
+ * from the remote server, an IOException will be thrown. This serves as
+ * a simple protection against possible hijacking of the error stream by
+ * an attacker monitoring the rexec() negotiation. You may disable this
+ * behavior with
+ * {@link org.apache.commons.net.bsd.RExecClient#setRemoteVerificationEnabled setRemoteVerificationEnabled()}
+ * .
+ *
+ * @param localUsername The user account on the local machine that is
+ * requesting the command execution.
+ * @param remoteUsername The account name on the server through which to
+ * execute the command.
+ * @param command The command, including any arguments, to execute.
+ * @param separateErrorStream True if you would like the standard error
+ * to be transmitted through a different stream than standard output.
+ * False if not.
+ * @exception IOException If the rcommand() attempt fails. The exception
+ * will contain a message indicating the nature of the failure.
+ ***/
+ public void rcommand(String localUsername, String remoteUsername,
+ String command, boolean separateErrorStream)
+ throws IOException
+ {
+ rexec(localUsername, remoteUsername, command, separateErrorStream);
+ }
+
+
+ /***
+ * Same as
+ *
+ * As with virtually all of the client classes in org.apache.commons.net, this
+ * class derives from SocketClient, inheriting its connection methods.
+ * The way to use RExecClient is to first connect
+ * to the server, call the {@link #rexec rexec() } method, and then
+ * fetch the connection's input, output, and optionally error streams.
+ * Interaction with the remote command is controlled entirely through the
+ * I/O streams. Once you have finished processing the streams, you should
+ * invoke {@link #disconnect disconnect() } to clean up properly.
+ *
+ * By default the standard output and standard error streams of the
+ * remote process are transmitted over the same connection, readable
+ * from the input stream returned by
+ * {@link #getInputStream getInputStream() }. However, it is
+ * possible to tell the rexecd daemon to return the standard error
+ * stream over a separate connection, readable from the input stream
+ * returned by {@link #getErrorStream getErrorStream() }. You
+ * can specify that a separate connection should be created for standard
+ * error by setting the boolean
+ *
+ * @author Daniel F. Savarese
+ * @see SocketClient
+ * @see RCommandClient
+ * @see RLoginClient
+ ***/
+
+public class RExecClient extends SocketClient
+{
+ /***
+ * The default rexec port. Set to 512 in BSD Unix.
+ ***/
+ public static final int DEFAULT_PORT = 512;
+
+ private boolean __remoteVerificationEnabled;
+
+ /***
+ * If a separate error stream is requested,
+ * @return The InputStream from which the standard output of the remote
+ * process can be read.
+ ***/
+ public InputStream getInputStream()
+ {
+ return _input_;
+ }
+
+
+ /***
+ * Returns the OutputStream through which the standard input of the remote
+ * process can be written. The output stream will only be set after a
+ * successful rexec() invocation.
+ *
+ * @return The OutputStream through which the standard input of the remote
+ * process can be written.
+ ***/
+ public OutputStream getOutputStream()
+ {
+ return _output_;
+ }
+
+
+ /***
+ * Returns the InputStream from which the standard error of the remote
+ * process can be read if a separate error stream is requested from
+ * the server. Otherwise, null will be returned. The error stream
+ * will only be set after a successful rexec() invocation.
+ *
+ * @return The InputStream from which the standard error of the remote
+ * process can be read if a separate error stream is requested from
+ * the server. Otherwise, null will be returned.
+ ***/
+ public InputStream getErrorStream()
+ {
+ return _errorStream_;
+ }
+
+
+ /***
+ * Remotely executes a command through the rexecd daemon on the server
+ * to which the RExecClient is connected. After calling this method,
+ * you may interact with the remote process through its standard input,
+ * output, and error streams. You will typically be able to detect
+ * the termination of the remote process after reaching end of file
+ * on its standard output (accessible through
+ * {@link #getInputStream getInputStream() }. Disconnecting
+ * from the server or closing the process streams before reaching
+ * end of file will not necessarily terminate the remote process.
+ *
+ * If a separate error stream is requested, the remote server will
+ * connect to a local socket opened by RExecClient, providing an
+ * independent stream through which standard error will be transmitted.
+ * RExecClient will do a simple security check when it accepts a
+ * connection for this error stream. If the connection does not originate
+ * from the remote server, an IOException will be thrown. This serves as
+ * a simple protection against possible hijacking of the error stream by
+ * an attacker monitoring the rexec() negotiation. You may disable this
+ * behavior with {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}
+ * .
+ *
+ * @param username The account name on the server through which to execute
+ * the command.
+ * @param password The plain text password of the user account.
+ * @param command The command, including any arguments, to execute.
+ * @param separateErrorStream True if you would like the standard error
+ * to be transmitted through a different stream than standard output.
+ * False if not.
+ * @exception IOException If the rexec() attempt fails. The exception
+ * will contain a message indicating the nature of the failure.
+ ***/
+ public void rexec(String username, String password,
+ String command, boolean separateErrorStream)
+ throws IOException
+ {
+ int ch;
+
+ if (separateErrorStream)
+ {
+ _errorStream_ = _createErrorStream();
+ }
+ else
+ {
+ _output_.write('\0');
+ }
+
+ _output_.write(username.getBytes());
+ _output_.write('\0');
+ _output_.write(password.getBytes());
+ _output_.write('\0');
+ _output_.write(command.getBytes());
+ _output_.write('\0');
+ _output_.flush();
+
+ ch = _input_.read();
+ if (ch > 0)
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ while ((ch = _input_.read()) != -1 && ch != '\n')
+ buffer.append((char)ch);
+
+ throw new IOException(buffer.toString());
+ }
+ else if (ch < 0)
+ {
+ throw new IOException("Server closed connection.");
+ }
+ }
+
+
+ /***
+ * Same as
+ * @exception IOException If there an error occurs while disconnecting.
+ ***/
+ @Override
+ public void disconnect() throws IOException
+ {
+ if (_errorStream_ != null)
+ _errorStream_.close();
+ _errorStream_ = null;
+ super.disconnect();
+ }
+
+
+ /***
+ * Enable or disable verification that the remote host connecting to
+ * create a separate error stream is the same as the host to which
+ * the standard out stream is connected. The default is for verification
+ * to be enabled. You may set this value at any time, whether the
+ * client is currently connected or not.
+ *
+ * @param enable True to enable verification, false to disable verification.
+ ***/
+ public final void setRemoteVerificationEnabled(boolean enable)
+ {
+ __remoteVerificationEnabled = enable;
+ }
+
+ /***
+ * Return whether or not verification of the remote host providing a
+ * separate error stream is enabled. The default behavior is for
+ * verification to be enabled.
+ *
+ * @return True if verification is enabled, false if not.
+ ***/
+ public final boolean isRemoteVerificationEnabled()
+ {
+ return __remoteVerificationEnabled;
+ }
+
+}
+
diff --git a/org/apache/commons/net/bsd/RLoginClient.java b/org/apache/commons/net/bsd/RLoginClient.java
new file mode 100644
index 0000000..3d7c63c
--- /dev/null
+++ b/org/apache/commons/net/bsd/RLoginClient.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.bsd;
+
+import java.io.IOException;
+
+/***
+ * RLoginClient is very similar to
+ * {@link org.apache.commons.net.bsd.RCommandClient},
+ * from which it is derived, and uses the rcmd() facility implemented
+ * in RCommandClient to implement the functionality of the rlogin command that
+ * first appeared in 4.2BSD Unix. rlogin is a command used to login to
+ * a remote machine from a trusted host, sometimes without issuing a
+ * password. The trust relationship is the same as described in
+ * the documentation for
+ * {@link org.apache.commons.net.bsd.RCommandClient}.
+ *
+ * As with virtually all of the client classes in org.apache.commons.net, this
+ * class derives from SocketClient. But it relies on the connection
+ * methods defined in RcommandClient which ensure that the local Socket
+ * will originate from an acceptable rshell port. The way to use
+ * RLoginClient is to first connect
+ * to the server, call the {@link #rlogin rlogin() } method,
+ * and then
+ * fetch the connection's input and output streams.
+ * Interaction with the remote command is controlled entirely through the
+ * I/O streams. Once you have finished processing the streams, you should
+ * invoke {@link org.apache.commons.net.bsd.RExecClient#disconnect disconnect() }
+ * to clean up properly.
+ *
+ * The standard output and standard error streams of the
+ * remote process are transmitted over the same connection, readable
+ * from the input stream returned by
+ * {@link org.apache.commons.net.bsd.RExecClient#getInputStream getInputStream() }
+ * . Unlike RExecClient and RCommandClient, it is
+ * not possible to tell the rlogind daemon to return the standard error
+ * stream over a separate connection.
+ * {@link org.apache.commons.net.bsd.RExecClient#getErrorStream getErrorStream() }
+ * will always return null.
+ * The standard input of the remote process can be written to through
+ * the output stream returned by
+ * {@link org.apache.commons.net.bsd.RExecClient#getOutputStream getOutputSream() }
+ * .
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see org.apache.commons.net.SocketClient
+ * @see RExecClient
+ * @see RCommandClient
+ ***/
+
+public class RLoginClient extends RCommandClient
+{
+ /***
+ * The default rlogin port. Set to 513 in BSD Unix and according
+ * to RFC 1282.
+ ***/
+ public static final int DEFAULT_PORT = 513;
+
+ /***
+ * The default RLoginClient constructor. Initializes the
+ * default port to
+ * If user authentication fails, the rlogind daemon will request that
+ * a password be entered interactively. You will be able to read the
+ * prompt from the output stream of the RLoginClient and write the
+ * password to the input stream of the RLoginClient.
+ *
+ * @param localUsername The user account on the local machine that is
+ * trying to login to the remote host.
+ * @param remoteUsername The account name on the server that is
+ * being logged in to.
+ * @param terminalType The name of the user's terminal (e.g., "vt100",
+ * "network", etc.)
+ * @param terminalSpeed The speed of the user's terminal, expressed
+ * as a baud rate or bps (e.g., 9600 or 38400)
+ * @exception IOException If the rlogin() attempt fails. The exception
+ * will contain a message indicating the nature of the failure.
+ ***/
+ public void rlogin(String localUsername, String remoteUsername,
+ String terminalType, int terminalSpeed)
+ throws IOException
+ {
+ rexec(localUsername, remoteUsername, terminalType + "/" + terminalSpeed,
+ false);
+ }
+
+ /***
+ * Same as the other rlogin method, but no terminal speed is defined.
+ ***/
+ public void rlogin(String localUsername, String remoteUsername,
+ String terminalType)
+ throws IOException
+ {
+ rexec(localUsername, remoteUsername, terminalType, false);
+ }
+
+}
diff --git a/org/apache/commons/net/chargen/CharGenTCPClient.java b/org/apache/commons/net/chargen/CharGenTCPClient.java
new file mode 100644
index 0000000..a023e58
--- /dev/null
+++ b/org/apache/commons/net/chargen/CharGenTCPClient.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.chargen;
+
+import java.io.InputStream;
+
+import org.apache.commons.net.SocketClient;
+
+/***
+ * The CharGenTCPClient class is a TCP implementation of a client for the
+ * character generator protocol described in RFC 864. It can also be
+ * used for Systat (RFC 866), Quote of the Day (RFC 865), and netstat
+ * (port 15). All of these protocols involve connecting to the appropriate
+ * port, and reading data from an input stream. The chargen protocol
+ * actually sends data until the receiving end closes the connection. All
+ * of the others send only a fixed amount of data and then close the
+ * connection.
+ *
+ * To use the CharGenTCPClient class, just establish a
+ * connection with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * and call {@link #getInputStream getInputStream() } to access
+ * the data. Don't close the input stream when you're done with it. Rather,
+ * call {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * to clean up properly.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see CharGenUDPClient
+ ***/
+
+public final class CharGenTCPClient extends SocketClient
+{
+ /*** The systat port value of 11 according to RFC 866. ***/
+ public static final int SYSTAT_PORT = 11;
+ /*** The netstat port value of 19. ***/
+ public static final int NETSTAT_PORT = 15;
+ /*** The quote of the day port value of 17 according to RFC 865. ***/
+ public static final int QUOTE_OF_DAY_PORT = 17;
+ /*** The character generator port value of 19 according to RFC 864. ***/
+ public static final int CHARGEN_PORT = 19;
+ /*** The default chargen port. It is set to 19 according to RFC 864. ***/
+ public static final int DEFAULT_PORT = 19;
+
+ /***
+ * The default constructor for CharGenTCPClient. It merely sets the
+ * default port to
+ * @return An InputStream from which the server generated data can be read.
+ ***/
+ public InputStream getInputStream()
+ {
+ return _input_;
+ }
+}
+
+
+
+
diff --git a/org/apache/commons/net/chargen/CharGenUDPClient.java b/org/apache/commons/net/chargen/CharGenUDPClient.java
new file mode 100644
index 0000000..f9a349a
--- /dev/null
+++ b/org/apache/commons/net/chargen/CharGenUDPClient.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.chargen;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+import org.apache.commons.net.DatagramSocketClient;
+
+/***
+ * The CharGenUDPClient class is a UDP implementation of a client for the
+ * character generator protocol described in RFC 864. It can also be
+ * used for Systat (RFC 866), Quote of the Day (RFC 865), and netstat
+ * (port 15). All of these protocols involve sending a datagram to the
+ * appropriate port, and reading data contained in one or more reply
+ * datagrams. The chargen and quote of the day protocols only send
+ * one reply datagram containing 512 bytes or less of data. The other
+ * protocols may reply with more than one datagram, in which case you
+ * must wait for a timeout to determine that all reply datagrams have
+ * been sent.
+ *
+ * To use the CharGenUDPClient class, just open a local UDP port
+ * with {@link org.apache.commons.net.DatagramSocketClient#open open }
+ * and call {@link #send send } to send the datagram that will
+ * initiate the data reply. For chargen or quote of the day, just
+ * call {@link #receive receive }, and you're done. For netstat and
+ * systat, call receive in a while loop, and catch a SocketException and
+ * InterruptedIOException to detect a timeout (don't forget to set the
+ * timeout duration beforehand). Don't forget to call
+ * {@link org.apache.commons.net.DatagramSocketClient#close close() }
+ * to clean up properly.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see CharGenTCPClient
+ ***/
+
+public final class CharGenUDPClient extends DatagramSocketClient
+{
+ /*** The systat port value of 11 according to RFC 866. ***/
+ public static final int SYSTAT_PORT = 11;
+ /*** The netstat port value of 19. ***/
+ public static final int NETSTAT_PORT = 15;
+ /*** The quote of the day port value of 17 according to RFC 865. ***/
+ public static final int QUOTE_OF_DAY_PORT = 17;
+ /*** The character generator port value of 19 according to RFC 864. ***/
+ public static final int CHARGEN_PORT = 19;
+ /*** The default chargen port. It is set to 19 according to RFC 864. ***/
+ public static final int DEFAULT_PORT = 19;
+
+ private byte[] __receiveData;
+ private DatagramPacket __receivePacket;
+ private DatagramPacket __sendPacket;
+
+ /***
+ * The default CharGenUDPClient constructor. It initializes some internal
+ * data structures for sending and receiving the necessary datagrams for
+ * the chargen and related protocols.
+ ***/
+ public CharGenUDPClient()
+ {
+ // CharGen return packets have a maximum length of 512
+ __receiveData = new byte[512];
+ __receivePacket = new DatagramPacket(__receiveData, 512);
+ __sendPacket = new DatagramPacket(new byte[0], 0);
+ }
+
+
+ /***
+ * Sends the data initiation datagram. This data in the packet is ignored
+ * by the server, and merely serves to signal that the server should send
+ * its reply.
+ *
+ * @param host The address of the server.
+ * @param port The port of the service.
+ * @exception IOException If an error occurs while sending the datagram.
+ ***/
+ public void send(InetAddress host, int port) throws IOException
+ {
+ __sendPacket.setAddress(host);
+ __sendPacket.setPort(port);
+ _socket_.send(__sendPacket);
+ }
+
+ /*** Same as
+ * @return The reply data from the server.
+ * @exception IOException If an error occurs while receiving the datagram.
+ ***/
+ public byte[] receive() throws IOException
+ {
+ int length;
+ byte[] result;
+
+ _socket_.receive(__receivePacket);
+
+ result = new byte[length = __receivePacket.getLength()];
+ System.arraycopy(__receiveData, 0, result, 0, length);
+
+ return result;
+ }
+
+}
+
diff --git a/org/apache/commons/net/daytime/DaytimeTCPClient.java b/org/apache/commons/net/daytime/DaytimeTCPClient.java
new file mode 100644
index 0000000..a77c8c1
--- /dev/null
+++ b/org/apache/commons/net/daytime/DaytimeTCPClient.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.daytime;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import org.apache.commons.net.SocketClient;
+
+/***
+ * The DaytimeTCPClient class is a TCP implementation of a client for the
+ * Daytime protocol described in RFC 867. To use the class, merely
+ * establish a connection with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * and call {@link #getTime getTime() } to retrieve the daytime
+ * string, then
+ * call {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * to close the connection properly.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see DaytimeUDPClient
+ ***/
+
+public final class DaytimeTCPClient extends SocketClient
+{
+ /*** The default daytime port. It is set to 13 according to RFC 867. ***/
+ public static final int DEFAULT_PORT = 13;
+
+ // Received dates will likely be less than 64 characters.
+ // This is a temporary buffer used while receiving data.
+ private char[] __buffer = new char[64];
+
+ /***
+ * The default DaytimeTCPClient constructor. It merely sets the default
+ * port to
+ * @return The time string retrieved from the server.
+ * @exception IOException If an error occurs while fetching the time string.
+ ***/
+ public String getTime() throws IOException
+ {
+ int read;
+ StringBuffer result = new StringBuffer(__buffer.length);
+ BufferedReader reader;
+
+ reader = new BufferedReader(new InputStreamReader(_input_));
+
+ while (true)
+ {
+ read = reader.read(__buffer, 0, __buffer.length);
+ if (read <= 0)
+ break;
+ result.append(__buffer, 0, read);
+ }
+
+ return result.toString();
+ }
+
+}
+
diff --git a/org/apache/commons/net/daytime/DaytimeUDPClient.java b/org/apache/commons/net/daytime/DaytimeUDPClient.java
new file mode 100644
index 0000000..64eef9d
--- /dev/null
+++ b/org/apache/commons/net/daytime/DaytimeUDPClient.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.daytime;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+import org.apache.commons.net.DatagramSocketClient;
+
+/***
+ * The DaytimeUDPClient class is a UDP implementation of a client for the
+ * Daytime protocol described in RFC 867. To use the class, merely
+ * open a local datagram socket with
+ * {@link org.apache.commons.net.DatagramSocketClient#open open }
+ * and call {@link #getTime getTime } to retrieve the daytime
+ * string, then
+ * call {@link org.apache.commons.net.DatagramSocketClient#close close }
+ * to close the connection properly. Unlike
+ * {@link org.apache.commons.net.daytime.DaytimeTCPClient},
+ * successive calls to {@link #getTime getTime } are permitted
+ * without re-establishing a connection. That is because UDP is a
+ * connectionless protocol and the Daytime protocol is stateless.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see DaytimeTCPClient
+ ***/
+
+public final class DaytimeUDPClient extends DatagramSocketClient
+{
+ /*** The default daytime port. It is set to 13 according to RFC 867. ***/
+ public static final int DEFAULT_PORT = 13;
+
+ private byte[] __dummyData = new byte[1];
+ // Received dates should be less than 256 bytes
+ private byte[] __timeData = new byte[256];
+
+ /***
+ * Retrieves the time string from the specified server and port and
+ * returns it.
+ *
+ * @param host The address of the server.
+ * @param port The port of the service.
+ * @return The time string.
+ * @exception IOException If an error occurs while retrieving the time.
+ ***/
+ public String getTime(InetAddress host, int port) throws IOException
+ {
+ DatagramPacket sendPacket, receivePacket;
+
+ sendPacket =
+ new DatagramPacket(__dummyData, __dummyData.length, host, port);
+ receivePacket = new DatagramPacket(__timeData, __timeData.length);
+
+ _socket_.send(sendPacket);
+ _socket_.receive(receivePacket);
+
+ return new String(receivePacket.getData(), 0, receivePacket.getLength());
+ }
+
+ /*** Same as
+ *
+ * @author Daniel F. Savarese
+ * @see DiscardUDPClient
+ ***/
+
+public class DiscardTCPClient extends SocketClient
+{
+ /*** The default discard port. It is set to 9 according to RFC 863. ***/
+ public static final int DEFAULT_PORT = 9;
+
+ /***
+ * The default DiscardTCPClient constructor. It merely sets the default
+ * port to
+ * @return An OutputStream through which you can write data to the server.
+ ***/
+ public OutputStream getOutputStream()
+ {
+ return _output_;
+ }
+}
diff --git a/org/apache/commons/net/discard/DiscardUDPClient.java b/org/apache/commons/net/discard/DiscardUDPClient.java
new file mode 100644
index 0000000..a81b955
--- /dev/null
+++ b/org/apache/commons/net/discard/DiscardUDPClient.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.discard;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+import org.apache.commons.net.DatagramSocketClient;
+
+/***
+ * The DiscardUDPClient class is a UDP implementation of a client for the
+ * Discard protocol described in RFC 863. To use the class,
+ * just open a local UDP port
+ * with {@link org.apache.commons.net.DatagramSocketClient#open open }
+ * and call {@link #send send } to send datagrams to the server
+ * After you're done sending discard data, call
+ * {@link org.apache.commons.net.DatagramSocketClient#close close() }
+ * to clean up properly.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see DiscardTCPClient
+ ***/
+
+public class DiscardUDPClient extends DatagramSocketClient
+{
+ /*** The default discard port. It is set to 9 according to RFC 863. ***/
+ public static final int DEFAULT_PORT = 9;
+
+ DatagramPacket _sendPacket;
+
+ public DiscardUDPClient()
+ {
+ _sendPacket = new DatagramPacket(new byte[0], 0);
+ }
+
+
+ /***
+ * Sends the specified data to the specified server at the specified port.
+ *
+ * @param data The discard data to send.
+ * @param length The length of the data to send. Should be less than
+ * or equal to the length of the data byte array.
+ * @param host The address of the server.
+ * @param port The service port.
+ * @exception IOException If an error occurs during the datagram send
+ * operation.
+ ***/
+ public void send(byte[] data, int length, InetAddress host, int port)
+ throws IOException
+ {
+ _sendPacket.setData(data);
+ _sendPacket.setLength(length);
+ _sendPacket.setAddress(host);
+ _sendPacket.setPort(port);
+ _socket_.send(_sendPacket);
+ }
+
+
+ /***
+ * Same as
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see EchoUDPClient
+ * @see DiscardTCPClient
+ ***/
+
+public final class EchoTCPClient extends DiscardTCPClient
+{
+ /*** The default echo port. It is set to 7 according to RFC 862. ***/
+ public static final int DEFAULT_PORT = 7;
+
+ /***
+ * The default EchoTCPClient constructor. It merely sets the default
+ * port to
+ * @return An InputStream from which you can read echoed data from the
+ * server.
+ ***/
+ public InputStream getInputStream()
+ {
+ return _input_;
+ }
+
+}
diff --git a/org/apache/commons/net/echo/EchoUDPClient.java b/org/apache/commons/net/echo/EchoUDPClient.java
new file mode 100644
index 0000000..70a4898
--- /dev/null
+++ b/org/apache/commons/net/echo/EchoUDPClient.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.echo;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+import org.apache.commons.net.discard.DiscardUDPClient;
+
+/***
+ * The EchoUDPClient class is a UDP implementation of a client for the
+ * Echo protocol described in RFC 862. To use the class,
+ * just open a local UDP port
+ * with {@link org.apache.commons.net.DatagramSocketClient#open open }
+ * and call {@link #send send } to send datagrams to the server,
+ * then call {@link #receive receive } to receive echoes.
+ * After you're done echoing data, call
+ * {@link org.apache.commons.net.DatagramSocketClient#close close() }
+ * to clean up properly.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see EchoTCPClient
+ * @see DiscardUDPClient
+ ***/
+
+public final class EchoUDPClient extends DiscardUDPClient
+{
+ /*** The default echo port. It is set to 7 according to RFC 862. ***/
+ public static final int DEFAULT_PORT = 7;
+
+ private DatagramPacket __receivePacket = new DatagramPacket(new byte[0], 0);
+
+ /***
+ * Sends the specified data to the specified server at the default echo
+ * port.
+ *
+ * @param data The echo data to send.
+ * @param length The length of the data to send. Should be less than
+ * or equal to the length of the data byte array.
+ * @param host The address of the server.
+ * @exception IOException If an error occurs during the datagram send
+ * operation.
+ ***/
+ @Override
+ public void send(byte[] data, int length, InetAddress host)
+ throws IOException
+ {
+ send(data, length, host, DEFAULT_PORT);
+ }
+
+
+ /*** Same as
+ * @return Length of actual data received.
+ * @exception IOException If an error occurs while receiving the data.
+ ***/
+ public int receive(byte[] data, int length) throws IOException
+ {
+ __receivePacket.setData(data);
+ __receivePacket.setLength(length);
+ _socket_.receive(__receivePacket);
+ return __receivePacket.getLength();
+ }
+
+ /*** Same as
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public class FingerClient extends SocketClient
+{
+ /***
+ * The default FINGER port. Set to 79 according to RFC 1288.
+ ***/
+ public static final int DEFAULT_PORT = 79;
+
+ private static final String __LONG_FLAG = "/W ";
+
+ private transient StringBuffer __query = new StringBuffer(64);
+ private transient char[] __buffer = new char[1024];
+
+ /***
+ * The default FingerClient constructor. Initializes the
+ * default port to
+ * @param longOutput Set to true if long output is requested, false if not.
+ * @param username The name of the user to finger.
+ * @return The result of the finger query.
+ * @exception IOException If an I/O error occurs while reading the socket.
+ ***/
+ public String query(boolean longOutput, String username) throws IOException
+ {
+ int read;
+ StringBuffer result = new StringBuffer(__buffer.length);
+ BufferedReader input;
+
+ input =
+ new BufferedReader(new InputStreamReader(getInputStream(longOutput,
+ username)));
+
+ while (true)
+ {
+ read = input.read(__buffer, 0, __buffer.length);
+ if (read <= 0)
+ break;
+ result.append(__buffer, 0, read);
+ }
+
+ input.close();
+
+ return result.toString();
+ }
+
+
+ /***
+ * Fingers the connected host and returns the output
+ * as a String. You must first connect to a finger server before
+ * calling this method, and you should disconnect afterward.
+ * This is equivalent to calling
+ * @param longOutput Set to true if long output is requested, false if not.
+ * @return The result of the finger query.
+ * @exception IOException If an I/O error occurs while reading the socket.
+ ***/
+ public String query(boolean longOutput) throws IOException
+ {
+ return query(longOutput, "");
+ }
+
+
+ /***
+ * Fingers a user and returns the input stream from the network connection
+ * of the finger query. You must first connect to a finger server before
+ * calling this method, and you should disconnect after finishing reading
+ * the stream.
+ *
+ * @param longOutput Set to true if long output is requested, false if not.
+ * @param username The name of the user to finger.
+ * @return The InputStream of the network connection of the finger query.
+ * Can be read to obtain finger results.
+ * @exception IOException If an I/O error during the operation.
+ ***/
+ public InputStream getInputStream(boolean longOutput, String username)
+ throws IOException
+ {
+ return getInputStream(longOutput, username, null);
+ }
+
+ /***
+ * Fingers a user and returns the input stream from the network connection
+ * of the finger query. You must first connect to a finger server before
+ * calling this method, and you should disconnect after finishing reading
+ * the stream.
+ *
+ * @param longOutput Set to true if long output is requested, false if not.
+ * @param username The name of the user to finger.
+ * @param encoding the character encoding that should be used for the query,
+ * null for the platform's default encoding
+ * @return The InputStream of the network connection of the finger query.
+ * Can be read to obtain finger results.
+ * @exception IOException If an I/O error during the operation.
+ ***/
+ public InputStream getInputStream(boolean longOutput, String username, String encoding)
+ throws IOException
+ {
+ DataOutputStream output;
+
+ __query.setLength(0);
+ if (longOutput)
+ __query.append(__LONG_FLAG);
+ __query.append(username);
+ __query.append(SocketClient.NETASCII_EOL);
+
+ byte[] encodedQuery =
+ (encoding == null ? __query.toString().getBytes() : __query.toString().getBytes(encoding));
+
+ output = new DataOutputStream(new BufferedOutputStream(_output_, 1024));
+ output.write(encodedQuery, 0, encodedQuery.length);
+ output.flush();
+
+ return _input_;
+ }
+
+
+ /***
+ * Fingers the connected host and returns the input stream from
+ * the network connection of the finger query. This is equivalent to
+ * calling getInputStream(longOutput, ""). You must first connect to a
+ * finger server before calling this method, and you should disconnect
+ * after finishing reading the stream.
+ *
+ * @param longOutput Set to true if long output is requested, false if not.
+ * @return The InputStream of the network connection of the finger query.
+ * Can be read to obtain finger results.
+ * @exception IOException If an I/O error during the operation.
+ ***/
+ public InputStream getInputStream(boolean longOutput) throws IOException
+ {
+ return getInputStream(longOutput, "");
+ }
+
+}
diff --git a/org/apache/commons/net/ftp/Configurable.class b/org/apache/commons/net/ftp/Configurable.class
new file mode 100644
index 0000000..abcae1f
Binary files /dev/null and b/org/apache/commons/net/ftp/Configurable.class differ
diff --git a/org/apache/commons/net/ftp/Configurable.java b/org/apache/commons/net/ftp/Configurable.java
new file mode 100644
index 0000000..5e8e749
--- /dev/null
+++ b/org/apache/commons/net/ftp/Configurable.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+
+
+/**
+ * This interface adds the aspect of configurability by means of
+ * a supplied FTPClientConfig object to other classes in the
+ * system, especially listing parsers.
+ */
+public interface Configurable {
+
+ /**
+ * @param config the object containing the configuration data
+ * @throws IllegalArgumentException if the elements of the
+ *
+ * To derive the full benefits of the FTP class requires some knowledge
+ * of the FTP protocol defined in RFC 959. However, there is no reason
+ * why you should have to use the FTP class. The
+ * {@link org.apache.commons.net.ftp.FTPClient} class,
+ * derived from FTP,
+ * implements all the functionality required of an FTP client. The
+ * FTP class is made public to provide access to various FTP constants
+ * and to make it easier for adventurous programmers (or those with
+ * special needs) to interact with the FTP protocol and implement their
+ * own clients. A set of methods with names corresponding to the FTP
+ * command names are provided to facilitate this interaction.
+ *
+ * You should keep in mind that the FTP server may choose to prematurely
+ * close a connection if the client has been idle for longer than a
+ * given time period (usually 900 seconds). The FTP class will detect a
+ * premature FTP server connection closing when it receives a
+ * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
+ * response to a command.
+ * When that occurs, the FTP class method encountering that reply will throw
+ * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
+ * .
+ * Rather than list it separately for each method, we mention here that
+ * every method communicating with the server and throwing an IOException
+ * can also throw a
+ * {@link org.apache.commons.net.MalformedServerReplyException}
+ * , which is a subclass
+ * of IOException. A MalformedServerReplyException will be thrown when
+ * the reply received from the server deviates enough from the protocol
+ * specification that it cannot be interpreted in a useful manner despite
+ * attempts to be as lenient as possible.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @author Rory Winston
+ * @author Joseph Hindsley
+ * @see FTPClient
+ * @see FTPConnectionClosedException
+ * @see org.apache.commons.net.MalformedServerReplyException
+ * @version $Id: FTP.java 658520 2008-05-21 01:14:11Z sebb $
+ ***/
+
+public class FTP extends SocketClient
+{
+ /*** The default FTP data port (20). ***/
+ public static final int DEFAULT_DATA_PORT = 20;
+ /*** The default FTP control port (21). ***/
+ public static final int DEFAULT_PORT = 21;
+
+ /***
+ * A constant used to indicate the file(s) being transfered should
+ * be treated as ASCII. This is the default file type. All constants
+ * ending in
+ * @param listener The ProtocolCommandListener to add.
+ ***/
+ public void addProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ _commandSupport_.addProtocolCommandListener(listener);
+ }
+
+ /***
+ * Removes a ProtocolCommandListener. Delegates this task to
+ * {@link #_commandSupport_ _commandSupport_ }.
+ *
+ * @param listener The ProtocolCommandListener to remove.
+ ***/
+ public void removeProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ _commandSupport_.removeProtocolCommandListener(listener);
+ }
+
+
+ /***
+ * Closes the control connection to the FTP server and sets to null
+ * some internal data so that the memory may be reclaimed by the
+ * garbage collector. The reply text and code information from the
+ * last command is voided so that the memory it used may be reclaimed.
+ * Also sets {@link #_controlInput_} and {@link #_controlOutput_} to null.
+ *
+ * @exception IOException If an error occurs while disconnecting.
+ ***/
+ @Override
+ public void disconnect() throws IOException
+ {
+ super.disconnect();
+ _controlInput_ = null;
+ _controlOutput_ = null;
+ _newReplyString = false;
+ _replyString = null;
+ }
+
+
+ /***
+ * Sends an FTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The text representation of the FTP command to send.
+ * @param args The arguments to the FTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(String command, String args) throws IOException
+ {
+ String message;
+
+ __commandBuffer.setLength(0);
+ __commandBuffer.append(command);
+
+ if (args != null)
+ {
+ __commandBuffer.append(' ');
+ __commandBuffer.append(args);
+ }
+ __commandBuffer.append(SocketClient.NETASCII_EOL);
+
+ try{
+ _controlOutput_.write(message = __commandBuffer.toString());
+ _controlOutput_.flush();
+ }
+ catch (SocketException e)
+ {
+ if (!isConnected() || !socketIsConnected(_socket_))
+ {
+ throw new FTPConnectionClosedException("Connection unexpectedly closed.");
+ }
+ else
+ {
+ throw e;
+ }
+ }
+
+
+ if (_commandSupport_.getListenerCount() > 0)
+ _commandSupport_.fireCommandSent(command, message);
+
+ __getReply();
+ return _replyCode;
+ }
+
+ /**
+ * Checks if the socket is connected
+ *
+ * @param socket
+ * @return true if connected
+ */
+ private boolean socketIsConnected(Socket socket)
+ {
+ if (socket == null)
+ {
+ return false;
+ }
+
+ return socket.isConnected();
+
+ }
+
+ /***
+ * Sends an FTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The FTPCommand constant corresponding to the FTP command
+ * to send.
+ * @param args The arguments to the FTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(int command, String args) throws IOException
+ {
+ return sendCommand(FTPCommand._commands[command], args);
+ }
+
+
+ /***
+ * Sends an FTP command with no arguments to the server, waits for a
+ * reply and returns the numerical response code. After invocation, for
+ * more detailed information, the actual reply text can be accessed by
+ * calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The text representation of the FTP command to send.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(String command) throws IOException
+ {
+ return sendCommand(command, null);
+ }
+
+
+ /***
+ * Sends an FTP command with no arguments to the server, waits for a
+ * reply and returns the numerical response code. After invocation, for
+ * more detailed information, the actual reply text can be accessed by
+ * calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The FTPCommand constant corresponding to the FTP command
+ * to send.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(int command) throws IOException
+ {
+ return sendCommand(command, null);
+ }
+
+
+ /***
+ * Returns the integer value of the reply code of the last FTP reply.
+ * You will usually only use this method after you connect to the
+ * FTP server to check that the connection was successful since
+ *
+ * @return The integer value of the reply code of the last FTP reply.
+ ***/
+ public int getReplyCode()
+ {
+ return _replyCode;
+ }
+
+ /***
+ * Fetches a reply from the FTP server and returns the integer reply
+ * code. After calling this method, the actual reply text can be accessed
+ * from either calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }. Only use this
+ * method if you are implementing your own FTP client or if you need to
+ * fetch a secondary response from the FTP server.
+ *
+ * @return The integer value of the reply code of the fetched FTP reply.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while receiving the
+ * server reply.
+ ***/
+ public int getReply() throws IOException
+ {
+ __getReply();
+ return _replyCode;
+ }
+
+
+ /***
+ * Returns the lines of text from the last FTP server response as an array
+ * of strings, one entry per line. The end of line markers of each are
+ * stripped from each line.
+ *
+ * @return The lines of text from the last FTP response as an array.
+ ***/
+ public String[] getReplyStrings()
+ {
+ String[] lines;
+ lines = new String[_replyLines.size()];
+ _replyLines.addAll(Arrays.asList(lines));
+ return lines;
+ }
+
+ /***
+ * Returns the entire text of the last FTP server response exactly
+ * as it was received, including all end of line markers in NETASCII
+ * format.
+ *
+ * @return The entire text from the last FTP response as a String.
+ ***/
+ public String getReplyString()
+ {
+ StringBuilder buffer;
+
+ if (!_newReplyString) {
+ return _replyString;
+ }
+
+ buffer = new StringBuilder(256);
+
+ for (String line : _replyLines) {
+ buffer.append(line);
+ buffer.append(SocketClient.NETASCII_EOL);
+ }
+
+ _newReplyString = false;
+
+ return (_replyString = buffer.toString());
+ }
+
+
+ /***
+ * A convenience method to send the FTP USER command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param username The username to login under.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int user(String username) throws IOException
+ {
+ return sendCommand(FTPCommand.USER, username);
+ }
+
+ /**
+ * A convenience method to send the FTP PASS command to the server,
+ * receive the reply, and return the reply code.
+ * @param password The plain text password of the username being logged into.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int pass(String password) throws IOException
+ {
+ return sendCommand(FTPCommand.PASS, password);
+ }
+
+ /***
+ * A convenience method to send the FTP ACCT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param account The account name to access.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int acct(String account) throws IOException
+ {
+ return sendCommand(FTPCommand.ACCT, account);
+ }
+
+
+ /***
+ * A convenience method to send the FTP ABOR command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int abor() throws IOException
+ {
+ return sendCommand(FTPCommand.ABOR);
+ }
+
+ /***
+ * A convenience method to send the FTP CWD command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param directory The new working directory.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int cwd(String directory) throws IOException
+ {
+ return sendCommand(FTPCommand.CWD, directory);
+ }
+
+ /***
+ * A convenience method to send the FTP CDUP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int cdup() throws IOException
+ {
+ return sendCommand(FTPCommand.CDUP);
+ }
+
+ /***
+ * A convenience method to send the FTP QUIT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int quit() throws IOException
+ {
+ return sendCommand(FTPCommand.QUIT);
+ }
+
+ /***
+ * A convenience method to send the FTP REIN command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rein() throws IOException
+ {
+ return sendCommand(FTPCommand.REIN);
+ }
+
+ /***
+ * A convenience method to send the FTP SMNT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param dir The directory name.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int smnt(String dir) throws IOException
+ {
+ return sendCommand(FTPCommand.SMNT, dir);
+ }
+
+ /***
+ * A convenience method to send the FTP PORT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param host The host owning the port.
+ * @param port The new port.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int port(InetAddress host, int port) throws IOException
+ {
+ int num;
+ StringBuffer info = new StringBuffer(24);
+
+ info.append(host.getHostAddress().replace('.', ','));
+ num = port >>> 8;
+ info.append(',');
+ info.append(num);
+ info.append(',');
+ num = port & 0xff;
+ info.append(num);
+
+ return sendCommand(FTPCommand.PORT, info.toString());
+ }
+
+ /***
+ * A convenience method to send the FTP PASV command to the server,
+ * receive the reply, and return the reply code. Remember, it's up
+ * to you to interpret the reply string containing the host/port
+ * information.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int pasv() throws IOException
+ {
+ return sendCommand(FTPCommand.PASV);
+ }
+
+ /**
+ * A convenience method to send the FTP TYPE command for text files
+ * to the server, receive the reply, and return the reply code.
+ * @param fileType The type of the file (one of the
+ * @param fileType The type of the file (one of the
+ * @param structure The structure of the file (one of the
+ *
+ * @param mode The transfer mode to use (one of the
+ *
+ * @param pathname The pathname of the file to retrieve.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int retr(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.RETR, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP STOR command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @param pathname The pathname to use for the file when stored at
+ * the remote end of the transfer.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stor(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.STOR, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP STOU command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stou() throws IOException
+ {
+ return sendCommand(FTPCommand.STOU);
+ }
+
+ /***
+ * A convenience method to send the FTP STOU command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ * @param pathname The base pathname to use for the file when stored at
+ * the remote end of the transfer. Some FTP servers
+ * require this.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int stou(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.STOU, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP APPE command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @param pathname The pathname to use for the file when stored at
+ * the remote end of the transfer.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int appe(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.APPE, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP ALLO command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param bytes The number of bytes to allocate.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int allo(int bytes) throws IOException
+ {
+ return sendCommand(FTPCommand.ALLO, Integer.toString(bytes));
+ }
+
+ /***
+ * A convenience method to send the FTP ALLO command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param bytes The number of bytes to allocate.
+ * @param recordSize The size of a record.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int allo(int bytes, int recordSize) throws IOException
+ {
+ return sendCommand(FTPCommand.ALLO, Integer.toString(bytes) + " R " +
+ Integer.toString(recordSize));
+ }
+
+ /***
+ * A convenience method to send the FTP REST command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param marker The marker at which to restart a transfer.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rest(String marker) throws IOException
+ {
+ return sendCommand(FTPCommand.REST, marker);
+ }
+
+
+ /**
+ * @since 2.0
+ **/
+ public int mdtm(String file) throws IOException
+ {
+ return sendCommand(FTPCommand.MDTM, file);
+ }
+
+ /***
+ * A convenience method to send the FTP RNFR command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname to rename from.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rnfr(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.RNFR, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP RNTO command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname to rename to
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rnto(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.RNTO, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP DELE command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname to delete.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int dele(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.DELE, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP RMD command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname of the directory to remove.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rmd(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.RMD, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP MKD command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname of the new directory to create.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int mkd(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.MKD, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP PWD command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int pwd() throws IOException
+ {
+ return sendCommand(FTPCommand.PWD);
+ }
+
+ /***
+ * A convenience method to send the FTP LIST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int list() throws IOException
+ {
+ return sendCommand(FTPCommand.LIST);
+ }
+
+ /***
+ * A convenience method to send the FTP LIST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @param pathname The pathname to list.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int list(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.LIST, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP NLST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int nlst() throws IOException
+ {
+ return sendCommand(FTPCommand.NLST);
+ }
+
+ /***
+ * A convenience method to send the FTP NLST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @param pathname The pathname to list.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int nlst(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.NLST, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP SITE command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param parameters The site parameters to send.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int site(String parameters) throws IOException
+ {
+ return sendCommand(FTPCommand.SITE, parameters);
+ }
+
+ /***
+ * A convenience method to send the FTP SYST command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int syst() throws IOException
+ {
+ return sendCommand(FTPCommand.SYST);
+ }
+
+ /***
+ * A convenience method to send the FTP STAT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stat() throws IOException
+ {
+ return sendCommand(FTPCommand.STAT);
+ }
+
+ /***
+ * A convenience method to send the FTP STAT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname A pathname to list.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stat(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.STAT, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP HELP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int help() throws IOException
+ {
+ return sendCommand(FTPCommand.HELP);
+ }
+
+ /***
+ * A convenience method to send the FTP HELP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param command The command name on which to request help.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int help(String command) throws IOException
+ {
+ return sendCommand(FTPCommand.HELP, command);
+ }
+
+ /***
+ * A convenience method to send the FTP NOOP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int noop() throws IOException
+ {
+ return sendCommand(FTPCommand.NOOP);
+ }
+
+ /**
+ * Return whether strict multiline parsing is enabled, as per RFX 959, section 4.2.
+ * @return True if strict, false if lenient
+ * @since 2.0
+ */
+ public boolean isStrictMultilineParsing() {
+ return strictMultilineParsing;
+ }
+
+ /**
+ * Set strict multiline parsing.
+ * @param strictMultilineParsing
+ * @since 2.0
+ */
+ public void setStrictMultilineParsing(boolean strictMultilineParsing) {
+ this.strictMultilineParsing = strictMultilineParsing;
+ }
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/org/apache/commons/net/ftp/FTPClient.class b/org/apache/commons/net/ftp/FTPClient.class
new file mode 100644
index 0000000..60ac793
Binary files /dev/null and b/org/apache/commons/net/ftp/FTPClient.class differ
diff --git a/org/apache/commons/net/ftp/FTPClient.java b/org/apache/commons/net/ftp/FTPClient.java
new file mode 100644
index 0000000..9a2c459
--- /dev/null
+++ b/org/apache/commons/net/ftp/FTPClient.java
@@ -0,0 +1,2447 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+
+import org.apache.commons.net.MalformedServerReplyException;
+import org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory;
+import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
+import org.apache.commons.net.ftp.parser.ParserInitializationException;
+import org.apache.commons.net.io.CopyStreamEvent;
+import org.apache.commons.net.io.CopyStreamException;
+import org.apache.commons.net.io.FromNetASCIIInputStream;
+import org.apache.commons.net.io.ToNetASCIIOutputStream;
+import org.apache.commons.net.io.Util;
+
+/***
+ * FTPClient encapsulates all the functionality necessary to store and
+ * retrieve files from an FTP server. This class takes care of all
+ * low level details of interacting with an FTP server and provides
+ * a convenient higher level interface. As with all classes derived
+ * from {@link org.apache.commons.net.SocketClient},
+ * you must first connect to the server with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * before doing anything, and finally
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * after you're completely finished interacting with the server.
+ * Then you need to check the FTP reply code to see if the connection
+ * was successful. For example:
+ *
+ * Immediately after connecting is the only real time you need to check the
+ * reply code (because connect is of type void). The convention for all the
+ * FTP command methods in FTPClient is such that they either return a
+ * boolean value or some other value.
+ * The boolean methods return true on a successful completion reply from
+ * the FTP server and false on a reply resulting in an error condition or
+ * failure. The methods returning a value other than boolean return a value
+ * containing the higher level data produced by the FTP command, or null if a
+ * reply resulted in an error condition or failure. If you want to access
+ * the exact FTP reply code causing a success or failure, you must call
+ * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode } after
+ * a success or failure.
+ *
+ * The default settings for FTPClient are for it to use
+ *
+ *
+ * Because the handling of sockets on different platforms can differ
+ * significantly, the FTPClient automatically issues a new PORT command
+ * prior to every transfer requiring that the server connect to the client's
+ * data port. This ensures identical problem-free behavior on Windows, Unix,
+ * and Macintosh platforms. Additionally, it relieves programmers from
+ * having to issue the PORT command themselves and dealing with platform
+ * dependent issues.
+ *
+ * Additionally, for security purposes, all data connections to the
+ * client are verified to ensure that they originated from the intended
+ * party (host and port). If a data connection is initiated by an unexpected
+ * party, the command will close the socket and throw an IOException. You
+ * may disable this behavior with
+ * {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}.
+ *
+ * You should keep in mind that the FTP server may choose to prematurely
+ * close a connection if the client has been idle for longer than a
+ * given time period (usually 900 seconds). The FTPClient class will detect a
+ * premature FTP server connection closing when it receives a
+ * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
+ * response to a command.
+ * When that occurs, the FTP class method encountering that reply will throw
+ * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
+ * .
+ *
+ * Rather than list it separately for each method, we mention here that
+ * every method communicating with the server and throwing an IOException
+ * can also throw a
+ * {@link org.apache.commons.net.MalformedServerReplyException}
+ * , which is a subclass
+ * of IOException. A MalformedServerReplyException will be thrown when
+ * the reply received from the server deviates enough from the protocol
+ * specification that it cannot be interpreted in a useful manner despite
+ * attempts to be as lenient as possible.
+ *
+ * Listing API Examples
+ * Both paged and unpaged examples of directory listings are available,
+ * as follows:
+ *
+ * Unpaged (whole list) access, using a parser accessible by auto-detect:
+ *
+ * Paged access, using a parser not accessible by auto-detect. The class
+ * defined in the first parameter of initateListParsing should be derived
+ * from org.apache.commons.net.FTPFileEntryParser:
+ *
+ * Paged access, using a parser accessible by auto-detect:
+ *
+ * For examples of using FTPClient on servers whose directory listings
+ *
+ * @author Daniel F. Savarese
+ * @author Rory Winston
+ * @see FTP
+ * @see FTPConnectionClosedException
+ * @see FTPFileEntryParser
+ * @see FTPFileEntryParserFactory
+ * @see DefaultFTPFileEntryParserFactory
+ * @see FTPClientConfig
+ *
+ * @see org.apache.commons.net.MalformedServerReplyException
+ **/
+public class FTPClient extends FTP
+implements Configurable
+{
+ /***
+ * A constant indicating the FTP session is expecting all transfers
+ * to occur between the client (local) and server and that the server
+ * should connect to the client's data port to initiate a data transfer.
+ * This is the default data connection mode when and FTPClient instance
+ * is created.
+ ***/
+ public static final int ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0;
+ /***
+ * A constant indicating the FTP session is expecting all transfers
+ * to occur between two remote servers and that the server
+ * the client is connected to should connect to the other server's
+ * data port to initiate a data transfer.
+ ***/
+ public static final int ACTIVE_REMOTE_DATA_CONNECTION_MODE = 1;
+ /***
+ * A constant indicating the FTP session is expecting all transfers
+ * to occur between the client (local) and server and that the server
+ * is in passive mode, requiring the client to connect to the
+ * server's data port to initiate a transfer.
+ ***/
+ public static final int PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2;
+ /***
+ * A constant indicating the FTP session is expecting all transfers
+ * to occur between two remote servers and that the server
+ * the client is connected to is in passive mode, requiring the other
+ * server to connect to the first server's data port to initiate a data
+ * transfer.
+ ***/
+ public static final int PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3;
+
+ private int __dataConnectionMode, __dataTimeout;
+ private int __passivePort;
+ private String __passiveHost;
+ private int __fileType, __fileFormat, __fileStructure, __fileTransferMode;
+ private boolean __remoteVerificationEnabled;
+ private long __restartOffset;
+ private FTPFileEntryParserFactory __parserFactory;
+ private int __bufferSize;
+ private boolean __listHiddenFiles;
+
+ // __systemName is a cached value that should not be referenced directly
+ // except when assigned in getSystemName and __initDefaults.
+ private String __systemName;
+
+ // __entryParser is a cached value that should not be referenced directly
+ // except when assigned in listFiles(String, String) and __initDefaults.
+ private FTPFileEntryParser __entryParser;
+
+ private FTPClientConfig __configuration;
+
+ /** Pattern for PASV mode responses */
+ private static String __parms = "\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}";
+ private static java.util.regex.Pattern __parms_pat;
+ static {
+ __parms_pat = java.util.regex.Pattern.compile(__parms);
+ }
+
+ /***
+ * Default FTPClient constructor. Creates a new FTPClient instance
+ * with the data connection mode set to
+ *
+ * @param command The text representation of the FTP command to send.
+ * @param arg The arguments to the FTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return A Socket corresponding to the established data connection.
+ * Null is returned if an FTP protocol error is reported at
+ * any point during the establishment and initialization of
+ * the connection.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ protected Socket _openDataConnection_(int command, String arg)
+ throws IOException
+ {
+ Socket socket;
+
+ if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE &&
+ __dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE)
+ return null;
+
+ if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE)
+ {
+ ServerSocket server;
+ server = _serverSocketFactory_.createServerSocket(0, 1, getLocalAddress());
+
+ if (!FTPReply.isPositiveCompletion(port(getLocalAddress(),
+ server.getLocalPort())))
+ {
+ server.close();
+ return null;
+ }
+
+ if ((__restartOffset > 0) && !restart(__restartOffset))
+ {
+ server.close();
+ return null;
+ }
+
+ if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
+ {
+ server.close();
+ return null;
+ }
+
+ // For now, let's just use the data timeout value for waiting for
+ // the data connection. It may be desirable to let this be a
+ // separately configurable value. In any case, we really want
+ // to allow preventing the accept from blocking indefinitely.
+ if (__dataTimeout >= 0)
+ server.setSoTimeout(__dataTimeout);
+ try {
+ socket = server.accept();
+ } finally {
+ server.close();
+ }
+ }
+ else
+ { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
+
+ if (pasv() != FTPReply.ENTERING_PASSIVE_MODE)
+ return null;
+
+ __parsePassiveModeReply(_replyLines.get(_replyLines.size() - 1));
+
+ socket = _socketFactory_.createSocket(__passiveHost, __passivePort);
+ if ((__restartOffset > 0) && !restart(__restartOffset))
+ {
+ socket.close();
+ return null;
+ }
+
+ if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
+ {
+ socket.close();
+ return null;
+ }
+ }
+
+ if (__remoteVerificationEnabled && !verifyRemote(socket))
+ {
+ InetAddress host1, host2;
+
+ host1 = socket.getInetAddress();
+ host2 = getRemoteAddress();
+
+ socket.close();
+
+ throw new IOException(
+ "Host attempting data connection " + host1.getHostAddress() +
+ " is not same as server " + host2.getHostAddress());
+ }
+
+ if (__dataTimeout >= 0)
+ socket.setSoTimeout(__dataTimeout);
+
+ return socket;
+ }
+
+
+ @Override
+ protected void _connectAction_() throws IOException
+ {
+ super._connectAction_();
+ __initDefaults();
+ }
+
+
+ /***
+ * Sets the timeout in milliseconds to use when reading from the
+ * data connection. This timeout will be set immediately after
+ * opening the data connection.
+ *
+ * @param timeout The default timeout in milliseconds that is used when
+ * opening a data connection socket.
+ ***/
+ public void setDataTimeout(int timeout)
+ {
+ __dataTimeout = timeout;
+ }
+
+ /**
+ * set the factory used for parser creation to the supplied factory object.
+ *
+ * @param parserFactory
+ * factory object used to create FTPFileEntryParsers
+ *
+ * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
+ * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
+ */
+ public void setParserFactory(FTPFileEntryParserFactory parserFactory) {
+ __parserFactory = parserFactory;
+ }
+
+
+ /***
+ * Closes the connection to the FTP server and restores
+ * connection parameters to the default values.
+ *
+ * @exception IOException If an error occurs while disconnecting.
+ ***/
+ @Override
+ public void disconnect() throws IOException
+ {
+ super.disconnect();
+ __initDefaults();
+ }
+
+
+ /***
+ * Enable or disable verification that the remote host taking part
+ * of a data connection is the same as the host to which the control
+ * connection is attached. The default is for verification to be
+ * enabled. You may set this value at any time, whether the
+ * FTPClient is currently connected or not.
+ *
+ * @param enable True to enable verification, false to disable verification.
+ ***/
+ public void setRemoteVerificationEnabled(boolean enable)
+ {
+ __remoteVerificationEnabled = enable;
+ }
+
+ /***
+ * Return whether or not verification of the remote host participating
+ * in data connections is enabled. The default behavior is for
+ * verification to be enabled.
+ *
+ * @return True if verification is enabled, false if not.
+ ***/
+ public boolean isRemoteVerificationEnabled()
+ {
+ return __remoteVerificationEnabled;
+ }
+
+ /***
+ * Login to the FTP server using the provided username and password.
+ *
+ * @param username The username to login under.
+ * @param password The password to use.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean login(String username, String password) throws IOException
+ {
+ user(username);
+
+ if (FTPReply.isPositiveCompletion(_replyCode))
+ return true;
+
+ // If we get here, we either have an error code, or an intermmediate
+ // reply requesting password.
+ if (!FTPReply.isPositiveIntermediate(_replyCode))
+ return false;
+
+ return FTPReply.isPositiveCompletion(pass(password));
+ }
+
+
+ /***
+ * Login to the FTP server using the provided username, password,
+ * and account. If no account is required by the server, only
+ * the username and password, the account information is not used.
+ *
+ * @param username The username to login under.
+ * @param password The password to use.
+ * @param account The account to use.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean login(String username, String password, String account)
+ throws IOException
+ {
+ user(username);
+
+ if (FTPReply.isPositiveCompletion(_replyCode))
+ return true;
+
+ // If we get here, we either have an error code, or an intermmediate
+ // reply requesting password.
+ if (!FTPReply.isPositiveIntermediate(_replyCode))
+ return false;
+
+ pass(password);
+
+ if (FTPReply.isPositiveCompletion(_replyCode))
+ return true;
+
+ if (!FTPReply.isPositiveIntermediate(_replyCode))
+ return false;
+
+ return FTPReply.isPositiveCompletion(acct(account));
+ }
+
+ /***
+ * Logout of the FTP server by sending the QUIT command.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean logout() throws IOException
+ {
+ return FTPReply.isPositiveCompletion(quit());
+ }
+
+
+ /***
+ * Change the current working directory of the FTP session.
+ *
+ * @param pathname The new current working directory.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean changeWorkingDirectory(String pathname) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(cwd(pathname));
+ }
+
+
+ /***
+ * Change to the parent directory of the current working directory.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean changeToParentDirectory() throws IOException
+ {
+ return FTPReply.isPositiveCompletion(cdup());
+ }
+
+
+ /***
+ * Issue the FTP SMNT command.
+ *
+ * @param pathname The pathname to mount.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean structureMount(String pathname) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(smnt(pathname));
+ }
+
+ /***
+ * Reinitialize the FTP session. Not all FTP servers support this
+ * command, which issues the FTP REIN command.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ boolean reinitialize() throws IOException
+ {
+ rein();
+
+ if (FTPReply.isPositiveCompletion(_replyCode) ||
+ (FTPReply.isPositivePreliminary(_replyCode) &&
+ FTPReply.isPositiveCompletion(getReply())))
+ {
+
+ __initDefaults();
+
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /***
+ * Set the current data connection mode to
+ *
+ * @param host The passive mode server accepting connections for data
+ * transfers.
+ * @param port The passive mode server's data port.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean enterRemoteActiveMode(InetAddress host, int port)
+ throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(port(host, port)))
+ {
+ __dataConnectionMode = ACTIVE_REMOTE_DATA_CONNECTION_MODE;
+ __passiveHost = null;
+ __passivePort = -1;
+ return true;
+ }
+ return false;
+ }
+
+ /***
+ * Set the current data connection mode to
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean enterRemotePassiveMode() throws IOException
+ {
+ if (pasv() != FTPReply.ENTERING_PASSIVE_MODE)
+ return false;
+
+ __dataConnectionMode = PASSIVE_REMOTE_DATA_CONNECTION_MODE;
+ __parsePassiveModeReply(_replyLines.get(0));
+
+ return true;
+ }
+
+ /***
+ * Returns the hostname or IP address (in the form of a string) returned
+ * by the server when entering passive mode. If not in passive mode,
+ * returns null. This method only returns a valid value AFTER a
+ * data connection has been opened after a call to
+ * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
+ * This is because FTPClient sends a PASV command to the server only
+ * just before opening a data connection, and not when you call
+ * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
+ *
+ * @return The passive host name if in passive mode, otherwise null.
+ ***/
+ public String getPassiveHost()
+ {
+ return __passiveHost;
+ }
+
+ /***
+ * If in passive mode, returns the data port of the passive host.
+ * This method only returns a valid value AFTER a
+ * data connection has been opened after a call to
+ * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
+ * This is because FTPClient sends a PASV command to the server only
+ * just before opening a data connection, and not when you call
+ * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
+ *
+ * @return The data port of the passive server. If not in passive
+ * mode, undefined.
+ ***/
+ public int getPassivePort()
+ {
+ return __passivePort;
+ }
+
+
+ /***
+ * Returns the current data connection mode (one of the
+ *
+ * @return The current data connection mode (one of the
+ *
+ * @param fileType The
+ * @param fileType The
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean setFileType(int fileType, int formatOrByteSize)
+ throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(type(fileType, formatOrByteSize)))
+ {
+ __fileType = fileType;
+ __fileFormat = formatOrByteSize;
+ return true;
+ }
+ return false;
+ }
+
+
+ /***
+ * Sets the file structure. The default structure is
+ *
+ * @param structure The structure of the file (one of the FTP class
+ *
+ * @param mode The new transfer mode to use (one of the FTP class
+ *
+ * @param filename The name of the file to retrieve.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean remoteRetrieve(String filename) throws IOException
+ {
+ if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
+ __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
+ return FTPReply.isPositivePreliminary(retr(filename));
+ return false;
+ }
+
+
+ /***
+ * Initiate a server to server file transfer. This method tells the
+ * server to which the client is connected to store a file on
+ * the other server using the given filename. The other server must
+ * have had a
+ * @param filename The name to call the file that is to be stored.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean remoteStore(String filename) throws IOException
+ {
+ if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
+ __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
+ return FTPReply.isPositivePreliminary(stor(filename));
+ return false;
+ }
+
+
+ /***
+ * Initiate a server to server file transfer. This method tells the
+ * server to which the client is connected to store a file on
+ * the other server using a unique filename based on the given filename.
+ * The other server must have had a
+ * @param filename The name on which to base the filename of the file
+ * that is to be stored.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean remoteStoreUnique(String filename) throws IOException
+ {
+ if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
+ __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
+ return FTPReply.isPositivePreliminary(stou(filename));
+ return false;
+ }
+
+
+ /***
+ * Initiate a server to server file transfer. This method tells the
+ * server to which the client is connected to store a file on
+ * the other server using a unique filename.
+ * The other server must have had a
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean remoteStoreUnique() throws IOException
+ {
+ if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
+ __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
+ return FTPReply.isPositivePreliminary(stou());
+ return false;
+ }
+
+ // For server to server transfers
+ /***
+ * Initiate a server to server file transfer. This method tells the
+ * server to which the client is connected to append to a given file on
+ * the other server. The other server must have had a
+ *
+ * @param filename The name of the file to be appended to, or if the
+ * file does not exist, the name to call the file being stored.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean remoteAppend(String filename) throws IOException
+ {
+ if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
+ __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
+ return FTPReply.isPositivePreliminary(stor(filename));
+ return false;
+ }
+
+ /***
+ * There are a few FTPClient methods that do not complete the
+ * entire sequence of FTP commands to complete a transaction. These
+ * commands require some action by the programmer after the reception
+ * of a positive intermediate command. After the programmer's code
+ * completes its actions, it must call this method to receive
+ * the completion reply from the server and verify the success of the
+ * entire transaction.
+ *
+ * For example,
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean completePendingCommand() throws IOException
+ {
+ return FTPReply.isPositiveCompletion(getReply());
+ }
+
+
+ /***
+ * Retrieves a named file from the server and writes it to the given
+ * OutputStream. This method does NOT close the given OutputStream.
+ * If the current file type is ASCII, line separators in the file are
+ * converted to the local representation.
+ *
+ * @param remote The name of the remote file.
+ * @param local The local OutputStream to which to write the file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception CopyStreamException If an I/O error occurs while actually
+ * transferring the file. The CopyStreamException allows you to
+ * determine the number of bytes transferred and the IOException
+ * causing the error. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean retrieveFile(String remote, OutputStream local)
+ throws IOException
+ {
+ InputStream input;
+ Socket socket;
+
+ if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null)
+ return false;
+
+ input = new BufferedInputStream(socket.getInputStream(),
+ getBufferSize());
+ if (__fileType == ASCII_FILE_TYPE)
+ input = new FromNetASCIIInputStream(input);
+ // Treat everything else as binary for now
+ try
+ {
+ Util.copyStream(input, local, getBufferSize(),
+ CopyStreamEvent.UNKNOWN_STREAM_SIZE, null,
+ false);
+ }
+ catch (IOException e)
+ {
+ try
+ {
+ socket.close();
+ }
+ catch (IOException f)
+ {}
+ throw e;
+ }
+ socket.close();
+ return completePendingCommand();
+ }
+
+ /***
+ * Returns an InputStream from which a named file from the server
+ * can be read. If the current file type is ASCII, the returned
+ * InputStream will convert line separators in the file to
+ * the local representation. You must close the InputStream when you
+ * finish reading from it. The InputStream itself will take care of
+ * closing the parent data connection socket upon being closed. To
+ * finalize the file transfer you must call
+ * {@link #completePendingCommand completePendingCommand } and
+ * check its return value to verify success.
+ *
+ * @param remote The name of the remote file.
+ * @return An InputStream from which the remote file can be read. If
+ * the data connection cannot be opened (e.g., the file does not
+ * exist), null is returned (in which case you may check the reply
+ * code to determine the exact reason for failure).
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public InputStream retrieveFileStream(String remote) throws IOException
+ {
+ InputStream input;
+ Socket socket;
+
+ if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null)
+ return null;
+
+ input = socket.getInputStream();
+ if (__fileType == ASCII_FILE_TYPE) {
+ // We buffer ascii transfers because the buffering has to
+ // be interposed between FromNetASCIIOutputSream and the underlying
+ // socket input stream. We don't buffer binary transfers
+ // because we don't want to impose a buffering policy on the
+ // programmer if possible. Programmers can decide on their
+ // own if they want to wrap the SocketInputStream we return
+ // for file types other than ASCII.
+ input = new BufferedInputStream(input,
+ getBufferSize());
+ input = new FromNetASCIIInputStream(input);
+ }
+ return new org.apache.commons.net.io.SocketInputStream(socket, input);
+ }
+
+
+ /***
+ * Stores a file on the server using the given name and taking input
+ * from the given InputStream. This method does NOT close the given
+ * InputStream. If the current file type is ASCII, line separators in
+ * the file are transparently converted to the NETASCII format (i.e.,
+ * you should not attempt to create a special InputStream to do this).
+ *
+ * @param remote The name to give the remote file.
+ * @param local The local InputStream from which to read the file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception CopyStreamException If an I/O error occurs while actually
+ * transferring the file. The CopyStreamException allows you to
+ * determine the number of bytes transferred and the IOException
+ * causing the error. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean storeFile(String remote, InputStream local)
+ throws IOException
+ {
+ return __storeFile(FTPCommand.STOR, remote, local);
+ }
+
+
+ /***
+ * Returns an OutputStream through which data can be written to store
+ * a file on the server using the given name. If the current file type
+ * is ASCII, the returned OutputStream will convert line separators in
+ * the file to the NETASCII format (i.e., you should not attempt to
+ * create a special OutputStream to do this). You must close the
+ * OutputStream when you finish writing to it. The OutputStream itself
+ * will take care of closing the parent data connection socket upon being
+ * closed. To finalize the file transfer you must call
+ * {@link #completePendingCommand completePendingCommand } and
+ * check its return value to verify success.
+ *
+ * @param remote The name to give the remote file.
+ * @return An OutputStream through which the remote file can be written. If
+ * the data connection cannot be opened (e.g., the file does not
+ * exist), null is returned (in which case you may check the reply
+ * code to determine the exact reason for failure).
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public OutputStream storeFileStream(String remote) throws IOException
+ {
+ return __storeFileStream(FTPCommand.STOR, remote);
+ }
+
+ /***
+ * Appends to a file on the server with the given name, taking input
+ * from the given InputStream. This method does NOT close the given
+ * InputStream. If the current file type is ASCII, line separators in
+ * the file are transparently converted to the NETASCII format (i.e.,
+ * you should not attempt to create a special InputStream to do this).
+ *
+ * @param remote The name of the remote file.
+ * @param local The local InputStream from which to read the data to
+ * be appended to the remote file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception CopyStreamException If an I/O error occurs while actually
+ * transferring the file. The CopyStreamException allows you to
+ * determine the number of bytes transferred and the IOException
+ * causing the error. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean appendFile(String remote, InputStream local)
+ throws IOException
+ {
+ return __storeFile(FTPCommand.APPE, remote, local);
+ }
+
+ /***
+ * Returns an OutputStream through which data can be written to append
+ * to a file on the server with the given name. If the current file type
+ * is ASCII, the returned OutputStream will convert line separators in
+ * the file to the NETASCII format (i.e., you should not attempt to
+ * create a special OutputStream to do this). You must close the
+ * OutputStream when you finish writing to it. The OutputStream itself
+ * will take care of closing the parent data connection socket upon being
+ * closed. To finalize the file transfer you must call
+ * {@link #completePendingCommand completePendingCommand } and
+ * check its return value to verify success.
+ *
+ * @param remote The name of the remote file.
+ * @return An OutputStream through which the remote file can be appended.
+ * If the data connection cannot be opened (e.g., the file does not
+ * exist), null is returned (in which case you may check the reply
+ * code to determine the exact reason for failure).
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public OutputStream appendFileStream(String remote) throws IOException
+ {
+ return __storeFileStream(FTPCommand.APPE, remote);
+ }
+
+ /***
+ * Stores a file on the server using a unique name derived from the
+ * given name and taking input
+ * from the given InputStream. This method does NOT close the given
+ * InputStream. If the current file type is ASCII, line separators in
+ * the file are transparently converted to the NETASCII format (i.e.,
+ * you should not attempt to create a special InputStream to do this).
+ *
+ * @param remote The name on which to base the unique name given to
+ * the remote file.
+ * @param local The local InputStream from which to read the file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception CopyStreamException If an I/O error occurs while actually
+ * transferring the file. The CopyStreamException allows you to
+ * determine the number of bytes transferred and the IOException
+ * causing the error. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean storeUniqueFile(String remote, InputStream local)
+ throws IOException
+ {
+ return __storeFile(FTPCommand.STOU, remote, local);
+ }
+
+
+ /***
+ * Returns an OutputStream through which data can be written to store
+ * a file on the server using a unique name derived from the given name.
+ * If the current file type
+ * is ASCII, the returned OutputStream will convert line separators in
+ * the file to the NETASCII format (i.e., you should not attempt to
+ * create a special OutputStream to do this). You must close the
+ * OutputStream when you finish writing to it. The OutputStream itself
+ * will take care of closing the parent data connection socket upon being
+ * closed. To finalize the file transfer you must call
+ * {@link #completePendingCommand completePendingCommand } and
+ * check its return value to verify success.
+ *
+ * @param remote The name on which to base the unique name given to
+ * the remote file.
+ * @return An OutputStream through which the remote file can be written. If
+ * the data connection cannot be opened (e.g., the file does not
+ * exist), null is returned (in which case you may check the reply
+ * code to determine the exact reason for failure).
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public OutputStream storeUniqueFileStream(String remote) throws IOException
+ {
+ return __storeFileStream(FTPCommand.STOU, remote);
+ }
+
+ /**
+ * Stores a file on the server using a unique name assigned by the
+ * server and taking input from the given InputStream. This method does
+ * NOT close the given
+ * InputStream. If the current file type is ASCII, line separators in
+ * the file are transparently converted to the NETASCII format (i.e.,
+ * you should not attempt to create a special InputStream to do this).
+ *
+ * @param local The local InputStream from which to read the file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception CopyStreamException If an I/O error occurs while actually
+ * transferring the file. The CopyStreamException allows you to
+ * determine the number of bytes transferred and the IOException
+ * causing the error. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ public boolean storeUniqueFile(InputStream local) throws IOException
+ {
+ return __storeFile(FTPCommand.STOU, null, local);
+ }
+
+ /**
+ * Returns an OutputStream through which data can be written to store
+ * a file on the server using a unique name assigned by the server.
+ * If the current file type
+ * is ASCII, the returned OutputStream will convert line separators in
+ * the file to the NETASCII format (i.e., you should not attempt to
+ * create a special OutputStream to do this). You must close the
+ * OutputStream when you finish writing to it. The OutputStream itself
+ * will take care of closing the parent data connection socket upon being
+ * closed. To finalize the file transfer you must call
+ * {@link #completePendingCommand completePendingCommand } and
+ * check its return value to verify success.
+ *
+ * @return An OutputStream through which the remote file can be written. If
+ * the data connection cannot be opened (e.g., the file does not
+ * exist), null is returned (in which case you may check the reply
+ * code to determine the exact reason for failure).
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ public OutputStream storeUniqueFileStream() throws IOException
+ {
+ return __storeFileStream(FTPCommand.STOU, null);
+ }
+
+ /***
+ * Reserve a number of bytes on the server for the next file transfer.
+ *
+ * @param bytes The number of bytes which the server should allocate.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean allocate(int bytes) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(allo(bytes));
+ }
+
+
+ /**
+ * Reserve space on the server for the next file transfer.
+ *
+ * @param bytes The number of bytes which the server should allocate.
+ * @param recordSize The size of a file record.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ public boolean allocate(int bytes, int recordSize) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(allo(bytes, recordSize));
+ }
+
+
+ /***
+ * Restart a
+ * @param offset The offset into the remote file at which to start the
+ * next file transfer.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ private boolean restart(long offset) throws IOException
+ {
+ __restartOffset = 0;
+ return FTPReply.isPositiveIntermediate(rest(Long.toString(offset)));
+ }
+
+ /***
+ * Sets the restart offset. The restart command is sent to the server
+ * only before sending the file transfer command. When this is done,
+ * the restart marker is reset to zero.
+ *
+ * @param offset The offset into the remote file at which to start the
+ * next file transfer. This must be a value greater than or
+ * equal to zero.
+ ***/
+ public void setRestartOffset(long offset)
+ {
+ if (offset >= 0)
+ __restartOffset = offset;
+ }
+
+ /***
+ * Fetches the restart offset.
+ *
+ * @return offset The offset into the remote file at which to start the
+ * next file transfer.
+ ***/
+ public long getRestartOffset()
+ {
+ return __restartOffset;
+ }
+
+
+
+ /***
+ * Renames a remote file.
+ *
+ * @param from The name of the remote file to rename.
+ * @param to The new name of the remote file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean rename(String from, String to) throws IOException
+ {
+ if (!FTPReply.isPositiveIntermediate(rnfr(from)))
+ return false;
+
+ return FTPReply.isPositiveCompletion(rnto(to));
+ }
+
+
+ /***
+ * Abort a transfer in progress.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean abort() throws IOException
+ {
+ return FTPReply.isPositiveCompletion(abor());
+ }
+
+ /***
+ * Deletes a file on the FTP server.
+ *
+ * @param pathname The pathname of the file to be deleted.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean deleteFile(String pathname) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(dele(pathname));
+ }
+
+
+ /***
+ * Removes a directory on the FTP server (if empty).
+ *
+ * @param pathname The pathname of the directory to remove.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean removeDirectory(String pathname) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(rmd(pathname));
+ }
+
+
+ /***
+ * Creates a new subdirectory on the FTP server in the current directory
+ * (if a relative pathname is given) or where specified (if an absolute
+ * pathname is given).
+ *
+ * @param pathname The pathname of the directory to create.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean makeDirectory(String pathname) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(mkd(pathname));
+ }
+
+
+ /***
+ * Returns the pathname of the current working directory.
+ *
+ * @return The pathname of the current working directory. If it cannot
+ * be obtained, returns null.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String printWorkingDirectory() throws IOException
+ {
+ if (pwd() != FTPReply.PATHNAME_CREATED)
+ return null;
+
+ return __parsePathname(_replyLines.get( _replyLines.size() - 1));
+ }
+
+
+ /**
+ * Send a site specific command.
+ * @param arguments The site specific command and arguments.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ public boolean sendSiteCommand(String arguments) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(site(arguments));
+ }
+
+
+ /***
+ * Fetches the system type name from the server and returns the string.
+ * This value is cached for the duration of the connection after the
+ * first call to this method. In other words, only the first time
+ * that you invoke this method will it issue a SYST command to the
+ * FTP server. FTPClient will remember the value and return the
+ * cached value until a call to disconnect.
+ *
+ * @return The system type name obtained from the server. null if the
+ * information could not be obtained.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String getSystemName() throws IOException
+ {
+ //if (syst() == FTPReply.NAME_SYSTEM_TYPE)
+ // Technically, we should expect a NAME_SYSTEM_TYPE response, but
+ // in practice FTP servers deviate, so we soften the condition to
+ // a positive completion.
+ if (__systemName == null && FTPReply.isPositiveCompletion(syst()))
+ __systemName = _replyLines.get(_replyLines.size() - 1).substring(4);
+
+ return __systemName;
+ }
+
+
+ /***
+ * Fetches the system help information from the server and returns the
+ * full string.
+ *
+ * @return The system help string obtained from the server. null if the
+ * information could not be obtained.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String listHelp() throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(help()))
+ return getReplyString();
+ return null;
+ }
+
+
+ /**
+ * Fetches the help information for a given command from the server and
+ * returns the full string.
+ * @param command The command on which to ask for help.
+ * @return The command help string obtained from the server. null if the
+ * information could not be obtained.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ public String listHelp(String command) throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(help(command)))
+ return getReplyString();
+ return null;
+ }
+
+
+ /***
+ * Sends a NOOP command to the FTP server. This is useful for preventing
+ * server timeouts.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean sendNoOp() throws IOException
+ {
+ return FTPReply.isPositiveCompletion(noop());
+ }
+
+
+ /***
+ * Obtain a list of filenames in a directory (or just the name of a given
+ * file, which is not particularly useful). This information is obtained
+ * through the NLST command. If the given pathname is a directory and
+ * contains no files, a zero length array is returned only
+ * if the FTP server returned a positive completion code, otherwise
+ * null is returned (the FTP server returned a 550 error No files found.).
+ * If the directory is not empty, an array of filenames in the directory is
+ * returned. If the pathname corresponds
+ * to a file, only that file will be listed. The server may or may not
+ * expand glob expressions.
+ *
+ * @param pathname The file or directory to list.
+ * @return The list of filenames contained in the given path. null if
+ * the list could not be obtained. If there are no filenames in
+ * the directory, a zero-length array is returned.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String[] listNames(String pathname) throws IOException
+ {
+ String line;
+ Socket socket;
+ BufferedReader reader;
+ ArrayList
+ * @return The list of filenames contained in the current working
+ * directory. null if the list could not be obtained.
+ * If there are no filenames in the directory, a zero-length array
+ * is returned.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String[] listNames() throws IOException
+ {
+ return listNames(null);
+ }
+
+
+
+ /**
+ * Using the default system autodetect mechanism, obtain a
+ * list of file information for the current working directory
+ * or for just a single file.
+ *
+ * This information is obtained through the LIST command. The contents of
+ * the returned array is determined by the
+ * @param pathname The file or directory to list. Since the server may
+ * or may not expand glob expressions, using them here
+ * is not recommended and may well cause this method to
+ * fail.
+ *
+ * @return The list of file information contained in the given path in
+ * the format determined by the autodetection mechanism
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection
+ * as a result of the client being idle or some other
+ * reason causing the server to send FTP reply code 421.
+ * This exception may be caught either as an IOException
+ * or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply
+ * from the server.
+ * @exception ParserInitializationException
+ * Thrown if the parserKey parameter cannot be
+ * resolved by the selected parser factory.
+ * In the DefaultFTPEntryParserFactory, this will
+ * happen when parserKey is neither
+ * the fully qualified class name of a class
+ * implementing the interface
+ * org.apache.commons.net.ftp.FTPFileEntryParser
+ * nor a string containing one of the recognized keys
+ * mapping to such a parser or if class loader
+ * security issues prevent its being loaded.
+ * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
+ * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser
+ */
+ public FTPFile[] listFiles(String pathname)
+ throws IOException
+ {
+ String key = null;
+ FTPListParseEngine engine =
+ initiateListParsing(key, pathname);
+ return engine.getFiles();
+
+ }
+ /**
+ * Using the default system autodetect mechanism, obtain a
+ * list of file information for the current working directory.
+ *
+ * This information is obtained through the LIST command. The contents of
+ * the returned array is determined by the
+ * @return The list of file information contained in the current directory
+ * in the format determined by the autodetection mechanism.
+ *
+ * NOTE: This array may contain null members if any of the
+ * individual file listings failed to parse. The caller should
+ * check each entry for null before referencing it.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection
+ * as a result of the client being idle or some other
+ * reason causing the server to send FTP reply code 421.
+ * This exception may be caught either as an IOException
+ * or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply
+ * from the server.
+ * @exception ParserInitializationException
+ * Thrown if the parserKey parameter cannot be
+ * resolved by the selected parser factory.
+ * In the DefaultFTPEntryParserFactory, this will
+ * happen when parserKey is neither
+ * the fully qualified class name of a class
+ * implementing the interface
+ * org.apache.commons.net.ftp.FTPFileEntryParser
+ * nor a string containing one of the recognized keys
+ * mapping to such a parser or if class loader
+ * security issues prevent its being loaded.
+ * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
+ * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser
+ */
+ public FTPFile[] listFiles()
+ throws IOException
+ {
+ return listFiles((String) null);
+ }
+
+ /**
+ * Using the default autodetect mechanism, initialize an FTPListParseEngine
+ * object containing a raw file information for the current working
+ * directory on the server
+ * This information is obtained through the LIST command. This object
+ * is then capable of being iterated to return a sequence of FTPFile
+ * objects with information filled in by the
+ *
+ * This method differs from using the listFiles() methods in that
+ * expensive FTPFile objects are not created until needed which may be
+ * an advantage on large lists.
+ *
+ * @return A FTPListParseEngine object that holds the raw information and
+ * is capable of providing parsed FTPFile objects, one for each file
+ * containing information contained in the given path in the format
+ * determined by the
+ * The server may or may not expand glob expressions. You should avoid
+ * using glob expressions because the return format for glob listings
+ * differs from server to server and will likely cause this method to fail.
+ *
+ * This method differs from using the listFiles() methods in that
+ * expensive FTPFile objects are not created until needed which may be
+ * an advantage on large lists.
+ *
+ *
+ * The server may or may not expand glob expressions. You should avoid
+ * using glob expressions because the return format for glob listings
+ * differs from server to server and will likely cause this method to fail.
+ *
+ * This method differs from using the listFiles() methods in that
+ * expensive FTPFile objects are not created until needed which may be
+ * an advantage on large lists.
+ *
+ * @param parserKey A string representing a designated code or fully-qualified
+ * class name of an
+ * @return The status information returned by the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String getStatus() throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(stat()))
+ return getReplyString();
+ return null;
+ }
+
+
+ /***
+ * Issue the FTP STAT command to the server for a given pathname. This
+ * should produce a listing of the file or directory.
+ *
+ * @return The status information returned by the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String getStatus(String pathname) throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(stat(pathname)))
+ return getReplyString();
+ return null;
+ }
+
+
+ /**
+ * Issue the FTP MDTM command (not supported by all servers to retrieve the last
+ * modification time of a file. The modification string should be in the
+ * ISO 3077 form "YYYYMMDDhhmmss(.xxx)?". The timestamp represented should also be in
+ * GMT, but not all FTP servers honour this.
+ *
+ * @param pathname The file path to query.
+ * @return A string representing the last file modification time in
+ * This class implements an alternate means of configuring the
+ * {@link org.apache.commons.net.ftp.FTPClient FTPClient} object and
+ * also subordinate objects which it uses. Any class implementing the
+ * {@link org.apache.commons.net.ftp.Configurable Configurable }
+ * interface can be configured by this object.
+ *
+ * In particular this class was designed primarily to support configuration
+ * of FTP servers which express file timestamps in formats and languages
+ * other than those for the US locale, which although it is the most common
+ * is not universal. Unfortunately, nothing in the FTP spec allows this to
+ * be determined in an automated way, so manual configuration such as this
+ * is necessary.
+ *
+ * This functionality was designed to allow existing clients to work exactly
+ * as before without requiring use of this component. This component should
+ * only need to be explicitly invoked by the user of this package for problem
+ * cases that previous implementations could not solve.
+ *
+ * Unpaged (whole list) access on a UNIX server that uses French month names
+ * but uses the "standard"
+ * Paged access on a UNIX server that uses Danish month names
+ * and "European" date formatting in Denmark's time zone, when you
+ * are in some other time zone.
+ *
+ * Unpaged (whole list) access on a VMS server that uses month names
+ * in a language not {@link #getSupportedLanguageCodes() supported} by the system.
+ * but uses the "standard" super._connectAction_()
first to ensure the
+ * initialization of the aforementioned protected variables.
+ */
+ protected void _connectAction_() throws IOException
+ {
+ _socket_.setSoTimeout(_timeout_);
+ _input_ = _socket_.getInputStream();
+ _output_ = _socket_.getOutputStream();
+ }
+
+
+ /**
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the current host at a system assigned port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ * separateErrorStream
+ * parameter of {@link #rcommand rcommand() } to true
.
+ * The standard input of the remote process can be written to through
+ * the output stream returned by
+ * {@link org.apache.commons.net.bsd.RExecClient#getOutputStream getOutputStream() }
+ * .
+ * DEFAULT_PORT
.
+ ***/
+ public RCommandClient()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+
+ /***
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the specified local address using a port in a range
+ * acceptable to the BSD rshell daemon.
+ * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ * MIN_CLIENT_PORT
and
+ * MAX_CLIENT_PORT
or an IllegalArgumentException will
+ * be thrown.
+ * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ * MIN_CLIENT_PORT
and
+ * MAX_CLIENT_PORT
or an IllegalArgumentException will
+ * be thrown.
+ * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ * rcommand(localUsername, remoteUsername, command, false);
+ ***/
+ public void rcommand(String localUsername, String remoteUsername,
+ String command)
+ throws IOException
+ {
+ rcommand(localUsername, remoteUsername, command, false);
+ }
+
+}
+
diff --git a/org/apache/commons/net/bsd/RExecClient.java b/org/apache/commons/net/bsd/RExecClient.java
new file mode 100644
index 0000000..2924120
--- /dev/null
+++ b/org/apache/commons/net/bsd/RExecClient.java
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.bsd;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import org.apache.commons.net.SocketClient;
+import org.apache.commons.net.io.SocketInputStream;
+
+/***
+ * RExecClient implements the rexec() facility that first appeared in
+ * 4.2BSD Unix. This class will probably only be of use for connecting
+ * to Unix systems and only when the rexecd daemon is configured to run,
+ * which is a rarity these days because of the security risks involved.
+ * However, rexec() can be very useful for performing administrative tasks
+ * on a network behind a firewall.
+ * separateErrorStream
+ * parameter of {@link #rexec rexec() } to true
.
+ * The standard input of the remote process can be written to through
+ * the output stream returned by
+ * {@link #getOutputStream getOutputSream() }.
+ * _errorStream_
+ * will point to an InputStream from which the standard error of the
+ * remote process can be read (after a call to rexec()). Otherwise,
+ * _errorStream_
will be null.
+ ***/
+ protected InputStream _errorStream_;
+
+ // This can be overridden in local package to implement port range
+ // limitations of rcmd and rlogin
+ InputStream _createErrorStream() throws IOException
+ {
+ ServerSocket server;
+ Socket socket;
+
+ server = _serverSocketFactory_.createServerSocket(0, 1, getLocalAddress());
+
+ _output_.write(Integer.toString(server.getLocalPort()).getBytes());
+ _output_.write('\0');
+ _output_.flush();
+
+ socket = server.accept();
+ server.close();
+
+ if (__remoteVerificationEnabled && !verifyRemote(socket))
+ {
+ socket.close();
+ throw new IOException(
+ "Security violation: unexpected connection attempt by " +
+ socket.getInetAddress().getHostAddress());
+ }
+
+ return (new SocketInputStream(socket, socket.getInputStream()));
+ }
+
+
+ /***
+ * The default RExecClient constructor. Initializes the
+ * default port to DEFAULT_PORT
.
+ ***/
+ public RExecClient()
+ {
+ _errorStream_ = null;
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+
+ /***
+ * Returns the InputStream from which the standard outputof the remote
+ * process can be read. The input stream will only be set after a
+ * successful rexec() invocation.
+ * rexec(username, password, command, false);
+ ***/
+ public void rexec(String username, String password,
+ String command)
+ throws IOException
+ {
+ rexec(username, password, command, false);
+ }
+
+ /***
+ * Disconnects from the server, closing all associated open sockets and
+ * streams.
+ * DEFAULT_PORT
.
+ ***/
+ public RLoginClient()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+
+ /***
+ * Logins into a remote machine through the rlogind daemon on the server
+ * to which the RLoginClient is connected. After calling this method,
+ * you may interact with the remote login shell through its standard input
+ * and output streams. Standard error is sent over the same stream as
+ * standard output. You will typically be able to detect
+ * the termination of the remote login shell after reaching end of file
+ * on its standard output (accessible through
+ * {@link #getInputStream getInputStream() }. Disconnecting
+ * from the server or closing the process streams before reaching
+ * end of file will terminate the remote login shell in most cases.
+ * DEFAULT_PORT
.
+ ***/
+ public CharGenTCPClient ()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+ /***
+ * Returns an InputStream from which the server generated data can be
+ * read. You should NOT close the InputStream when you're finished
+ * reading from it. Rather, you should call
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * to clean up properly.
+ * send(host, CharGenUDPClient.DEFAULT_PORT);
***/
+ public void send(InetAddress host) throws IOException
+ {
+ send(host, DEFAULT_PORT);
+ }
+
+ /***
+ * Receive the reply data from the server. This will always be 512 bytes
+ * or less. Chargen and quote of the day only return one packet. Netstat
+ * and systat require multiple calls to receive() with timeout detection.
+ * DEFAULT_PORT
.
+ ***/
+ public DaytimeTCPClient ()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+ /***
+ * Retrieves the time string from the server and returns it. The
+ * server will have closed the connection at this point, so you should
+ * call
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * after calling this method. To retrieve another time, you must
+ * initiate another connection with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * before calling getTime()
again.
+ * getTime(host, DaytimeUDPClient.DEFAULT_PORT);
***/
+ public String getTime(InetAddress host) throws IOException
+ {
+ return getTime(host, DEFAULT_PORT);
+ }
+
+}
+
diff --git a/org/apache/commons/net/discard/DiscardTCPClient.java b/org/apache/commons/net/discard/DiscardTCPClient.java
new file mode 100644
index 0000000..7a771c9
--- /dev/null
+++ b/org/apache/commons/net/discard/DiscardTCPClient.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.discard;
+
+import java.io.OutputStream;
+
+import org.apache.commons.net.SocketClient;
+
+/***
+ * The DiscardTCPClient class is a TCP implementation of a client for the
+ * Discard protocol described in RFC 863. To use the class, merely
+ * establish a connection with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * and call {@link #getOutputStream getOutputStream() } to
+ * retrieve the discard output stream. Don't close the output stream
+ * when you're done writing to it. Rather, call
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * to clean up properly.
+ * DEFAULT_PORT
.
+ ***/
+ public DiscardTCPClient ()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+ /***
+ * Returns an OutputStream through which you may write data to the server.
+ * You should NOT close the OutputStream when you're finished
+ * reading from it. Rather, you should call
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * to clean up properly.
+ * send(data, length, host. DiscardUDPClient.DEFAULT_PORT)
.
+ ***/
+ public void send(byte[] data, int length, InetAddress host)
+ throws IOException
+ {
+ send(data, length, host, DEFAULT_PORT);
+ }
+
+
+ /***
+ * Same as
+ * send(data, data.length, host. DiscardUDPClient.DEFAULT_PORT)
.
+ ***/
+ public void send(byte[] data, InetAddress host) throws IOException
+ {
+ send(data, data.length, host, DEFAULT_PORT);
+ }
+
+}
+
diff --git a/org/apache/commons/net/echo/EchoTCPClient.java b/org/apache/commons/net/echo/EchoTCPClient.java
new file mode 100644
index 0000000..b4d43e2
--- /dev/null
+++ b/org/apache/commons/net/echo/EchoTCPClient.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.echo;
+
+import java.io.InputStream;
+
+import org.apache.commons.net.discard.DiscardTCPClient;
+
+/***
+ * The EchoTCPClient class is a TCP implementation of a client for the
+ * Echo protocol described in RFC 862. To use the class, merely
+ * establish a connection with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * and call {@link DiscardTCPClient#getOutputStream getOutputStream() } to
+ * retrieve the echo output stream and
+ * {@link #getInputStream getInputStream() }
+ * to get the echo input stream.
+ * Don't close either stream when you're done using them. Rather, call
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * to clean up properly.
+ * DEFAULT_PORT
.
+ ***/
+ public EchoTCPClient ()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+ /***
+ * Returns an InputStream from which you may read echoed data from
+ * the server. You should NOT close the InputStream when you're finished
+ * reading from it. Rather, you should call
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * to clean up properly.
+ * send(data, data.length, host)
***/
+ @Override
+ public void send(byte[] data, InetAddress host) throws IOException
+ {
+ send(data, data.length, host, DEFAULT_PORT);
+ }
+
+
+ /***
+ * Receives echoed data and returns its length. The data may be divided
+ * up among multiple datagrams, requiring multiple calls to receive.
+ * Also, the UDP packets will not necessarily arrive in the same order
+ * they were sent.
+ * receive(data, data.length)
***/
+ public int receive(byte[] data) throws IOException
+ {
+ return receive(data, data.length);
+ }
+
+}
+
diff --git a/org/apache/commons/net/finger/FingerClient.java b/org/apache/commons/net/finger/FingerClient.java
new file mode 100644
index 0000000..d3b6893
--- /dev/null
+++ b/org/apache/commons/net/finger/FingerClient.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.net.finger;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedOutputStream;
+import java.io.DataOutputStream;
+
+import org.apache.commons.net.SocketClient;
+
+/***
+ * The FingerClient class implements the client side of the Internet Finger
+ * Protocol defined in RFC 1288. To finger a host you create a
+ * FingerClient instance, connect to the host, query the host, and finally
+ * disconnect from the host. If the finger service you want to query is on
+ * a non-standard port, connect to the host at that port.
+ * Here's a sample use:
+ *
+ * FingerClient finger;
+ *
+ * finger = new FingerClient();
+ *
+ * try {
+ * finger.connect("foo.bar.com");
+ * System.out.println(finger.query("foobar", false));
+ * finger.disconnect();
+ * } catch(IOException e) {
+ * System.err.println("Error I/O exception: " + e.getMessage());
+ * return;
+ * }
+ *
+ * DEFAULT_PORT
.
+ ***/
+ public FingerClient()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+
+ /***
+ * Fingers a user at the connected host and returns the output
+ * as a String. You must first connect to a finger server before
+ * calling this method, and you should disconnect afterward.
+ * query(longOutput, "")
.
+ * config
are somehow inadequate to configure the
+ * Configurable object.
+ */
+ public void configure(FTPClientConfig config);
+}
diff --git a/org/apache/commons/net/ftp/FTP.class b/org/apache/commons/net/ftp/FTP.class
new file mode 100644
index 0000000..a363d55
Binary files /dev/null and b/org/apache/commons/net/ftp/FTP.class differ
diff --git a/org/apache/commons/net/ftp/FTP.java b/org/apache/commons/net/ftp/FTP.java
new file mode 100644
index 0000000..6e2eff8
--- /dev/null
+++ b/org/apache/commons/net/ftp/FTP.java
@@ -0,0 +1,1513 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.apache.commons.net.MalformedServerReplyException;
+import org.apache.commons.net.ProtocolCommandListener;
+import org.apache.commons.net.ProtocolCommandSupport;
+import org.apache.commons.net.SocketClient;
+
+/***
+ * FTP provides the basic the functionality necessary to implement your
+ * own FTP client. It extends org.apache.commons.net.SocketClient since
+ * extending TelnetClient was causing unwanted behavior (like connections
+ * that did not time out properly).
+ * FTPConectionClosedException
+ * is a subclass of IOException
and therefore need not be
+ * caught separately, but if you are going to catch it separately, its
+ * catch block must appear before the more general IOException
+ * catch block. When you encounter an
+ * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
+ * , you must disconnect the connection with
+ * {@link #disconnect disconnect() } to properly clean up the
+ * system resources used by FTP. Before disconnecting, you may check the
+ * last reply code and text with
+ * {@link #getReplyCode getReplyCode },
+ * {@link #getReplyString getReplyString },
+ * and {@link #getReplyStrings getReplyStrings}.
+ * You may avoid server disconnections while the client is idle by
+ * periodicaly sending NOOP commands to the server.
+ * FILE_TYPE
are used to indicate file types.
+ ***/
+ public static final int ASCII_FILE_TYPE = 0;
+
+ /***
+ * A constant used to indicate the file(s) being transfered should
+ * be treated as EBCDIC. Note however that there are several different
+ * EBCDIC formats. All constants ending in FILE_TYPE
+ * are used to indicate file types.
+ ***/
+ public static final int EBCDIC_FILE_TYPE = 1;
+
+
+ /***
+ * A constant used to indicate the file(s) being transfered should
+ * be treated as a binary image, i.e., no translations should be
+ * performed. All constants ending in FILE_TYPE
are used to
+ * indicate file types.
+ ***/
+ public static final int BINARY_FILE_TYPE = 2;
+
+ /***
+ * A constant used to indicate the file(s) being transfered should
+ * be treated as a local type. All constants ending in
+ * FILE_TYPE
are used to indicate file types.
+ ***/
+ public static final int LOCAL_FILE_TYPE = 3;
+
+ /***
+ * A constant used for text files to indicate a non-print text format.
+ * This is the default format.
+ * All constants ending in TEXT_FORMAT
are used to indicate
+ * text formatting for text transfers (both ASCII and EBCDIC).
+ ***/
+ public static final int NON_PRINT_TEXT_FORMAT = 4;
+
+ /***
+ * A constant used to indicate a text file contains format vertical format
+ * control characters.
+ * All constants ending in TEXT_FORMAT
are used to indicate
+ * text formatting for text transfers (both ASCII and EBCDIC).
+ ***/
+ public static final int TELNET_TEXT_FORMAT = 5;
+
+ /***
+ * A constant used to indicate a text file contains ASA vertical format
+ * control characters.
+ * All constants ending in TEXT_FORMAT
are used to indicate
+ * text formatting for text transfers (both ASCII and EBCDIC).
+ ***/
+ public static final int CARRIAGE_CONTROL_TEXT_FORMAT = 6;
+
+ /***
+ * A constant used to indicate a file is to be treated as a continuous
+ * sequence of bytes. This is the default structure. All constants ending
+ * in _STRUCTURE
are used to indicate file structure for
+ * file transfers.
+ ***/
+ public static final int FILE_STRUCTURE = 7;
+
+ /***
+ * A constant used to indicate a file is to be treated as a sequence
+ * of records. All constants ending in _STRUCTURE
+ * are used to indicate file structure for file transfers.
+ ***/
+ public static final int RECORD_STRUCTURE = 8;
+
+ /***
+ * A constant used to indicate a file is to be treated as a set of
+ * independent indexed pages. All constants ending in
+ * _STRUCTURE
are used to indicate file structure for file
+ * transfers.
+ ***/
+ public static final int PAGE_STRUCTURE = 9;
+
+ /***
+ * A constant used to indicate a file is to be transfered as a stream
+ * of bytes. This is the default transfer mode. All constants ending
+ * in TRANSFER_MODE
are used to indicate file transfer
+ * modes.
+ ***/
+ public static final int STREAM_TRANSFER_MODE = 10;
+
+ /***
+ * A constant used to indicate a file is to be transfered as a series
+ * of blocks. All constants ending in TRANSFER_MODE
are used
+ * to indicate file transfer modes.
+ ***/
+ public static final int BLOCK_TRANSFER_MODE = 11;
+
+ /***
+ * A constant used to indicate a file is to be transfered as FTP
+ * compressed data. All constants ending in TRANSFER_MODE
+ * are used to indicate file transfer modes.
+ ***/
+ public static final int COMPRESSED_TRANSFER_MODE = 12;
+
+ // We have to ensure that the protocol communication is in ASCII
+ // but we use ISO-8859-1 just in case 8-bit characters cross
+ // the wire.
+ /**
+ * The default character encoding used for communicating over an
+ * FTP control connection. The default encoding is an
+ * ASCII-compatible encoding. Some FTP servers expect other
+ * encodings. You can change the encoding used by an FTP instance
+ * with {@link #setControlEncoding setControlEncoding}.
+ */
+ public static final String DEFAULT_CONTROL_ENCODING = "ISO-8859-1";
+ private static final String __modes = "AEILNTCFRPSBC";
+
+ private StringBuilder __commandBuffer = new StringBuilder();
+
+ protected int _replyCode;
+ protected ArrayListDEFAULT_PORT
and initializes internal data structures
+ * for saving FTP reply information.
+ ***/
+ public FTP()
+ {
+ super();
+ setDefaultPort(DEFAULT_PORT);
+ _replyLines = new ArrayList connect
is of type void.
+ * FILE_TYPE
+ * constants).
+ * @param formatOrByteSize The format of the file (one of the
+ * _FORMAT
constants. In the case of
+ * LOCAL_FILE_TYPE
, the byte size.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int type(int fileType, int formatOrByteSize) throws IOException
+ {
+ StringBuffer arg = new StringBuffer();
+
+ arg.append(__modes.charAt(fileType));
+ arg.append(' ');
+ if (fileType == LOCAL_FILE_TYPE)
+ arg.append(formatOrByteSize);
+ else
+ arg.append(__modes.charAt(formatOrByteSize));
+
+ return sendCommand(FTPCommand.TYPE, arg.toString());
+ }
+
+
+ /**
+ * A convenience method to send the FTP TYPE command to the server,
+ * receive the reply, and return the reply code.
+ * FILE_TYPE
+ * constants).
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int type(int fileType) throws IOException
+ {
+ return sendCommand(FTPCommand.TYPE,
+ __modes.substring(fileType, fileType + 1));
+ }
+
+ /***
+ * A convenience method to send the FTP STRU command to the server,
+ * receive the reply, and return the reply code.
+ * _STRUCTURE
constants).
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stru(int structure) throws IOException
+ {
+ return sendCommand(FTPCommand.STRU,
+ __modes.substring(structure, structure + 1));
+ }
+
+ /***
+ * A convenience method to send the FTP MODE command to the server,
+ * receive the reply, and return the reply code.
+ * TRANSFER_MODE
constants).
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int mode(int mode) throws IOException
+ {
+ return sendCommand(FTPCommand.MODE,
+ __modes.substring(mode, mode + 1));
+ }
+
+ /***
+ * A convenience method to send the FTP RETR command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * boolean error = false;
+ * try {
+ * int reply;
+ * ftp.connect("ftp.foobar.com");
+ * System.out.println("Connected to " + server + ".");
+ * System.out.print(ftp.getReplyString());
+ *
+ * // After connection attempt, you should check the reply code to verify
+ * // success.
+ * reply = ftp.getReplyCode();
+ *
+ * if(!FTPReply.isPositiveCompletion(reply)) {
+ * ftp.disconnect();
+ * System.err.println("FTP server refused connection.");
+ * System.exit(1);
+ * }
+ * ... // transfer files
+ * ftp.logout();
+ * } catch(IOException e) {
+ * error = true;
+ * e.printStackTrace();
+ * } finally {
+ * if(ftp.isConnected()) {
+ * try {
+ * ftp.disconnect();
+ * } catch(IOException ioe) {
+ * // do nothing
+ * }
+ * }
+ * System.exit(error ? 1 : 0);
+ * }
+ *
+ * FTP.ASCII_FILE_TYPE
,
+ * FTP.NON_PRINT_TEXT_FORMAT
,
+ * FTP.STREAM_TRANSFER_MODE
, and
+ * FTP.FILE_STRUCTURE
. The only file types directly supported
+ * are FTP.ASCII_FILE_TYPE
and
+ * FTP.BINARY_FILE_TYPE
. Because there are at least 4
+ * different EBCDIC encodings, we have opted not to provide direct support
+ * for EBCDIC. To transfer EBCDIC and other unsupported file types you
+ * must create your own filter InputStreams and OutputStreams and wrap
+ * them around the streams returned or required by the FTPClient methods.
+ * FTPClient uses the {@link ToNetASCIIOutputStream NetASCII}
+ * filter streams to provide transparent handling of ASCII files. We will
+ * consider incorporating EBCDIC support if there is enough demand.
+ * FTP.NON_PRINT_TEXT_FORMAT
,
+ * FTP.STREAM_TRANSFER_MODE
, and
+ * FTP.FILE_STRUCTURE
are the only supported formats,
+ * transfer modes, and file structures.
+ * FTPConnectionClosedException
+ * is a subclass of IOException
and therefore need not be
+ * caught separately, but if you are going to catch it separately, its
+ * catch block must appear before the more general IOException
+ * catch block. When you encounter an
+ * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
+ * , you must disconnect the connection with
+ * {@link #disconnect disconnect() } to properly clean up the
+ * system resources used by FTPClient. Before disconnecting, you may check the
+ * last reply code and text with
+ * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode },
+ * {@link org.apache.commons.net.ftp.FTP#getReplyString getReplyString },
+ * and
+ * {@link org.apache.commons.net.ftp.FTP#getReplyStrings getReplyStrings}.
+ * You may avoid server disconnections while the client is idle by
+ * periodicaly sending NOOP commands to the server.
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = listFiles(directory);
+ *
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPListParseEngine engine =
+ * f.initiateListParsing("com.whatever.YourOwnParser", directory);
+ *
+ * while (engine.hasNext()) {
+ * FTPFile[] files = engine.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPListParseEngine engine = f.initiateListParsing(directory);
+ *
+ * while (engine.hasNext()) {
+ * FTPFile[] files = engine.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ *
+ *
see {@link FTPClientConfig FTPClientConfig}.
+ * MM d yyyy
ACTIVE_LOCAL_DATA_CONNECTION_MODE
, the file type
+ * set to FTP.ASCII_FILE_TYPE
, the
+ * file format set to FTP.NON_PRINT_TEXT_FORMAT
,
+ * the file structure set to FTP.FILE_STRUCTURE
, and
+ * the transfer mode set to FTP.STREAM_TRANSFER_MODE
.
+ ***/
+ public FTPClient()
+ {
+ __initDefaults();
+ __dataTimeout = -1;
+ __remoteVerificationEnabled = true;
+ __parserFactory = new DefaultFTPFileEntryParserFactory();
+ __configuration = null;
+ __listHiddenFiles = false;
+ }
+
+
+ private void __initDefaults()
+ {
+ __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
+ __passiveHost = null;
+ __passivePort = -1;
+ __fileType = FTP.ASCII_FILE_TYPE;
+ __fileStructure = FTP.FILE_STRUCTURE;
+ __fileFormat = FTP.NON_PRINT_TEXT_FORMAT;
+ __fileTransferMode = FTP.STREAM_TRANSFER_MODE;
+ __restartOffset = 0;
+ __systemName = null;
+ __entryParser = null;
+ __bufferSize = Util.DEFAULT_COPY_BUFFER_SIZE;
+ }
+
+ private String __parsePathname(String reply)
+ {
+ int begin, end;
+
+ begin = reply.indexOf('"') + 1;
+ end = reply.indexOf('"', begin);
+
+ return reply.substring(begin, end);
+ }
+
+
+ private void __parsePassiveModeReply(String reply)
+ throws MalformedServerReplyException
+ {
+ java.util.regex.Matcher m = __parms_pat.matcher(reply);
+ if (!m.find()) {
+ throw new MalformedServerReplyException(
+ "Could not parse passive host information.\nServer Reply: " + reply);
+ }
+ reply = m.group();
+ String parts[] = m.group().split(",");
+
+ __passiveHost = parts[0] + '.' + parts[1] + '.' + parts[2] + '.' + parts[3];
+
+ try
+ {
+ int oct1 = Integer.parseInt(parts[4]);
+ int oct2 = Integer.parseInt(parts[5]);
+ __passivePort = (oct1 << 8) | oct2;
+ }
+ catch (NumberFormatException e)
+ {
+ throw new MalformedServerReplyException(
+ "Could not parse passive host information.\nServer Reply: " + reply);
+ }
+
+ }
+
+ private boolean __storeFile(int command, String remote, InputStream local)
+ throws IOException
+ {
+ OutputStream output;
+ Socket socket;
+
+ if ((socket = _openDataConnection_(command, remote)) == null)
+ return false;
+
+ output = new BufferedOutputStream(socket.getOutputStream(),
+ getBufferSize()
+ );
+ if (__fileType == ASCII_FILE_TYPE)
+ output = new ToNetASCIIOutputStream(output);
+ // Treat everything else as binary for now
+ try
+ {
+ Util.copyStream(local, output, getBufferSize(),
+ CopyStreamEvent.UNKNOWN_STREAM_SIZE, null,
+ false);
+ }
+ catch (IOException e)
+ {
+ try
+ {
+ socket.close();
+ }
+ catch (IOException f)
+ {}
+ throw e;
+ }
+ output.close();
+ socket.close();
+ return completePendingCommand();
+ }
+
+ private OutputStream __storeFileStream(int command, String remote)
+ throws IOException
+ {
+ OutputStream output;
+ Socket socket;
+
+ if ((socket = _openDataConnection_(command, remote)) == null)
+ return null;
+
+ output = socket.getOutputStream();
+ if (__fileType == ASCII_FILE_TYPE) {
+ // We buffer ascii transfers because the buffering has to
+ // be interposed between ToNetASCIIOutputSream and the underlying
+ // socket output stream. We don't buffer binary transfers
+ // because we don't want to impose a buffering policy on the
+ // programmer if possible. Programmers can decide on their
+ // own if they want to wrap the SocketOutputStream we return
+ // for file types other than ASCII.
+ output = new BufferedOutputStream(output,
+ getBufferSize());
+ output = new ToNetASCIIOutputStream(output);
+
+ }
+ return new org.apache.commons.net.io.SocketOutputStream(socket, output);
+ }
+
+
+ /**
+ * Establishes a data connection with the FTP server, returning
+ * a Socket for the connection if successful. If a restart
+ * offset has been set with {@link #setRestartOffset(long)},
+ * a REST command is issued to the server with the offset as
+ * an argument before establishing the data connection. Active
+ * mode connections also cause a local PORT command to be issued.
+ * ACTIVE_LOCAL_DATA_CONNECTION_MODE
. No communication
+ * with the FTP server is conducted, but this causes all future data
+ * transfers to require the FTP server to connect to the client's
+ * data port. Additionally, to accommodate differences between socket
+ * implementations on different platforms, this method causes the
+ * client to issue a PORT command before every data transfer.
+ ***/
+ public void enterLocalActiveMode()
+ {
+ __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
+ __passiveHost = null;
+ __passivePort = -1;
+ }
+
+
+ /***
+ * Set the current data connection mode to
+ * PASSIVE_LOCAL_DATA_CONNECTION_MODE
. Use this
+ * method only for data transfers between the client and server.
+ * This method causes a PASV command to be issued to the server
+ * before the opening of every data connection, telling the server to
+ * open a data port to which the client will connect to conduct
+ * data transfers. The FTPClient will stay in
+ * PASSIVE_LOCAL_DATA_CONNECTION_MODE
until the
+ * mode is changed by calling some other method such as
+ * {@link #enterLocalActiveMode enterLocalActiveMode() }
+ ***/
+ public void enterLocalPassiveMode()
+ {
+ __dataConnectionMode = PASSIVE_LOCAL_DATA_CONNECTION_MODE;
+ // These will be set when just before a data connection is opened
+ // in _openDataConnection_()
+ __passiveHost = null;
+ __passivePort = -1;
+ }
+
+
+ /***
+ * Set the current data connection mode to
+ * ACTIVE_REMOTE_DATA_CONNECTION
. Use this method only
+ * for server to server data transfers. This method issues a PORT
+ * command to the server, indicating the other server and port to which
+ * it should connect for data transfers. You must call this method
+ * before EVERY server to server transfer attempt. The FTPClient will
+ * NOT automatically continue to issue PORT commands. You also
+ * must remember to call
+ * {@link #enterLocalActiveMode enterLocalActiveMode() } if you
+ * wish to return to the normal data connection mode.
+ * PASSIVE_REMOTE_DATA_CONNECTION_MODE
. Use this
+ * method only for server to server data transfers.
+ * This method issues a PASV command to the server, telling it to
+ * open a data port to which the active server will connect to conduct
+ * data transfers. You must call this method
+ * before EVERY server to server transfer attempt. The FTPClient will
+ * NOT automatically continue to issue PASV commands. You also
+ * must remember to call
+ * {@link #enterLocalActiveMode enterLocalActiveMode() } if you
+ * wish to return to the normal data connection mode.
+ * _DATA_CONNECTION_MODE
constants.
+ * _DATA_CONNECTION_MODE
constants.
+ ***/
+ public int getDataConnectionMode()
+ {
+ return __dataConnectionMode;
+ }
+
+
+ /***
+ * Sets the file type to be transferred. This should be one of
+ * FTP.ASCII_FILE_TYPE
, FTP.BINARY_FILE_TYPE
,
+ * etc. The file type only needs to be set when you want to change the
+ * type. After changing it, the new type stays in effect until you change
+ * it again. The default file type is FTP.ASCII_FILE_TYPE
+ * if this method is never called.
+ * _FILE_TYPE
constant indcating the
+ * type of file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean setFileType(int fileType) throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(type(fileType)))
+ {
+ __fileType = fileType;
+ __fileFormat = FTP.NON_PRINT_TEXT_FORMAT;
+ return true;
+ }
+ return false;
+ }
+
+
+ /***
+ * Sets the file type to be transferred and the format. The type should be
+ * one of FTP.ASCII_FILE_TYPE
,
+ * FTP.BINARY_FILE_TYPE
, etc. The file type only needs to
+ * be set when you want to change the type. After changing it, the new
+ * type stays in effect until you change it again. The default file type
+ * is FTP.ASCII_FILE_TYPE
if this method is never called.
+ * The format should be one of the FTP class TEXT_FORMAT
+ * constants, or if the type is FTP.LOCAL_FILE_TYPE
, the
+ * format should be the byte size for that type. The default format
+ * is FTP.NON_PRINT_TEXT_FORMAT
if this method is never
+ * called.
+ * _FILE_TYPE
constant indcating the
+ * type of file.
+ * @param formatOrByteSize The format of the file (one of the
+ * _FORMAT
constants. In the case of
+ * LOCAL_FILE_TYPE
, the byte size.
+ * FTP.FILE_STRUCTURE
if this method is never called.
+ * _STRUCTURE
constants).
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean setFileStructure(int structure) throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(stru(structure)))
+ {
+ __fileStructure = structure;
+ return true;
+ }
+ return false;
+ }
+
+
+ /***
+ * Sets the transfer mode. The default transfer mode
+ * FTP.STREAM_TRANSFER_MODE
if this method is never called.
+ * _TRANSFER_MODE
constants).
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean setFileTransferMode(int mode) throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(mode(mode)))
+ {
+ __fileTransferMode = mode;
+ return true;
+ }
+ return false;
+ }
+
+
+ /***
+ * Initiate a server to server file transfer. This method tells the
+ * server to which the client is connected to retrieve a given file from
+ * the other server.
+ * remoteRetrieve
issued to it by another
+ * FTPClient.
+ * remoteRetrieve
issued
+ * to it by another FTPClient.
+ * remoteRetrieve
issued
+ * to it by another FTPClient. Many FTP servers require that a base
+ * filename be given from which the unique filename can be derived. For
+ * those servers use the other version of remoteStoreUnique
+ * remoteRetrieve
issued to it by another FTPClient.
+ *
+ * InputStream input;
+ * OutputStream output;
+ * input = new FileInputStream("foobaz.txt");
+ * output = ftp.storeFileStream("foobar.txt")
+ * if(!FTPReply.isPositiveIntermediate(ftp.getReplyCode())) {
+ * input.close();
+ * output.close();
+ * ftp.logout();
+ * ftp.disconnect();
+ * System.err.println("File transfer failed.");
+ * System.exit(1);
+ * }
+ * Util.copyStream(input, output);
+ * input.close();
+ * output.close();
+ * // Must call completePendingCommand() to finish command.
+ * if(!ftp.completePendingCommand()) {
+ * ftp.logout();
+ * ftp.disconnect();
+ * System.err.println("File transfer failed.");
+ * System.exit(1);
+ * }
+ *
+ * STREAM_TRANSFER_MODE
file transfer starting
+ * from the given offset. This will only work on FTP servers supporting
+ * the REST comand for the stream transfer mode. However, most FTP
+ * servers support this. Any subsequent file transfer will start
+ * reading or writing the remote file from the indicated offset.
+ * FTPFileEntryParser
+ * used.
+ * FTPFileEntryParser
+ * used.
+ * FTPFileEntryParser
used.
+ * parser
parameter. Null will be
+ * returned if a data connection cannot be opened. If the current working
+ * directory contains no files, an empty array will be the return.
+ *
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ * @exception ParserInitializationException
+ * Thrown if the autodetect mechanism cannot
+ * resolve the type of system we are connected with.
+ * @see FTPListParseEngine
+ */
+ public FTPListParseEngine initiateListParsing()
+ throws IOException
+ {
+ return initiateListParsing((String) null);
+ }
+
+ /**
+ * Using the default autodetect mechanism, initialize an FTPListParseEngine
+ * object containing a raw file information for the supplied directory.
+ * This information is obtained through the LIST command. This object
+ * is then capable of being iterated to return a sequence of FTPFile
+ * objects with information filled in by the
+ * FTPFileEntryParser
used.
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPListParseEngine engine = f.initiateListParsing(directory);
+ *
+ * while (engine.hasNext()) {
+ * FTPFile[] files = engine.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ *
+ * @return A FTPListParseEngine object that holds the raw information and
+ * is capable of providing parsed FTPFile objects, one for each file
+ * containing information contained in the given path in the format
+ * determined by the parser
parameter. Null will be
+ * returned if a data connection cannot be opened. If the current working
+ * directory contains no files, an empty array will be the return.
+ *
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ * @exception ParserInitializationException
+ * Thrown if the autodetect mechanism cannot
+ * resolve the type of system we are connected with.
+ * @see FTPListParseEngine
+ */
+ public FTPListParseEngine initiateListParsing(
+ String pathname)
+ throws IOException
+ {
+ String key = null;
+ return initiateListParsing(key, pathname);
+ }
+
+ /**
+ * Using the supplied parser key, initialize an FTPListParseEngine
+ * object containing a raw file information for the supplied directory.
+ * This information is obtained through the LIST command. This object
+ * is then capable of being iterated to return a sequence of FTPFile
+ * objects with information filled in by the
+ * FTPFileEntryParser
used.
+ * FTPFileEntryParser
that should be
+ * used to parse each server file listing.
+ *
+ * @return A FTPListParseEngine object that holds the raw information and
+ * is capable of providing parsed FTPFile objects, one for each file
+ * containing information contained in the given path in the format
+ * determined by the parser
parameter. Null will be
+ * returned if a data connection cannot be opened. If the current working
+ * directory contains no files, an empty array will be the return.
+ *
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ * @exception ParserInitializationException
+ * Thrown if the parserKey parameter cannot be
+ * resolved by the selected parser factory.
+ * In the DefaultFTPEntryParserFactory, this will
+ * happen when parserKey is neither
+ * the fully qualified class name of a class
+ * implementing the interface
+ * org.apache.commons.net.ftp.FTPFileEntryParser
+ * nor a string containing one of the recognized keys
+ * mapping to such a parser or if class loader
+ * security issues prevent its being loaded.
+ * @see FTPListParseEngine
+ */
+ public FTPListParseEngine initiateListParsing(
+ String parserKey, String pathname)
+ throws IOException
+ {
+ // We cache the value to avoid creation of a new object every
+ // time a file listing is generated.
+ if(__entryParser == null) {
+ if (null != parserKey) {
+ // if a parser key was supplied in the parameters,
+ // use that to create the paraser
+ __entryParser =
+ __parserFactory.createFileEntryParser(parserKey);
+
+ } else {
+ // if no parserKey was supplied, check for a configuration
+ // in the params, and if non-null, use that.
+ if (null != __configuration) {
+ __entryParser =
+ __parserFactory.createFileEntryParser(__configuration);
+ } else {
+ // if a parserKey hasn't been supplied, and a configuration
+ // hasn't been supplied, then autodetect by calling
+ // the SYST command and use that to choose the parser.
+ __entryParser =
+ __parserFactory.createFileEntryParser(getSystemName());
+ }
+ }
+ }
+
+ return initiateListParsing(__entryParser, pathname);
+
+ }
+
+
+ /**
+ * private method through which all listFiles() and
+ * initiateListParsing methods pass once a parser is determined.
+ *
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ * @see FTPListParseEngine
+ */
+ private FTPListParseEngine initiateListParsing(
+ FTPFileEntryParser parser, String pathname)
+ throws IOException
+ {
+ Socket socket;
+
+ FTPListParseEngine engine = new FTPListParseEngine(parser);
+
+ if ((socket = _openDataConnection_(FTPCommand.LIST, getListArguments(pathname))) == null)
+ {
+ return engine;
+ }
+
+
+ try {
+ engine.readServerList(socket.getInputStream(), getControlEncoding());
+ }
+ finally {
+ socket.close();
+ }
+
+ completePendingCommand();
+ return engine;
+ }
+
+ /**
+ * @since 2.0
+ */
+ protected String getListArguments(String pathname) {
+ if (getListHiddenFiles())
+ {
+ StringBuffer sb = new StringBuffer(pathname.length() + 3);
+ sb.append("-a ");
+ sb.append(pathname);
+ return sb.toString();
+ }
+
+ return pathname;
+ }
+
+
+ /***
+ * Issue the FTP STAT command to the server.
+ * YYYYMMDDhhmmss
format.
+ * @throws IOException if an I/O error occurs.
+ * @since 2.0
+ */
+ public String getModificationTime(String pathname) throws IOException {
+ if (FTPReply.isPositiveCompletion(mdtm(pathname)))
+ return getReplyString();
+ return null;
+ }
+
+
+ /**
+ * Set the internal buffer size.
+ *
+ * @param bufSize The size of the buffer
+ */
+ public void setBufferSize(int bufSize) {
+ __bufferSize = bufSize;
+ }
+
+ /**
+ * Retrieve the current internal buffer size.
+ * @return The current buffer size.
+ */
+ public int getBufferSize() {
+ return __bufferSize;
+ }
+
+
+ /**
+ * Implementation of the {@link Configurable Configurable} interface.
+ * In the case of this class, configuring merely makes the config object available for the
+ * factory methods that construct parsers.
+ * @param config {@link FTPClientConfig FTPClientConfig} object used to
+ * provide non-standard configurations to the parser.
+ * @since 1.4
+ */
+ public void configure(FTPClientConfig config) {
+ this.__configuration = config;
+ }
+
+ /**
+ * You can set this to true if you would like to get hidden files when {@link #listFiles} too.
+ * A LIST -a
will be issued to the ftp server.
+ * It depends on your ftp server if you need to call this method, also dont expect to get rid
+ * of hidden files if you call this method with "false".
+ *
+ * @param listHiddenFiles true if hidden files should be listed
+ * @since 2.0
+ */
+ public void setListHiddenFiles(boolean listHiddenFiles) {
+ this.__listHiddenFiles = listHiddenFiles;
+ }
+
+ /**
+ * @see #setListHiddenFiles(boolean)
+ * @return the current state
+ * @since 2.0
+ */
+ public boolean getListHiddenFiles() {
+ return this.__listHiddenFiles;
+ }
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/org/apache/commons/net/ftp/FTPClientConfig.class b/org/apache/commons/net/ftp/FTPClientConfig.class
new file mode 100644
index 0000000..b42c8ee
Binary files /dev/null and b/org/apache/commons/net/ftp/FTPClientConfig.class differ
diff --git a/org/apache/commons/net/ftp/FTPClientConfig.java b/org/apache/commons/net/ftp/FTPClientConfig.java
new file mode 100644
index 0000000..450eddc
--- /dev/null
+++ b/org/apache/commons/net/ftp/FTPClientConfig.java
@@ -0,0 +1,580 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+
+import java.text.DateFormatSymbols;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+
+/**
+ * Examples of use of FTPClientConfig
+ * Use cases:
+ * You are trying to access a server that
+ *
+ *
+ * MM dd yyyy
MMM d yyyy
date formatting
+ *
+ * FTPClient f=FTPClient();
+ * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
+ * conf.setServerLanguageCode("fr");
+ * f.configure(conf);
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = listFiles(directory);
+ *
+ *
+ * FTPClient f=FTPClient();
+ * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
+ * conf.setServerLanguageCode("da");
+ * conf.setDefaultDateFormat("d MMM yyyy");
+ * conf.setRecentDateFormat("d MMM HH:mm");
+ * conf.setTimeZoneId("Europe/Copenhagen");
+ * f.configure(conf);
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPListParseEngine engine =
+ * f.initiateListParsing("com.whatever.YourOwnParser", directory);
+ *
+ * while (engine.hasNext()) {
+ * FTPFile[] files = engine.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ * MMM d yyyy
date formatting
+ *
+ * FTPClient f=FTPClient();
+ * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_VMS);
+ * conf.setShortMonthNames(
+ * "jan|feb|mar|apr|ma\u00ED|j\u00FAn|j\u00FAl|\u00e1g\u00FA|sep|okt|n\u00F3v|des");
+ * f.configure(conf);
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = listFiles(directory);
+ *
+ *
+ * Unpaged (whole list) access on a Windows-NT server in a different time zone. + * (Note, since the NT Format uses numeric date formatting, language issues + * are irrelevant here). + *
+ * FTPClient f=FTPClient(); + * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT); + * conf.setTimeZoneId("America/Denver"); + * f.configure(conf); + * f.connect(server); + * f.login(username, password); + * FTPFile[] files = listFiles(directory); + *+ * + * Unpaged (whole list) access on a Windows-NT server in a different time zone + * but which has been configured to use a unix-style listing format. + *
+ * FTPClient f=FTPClient(); + * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX); + * conf.setTimeZoneId("America/Denver"); + * f.configure(conf); + * f.connect(server); + * f.login(username, password); + * FTPFile[] files = listFiles(directory); + *+ * + * @since 1.4 + * @see org.apache.commons.net.ftp.Configurable + * @see org.apache.commons.net.ftp.FTPClient + * @see org.apache.commons.net.ftp.parser.FTPTimestampParserImpl#configure(FTPClientConfig) + * @see org.apache.commons.net.ftp.parser.ConfigurableFTPFileEntryParserImpl + */ +public class FTPClientConfig +{ + + /** + * Identifier by which a unix-based ftp server is known throughout + * the commons-net ftp system. + */ + public static final String SYST_UNIX = "UNIX"; + + /** + * Identifier by which a vms-based ftp server is known throughout + * the commons-net ftp system. + */ + public static final String SYST_VMS = "VMS"; + + /** + * Identifier by which a WindowsNT-based ftp server is known throughout + * the commons-net ftp system. + */ + public static final String SYST_NT = "WINDOWS"; + + /** + * Identifier by which an OS/2-based ftp server is known throughout + * the commons-net ftp system. + */ + public static final String SYST_OS2 = "OS/2"; + + /** + * Identifier by which an OS/400-based ftp server is known throughout + * the commons-net ftp system. + */ + public static final String SYST_OS400 = "OS/400"; + + /** + * Identifier by which an AS/400-based ftp server is known throughout + * the commons-net ftp system. + */ + public static final String SYST_AS400 = "AS/400"; + + /** + * Identifier by which an MVS-based ftp server is known throughout + * the commons-net ftp system. + */ + public static final String SYST_MVS = "MVS"; + + /** + * Some servers return an "UNKNOWN Type: L8" message + * in response to the SYST command. We set these to be a Unix-type system. + * This may happen if the ftpd in question was compiled without system + * information. + * + * NET-230 - Updated to be UPPERCASE so that the check done in + * createFileEntryParser will succeed. + * + * @since 1.5 + */ + public static final String SYST_L8 = "TYPE: L8"; + + /** + * Identifier by which an Netware-based ftp server is known throughout + * the commons-net ftp system. + * + * @since 1.5 + */ + public static final String SYST_NETWARE = "NETWARE"; + + private final String serverSystemKey; + private String defaultDateFormatStr = null; + private String recentDateFormatStr = null; + private boolean lenientFutureDates = false; + private String serverLanguageCode = null; + private String shortMonthNames = null; + private String serverTimeZoneId = null; + + + /** + * The main constructor for an FTPClientConfig object + * @param systemKey key representing system type of the server being + * connected to. See {@link #getServerSystemKey() serverSystemKey} + */ + public FTPClientConfig(String systemKey) { + this.serverSystemKey = systemKey; + } + + /** + * Convenience constructor mainly for use in testing. + * Constructs a UNIX configuration. + */ + public FTPClientConfig() { + this(SYST_UNIX); + } + + /** + * Constructor which allows setting of all member fields + * @param systemKey key representing system type of the server being + * connected to. See + * {@link #getServerSystemKey() serverSystemKey} + * @param defaultDateFormatStr See + * {@link #setDefaultDateFormatStr(String) defaultDateFormatStr} + * @param recentDateFormatStr See + * {@link #setRecentDateFormatStr(String) recentDateFormatStr} + * @param serverLanguageCode See + * {@link #setServerLanguageCode(String) serverLanguageCode} + * @param shortMonthNames See + * {@link #setShortMonthNames(String) shortMonthNames} + * @param serverTimeZoneId See + * {@link #setServerTimeZoneId(String) serverTimeZoneId} + */ + public FTPClientConfig(String systemKey, + String defaultDateFormatStr, + String recentDateFormatStr, + String serverLanguageCode, + String shortMonthNames, + String serverTimeZoneId) + { + this(systemKey); + this.defaultDateFormatStr = defaultDateFormatStr; + this.recentDateFormatStr = recentDateFormatStr; + this.serverLanguageCode = serverLanguageCode; + this.shortMonthNames = shortMonthNames; + this.serverTimeZoneId = serverTimeZoneId; + } + + private static Map
FTPClientConfig.SYST_*
codes
+ * or else the fully qualified class name of a parser implementing both
+ * the FTPFileEntryParser
and Configurable
+ * interfaces.
+ * @return Returns the serverSystemKey property.
+ */
+ public String getServerSystemKey() {
+ return serverSystemKey;
+ }
+
+ /**
+ * getter for the {@link #setDefaultDateFormatStr(String) defaultDateFormatStr}
+ * property.
+ * @return Returns the defaultDateFormatStr property.
+ */
+ public String getDefaultDateFormatStr() {
+ return defaultDateFormatStr;
+ }
+
+ /**
+ * getter for the {@link #setRecentDateFormatStr(String) recentDateFormatStr} property.
+ * @return Returns the recentDateFormatStr property.
+ */
+
+ public String getRecentDateFormatStr() {
+ return recentDateFormatStr;
+ }
+
+ /**
+ * getter for the {@link #setServerTimeZoneId(String) serverTimeZoneId} property.
+ * @return Returns the serverTimeZoneId property.
+ */
+ public String getServerTimeZoneId() {
+ return serverTimeZoneId;
+ }
+
+ /**
+ * + * getter for the {@link #setShortMonthNames(String) shortMonthNames} + * property. + *
+ * @return Returns the shortMonthNames. + */ + public String getShortMonthNames() { + return shortMonthNames; + } + + /** + *+ * getter for the {@link #setServerLanguageCode(String) serverLanguageCode} property. + *
+ * @return Returns the serverLanguageCode property. + */ + public String getServerLanguageCode() { + return serverLanguageCode; + } + + /** + *+ * getter for the {@link #setLenientFutureDates(boolean) lenientFutureDates} property. + *
+ * @return Returns the lenientFutureDates. + * @since 1.5 + */ + public boolean isLenientFutureDates() { + return lenientFutureDates; + } + /** + *
+ * setter for the defaultDateFormatStr property. This property
+ * specifies the main date format that will be used by a parser configured
+ * by this configuration to parse file timestamps. If this is not
+ * specified, such a parser will use as a default value, the most commonly
+ * used format which will be in as used in en_US
locales.
+ *
+ * This should be in the format described for
+ * java.text.SimpleDateFormat
.
+ * property.
+ *
+ * setter for the recentDateFormatStr property. This property + * specifies a secondary date format that will be used by a parser + * configured by this configuration to parse file timestamps, typically + * those less than a year old. If this is not specified, such a parser + * will not attempt to parse using an alternate format. + *
+ * This is used primarily in unix-based systems. + * + * This should be in the format described for + *java.text.SimpleDateFormat
.
+ *
+ * @param recentDateFormatStr The recentDateFormatStr to set.
+ */
+ public void setRecentDateFormatStr(String recentDateFormatStr) {
+ this.recentDateFormatStr = recentDateFormatStr;
+ }
+
+ /**
+ * + * setter for the lenientFutureDates property. This boolean property + * (default: false) only has meaning when a + * {@link #setRecentDateFormatStr(String) recentDateFormatStr} property + * has been set. In that case, if this property is set true, then the + * parser, when it encounters a listing parseable with the recent date + * format, will only consider a date to belong to the previous year if + * it is more than one day in the future. This will allow all + * out-of-synch situations (whether based on "slop" - i.e. servers simply + * out of synch with one another or because of time zone differences - + * but in the latter case it is highly recommended to use the + * {@link #setServerTimeZoneId(String) serverTimeZoneId} property + * instead) to resolve correctly. + *
+ * This is used primarily in unix-based systems. + *
+ * @param lenientFutureDates set true to compensate for out-of-synch + * conditions. + */ + public void setLenientFutureDates(boolean lenientFutureDates) { + this.lenientFutureDates = lenientFutureDates; + } + /** + *+ * setter for the serverTimeZoneId property. This property + * allows a time zone to be specified corresponding to that known to be + * used by an FTP server in file listings. This might be particularly + * useful to clients such as Ant that try to use these timestamps for + * dependency checking. + *
+ * This should be one of the identifiers used by
+ * java.util.TimeZone
to refer to time zones, for example,
+ * America/Chicago
or Asia/Rangoon
.
+ *
+ * setter for the shortMonthNames property. + * This property allows the user to specify a set of month names + * used by the server that is different from those that may be + * specified using the {@link #setServerLanguageCode(String) serverLanguageCode} + * property. + *
+ * This should be a string containing twelve strings each composed of
+ * three characters, delimited by pipe (|) characters. Currently,
+ * only 8-bit ASCII characters are known to be supported. For example,
+ * a set of month names used by a hypothetical Icelandic FTP server might
+ * conceivably be specified as
+ * "jan|feb|mar|apr|maí|jún|júl|ágú|sep|okt|nóv|des"
.
+ *
+ * setter for the serverLanguageCode property. This property allows + * user to specify a + * + * two-letter ISO-639 language code that will be used to + * configure the set of month names used by the file timestamp parser. + * If neither this nor the {@link #setShortMonthNames(String) shortMonthNames} + * is specified, parsing will assume English month names, which may or + * may not be significant, depending on whether the date format(s) + * specified via {@link #setDefaultDateFormatStr(String) defaultDateFormatStr} + * and/or {@link #setRecentDateFormatStr(String) recentDateFormatStr} are using + * numeric or alphabetic month names. + *
+ *If the code supplied is not supported here, en_US
+ * month names will be used. We are supporting here those language
+ * codes which, when a java.util.Locale
is constucted
+ * using it, and a java.text.SimpleDateFormat
is
+ * constructed using that Locale, the array returned by the
+ * SimpleDateFormat's getShortMonths()
method consists
+ * solely of three 8-bit ASCII character strings. Additionally,
+ * languages which do not meet this requirement are included if a
+ * common alternative set of short month names is known to be used.
+ * This means that users who can tell us of additional such encodings
+ * may get them added to the list of supported languages by contacting
+ * the jakarta-commons-net team.
+ *
+ * Please note that this attribute will NOT be used to determine a
+ * locale-based date format for the language.
+ * Experience has shown that many if not most FTP servers outside the
+ * United States employ the standard en_US
date format
+ * orderings of MMM d yyyy
and MMM d HH:mm
+ * and attempting to deduce this automatically here would cause more
+ * problems than it would solve. The date format must be changed
+ * via the {@link #setDefaultDateFormatStr(String) defaultDateFormatStr} and/or
+ * {@link #setRecentDateFormatStr(String) recentDateFormatStr} parameters.
+ *
Locale.US
+ * @param languageCode See {@link #setServerLanguageCode(String) serverLanguageCode}
+ * @return a DateFormatSymbols object configured with short month names
+ * corresponding to the supplied code, or with month names for
+ * Locale.US
if there is no corresponding entry in the internal
+ * table.
+ */
+ public static DateFormatSymbols lookupDateFormatSymbols(String languageCode)
+ {
+ Object lang = LANGUAGE_CODE_MAP.get(languageCode);
+ if (lang != null) {
+ if (lang instanceof Locale) {
+ return new DateFormatSymbols((Locale) lang);
+ } else if (lang instanceof String){
+ return getDateFormatSymbols((String) lang);
+ }
+ }
+ return new DateFormatSymbols(Locale.US);
+ }
+
+ /**
+ * Returns a DateFormatSymbols object configured with short month names
+ * as in the supplied string
+ * @param shortmonths This should be as described in
+ * {@link #setShortMonthNames(String) shortMonthNames}
+ * @return a DateFormatSymbols object configured with short month names
+ * as in the supplied string
+ */
+ public static DateFormatSymbols getDateFormatSymbols(String shortmonths)
+ {
+ String[] months = splitShortMonthString(shortmonths);
+ DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+ dfs.setShortMonths(months);
+ return dfs;
+ }
+
+ private static String[] splitShortMonthString(String shortmonths) {
+ StringTokenizer st = new StringTokenizer(shortmonths, "|");
+ int monthcnt = st.countTokens();
+ if (12 != monthcnt) {
+ throw new IllegalArgumentException(
+ "expecting a pipe-delimited string containing 12 tokens");
+ }
+ String[] months = new String[13];
+ int pos = 0;
+ while(st.hasMoreTokens()) {
+ months[pos++] = st.nextToken();
+ }
+ months[pos]="";
+ return months;
+ }
+
+ /**
+ * Returns a Collection of all the language codes currently supported
+ * by this class. See {@link #setServerLanguageCode(String) serverLanguageCode}
+ * for a functional descrption of language codes within this system.
+ *
+ * @return a Collection of all the language codes currently supported
+ * by this class
+ */
+ public static Collection+ *
+ * @author Daniel F. Savarese + ***/ + +public final class FTPCommand +{ + + + public static final int USER = 0; + public static final int PASS = 1; + public static final int ACCT = 2; + public static final int CWD = 3; + public static final int CDUP = 4; + public static final int SMNT = 5; + public static final int REIN = 6; + public static final int QUIT = 7; + public static final int PORT = 8; + public static final int PASV = 9; + public static final int TYPE = 10; + public static final int STRU = 11; + public static final int MODE = 12; + public static final int RETR = 13; + public static final int STOR = 14; + public static final int STOU = 15; + public static final int APPE = 16; + public static final int ALLO = 17; + public static final int REST = 18; + public static final int RNFR = 19; + public static final int RNTO = 20; + public static final int ABOR = 21; + public static final int DELE = 22; + public static final int RMD = 23; + public static final int MKD = 24; + public static final int PWD = 25; + public static final int LIST = 26; + public static final int NLST = 27; + public static final int SITE = 28; + public static final int SYST = 29; + public static final int STAT = 30; + public static final int HELP = 31; + public static final int NOOP = 32; + /** @since 2.0 */ + public static final int MDTM = 33; + + public static final int USERNAME = USER; + public static final int PASSWORD = PASS; + public static final int ACCOUNT = ACCT; + public static final int CHANGE_WORKING_DIRECTORY = CWD; + public static final int CHANGE_TO_PARENT_DIRECTORY = CDUP; + public static final int STRUCTURE_MOUNT = SMNT; + public static final int REINITIALIZE = REIN; + public static final int LOGOUT = QUIT; + public static final int DATA_PORT = PORT; + public static final int PASSIVE = PASV; + public static final int REPRESENTATION_TYPE = TYPE; + public static final int FILE_STRUCTURE = STRU; + public static final int TRANSFER_MODE = MODE; + public static final int RETRIEVE = RETR; + public static final int STORE = STOR; + public static final int STORE_UNIQUE = STOU; + public static final int APPEND = APPE; + public static final int ALLOCATE = ALLO; + public static final int RESTART = REST; + public static final int RENAME_FROM = RNFR; + public static final int RENAME_TO = RNTO; + public static final int ABORT = ABOR; + public static final int DELETE = DELE; + public static final int REMOVE_DIRECTORY = RMD; + public static final int MAKE_DIRECTORY = MKD; + public static final int PRINT_WORKING_DIRECTORY = PWD; + // public static final int LIST = LIST; + public static final int NAME_LIST = NLST; + public static final int SITE_PARAMETERS = SITE; + public static final int SYSTEM = SYST; + public static final int STATUS = STAT; + //public static final int HELP = HELP; + //public static final int NOOP = NOOP; + /** @since 2.0 */ + public static final int MOD_TIME = MDTM; + + // Cannot be instantiated + private FTPCommand() + {} + + static final String[] _commands = { + "USER", "PASS", "ACCT", "CWD", "CDUP", "SMNT", "REIN", "QUIT", "PORT", + "PASV", "TYPE", "STRU", "MODE", "RETR", "STOR", "STOU", "APPE", "ALLO", + "REST", "RNFR", "RNTO", "ABOR", "DELE", "RMD", "MKD", "PWD", "LIST", + "NLST", "SITE", "SYST", "STAT", "HELP", "NOOP" + }; + + /** + * Retrieve the FTP protocol command string corresponding to a specified + * command code. + *
+ * @param command The command code. + * @return The FTP protcol command string corresponding to a specified + * command code. + */ + public static final String getCommand(int command) + { + return _commands[command]; + } +} diff --git a/org/apache/commons/net/ftp/FTPConnectionClosedException.class b/org/apache/commons/net/ftp/FTPConnectionClosedException.class new file mode 100644 index 0000000..38004cb Binary files /dev/null and b/org/apache/commons/net/ftp/FTPConnectionClosedException.class differ diff --git a/org/apache/commons/net/ftp/FTPConnectionClosedException.java b/org/apache/commons/net/ftp/FTPConnectionClosedException.java new file mode 100644 index 0000000..3eccbf4 --- /dev/null +++ b/org/apache/commons/net/ftp/FTPConnectionClosedException.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.net.ftp; +import java.io.IOException; + +/*** + * FTPConnectionClosedException is used to indicate the premature or + * unexpected closing of an FTP connection resulting from a + * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE } + * response (FTP reply code 421) to a + * failed FTP command. This exception is derived from IOException and + * therefore may be caught either as an IOException or specifically as an + * FTPConnectionClosedException. + *
+ *
+ * @author Daniel F. Savarese + * @see FTP + * @see FTPClient + ***/ + +public class FTPConnectionClosedException extends IOException +{ + + /*** Constructs a FTPConnectionClosedException with no message ***/ + public FTPConnectionClosedException() + { + super(); + } + + /*** + * Constructs a FTPConnectionClosedException with a specified message. + *
+ * @param message The message explaining the reason for the exception. + ***/ + public FTPConnectionClosedException(String message) + { + super(message); + } + +} diff --git a/org/apache/commons/net/ftp/FTPFile.class b/org/apache/commons/net/ftp/FTPFile.class new file mode 100644 index 0000000..6cb7744 Binary files /dev/null and b/org/apache/commons/net/ftp/FTPFile.class differ diff --git a/org/apache/commons/net/ftp/FTPFile.java b/org/apache/commons/net/ftp/FTPFile.java new file mode 100644 index 0000000..dd67904 --- /dev/null +++ b/org/apache/commons/net/ftp/FTPFile.java @@ -0,0 +1,392 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.net.ftp; +import java.io.Serializable; +import java.util.Calendar; + +/*** + * The FTPFile class is used to represent information about files stored + * on an FTP server. Because there is no standard representation for + * file information on FTP servers, it may not always be possible to + * extract all the information that can be represented by FTPFile, or + * it may even be possible to extract more information. In cases where + * more information can be extracted, you will want to subclass FTPFile + * and implement your own {@link org.apache.commons.net.ftp.FTPFileListParser} + * to extract the information. + * However, most FTP servers return file information in a format that + * can be completely parsed by + * {@link org.apache.commons.net.ftp.DefaultFTPFileListParser} + * and stored in FTPFile. + *
+ *
+ * @author Daniel F. Savarese + * @see FTPFileListParser + * @see DefaultFTPFileListParser + * @see FTPClient#listFiles + ***/ + +public class FTPFile implements Serializable +{ + /** A constant indicating an FTPFile is a file. ***/ + public static final int FILE_TYPE = 0; + /** A constant indicating an FTPFile is a directory. ***/ + public static final int DIRECTORY_TYPE = 1; + /** A constant indicating an FTPFile is a symbolic link. ***/ + public static final int SYMBOLIC_LINK_TYPE = 2; + /** A constant indicating an FTPFile is of unknown type. ***/ + public static final int UNKNOWN_TYPE = 3; + + /** A constant indicating user access permissions. ***/ + public static final int USER_ACCESS = 0; + /** A constant indicating group access permissions. ***/ + public static final int GROUP_ACCESS = 1; + /** A constant indicating world access permissions. ***/ + public static final int WORLD_ACCESS = 2; + + /** A constant indicating file/directory read permission. ***/ + public static final int READ_PERMISSION = 0; + /** A constant indicating file/directory write permission. ***/ + public static final int WRITE_PERMISSION = 1; + /** + * A constant indicating file execute permission or directory listing + * permission. + ***/ + public static final int EXECUTE_PERMISSION = 2; + + int _type, _hardLinkCount; + long _size; + String _rawListing, _user, _group, _name, _link; + Calendar _date; + boolean[] _permissions[]; + + /*** Creates an empty FTPFile. ***/ + public FTPFile() + { + _permissions = new boolean[3][3]; + _rawListing = null; + _type = UNKNOWN_TYPE; + _hardLinkCount = 0; + _size = 0; + _user = null; + _group = null; + _date = null; + _name = null; + } + + + /*** + * Set the original FTP server raw listing from which the FTPFile was + * created. + *
+ * @param rawListing The raw FTP server listing. + ***/ + public void setRawListing(String rawListing) + { + _rawListing = rawListing; + } + + /*** + * Get the original FTP server raw listing used to initialize the FTPFile. + *
+ * @return The original FTP server raw listing used to initialize the + * FTPFile. + ***/ + public String getRawListing() + { + return _rawListing; + } + + + /*** + * Determine if the file is a directory. + *
+ * @return True if the file is of type DIRECTORY_TYPE
, false if
+ * not.
+ ***/
+ public boolean isDirectory()
+ {
+ return (_type == DIRECTORY_TYPE);
+ }
+
+ /***
+ * Determine if the file is a regular file.
+ *
+ * @return True if the file is of type FILE_TYPE
, false if
+ * not.
+ ***/
+ public boolean isFile()
+ {
+ return (_type == FILE_TYPE);
+ }
+
+ /***
+ * Determine if the file is a symbolic link.
+ *
+ * @return True if the file is of type UNKNOWN_TYPE
, false if
+ * not.
+ ***/
+ public boolean isSymbolicLink()
+ {
+ return (_type == SYMBOLIC_LINK_TYPE);
+ }
+
+ /***
+ * Determine if the type of the file is unknown.
+ *
+ * @return True if the file is of type UNKNOWN_TYPE
, false if
+ * not.
+ ***/
+ public boolean isUnknown()
+ {
+ return (_type == UNKNOWN_TYPE);
+ }
+
+
+ /***
+ * Set the type of the file (DIRECTORY_TYPE
,
+ * FILE_TYPE
, etc.).
+ *
+ * @param type The integer code representing the type of the file.
+ ***/
+ public void setType(int type)
+ {
+ _type = type;
+ }
+
+
+ /***
+ * Return the type of the file (one of the _TYPE
constants),
+ * e.g., if it is a directory, a regular file, or a symbolic link.
+ *
+ * @return The type of the file. + ***/ + public int getType() + { + return _type; + } + + + /*** + * Set the name of the file. + *
+ * @param name The name of the file. + ***/ + public void setName(String name) + { + _name = name; + } + + /*** + * Return the name of the file. + *
+ * @return The name of the file. + ***/ + public String getName() + { + return _name; + } + + + /** + * Set the file size in bytes. + * @param size The file size in bytes. + */ + public void setSize(long size) + { + _size = size; + } + + + /*** + * Return the file size in bytes. + *
+ * @return The file size in bytes. + ***/ + public long getSize() + { + return _size; + } + + + /*** + * Set the number of hard links to this file. This is not to be + * confused with symbolic links. + *
+ * @param links The number of hard links to this file. + ***/ + public void setHardLinkCount(int links) + { + _hardLinkCount = links; + } + + + /*** + * Return the number of hard links to this file. This is not to be + * confused with symbolic links. + *
+ * @return The number of hard links to this file. + ***/ + public int getHardLinkCount() + { + return _hardLinkCount; + } + + + /*** + * Set the name of the group owning the file. This may be + * a string representation of the group number. + *
+ * @param group The name of the group owning the file. + ***/ + public void setGroup(String group) + { + _group = group; + } + + + /*** + * Returns the name of the group owning the file. Sometimes this will be + * a string representation of the group number. + *
+ * @return The name of the group owning the file. + ***/ + public String getGroup() + { + return _group; + } + + + /*** + * Set the name of the user owning the file. This may be + * a string representation of the user number; + *
+ * @param user The name of the user owning the file. + ***/ + public void setUser(String user) + { + _user = user; + } + + /*** + * Returns the name of the user owning the file. Sometimes this will be + * a string representation of the user number. + *
+ * @return The name of the user owning the file. + ***/ + public String getUser() + { + return _user; + } + + + /*** + * If the FTPFile is a symbolic link, use this method to set the name of the + * file being pointed to by the symbolic link. + *
+ * @param link The file pointed to by the symbolic link. + ***/ + public void setLink(String link) + { + _link = link; + } + + + /*** + * If the FTPFile is a symbolic link, this method returns the name of the + * file being pointed to by the symbolic link. Otherwise it returns null. + *
+ * @return The file pointed to by the symbolic link (null if the FTPFile + * is not a symbolic link). + ***/ + public String getLink() + { + return _link; + } + + + /*** + * Set the file timestamp. This usually the last modification time. + * The parameter is not cloned, so do not alter its value after calling + * this method. + *
+ * @param date A Calendar instance representing the file timestamp. + ***/ + public void setTimestamp(Calendar date) + { + _date = date; + } + + + /*** + * Returns the file timestamp. This usually the last modification time. + *
+ * @return A Calendar instance representing the file timestamp.
+ ***/
+ public Calendar getTimestamp()
+ {
+ return _date;
+ }
+
+
+ /***
+ * Set if the given access group (one of the _ACCESS
+ * constants) has the given access permission (one of the
+ * _PERMISSION
constants) to the file.
+ *
+ * @param access The access group (one of the _ACCESS
+ * constants)
+ * @param permission The access permission (one of the
+ * _PERMISSION
constants)
+ * @param value True if permission is allowed, false if not.
+ ***/
+ public void setPermission(int access, int permission, boolean value)
+ {
+ _permissions[access][permission] = value;
+ }
+
+
+ /***
+ * Determines if the given access group (one of the _ACCESS
+ * constants) has the given access permission (one of the
+ * _PERMISSION
constants) to the file.
+ *
+ * @param access The access group (one of the _ACCESS
+ * constants)
+ * @param permission The access permission (one of the
+ * _PERMISSION
constants)
+ ***/
+ public boolean hasPermission(int access, int permission)
+ {
+ return _permissions[access][permission];
+ }
+
+
+ /***
+ * Returns a string representation of the FTPFile information. This
+ * will be the raw FTP server listing that was used to initialize the
+ * FTPFile instance.
+ *
+ * @return A string representation of the FTPFile information. + ***/ + @Override + public String toString() + { + return _rawListing; + } + +} diff --git a/org/apache/commons/net/ftp/FTPFileEntryParser.class b/org/apache/commons/net/ftp/FTPFileEntryParser.class new file mode 100644 index 0000000..2643bb2 Binary files /dev/null and b/org/apache/commons/net/ftp/FTPFileEntryParser.class differ diff --git a/org/apache/commons/net/ftp/FTPFileEntryParser.java b/org/apache/commons/net/ftp/FTPFileEntryParser.java new file mode 100644 index 0000000..8e6d09c --- /dev/null +++ b/org/apache/commons/net/ftp/FTPFileEntryParser.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.net.ftp; +import java.io.BufferedReader; +import java.io.IOException; +import java.util.List; + +/** + * FTPFileEntryParser defines the interface for parsing a single FTP file + * listing and converting that information into an + * {@link org.apache.commons.net.ftp.FTPFile} instance. + * Sometimes you will want to parse unusual listing formats, in which + * case you would create your own implementation of FTPFileEntryParser and + * if necessary, subclass FTPFile. + *
+ * Here are some examples showing how to use one of the classes that + * implement this interface. + *
+ * The first example shows how to get an iterable list of files in which the
+ * more expensive FTPFile
objects are not created until needed. This
+ * is suitable for paged displays. It requires that a parser object be created
+ * beforehand: parser
is an object (in the package
+ * org.apache.commons.net.ftp.parser
)
+ * implementing this inteface.
+ *
+ *
+ * FTPClient f=FTPClient(); + * f.connect(server); + * f.login(username, password); + * FTPFileList list = f.createFileList(directory, parser); + * FTPFileIterator iter = list.iterator(); + * + * while (iter.hasNext()) { + * FTPFile[] files = iter.getNext(25); // "page size" you want + * //do whatever you want with these files, display them, etc. + * //expensive FTPFile objects not created until needed. + * } + *+ * + * The second example uses the revised
FTPClient.listFiles()
+ * API to pull the whole list from the subfolder subfolder
in
+ * one call, attempting to automatically detect the parser type. This
+ * method, without a parserKey parameter, indicates that autodection should
+ * be used.
+ *
+ * + * FTPClient f=FTPClient(); + * f.connect(server); + * f.login(username, password); + * FTPFile[] files = f.listFiles("subfolder"); + *+ * + * The third example uses the revised
FTPClient.listFiles()
>
+ * API to pull the whole list from the current working directory in one call,
+ * but specifying by classname the parser to be used. For this particular
+ * parser class, this approach is necessary since there is no way to
+ * autodetect this server type.
+ *
+ * + * FTPClient f=FTPClient(); + * f.connect(server); + * f.login(username, password); + * FTPFile[] files = f.listFiles( + * "org.apache.commons.net.ftp.parser.EnterpriseUnixFTPFileEntryParser", + * "."); + *+ * + * The fourth example uses the revised
FTPClient.listFiles()
+ * API to pull a single file listing in an arbitrary directory in one call,
+ * specifying by KEY the parser to be used, in this case, VMS.
+ *
+ * + * FTPClient f=FTPClient(); + * f.connect(server); + * f.login(username, password); + * FTPFile[] files = f.listFiles("VMS", "subfolder/foo.java"); + *+ * + * @author Steve Cohen + * @version $Id: FTPFileEntryParser.java 636854 2008-03-13 19:55:01Z sebb $ + * @see org.apache.commons.net.ftp.FTPFile + * @see org.apache.commons.net.ftp.FTPClient#createFileList + */ +public interface FTPFileEntryParser +{ + /** + * Parses a line of an FTP server file listing and converts it into a usable + * format in the form of an
FTPFile
instance. If the
+ * file listing line doesn't describe a file, null
should be
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ *
+ * @param listEntry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ FTPFile parseFTPEntry(String listEntry);
+
+ /**
+ * Reads the next entry using the supplied BufferedReader object up to
+ * whatever delemits one entry from the next. Implementors must define
+ * this for the particular ftp system being parsed. In many but not all
+ * cases, this can be defined simply by calling BufferedReader.readLine().
+ *
+ * @param reader The BufferedReader object from which entries are to be
+ * read.
+ *
+ * @return A string representing the next ftp entry or null if none found.
+ * @exception IOException thrown on any IO Error reading from the reader.
+ */
+ String readNextEntry(BufferedReader reader) throws IOException;
+
+
+ /**
+ * This method is a hook for those implementors (such as
+ * VMSVersioningFTPEntryParser, and possibly others) which need to
+ * perform some action upon the FTPFileList after it has been created
+ * from the server stream, but before any clients see the list.
+ *
+ * The default implementation can be a no-op.
+ *
+ * @param original Original list after it has been created from the server stream
+ *
+ * @return Original list as processed by this method.
+ */
+ List
+ * This object defines a two-part parsing mechanism.
+ *
+ * The first part is comprised of reading the raw input into an internal
+ * list of strings. Every item in this list corresponds to an actual
+ * file. All extraneous matter emitted by the server will have been
+ * removed by the end of this phase. This is accomplished in conjunction
+ * with the FTPFileEntryParser associated with this engine, by calling
+ * its methods
+ * The second part is composed of the actual parsing, again in conjunction
+ * with the particular parser used by this engine. This is controlled
+ * by an iterator over the internal list of strings. This may be done
+ * either in block mode, by calling the
+ * Examples:
+ *
+ * Paged access:
+ *
+ * For unpaged access, simply use FTPClient.listFiles(). That method
+ * uses this class transparently.
+ * @version $Id: FTPListParseEngine.java 658518 2008-05-21 01:04:30Z sebb $
+ */
+public class FTPListParseEngine {
+ private List
+ * NOTE: This array may contain null members if any of the
+ * individual file listings failed to parse. The caller should
+ * check each entry for null before referencing it.
+ */
+ public FTPFile[] getNext(int quantityRequested) {
+ List
+ * NOTE: This array may contain null members if any of the
+ * individual file listings failed to parse. The caller should
+ * check each entry for null before referencing it.
+ */
+ public FTPFile[] getPrevious(int quantityRequested) {
+ List
+ * NOTE: This array may contain null members if any of the
+ * individual file listings failed to parse. The caller should
+ * check each entry for null before referencing it.
+ * @exception IOException
+ */
+ public FTPFile[] getFiles()
+ throws IOException
+ {
+ List
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class FTPReply
+{
+
+ public static final int CODE_110 = 110;
+ public static final int CODE_120 = 120;
+ public static final int CODE_125 = 125;
+ public static final int CODE_150 = 150;
+ public static final int CODE_200 = 200;
+ public static final int CODE_202 = 202;
+ public static final int CODE_211 = 211;
+ public static final int CODE_212 = 212;
+ public static final int CODE_213 = 213;
+ public static final int CODE_214 = 214;
+ public static final int CODE_215 = 215;
+ public static final int CODE_220 = 220;
+ public static final int CODE_221 = 221;
+ public static final int CODE_225 = 225;
+ public static final int CODE_226 = 226;
+ public static final int CODE_227 = 227;
+ public static final int CODE_230 = 230;
+ public static final int CODE_250 = 250;
+ public static final int CODE_257 = 257;
+ public static final int CODE_331 = 331;
+ public static final int CODE_332 = 332;
+ public static final int CODE_350 = 350;
+ public static final int CODE_421 = 421;
+ public static final int CODE_425 = 425;
+ public static final int CODE_426 = 426;
+ public static final int CODE_450 = 450;
+ public static final int CODE_451 = 451;
+ public static final int CODE_452 = 452;
+ public static final int CODE_500 = 500;
+ public static final int CODE_501 = 501;
+ public static final int CODE_502 = 502;
+ public static final int CODE_503 = 503;
+ public static final int CODE_504 = 504;
+ public static final int CODE_521 = 521;
+ public static final int CODE_530 = 530;
+ public static final int CODE_532 = 532;
+ public static final int CODE_550 = 550;
+ public static final int CODE_551 = 551;
+ public static final int CODE_552 = 552;
+ public static final int CODE_553 = 553;
+
+ public static final int RESTART_MARKER = CODE_110;
+ public static final int SERVICE_NOT_READY = CODE_120;
+ public static final int DATA_CONNECTION_ALREADY_OPEN = CODE_125;
+ public static final int FILE_STATUS_OK = CODE_150;
+ public static final int COMMAND_OK = CODE_200;
+ public static final int COMMAND_IS_SUPERFLUOUS = CODE_202;
+ public static final int SYSTEM_STATUS = CODE_211;
+ public static final int DIRECTORY_STATUS = CODE_212;
+ public static final int FILE_STATUS = CODE_213;
+ public static final int HELP_MESSAGE = CODE_214;
+ public static final int NAME_SYSTEM_TYPE = CODE_215;
+ public static final int SERVICE_READY = CODE_220;
+ public static final int SERVICE_CLOSING_CONTROL_CONNECTION = CODE_221;
+ public static final int DATA_CONNECTION_OPEN = CODE_225;
+ public static final int CLOSING_DATA_CONNECTION = CODE_226;
+ public static final int ENTERING_PASSIVE_MODE = CODE_227;
+ public static final int USER_LOGGED_IN = CODE_230;
+ public static final int FILE_ACTION_OK = CODE_250;
+ public static final int PATHNAME_CREATED = CODE_257;
+ public static final int NEED_PASSWORD = CODE_331;
+ public static final int NEED_ACCOUNT = CODE_332;
+ public static final int FILE_ACTION_PENDING = CODE_350;
+ public static final int SERVICE_NOT_AVAILABLE = CODE_421;
+ public static final int CANNOT_OPEN_DATA_CONNECTION = CODE_425;
+ public static final int TRANSFER_ABORTED = CODE_426;
+ public static final int FILE_ACTION_NOT_TAKEN = CODE_450;
+ public static final int ACTION_ABORTED = CODE_451;
+ public static final int INSUFFICIENT_STORAGE = CODE_452;
+ public static final int UNRECOGNIZED_COMMAND = CODE_500;
+ public static final int SYNTAX_ERROR_IN_ARGUMENTS = CODE_501;
+ public static final int COMMAND_NOT_IMPLEMENTED = CODE_502;
+ public static final int BAD_COMMAND_SEQUENCE = CODE_503;
+ public static final int COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER = CODE_504;
+ public static final int NOT_LOGGED_IN = CODE_530;
+ public static final int NEED_ACCOUNT_FOR_STORING_FILES = CODE_532;
+ public static final int FILE_UNAVAILABLE = CODE_550;
+ public static final int PAGE_TYPE_UNKNOWN = CODE_551;
+ public static final int STORAGE_ALLOCATION_EXCEEDED = CODE_552;
+ public static final int FILE_NAME_NOT_ALLOWED = CODE_553;
+
+ // FTPS Reply Codes
+ /** @since 2.0 */
+ public static final int CODE_234 = 234;
+ /** @since 2.0 */
+ public static final int CODE_235 = 235;
+ /** @since 2.0 */
+ public static final int CODE_334 = 334;
+ /** @since 2.0 */
+ public static final int CODE_335 = 335;
+ /** @since 2.0 */
+ public static final int CODE_431 = 431;
+ /** @since 2.0 */
+ public static final int CODE_533 = 533;
+ /** @since 2.0 */
+ public static final int CODE_534 = 534;
+ /** @since 2.0 */
+ public static final int CODE_535 = 535;
+ /** @since 2.0 */
+ public static final int CODE_536 = 536;
+
+ /** @since 2.0 */
+ public static final int SECURITY_DATA_EXCHANGE_COMPLETE = CODE_234;
+ /** @since 2.0 */
+ public static final int SECURITY_DATA_EXCHANGE_SUCCESSFULLY = CODE_235;
+ /** @since 2.0 */
+ public static final int SECURITY_MECHANISM_IS_OK = CODE_334;
+ /** @since 2.0 */
+ public static final int SECURITY_DATA_IS_ACCEPTABLE = CODE_335;
+ /** @since 2.0 */
+ public static final int UNAVAILABLE_RESOURCE = CODE_431;
+ /** @since 2.0 */
+ public static final int DENIED_FOR_POLICY_REASONS = CODE_533;
+ /** @since 2.0 */
+ public static final int REQUEST_DENIED = CODE_534;
+ /** @since 2.0 */
+ public static final int FAILED_SECURITY_CHECK = CODE_535;
+ /** @since 2.0 */
+ public static final int REQUESTED_PROT_LEVEL_NOT_SUPPORTED = CODE_536;
+
+
+ // Cannot be instantiated
+ private FTPReply()
+ {}
+
+ /***
+ * Determine if a reply code is a positive preliminary response. All
+ * codes beginning with a 1 are positive preliminary responses.
+ * Postitive preliminary responses are used to indicate tentative success.
+ * No further commands can be issued to the FTP server after a positive
+ * preliminary response until a follow up response is received from the
+ * server.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive preliminary response, false
+ * if not.
+ ***/
+ public static boolean isPositivePreliminary(int reply)
+ {
+ return (reply >= 100 && reply < 200);
+ }
+
+ /***
+ * Determine if a reply code is a positive completion response. All
+ * codes beginning with a 2 are positive completion responses.
+ * The FTP server will send a positive completion response on the final
+ * successful completion of a command.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive completion response, false
+ * if not.
+ ***/
+ public static boolean isPositiveCompletion(int reply)
+ {
+ return (reply >= 200 && reply < 300);
+ }
+
+ /***
+ * Determine if a reply code is a positive intermediate response. All
+ * codes beginning with a 3 are positive intermediate responses.
+ * The FTP server will send a positive intermediate response on the
+ * successful completion of one part of a multi-part sequence of
+ * commands. For example, after a successful USER command, a positive
+ * intermediate response will be sent to indicate that the server is
+ * ready for the PASS command.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive intermediate response, false
+ * if not.
+ ***/
+ public static boolean isPositiveIntermediate(int reply)
+ {
+ return (reply >= 300 && reply < 400);
+ }
+
+ /***
+ * Determine if a reply code is a negative transient response. All
+ * codes beginning with a 4 are negative transient responses.
+ * The FTP server will send a negative transient response on the
+ * failure of a command that can be reattempted with success.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a negative transient response, false
+ * if not.
+ ***/
+ public static boolean isNegativeTransient(int reply)
+ {
+ return (reply >= 400 && reply < 500);
+ }
+
+ /***
+ * Determine if a reply code is a negative permanent response. All
+ * codes beginning with a 5 are negative permanent responses.
+ * The FTP server will send a negative permanent response on the
+ * failure of a command that cannot be reattempted with success.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a negative permanent response, false
+ * if not.
+ ***/
+ public static boolean isNegativePermanent(int reply)
+ {
+ return (reply >= 500 && reply < 600);
+ }
+
+}
diff --git a/org/apache/commons/net/ftp/FTPSClient.java b/org/apache/commons/net/ftp/FTPSClient.java
new file mode 100644
index 0000000..f809c41
--- /dev/null
+++ b/org/apache/commons/net/ftp/FTPSClient.java
@@ -0,0 +1,533 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+/**
+ * FTP over SSL processing. If desired, the JVM property -Djavax.net.debug=all can be used to
+ * see wire-level SSL details.
+ *
+ * @version $Id: FTPSClient.java 658520 2008-05-21 01:14:11Z sebb $
+ * @since 2.0
+ */
+public class FTPSClient extends FTPClient {
+
+ /** keystore algorithm name. */
+ public static String KEYSTORE_ALGORITHM;
+ /** truststore algorithm name. */
+ public static String TRUSTSTORE_ALGORITHM;
+ /** provider name. */
+ public static String PROVIDER;
+ /** truststore type. */
+ public static String STORE_TYPE;
+
+ /** The value that I can set in PROT command */
+ private static final String[] PROT_COMMAND_VALUE = {"C","E","S","P"};
+ /** Default PROT Command */
+ private static final String DEFAULT_PROT = "C";
+ /** Default protocol name */
+ private static final String DEFAULT_PROTOCOL = "TLS";
+
+ /** The security mode. (True - Implicit Mode / False - Explicit Mode) */
+ private boolean isImplicit;
+ /** The use SSL/TLS protocol. */
+ private String protocol = DEFAULT_PROTOCOL;
+ /** The AUTH Command value */
+ private String auth = DEFAULT_PROTOCOL;
+ /** The context object. */
+ private SSLContext context;
+ /** The socket object. */
+ private Socket planeSocket;
+ /** The established socket flag. */
+ private boolean isCreation = true;
+ /** The use client mode flag. */
+ private boolean isClientMode = true;
+ /** The need client auth flag. */
+ private boolean isNeedClientAuth = false;
+ /** The want client auth flag. */
+ private boolean isWantClientAuth = false;
+ /** The cipher suites */
+ private String[] suites = null;
+ /** The protocol versions */
+ private String[] protocols = null;
+
+ /** The FTPS {@link TrustManager} implementation. */
+ private TrustManager trustManager = new FTPSTrustManager();
+
+ /** The {@link KeyManager} */
+ private KeyManager keyManager;
+
+ /**
+ * Constructor for FTPSClient.
+ * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+ * is not available in the environment.
+ */
+ public FTPSClient() throws NoSuchAlgorithmException {
+ this.protocol = DEFAULT_PROTOCOL;
+ this.isImplicit = false;
+ }
+
+ /**
+ * Constructor for FTPSClient.
+ * @param isImplicit The secutiry mode(Implicit/Explicit).
+ * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+ * is not available in the environment.
+ */
+ public FTPSClient(boolean isImplicit) throws NoSuchAlgorithmException {
+ this.protocol = DEFAULT_PROTOCOL;
+ this.isImplicit = isImplicit;
+ }
+
+ /**
+ * Constructor for FTPSClient.
+ * @param protocol the protocol
+ * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+ * is not available in the environment.
+ */
+ public FTPSClient(String protocol) throws NoSuchAlgorithmException {
+ this.protocol = protocol;
+ this.isImplicit = false;
+ }
+
+ /**
+ * Constructor for FTPSClient.
+ * @param protocol the protocol
+ * @param isImplicit The secutiry mode(Implicit/Explicit).
+ * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+ * is not available in the environment.
+ */
+ public FTPSClient(String protocol, boolean isImplicit)
+ throws NoSuchAlgorithmException {
+ this.protocol = protocol;
+ this.isImplicit = isImplicit;
+ }
+
+
+ /**
+ * Set AUTH command use value.
+ * This processing is done before connected processing.
+ * @param auth AUTH command use value.
+ */
+ public void setAuthValue(String auth) {
+ this.auth = auth;
+ }
+
+ /**
+ * Return AUTH command use value.
+ * @return AUTH command use value.
+ */
+ public String getAuthValue() {
+ return this.auth;
+ }
+
+
+ /**
+ * Because there are so many connect() methods,
+ * the _connectAction_() method is provided as a means of performing
+ * some action immediately after establishing a connection,
+ * rather than reimplementing all of the connect() methods.
+ * @throws IOException If it throw by _connectAction_.
+ * @see org.apache.commons.net.SocketClient#_connectAction_()
+ */
+ @Override
+ protected void _connectAction_() throws IOException {
+ // Implicit mode.
+ if (isImplicit) sslNegotiation();
+ super._connectAction_();
+ // Explicit mode.
+ if (!isImplicit) {
+ execAUTH();
+ sslNegotiation();
+ }
+ }
+
+ /**
+ * AUTH command.
+ * @throws SSLException If it server reply code not equal "234" and "334".
+ * @throws IOException If an I/O error occurs while either sending
+ * the command.
+ */
+ private void execAUTH() throws SSLException, IOException {
+ int replyCode = sendCommand(
+ FTPSCommand._commands[FTPSCommand.AUTH], auth);
+ if (FTPReply.SECURITY_MECHANISM_IS_OK == replyCode) {
+ // replyCode = 334
+ // I carry out an ADAT command.
+ } else if (FTPReply.SECURITY_DATA_EXCHANGE_COMPLETE != replyCode) {
+ throw new SSLException(getReplyString());
+ }
+ }
+
+ /**
+ * Performs a lazy init of the SSL context
+ * @throws IOException
+ */
+ private void initSslContext() throws IOException {
+ if(context == null) {
+ try {
+ context = SSLContext.getInstance(protocol);
+
+ context.init(new KeyManager[] { getKeyManager() } , new TrustManager[] { getTrustManager() } , null);
+ } catch (KeyManagementException e) {
+ IOException ioe = new IOException("Could not initialize SSL context");
+ ioe.initCause(e);
+ throw ioe;
+ } catch (NoSuchAlgorithmException e) {
+ IOException ioe = new IOException("Could not initialize SSL context");
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+ }
+
+ /**
+ * SSL/TLS negotiation. Acquires an SSL socket of a control
+ * connection and carries out handshake processing.
+ * @throws IOException A handicap breaks out by sever negotiation.
+ */
+ private void sslNegotiation() throws IOException {
+ // Evacuation not ssl socket.
+ planeSocket = _socket_;
+
+ initSslContext();
+
+ SSLSocketFactory ssf = context.getSocketFactory();
+ String ip = _socket_.getInetAddress().getHostAddress();
+ int port = _socket_.getPort();
+ SSLSocket socket =
+ (SSLSocket) ssf.createSocket(_socket_, ip, port, true);
+ socket.setEnableSessionCreation(isCreation);
+ socket.setUseClientMode(isClientMode);
+ // server mode
+ if (!isClientMode) {
+ socket.setNeedClientAuth(isNeedClientAuth);
+ socket.setWantClientAuth(isWantClientAuth);
+ }
+ if (protocols != null) socket.setEnabledProtocols(protocols);
+ if (suites != null) socket.setEnabledCipherSuites(suites);
+
+ socket.startHandshake();
+
+ _socket_ = socket;
+ _controlInput_ = new BufferedReader(new InputStreamReader(
+ socket .getInputStream(), getControlEncoding()));
+ _controlOutput_ = new BufferedWriter(new OutputStreamWriter(
+ socket.getOutputStream(), getControlEncoding()));
+ }
+
+ /**
+ * Get the {@link KeyManager} instance.
+ * @return The {@link KeyManager} instance
+ */
+ private KeyManager getKeyManager() {
+ return keyManager;
+ }
+
+ /**
+ * Set a {@link KeyManager} to use
+ *
+ * @param keyManager The KeyManager implementation to set.
+ */
+ public void setKeyManager(KeyManager keyManager) {
+ this.keyManager = keyManager;
+ }
+
+ /**
+ * Controls whether new a SSL session may be established by this socket.
+ * @param isCreation The established socket flag.
+ */
+ public void setEnabledSessionCreation(boolean isCreation) {
+ this.isCreation = isCreation;
+ }
+
+ /**
+ * Returns true if new SSL sessions may be established by this socket.
+ * When a socket does not have a ssl socket, This return False.
+ * @return true - Indicates that sessions may be created;
+ * this is the default.
+ * false - indicates that an existing session must be resumed.
+ */
+ public boolean getEnableSessionCreation() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getEnableSessionCreation();
+ return false;
+ }
+
+ /**
+ * Configures the socket to require client authentication.
+ * @param isNeedClientAuth The need client auth flag.
+ */
+ public void setNeedClientAuth(boolean isNeedClientAuth) {
+ this.isNeedClientAuth = isNeedClientAuth;
+ }
+
+ /**
+ * Returns true if the socket will require client authentication.
+ * When a socket does not have a ssl socket, This return False.
+ * @return true - If the server mode socket should request
+ * that the client authenticate itself.
+ */
+ public boolean getNeedClientAuth() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getNeedClientAuth();
+ return false;
+ }
+
+ /**
+ * Configures the socket to request client authentication,
+ * but only if such a request is appropriate to the cipher
+ * suite negotiated.
+ * @param isWantClientAuth The want client auth flag.
+ */
+ public void setWantClientAuth(boolean isWantClientAuth) {
+ this.isWantClientAuth = isWantClientAuth;
+ }
+
+ /**
+ * Returns true if the socket will request client authentication.
+ * When a socket does not have a ssl socket, This return False.
+ * @return true - If the server mode socket should request
+ * that the client authenticate itself.
+ */
+ public boolean getWantClientAuth() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getWantClientAuth();
+ return false;
+ }
+
+ /**
+ * Configures the socket to use client (or server) mode in its first
+ * handshake.
+ * @param isClientMode The use client mode flag.
+ */
+ public void setUseClientMode(boolean isClientMode) {
+ this.isClientMode = isClientMode;
+ }
+
+ /**
+ * Returns true if the socket is set to use client mode
+ * in its first handshake.
+ * When a socket does not have a ssl socket, This return False.
+ * @return true - If the socket should start its first handshake
+ * in "client" mode.
+ */
+ public boolean getUseClientMode() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getUseClientMode();
+ return false;
+ }
+
+ /**
+ * Controls which particular cipher suites are enabled for use on this
+ * connection. I perform setting before a server negotiation.
+ * @param cipherSuites The cipher suites.
+ */
+ public void setEnabledCipherSuites(String[] cipherSuites) {
+ suites = new String[cipherSuites.length];
+ System.arraycopy(cipherSuites, 0, suites, 0, cipherSuites.length);
+ }
+
+ /**
+ * Returns the names of the cipher suites which could be enabled
+ * for use on this connection.
+ * When a socket does not have a ssl socket, This return null.
+ * @return An array of cipher suite names.
+ */
+ public String[] getEnabledCipherSuites() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getEnabledCipherSuites();
+ return null;
+ }
+
+ /**
+ * Controls which particular protocol versions are enabled for use on this
+ * connection. I perform setting before a server negotiation.
+ * @param protocolVersions The protocol versions.
+ */
+ public void setEnabledProtocols(String[] protocolVersions) {
+ protocols = new String[protocolVersions.length];
+ System.arraycopy(protocolVersions, 0, protocols, 0, protocolVersions.length);
+ }
+
+ /**
+ * Returns the names of the protocol versions which are currently
+ * enabled for use on this connection.
+ * When a socket does not have a ssl socket, This return null.
+ * @return An array of protocols.
+ */
+ public String[] getEnabledProtocols() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getEnabledProtocols();
+ return null;
+ }
+
+ /**
+ * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer.
+ * @param pbsz Protection Buffer Size.
+ * @throws SSLException If it server reply code not equal "200".
+ * @throws IOException If an I/O error occurs while either sending
+ * the command.
+ */
+ public void execPBSZ(long pbsz) throws SSLException, IOException {
+ if (pbsz < 0 || 4294967295L < pbsz)
+ throw new IllegalArgumentException();
+ if (FTPReply.COMMAND_OK != sendCommand(
+ FTPSCommand._commands[FTPSCommand.PBSZ],String.valueOf(pbsz)))
+ throw new SSLException(getReplyString());
+ }
+
+ /**
+ * PROT command.
+ * C - Clear
+ * S - Safe(SSL protocol only)
+ * E - Confidential(SSL protocol only)
+ * P - Private
+ * @param prot Data Channel Protection Level.
+ * @throws SSLException If it server reply code not equal "200".
+ * @throws IOException If an I/O error occurs while either sending
+ * the command.
+ */
+ public void execPROT(String prot) throws SSLException, IOException {
+ if (prot == null) prot = DEFAULT_PROT;
+ if (!checkPROTValue(prot)) throw new IllegalArgumentException();
+ if (FTPReply.COMMAND_OK != sendCommand(
+ FTPSCommand._commands[FTPSCommand.PROT], prot))
+ throw new SSLException(getReplyString());
+ if (DEFAULT_PROT.equals(prot)) {
+ setSocketFactory(null);
+ setServerSocketFactory(null);
+ } else {
+ setSocketFactory(new FTPSSocketFactory(context));
+
+ initSslContext();
+
+ SSLServerSocketFactory ssf = context.getServerSocketFactory();
+
+ setServerSocketFactory(ssf);
+ }
+ }
+
+ /**
+ * I check the value that I can set in PROT Command value.
+ * @param prot Data Channel Protection Level.
+ * @return True - A set point is right / False - A set point is not right
+ */
+ private boolean checkPROTValue(String prot) {
+ for (int p = 0; p < PROT_COMMAND_VALUE.length; p++) {
+ if (PROT_COMMAND_VALUE[p].equals(prot)) return true;
+ }
+ return false;
+ }
+
+ /**
+ * I carry out an ftp command.
+ * When a CCC command was carried out, I steep socket and SocketFactory
+ * in a state of not ssl.
+ * @parm command ftp command.
+ * @return server reply.
+ * @throws IOException If an I/O error occurs while either sending
+ * the command.
+ * @see org.apache.commons.net.ftp.FTP#sendCommand(java.lang.String)
+ */
+ @Override
+ public int sendCommand(String command, String args) throws IOException {
+ int repCode = super.sendCommand(command, args);
+ if (FTPSCommand._commands[FTPSCommand.CCC].equals(command)) {
+ if (FTPReply.COMMAND_OK == repCode) {
+ // TODO Check this - is this necessary at all?
+ _socket_ = planeSocket;
+ setSocketFactory(null);
+ } else {
+ throw new SSLException(getReplyString());
+ }
+ }
+ return repCode;
+ }
+
+ /**
+ * Returns a socket of the data connection.
+ * Wrapped as an {@link SSLSocket}, which carries out handshake processing.
+ * @pram command The text representation of the FTP command to send.
+ * @param arg The arguments to the FTP command.
+ * If this parameter is set to null, then the command is sent with
+ * no argument.
+ * @return A Socket corresponding to the established data connection.
+ * Null is returned if an FTP protocol error is reported at any point
+ * during the establishment and initialization of the connection.
+ * @throws IOException If there is any problem with the connection.
+ * @see org.apache.commons.net.ftp.FTPClient#_openDataConnection_(java.lang.String, int)
+ */
+ @Override
+ protected Socket _openDataConnection_(int command, String arg)
+ throws IOException {
+ Socket socket = super._openDataConnection_(command, arg);
+ if (socket != null && socket instanceof SSLSocket) {
+ SSLSocket sslSocket = (SSLSocket)socket;
+ sslSocket.setUseClientMode(isClientMode);
+ sslSocket.setEnableSessionCreation(isCreation);
+ // server mode
+ if (!isClientMode) {
+ sslSocket.setNeedClientAuth(isNeedClientAuth);
+ sslSocket.setWantClientAuth(isWantClientAuth);
+ }
+ if (suites != null)
+ sslSocket.setEnabledCipherSuites(suites);
+ if (protocols != null)
+ sslSocket.setEnabledProtocols(protocols);
+ sslSocket.startHandshake();
+ }
+ return socket;
+ }
+
+ /**
+ * Get the currently configured {@link TrustManager}.
+ *
+ * @return A TrustManager instance.
+ */
+ public TrustManager getTrustManager() {
+ return trustManager;
+ }
+
+ /**
+ * Override the default {@link TrustManager} to use.
+ *
+ * @param trustManager The TrustManager implementation to set.
+ */
+ public void setTrustManager(TrustManager trustManager) {
+ this.trustManager = trustManager;
+ }
+
+
+
+}
diff --git a/org/apache/commons/net/ftp/FTPSCommand.java b/org/apache/commons/net/ftp/FTPSCommand.java
new file mode 100644
index 0000000..6fd2efa
--- /dev/null
+++ b/org/apache/commons/net/ftp/FTPSCommand.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+
+/**
+ * I acquire a command added in FTPS.
+ * @since 2.0
+ */
+public final class FTPSCommand {
+ public static final int AUTH = 0;
+ public static final int ADAT = 1;
+ public static final int PBSZ = 2;
+ public static final int PROT = 3;
+ public static final int CCC = 4;
+
+ public static final int AUTHENTICATION_SECURITY_MECHANISM = AUTH;
+ public static final int AUTHENTICATION_SECURITY_DATA = ADAT;
+ public static final int PROTECTION_BUFFER_SIZE = PBSZ;
+ public static final int DATA_CHANNEL_PROTECTION_LEVEL = PROT;
+ public static final int CLEAR_COMMAND_CHANNEL = CCC;
+
+ static final String[] _commands = {"AUTH","ADAT","PBSZ","PROT","CCC"};
+
+ /**
+ * Retrieve the FTPS command string corresponding to a specified
+ * command code.
+ *
+ * @param command The command code.
+ * @return The FTPS command string corresponding to a specified
+ * command code.
+ */
+ public static final String getCommand(int command) {
+ return _commands[command];
+ }
+}
diff --git a/org/apache/commons/net/ftp/FTPSSocketFactory.java b/org/apache/commons/net/ftp/FTPSSocketFactory.java
new file mode 100644
index 0000000..b7e1186
--- /dev/null
+++ b/org/apache/commons/net/ftp/FTPSSocketFactory.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.net.ftp;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+
+
+/**
+ *
+ * Implementation of org.apache.commons.net.SocketFactory
+ *
+ * @since 2.0
+ */
+public class FTPSSocketFactory extends SocketFactory {
+
+ private SSLContext context;
+
+ public FTPSSocketFactory(SSLContext context) {
+ this.context = context;
+ }
+
+ @Override
+ public Socket createSocket(String address, int port) throws UnknownHostException, IOException {
+ return this.context.getSocketFactory().createSocket(address, port);
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port) throws IOException {
+ return this.context.getSocketFactory().createSocket(address, port);
+ }
+
+ @Override
+ public Socket createSocket(String address, int port, InetAddress localAddress, int localPort) throws UnknownHostException, IOException {
+ return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort);
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
+ return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort);
+ }
+
+ public ServerSocket createServerSocket(int port) throws IOException {
+ return this.init(this.context.getServerSocketFactory().createServerSocket(port));
+ }
+
+ public ServerSocket createServerSocket(int port, int backlog) throws IOException {
+ return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog));
+ }
+
+ public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException {
+ return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog, ifAddress));
+ }
+
+ public ServerSocket init(ServerSocket socket) throws IOException {
+ ((SSLServerSocket) socket).setUseClientMode(true);
+ return socket;
+ }
+}
diff --git a/org/apache/commons/net/ftp/FTPSTrustManager.java b/org/apache/commons/net/ftp/FTPSTrustManager.java
new file mode 100644
index 0000000..d1a2dd7
--- /dev/null
+++ b/org/apache/commons/net/ftp/FTPSTrustManager.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * Custom {@link TrustManager} implementation.
+ *
+ * @version $Id: FTPSTrustManager.java 658520 2008-05-21 01:14:11Z sebb $
+ * @since 2.0
+ */
+public class FTPSTrustManager implements X509TrustManager
+{
+ /**
+ * No-op
+ */
+ public void checkClientTrusted(X509Certificate[] certificates, String authType)
+ {
+ return;
+ }
+
+ public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException
+ {
+ for (int i = 0; i < certificates.length; ++i)
+ {
+ certificates[i].checkValidity();
+ }
+ }
+
+ public X509Certificate[] getAcceptedIssuers()
+ {
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.class b/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.class
new file mode 100644
index 0000000..0beda53
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.class differ
diff --git a/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java b/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java
new file mode 100644
index 0000000..4977b3f
--- /dev/null
+++ b/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.net.ftp.FTPFileEntryParser;
+import org.apache.commons.net.ftp.FTPFileEntryParserImpl;
+
+/**
+ * This implementation allows to pack some FileEntryParsers together
+ * and handle the case where to returned dirstyle isnt clearly defined.
+ * The matching parser will be cached.
+ * If the cached parser wont match due to the server changed the dirstyle,
+ * a new matching parser will be searched.
+ *
+ * @author Mario Ivankovits
+ * This abstract class implements the common timestamp parsing
+ * algorithm for all the concrete parsers. Classes derived from
+ * this one will parse file listings via a supplied regular expression
+ * that pulls out the date portion as a separate string which is
+ * passed to the underlying {@link FTPTimestampParser delegate} to
+ * handle parsing of the file timestamp.
+ *
+ * This class also implements the {@link Configurable Configurable}
+ * interface to allow the parser to be configured from the outside.
+ *
+ * @param timestampStr the timestamp string pulled from the
+ * file listing by the regular expression parser, to be submitted
+ * to the Implementation extracts a key from the supplied
+ * {@link FTPClientConfig FTPClientConfig}
+ * parameter and creates an object implementing the
+ * interface FTPFileEntryParser and uses the supplied configuration
+ * to configure it.
+ *
+ * Note that this method will generally not be called in scenarios
+ * that call for autodetection of parser type but rather, for situations
+ * where the user knows that the server uses a non-default configuration
+ * and knows what that configuration is.
+ *
+ * Note: EnterpriseUnixFTPEntryParser can only be instantiated through the
+ * DefaultFTPParserFactory by classname. It will not be chosen
+ * by the autodetection scheme.
+ *
+ * @version $Id: EnterpriseUnixFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
+ * @author Winston Ojeda
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
+ */
+public class EnterpriseUnixFTPEntryParser extends RegexFTPFileEntryParserImpl
+{
+
+ /**
+ * months abbreviations looked for by this parser. Also used
+ * to determine which month has been matched by the parser.
+ */
+ private static final String MONTHS =
+ "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)";
+
+ /**
+ * this is the regular expression used by this parser.
+ */
+ private static final String REGEX =
+ "(([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])"
+ + "([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z]))"
+ + "(\\S*)\\s*"
+ + "(\\S+)\\s*"
+ + "(\\S*)\\s*"
+ + "(\\d*)\\s*"
+ + "(\\d*)\\s*"
+ + MONTHS
+ + "\\s*"
+ + "((?:[012]\\d*)|(?:3[01]))\\s*"
+ + "((\\d\\d\\d\\d)|((?:[01]\\d)|(?:2[0123])):([012345]\\d))\\s"
+ + "(\\S*)(\\s*.*)";
+
+ /**
+ * The sole constructor for a EnterpriseUnixFTPEntryParser object.
+ *
+ */
+ public EnterpriseUnixFTPEntryParser()
+ {
+ super(REGEX);
+ }
+
+ /**
+ * Parses a line of a unix FTP server file listing and converts it into a
+ * usable format in the form of an
+ * Implementation should be a method that extracts
+ * a key from the supplied {@link FTPClientConfig FTPClientConfig}
+ * parameter and creates an object implementing the
+ * interface FTPFileEntryParser and uses the supplied configuration
+ * to configure it.
+ *
+ * Note that this method will generally not be called in scenarios
+ * that call for autodetection of parser type but rather, for situations
+ * where the user knows that the server uses a non-default configuration
+ * and knows what that configuration is.
+ *
+ * Set up the {@link FTPClientConfig#setDefaultDateFormatStr(java.lang.String) defaultDateFormat}
+ * and optionally the {@link FTPClientConfig#setRecentDateFormatStr(String) recentDateFormat}
+ * to values supplied in the config based on month names configured as follows:
+ *
+ * Finally if a {@link org.apache.commons.net.ftp.FTPClientConfig#setServerTimeZoneId(String) serverTimeZoneId}
+ * has been supplied via the config, set that into all date formats that have
+ * been configured.
+ *
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry)
+ {
+ FTPFile f = new FTPFile();
+ f.setRawListing(entry);
+
+ if (matches(entry))
+ {
+ String datestr = group(1)+" "+group(2);
+ String dirString = group(3);
+ String size = group(4);
+ String name = group(5);
+ try
+ {
+ f.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+ if (null == name || name.equals(".") || name.equals(".."))
+ {
+ return (null);
+ }
+ f.setName(name);
+
+
+ if ("
+ *
+ * Netware file permissions are in the following format: RWCEAFMS, and are explained as follows:
+ *
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry)
+ {
+
+ FTPFile f = new FTPFile();
+ if (matches(entry))
+ {
+ String size = group(1);
+ String attrib = group(2);
+ String dirString = group(3);
+ String datestr = group(4)+" "+group(5);
+ String name = group(6);
+ try
+ {
+ f.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+
+ //is it a DIR or a file
+ if (dirString.trim().equals("DIR") || attrib.trim().equals("DIR"))
+ {
+ f.setType(FTPFile.DIRECTORY_TYPE);
+ }
+ else
+ {
+ f.setType(FTPFile.FILE_TYPE);
+ }
+
+
+ //set the name
+ f.setName(name.trim());
+
+ //set the size
+ f.setSize(Long.parseLong(size.trim()));
+
+ return (f);
+ }
+ return null;
+
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_OS2,
+ DEFAULT_DATE_FORMAT,
+ null, null, null, null);
+ }
+
+}
diff --git a/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.class b/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.class
new file mode 100644
index 0000000..b77795b
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.class differ
diff --git a/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java b/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
new file mode 100644
index 0000000..66c370b
--- /dev/null
+++ b/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+
+import java.text.ParseException;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFile;
+
+/**
+ * @version $Id: OS400FTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
+ */
+
+public class OS400FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
+{
+ private static final String DEFAULT_DATE_FORMAT
+ = "yy/MM/dd HH:mm:ss"; //01/11/09 12:30:24
+
+
+
+ private static final String REGEX =
+ "(\\S+)\\s+" // user
+ + "(\\d+)\\s+" // size
+ + "(\\S+)\\s+(\\S+)\\s+" // date stuff
+ + "(\\*\\S+)\\s+" // *STMF/*DIR
+ + "(\\S+/?)\\s*"; // filename
+
+
+ /**
+ * The default constructor for a OS400FTPEntryParser object.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ *
+ * For now end users may specify this format only via
+ *
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry) {
+ FTPFile file = new FTPFile();
+ file.setRawListing(entry);
+ int type;
+ boolean isDevice = false;
+
+ if (matches(entry))
+ {
+ String typeStr = group(1);
+ String hardLinkCount = group(15);
+ String usr = group(16);
+ String grp = group(17);
+ String filesize = group(18);
+ String datestr = group(19) + " " + group(20);
+ String name = group(21);
+ String endtoken = group(22);
+
+ try
+ {
+ file.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+
+ // bcdlfmpSs-
+ switch (typeStr.charAt(0))
+ {
+ case 'd':
+ type = FTPFile.DIRECTORY_TYPE;
+ break;
+ case 'e':
+ type = FTPFile.SYMBOLIC_LINK_TYPE;
+ break;
+ case 'l':
+ type = FTPFile.SYMBOLIC_LINK_TYPE;
+ break;
+ case 'b':
+ case 'c':
+ isDevice = true;
+ // break; - fall through
+ case 'f':
+ case '-':
+ type = FTPFile.FILE_TYPE;
+ break;
+ default:
+ type = FTPFile.UNKNOWN_TYPE;
+ }
+
+ file.setType(type);
+
+ int g = 4;
+ for (int access = 0; access < 3; access++, g += 4)
+ {
+ // Use != '-' to avoid having to check for suid and sticky bits
+ file.setPermission(access, FTPFile.READ_PERMISSION,
+ (!group(g).equals("-")));
+ file.setPermission(access, FTPFile.WRITE_PERMISSION,
+ (!group(g + 1).equals("-")));
+
+ String execPerm = group(g + 2);
+ if (!execPerm.equals("-") && !Character.isUpperCase(execPerm.charAt(0)))
+ {
+ file.setPermission(access, FTPFile.EXECUTE_PERMISSION, true);
+ }
+ else
+ {
+ file.setPermission(access, FTPFile.EXECUTE_PERMISSION, false);
+ }
+ }
+
+ if (!isDevice)
+ {
+ try
+ {
+ file.setHardLinkCount(Integer.parseInt(hardLinkCount));
+ }
+ catch (NumberFormatException e)
+ {
+ // intentionally do nothing
+ }
+ }
+
+ file.setUser(usr);
+ file.setGroup(grp);
+
+ try
+ {
+ file.setSize(Long.parseLong(filesize));
+ }
+ catch (NumberFormatException e)
+ {
+ // intentionally do nothing
+ }
+
+ if (null == endtoken)
+ {
+ file.setName(name);
+ }
+ else
+ {
+ // oddball cases like symbolic links, file names
+ // with spaces in them.
+ name += endtoken;
+ if (type == FTPFile.SYMBOLIC_LINK_TYPE)
+ {
+
+ int end = name.indexOf(" -> ");
+ // Give up if no link indicator is present
+ if (end == -1)
+ {
+ file.setName(name);
+ }
+ else
+ {
+ file.setName(name.substring(0, end));
+ file.setLink(name.substring(end + 4));
+ }
+
+ }
+ else
+ {
+ file.setName(name);
+ }
+ }
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_UNIX,
+ DEFAULT_DATE_FORMAT,
+ DEFAULT_RECENT_DATE_FORMAT,
+ null, null, null);
+ }
+
+}
diff --git a/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.class b/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.class
new file mode 100644
index 0000000..ee8d5f3
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.class differ
diff --git a/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java b/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java
new file mode 100644
index 0000000..1e55ede
--- /dev/null
+++ b/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
+import java.util.StringTokenizer;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.net.ftp.FTPListParseEngine;
+
+/**
+ * Implementation FTPFileEntryParser and FTPFileListParser for VMS Systems.
+ * This is a sample of VMS LIST output
+ *
+ * "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ * "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ * "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ *
+ * Note: VMSFTPEntryParser can only be instantiated through the
+ * DefaultFTPParserFactory by classname. It will not be chosen
+ * by the autodetection scheme.
+ *
+ *
+ *
+ * @author Winston Ojeda
+ * @author Steve Cohen
+ * @author Stephane ESTE-GRACIAS
+ * @version $Id: VMSFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
+ *
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
+ */
+public class VMSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
+{
+
+ private static final String DEFAULT_DATE_FORMAT
+ = "d-MMM-yyyy HH:mm:ss"; //9-NOV-2001 12:30:24
+
+ /**
+ * this is the regular expression used by this parser.
+ */
+ private static final String REGEX =
+ "(.*;[0-9]+)\\s*" //1 file and version
+ + "(\\d+)/\\d+\\s*" //2 size/allocated
+ +"(\\S+)\\s+(\\S+)\\s+" //3+4 date and time
+ + "\\[(([0-9$A-Za-z_]+)|([0-9$A-Za-z_]+),([0-9$a-zA-Z_]+))\\]?\\s*" //5(6,7,8) owner
+ + "\\([a-zA-Z]*,([a-zA-Z]*),([a-zA-Z]*),([a-zA-Z]*)\\)"; //9,10,11 Permissions (O,G,W)
+ // TODO - perhaps restrict permissions to [RWED]* ?
+
+
+
+ /**
+ * Constructor for a VMSFTPEntryParser object.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ *
+ * @param listStream The InputStream from which the file list should be
+ * read.
+ * @return The list of file information contained in the given path. null
+ * if the list could not be obtained or if there are no files in
+ * the directory.
+ * @exception IOException If an I/O error occurs reading the listStream.
+ ***/
+ public FTPFile[] parseFileList(InputStream listStream) throws IOException {
+ FTPListParseEngine engine = new FTPListParseEngine(this);
+ engine.readServerList(listStream);
+ return engine.getFiles();
+ }
+
+
+
+ /**
+ * Parses a line of a VMS FTP server file listing and converts it into a
+ * usable format in the form of an
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry)
+ {
+ //one block in VMS equals 512 bytes
+ long longBlock = 512;
+
+ if (matches(entry))
+ {
+ FTPFile f = new FTPFile();
+ f.setRawListing(entry);
+ String name = group(1);
+ String size = group(2);
+ String datestr = group(3)+" "+group(4);
+ String owner = group(5);
+ String permissions[] = new String[3];
+ permissions[0]= group(9);
+ permissions[1]= group(10);
+ permissions[2]= group(11);
+ try
+ {
+ f.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+
+ String grp;
+ String user;
+ StringTokenizer t = new StringTokenizer(owner, ",");
+ switch (t.countTokens()) {
+ case 1:
+ grp = null;
+ user = t.nextToken();
+ break;
+ case 2:
+ grp = t.nextToken();
+ user = t.nextToken();
+ break;
+ default:
+ grp = null;
+ user = null;
+ }
+
+ if (name.lastIndexOf(".DIR") != -1)
+ {
+ f.setType(FTPFile.DIRECTORY_TYPE);
+ }
+ else
+ {
+ f.setType(FTPFile.FILE_TYPE);
+ }
+ //set FTPFile name
+ //Check also for versions to be returned or not
+ if (isVersioning())
+ {
+ f.setName(name);
+ }
+ else
+ {
+ name = name.substring(0, name.lastIndexOf(";"));
+ f.setName(name);
+ }
+ //size is retreived in blocks and needs to be put in bytes
+ //for us humans and added to the FTPFile array
+ long sizeInBytes = Long.parseLong(size) * longBlock;
+ f.setSize(sizeInBytes);
+
+ f.setGroup(grp);
+ f.setUser(user);
+ //set group and owner
+
+ //Set file permission.
+ //VMS has (SYSTEM,OWNER,GROUP,WORLD) users that can contain
+ //R (read) W (write) E (execute) D (delete)
+
+ //iterate for OWNER GROUP WORLD permissions
+ for (int access = 0; access < 3; access++)
+ {
+ String permission = permissions[access];
+
+ f.setPermission(access, FTPFile.READ_PERMISSION, permission.indexOf('R')>=0);
+ f.setPermission(access, FTPFile.WRITE_PERMISSION, permission.indexOf('W')>=0);
+ f.setPermission(access, FTPFile.EXECUTE_PERMISSION, permission.indexOf('E')>=0);
+ }
+
+ return f;
+ }
+ return null;
+ }
+
+
+ /**
+ * Reads the next entry using the supplied BufferedReader object up to
+ * whatever delemits one entry from the next. This parser cannot use
+ * the default implementation of simply calling BufferedReader.readLine(),
+ * because one entry may span multiple lines.
+ *
+ * @param reader The BufferedReader object from which entries are to be
+ * read.
+ *
+ * @return A string representing the next ftp entry or null if none found.
+ * @exception IOException thrown on any IO Error reading from the reader.
+ */
+ @Override
+ public String readNextEntry(BufferedReader reader) throws IOException
+ {
+ String line = reader.readLine();
+ StringBuffer entry = new StringBuffer();
+ while (line != null)
+ {
+ if (line.startsWith("Directory") || line.startsWith("Total")) {
+ line = reader.readLine();
+ continue;
+ }
+
+ entry.append(line);
+ if (line.trim().endsWith(")"))
+ {
+ break;
+ }
+ line = reader.readLine();
+ }
+ return (entry.length() == 0 ? null : entry.toString());
+ }
+
+ protected boolean isVersioning() {
+ return false;
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_VMS,
+ DEFAULT_DATE_FORMAT,
+ null, null, null, null);
+ }
+
+
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser$NameVersion.class b/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser$NameVersion.class
new file mode 100644
index 0000000..fd27f2a
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser$NameVersion.class differ
diff --git a/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.class b/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.class
new file mode 100644
index 0000000..c0e20b6
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.class differ
diff --git a/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java b/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java
new file mode 100644
index 0000000..cb25709
--- /dev/null
+++ b/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+
+/**
+ * Special implementation VMSFTPEntryParser with versioning turned on.
+ * This parser removes all duplicates and only leaves the version with the highest
+ * version number for each filename.
+ *
+ * This is a sample of VMS LIST output
+ *
+ * "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ * "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ * "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ *
+ *
+ * @author Winston Ojeda
+ * @author Stephane ESTE-GRACIAS
+ * @version $Id: VMSVersioningFTPEntryParser.java 636854 2008-03-13 19:55:01Z sebb $
+ *
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ */
+public class VMSVersioningFTPEntryParser extends VMSFTPEntryParser
+{
+
+ private Matcher _preparse_matcher_;
+ private Pattern _preparse_pattern_;
+ private static final String PRE_PARSE_REGEX =
+ "(.*);([0-9]+)\\s*.*";
+
+ /**
+ * Constructor for a VMSFTPEntryParser object. Sets the versioning member
+ * to the supplied value.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ *
+ *
+ * @see CopyStreamEvent
+ * @see CopyStreamListener
+ * @see Util
+ * @author Daniel F. Savarese
+ * @version $Id: CopyStreamAdapter.java 489397 2006-12-21 16:28:51Z rwinston $
+ */
+public class CopyStreamAdapter implements CopyStreamListener
+{
+ private ListenerList internalListeners;
+
+ /**
+ * Creates a new copyStreamAdapter.
+ */
+ public CopyStreamAdapter()
+ {
+ internalListeners = new ListenerList();
+ }
+
+ /**
+ * This method is invoked by a CopyStreamEvent source after copying
+ * a block of bytes from a stream. The CopyStreamEvent will contain
+ * the total number of bytes transferred so far and the number of bytes
+ * transferred in the last write. The CopyStreamAdapater will relay
+ * the event to all of its registered listeners, listing itself as the
+ * source of the event.
+ * @param event The CopyStreamEvent fired by the copying of a block of
+ * bytes.
+ */
+ public void bytesTransferred(CopyStreamEvent event)
+ {
+ bytesTransferred(event.getTotalBytesTransferred(),
+ event.getBytesTransferred(),
+ event.getStreamSize());
+ }
+
+ /**
+ * This method is not part of the JavaBeans model and is used by the
+ * static methods in the org.apache.commons.io.Util class for efficiency.
+ * It is invoked after a block of bytes to inform the listener of the
+ * transfer. The CopyStreamAdapater will create a CopyStreamEvent
+ * from the arguments and relay the event to all of its registered
+ * listeners, listing itself as the source of the event.
+ * @param totalBytesTransferred The total number of bytes transferred
+ * so far by the copy operation.
+ * @param bytesTransferred The number of bytes copied by the most recent
+ * write.
+ * @param streamSize The number of bytes in the stream being copied.
+ * This may be equal to CopyStreamEvent.UNKNOWN_STREAM_SIZE if
+ * the size is unknown.
+ */
+ public void bytesTransferred(long totalBytesTransferred,
+ int bytesTransferred, long streamSize)
+ {
+ CopyStreamEvent event;
+
+ event = new CopyStreamEvent(this,
+ totalBytesTransferred,
+ bytesTransferred,
+ streamSize);
+
+ for (EventListener listener : internalListeners)
+ {
+ ((CopyStreamListener) (listener)).bytesTransferred(event);
+ }
+ }
+
+ /**
+ * Registers a CopyStreamListener to receive CopyStreamEvents.
+ * Although this method is not declared to be synchronized, it is
+ * implemented in a thread safe manner.
+ * @param listener The CopyStreamlistener to register.
+ */
+ public void addCopyStreamListener(CopyStreamListener listener)
+ {
+ internalListeners.addListener(listener);
+ }
+
+ /**
+ * Unregisters a CopyStreamListener. Although this method is not
+ * synchronized, it is implemented in a thread safe manner.
+ * @param listener The CopyStreamlistener to unregister.
+ */
+ public void removeCopyStreamListener(CopyStreamListener listener)
+ {
+ internalListeners.removeListener(listener);
+ }
+}
diff --git a/org/apache/commons/net/io/CopyStreamEvent.class b/org/apache/commons/net/io/CopyStreamEvent.class
new file mode 100644
index 0000000..66d719c
Binary files /dev/null and b/org/apache/commons/net/io/CopyStreamEvent.class differ
diff --git a/org/apache/commons/net/io/CopyStreamEvent.java b/org/apache/commons/net/io/CopyStreamEvent.java
new file mode 100644
index 0000000..d7d0ec3
--- /dev/null
+++ b/org/apache/commons/net/io/CopyStreamEvent.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.util.EventObject;
+
+/**
+ * A CopyStreamEvent is triggered after every write performed by a
+ * stream copying operation. The event stores the number of bytes
+ * transferred by the write triggering the event as well as the total
+ * number of bytes transferred so far by the copy operation.
+ *
+ *
+ * @see CopyStreamListener
+ * @see CopyStreamAdapter
+ * @see Util
+ * @author Daniel F. Savarese
+ * @version $Id: CopyStreamEvent.java 489397 2006-12-21 16:28:51Z rwinston $
+ */
+public class CopyStreamEvent extends EventObject
+{
+ /**
+ * Constant used to indicate the stream size is unknown.
+ */
+ public static final long UNKNOWN_STREAM_SIZE = -1;
+
+ private int bytesTransferred;
+ private long totalBytesTransferred;
+ private long streamSize;
+
+ /**
+ * Creates a new CopyStreamEvent instance.
+ * @param source The source of the event.
+ * @param totalBytesTransferred The total number of bytes transferred so
+ * far during a copy operation.
+ * @param bytesTransferred The number of bytes transferred during the
+ * write that triggered the CopyStreamEvent.
+ * @param streamSize The number of bytes in the stream being copied.
+ * This may be set to
+ *
+ * @see CopyStreamEvent
+ * @see CopyStreamAdapter
+ * @see Util
+ * @author Daniel F. Savarese
+ * @version $Id: CopyStreamListener.java 489397 2006-12-21 16:28:51Z rwinston $
+ */
+public interface CopyStreamListener extends EventListener
+{
+ /**
+ * This method is invoked by a CopyStreamEvent source after copying
+ * a block of bytes from a stream. The CopyStreamEvent will contain
+ * the total number of bytes transferred so far and the number of bytes
+ * transferred in the last write.
+ * @param event The CopyStreamEvent fired by the copying of a block of
+ * bytes.
+ */
+ public void bytesTransferred(CopyStreamEvent event);
+
+
+ /**
+ * This method is not part of the JavaBeans model and is used by the
+ * static methods in the org.apache.commons.io.Util class for efficiency.
+ * It is invoked after a block of bytes to inform the listener of the
+ * transfer.
+ * @param totalBytesTransferred The total number of bytes transferred
+ * so far by the copy operation.
+ * @param bytesTransferred The number of bytes copied by the most recent
+ * write.
+ * @param streamSize The number of bytes in the stream being copied.
+ * This may be equal to CopyStreamEvent.UNKNOWN_STREAM_SIZE if
+ * the size is unknown.
+ */
+ public void bytesTransferred(long totalBytesTransferred,
+ int bytesTransferred,
+ long streamSize);
+}
diff --git a/org/apache/commons/net/io/DotTerminatedMessageReader.java b/org/apache/commons/net/io/DotTerminatedMessageReader.java
new file mode 100644
index 0000000..c0f344d
--- /dev/null
+++ b/org/apache/commons/net/io/DotTerminatedMessageReader.java
@@ -0,0 +1,280 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.Reader;
+
+/**
+ * DotTerminatedMessageReader is a class used to read messages from a
+ * server that are terminated by a single dot followed by a
+ * <CR><LF>
+ * sequence and with double dots appearing at the begining of lines which
+ * do not signal end of message yet start with a dot. Various Internet
+ * protocols such as NNTP and POP3 produce messages of this type.
+ *
+ * This class handles stripping of the duplicate period at the beginning
+ * of lines starting with a period, converts NETASCII newlines to the
+ * local line separator format, truncates the end of message indicator,
+ * and ensures you cannot read past the end of the message.
+ * @author Daniel F. Savarese
+ * @version $Id: DotTerminatedMessageReader.java 636825 2008-03-13 18:34:52Z sebb $
+ */
+public final class DotTerminatedMessageReader extends Reader
+{
+ private static final String LS;
+ private static final char[] LS_CHARS;
+
+ static
+ {
+ LS = System.getProperty("line.separator");
+ LS_CHARS = LS.toCharArray();
+ }
+
+ private boolean atBeginning;
+ private boolean eof;
+ private int pos;
+ private char[] internalBuffer;
+ private PushbackReader internalReader;
+
+ /**
+ * Creates a DotTerminatedMessageReader that wraps an existing Reader
+ * input source.
+ * @param reader The Reader input source containing the message.
+ */
+ public DotTerminatedMessageReader(Reader reader)
+ {
+ super(reader);
+ internalBuffer = new char[LS_CHARS.length + 3];
+ pos = internalBuffer.length;
+ // Assumes input is at start of message
+ atBeginning = true;
+ eof = false;
+ internalReader = new PushbackReader(reader);
+ }
+
+ /**
+ * Reads and returns the next character in the message. If the end of the
+ * message has been reached, returns -1. Note that a call to this method
+ * may result in multiple reads from the underlying input stream to decode
+ * the message properly (removing doubled dots and so on). All of
+ * this is transparent to the programmer and is only mentioned for
+ * completeness.
+ * @return The next character in the message. Returns -1 if the end of the
+ * message has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ */
+ @Override
+ public int read() throws IOException
+ {
+ int ch;
+
+ synchronized (lock)
+ {
+ if (pos < internalBuffer.length)
+ {
+ return internalBuffer[pos++];
+ }
+
+ if (eof)
+ {
+ return -1;
+ }
+
+ if ((ch = internalReader.read()) == -1)
+ {
+ eof = true;
+ return -1;
+ }
+
+ if (atBeginning)
+ {
+ atBeginning = false;
+ if (ch == '.')
+ {
+ ch = internalReader.read();
+
+ if (ch != '.')
+ {
+ // read newline
+ eof = true;
+ internalReader.read();
+ return -1;
+ }
+ else
+ {
+ return '.';
+ }
+ }
+ }
+
+ if (ch == '\r')
+ {
+ ch = internalReader.read();
+
+ if (ch == '\n')
+ {
+ ch = internalReader.read();
+
+ if (ch == '.')
+ {
+ ch = internalReader.read();
+
+ if (ch != '.')
+ {
+ // read newline and indicate end of file
+ internalReader.read();
+ eof = true;
+ }
+ else
+ {
+ internalBuffer[--pos] = (char) ch;
+ }
+ }
+ else
+ {
+ internalReader.unread(ch);
+ }
+
+ pos -= LS_CHARS.length;
+ System.arraycopy(LS_CHARS, 0, internalBuffer, pos,
+ LS_CHARS.length);
+ ch = internalBuffer[pos++];
+ }
+ else
+ {
+ internalBuffer[--pos] = (char) ch;
+ return '\r';
+ }
+ }
+
+ return ch;
+ }
+ }
+
+ /**
+ * Reads the next characters from the message into an array and
+ * returns the number of characters read. Returns -1 if the end of the
+ * message has been reached.
+ * @param buffer The character array in which to store the characters.
+ * @return The number of characters read. Returns -1 if the
+ * end of the message has been reached.
+ * @exception IOException If an error occurs in reading the underlying
+ * stream.
+ */
+ @Override
+ public int read(char[] buffer) throws IOException
+ {
+ return read(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Reads the next characters from the message into an array and
+ * returns the number of characters read. Returns -1 if the end of the
+ * message has been reached. The characters are stored in the array
+ * starting from the given offset and up to the length specified.
+ * @param buffer The character array in which to store the characters.
+ * @param offset The offset into the array at which to start storing
+ * characters.
+ * @param length The number of characters to read.
+ * @return The number of characters read. Returns -1 if the
+ * end of the message has been reached.
+ * @exception IOException If an error occurs in reading the underlying
+ * stream.
+ */
+ @Override
+ public int read(char[] buffer, int offset, int length) throws IOException
+ {
+ int ch, off;
+ synchronized (lock)
+ {
+ if (length < 1)
+ {
+ return 0;
+ }
+ if ((ch = read()) == -1)
+ {
+ return -1;
+ }
+ off = offset;
+
+ do
+ {
+ buffer[offset++] = (char) ch;
+ }
+ while (--length > 0 && (ch = read()) != -1);
+
+ return (offset - off);
+ }
+ }
+
+ /**
+ * Determines if the message is ready to be read.
+ * @return True if the message is ready to be read, false if not.
+ * @exception IOException If an error occurs while checking the underlying
+ * stream.
+ */
+ @Override
+ public boolean ready() throws IOException
+ {
+ synchronized (lock)
+ {
+ return (pos < internalBuffer.length || internalReader.ready());
+ }
+ }
+
+ /**
+ * Closes the message for reading. This doesn't actually close the
+ * underlying stream. The underlying stream may still be used for
+ * communicating with the server and therefore is not closed.
+ *
+ * If the end of the message has not yet been reached, this method
+ * will read the remainder of the message until it reaches the end,
+ * so that the underlying stream may continue to be used properly
+ * for communicating with the server. If you do not fully read
+ * a message, you MUST close it, otherwise your program will likely
+ * hang or behave improperly.
+ * @exception IOException If an error occurs while reading the
+ * underlying stream.
+ */
+ @Override
+ public void close() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (internalReader == null)
+ {
+ return;
+ }
+
+ if (!eof)
+ {
+ while (read() != -1)
+ {
+ ;
+ }
+ }
+ eof = true;
+ atBeginning = false;
+ pos = internalBuffer.length;
+ internalReader = null;
+ }
+ }
+}
diff --git a/org/apache/commons/net/io/DotTerminatedMessageWriter.java b/org/apache/commons/net/io/DotTerminatedMessageWriter.java
new file mode 100644
index 0000000..853e42f
--- /dev/null
+++ b/org/apache/commons/net/io/DotTerminatedMessageWriter.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/***
+ * DotTerminatedMessageWriter is a class used to write messages to a
+ * server that are terminated by a single dot followed by a
+ * <CR><LF>
+ * sequence and with double dots appearing at the begining of lines which
+ * do not signal end of message yet start with a dot. Various Internet
+ * protocols such as NNTP and POP3 produce messages of this type.
+ *
+ * This class handles the doubling of line-starting periods,
+ * converts single linefeeds to NETASCII newlines, and on closing
+ * will send the final message terminator dot and NETASCII newline
+ * sequence.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class DotTerminatedMessageWriter extends Writer
+{
+ private static final int __NOTHING_SPECIAL_STATE = 0;
+ private static final int __LAST_WAS_CR_STATE = 1;
+ private static final int __LAST_WAS_NL_STATE = 2;
+
+ private int __state;
+ private Writer __output;
+
+
+ /***
+ * Creates a DotTerminatedMessageWriter that wraps an existing Writer
+ * output destination.
+ *
+ * @param output The Writer output destination to write the message.
+ ***/
+ public DotTerminatedMessageWriter(Writer output)
+ {
+ super(output);
+ __output = output;
+ __state = __NOTHING_SPECIAL_STATE;
+ }
+
+
+ /***
+ * Writes a character to the output. Note that a call to this method
+ * may result in multiple writes to the underling Writer in order to
+ * convert naked linefeeds to NETASCII line separators and to double
+ * line-leading periods. This is transparent to the programmer and
+ * is only mentioned for completeness.
+ *
+ * @param ch The character to write.
+ * @exception IOException If an error occurs while writing to the
+ * underlying output.
+ ***/
+ @Override
+ public void write(int ch) throws IOException
+ {
+ synchronized (lock)
+ {
+ switch (ch)
+ {
+ case '\r':
+ __state = __LAST_WAS_CR_STATE;
+ __output.write('\r');
+ return ;
+ case '\n':
+ if (__state != __LAST_WAS_CR_STATE)
+ __output.write('\r');
+ __output.write('\n');
+ __state = __LAST_WAS_NL_STATE;
+ return ;
+ case '.':
+ // Double the dot at the beginning of a line
+ if (__state == __LAST_WAS_NL_STATE)
+ __output.write('.');
+ // Fall through
+ default:
+ __state = __NOTHING_SPECIAL_STATE;
+ __output.write(ch);
+ return ;
+ }
+ }
+ }
+
+
+ /***
+ * Writes a number of characters from a character array to the output
+ * starting from a given offset.
+ *
+ * @param buffer The character array to write.
+ * @param offset The offset into the array at which to start copying data.
+ * @param length The number of characters to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * output.
+ ***/
+ @Override
+ public void write(char[] buffer, int offset, int length) throws IOException
+ {
+ synchronized (lock)
+ {
+ while (length-- > 0)
+ write(buffer[offset++]);
+ }
+ }
+
+
+ /***
+ * Writes a character array to the output.
+ *
+ * @param buffer The character array to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * output.
+ ***/
+ @Override
+ public void write(char[] buffer) throws IOException
+ {
+ write(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Writes a String to the output.
+ *
+ * @param string The String to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * output.
+ ***/
+ @Override
+ public void write(String string) throws IOException
+ {
+ write(string.toCharArray());
+ }
+
+
+ /***
+ * Writes part of a String to the output starting from a given offset.
+ *
+ * @param string The String to write.
+ * @param offset The offset into the String at which to start copying data.
+ * @param length The number of characters to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * output.
+ ***/
+ @Override
+ public void write(String string, int offset, int length) throws IOException
+ {
+ write(string.toCharArray(), offset, length);
+ }
+
+
+ /***
+ * Flushes the underlying output, writing all buffered output.
+ *
+ * @exception IOException If an error occurs while writing to the underlying
+ * output.
+ ***/
+ @Override
+ public void flush() throws IOException
+ {
+ synchronized (lock)
+ {
+ __output.flush();
+ }
+ }
+
+
+ /***
+ * Flushes the underlying output, writing all buffered output, but doesn't
+ * actually close the underlying stream. The underlying stream may still
+ * be used for communicating with the server and therefore is not closed.
+ *
+ * @exception IOException If an error occurs while writing to the underlying
+ * output or closing the Writer.
+ ***/
+ @Override
+ public void close() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (__output == null)
+ return ;
+
+ if (__state == __LAST_WAS_CR_STATE)
+ __output.write('\n');
+ else if (__state != __LAST_WAS_NL_STATE)
+ __output.write("\r\n");
+
+ __output.write(".\r\n");
+
+ __output.flush();
+ __output = null;
+ }
+ }
+
+}
diff --git a/org/apache/commons/net/io/FromNetASCIIInputStream.class b/org/apache/commons/net/io/FromNetASCIIInputStream.class
new file mode 100644
index 0000000..d3bf9c1
Binary files /dev/null and b/org/apache/commons/net/io/FromNetASCIIInputStream.class differ
diff --git a/org/apache/commons/net/io/FromNetASCIIInputStream.java b/org/apache/commons/net/io/FromNetASCIIInputStream.java
new file mode 100644
index 0000000..76588ab
--- /dev/null
+++ b/org/apache/commons/net/io/FromNetASCIIInputStream.java
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+
+/***
+ * This class wraps an input stream, replacing all occurrences
+ * of <CR><LF> (carriage return followed by a linefeed),
+ * which is the NETASCII standard for representing a newline, with the
+ * local line separator representation. You would use this class to
+ * implement ASCII file transfers requiring conversion from NETASCII.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class FromNetASCIIInputStream extends PushbackInputStream
+{
+ static final boolean _noConversionRequired;
+ static final String _lineSeparator;
+ static final byte[] _lineSeparatorBytes;
+
+ static {
+ _lineSeparator = System.getProperty("line.separator");
+ _noConversionRequired = _lineSeparator.equals("\r\n");
+ _lineSeparatorBytes = _lineSeparator.getBytes();
+ }
+
+ private int __length = 0;
+
+ /***
+ * Returns true if the NetASCII line separator differs from the system
+ * line separator, false if they are the same. This method is useful
+ * to determine whether or not you need to instantiate a
+ * FromNetASCIIInputStream object.
+ *
+ * @return True if the NETASCII line separator differs from the local
+ * system line separator, false if they are the same.
+ ***/
+ public static final boolean isConversionRequired()
+ {
+ return !_noConversionRequired;
+ }
+
+ /***
+ * Creates a FromNetASCIIInputStream instance that wraps an existing
+ * InputStream.
+ ***/
+ public FromNetASCIIInputStream(InputStream input)
+ {
+ super(input, _lineSeparatorBytes.length + 1);
+ }
+
+
+ private int __read() throws IOException
+ {
+ int ch;
+
+ ch = super.read();
+
+ if (ch == '\r')
+ {
+ ch = super.read();
+ if (ch == '\n')
+ {
+ unread(_lineSeparatorBytes);
+ ch = super.read();
+ // This is a kluge for read(byte[], ...) to read the right amount
+ --__length;
+ }
+ else
+ {
+ if (ch != -1)
+ unread(ch);
+ return '\r';
+ }
+ }
+
+ return ch;
+ }
+
+
+ /***
+ * Reads and returns the next byte in the stream. If the end of the
+ * message has been reached, returns -1. Note that a call to this method
+ * may result in multiple reads from the underlying input stream in order
+ * to convert NETASCII line separators to the local line separator format.
+ * This is transparent to the programmer and is only mentioned for
+ * completeness.
+ *
+ * @return The next character in the stream. Returns -1 if the end of the
+ * stream has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read() throws IOException
+ {
+ if (_noConversionRequired)
+ return super.read();
+
+ return __read();
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and
+ * returns the number of bytes read. Returns -1 if the end of the
+ * stream has been reached.
+ *
+ * @param buffer The byte array in which to store the data.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the message has been reached.
+ * @exception IOException If an error occurs in reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[]) throws IOException
+ {
+ return read(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and returns
+ * the number of bytes read. Returns -1 if the end of the
+ * message has been reached. The characters are stored in the array
+ * starting from the given offset and up to the length specified.
+ *
+ * @param buffer The byte array in which to store the data.
+ * @param offset The offset into the array at which to start storing data.
+ * @param length The number of bytes to read.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the stream has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[], int offset, int length) throws IOException
+ {
+ int ch, off;
+
+ if (length < 1)
+ return 0;
+
+ ch = available();
+
+ __length = (length > ch ? ch : length);
+
+ // If nothing is available, block to read only one character
+ if (__length < 1)
+ __length = 1;
+
+ if (_noConversionRequired)
+ return super.read(buffer, offset, __length);
+
+ if ((ch = __read()) == -1)
+ return -1;
+
+ off = offset;
+
+ do
+ {
+ buffer[offset++] = (byte)ch;
+ }
+ while (--__length > 0 && (ch = __read()) != -1);
+
+
+ return (offset - off);
+ }
+
+
+ // PushbackInputStream in JDK 1.1.3 returns the wrong thing
+ /***
+ * Returns the number of bytes that can be read without blocking EXCEPT
+ * when newline conversions have to be made somewhere within the
+ * available block of bytes. In other words, you really should not
+ * rely on the value returned by this method if you are trying to avoid
+ * blocking.
+ ***/
+ @Override
+ public int available() throws IOException
+ {
+ return (buf.length - pos) + in.available();
+ }
+
+}
diff --git a/org/apache/commons/net/io/FromNetASCIIOutputStream.java b/org/apache/commons/net/io/FromNetASCIIOutputStream.java
new file mode 100644
index 0000000..c025a1b
--- /dev/null
+++ b/org/apache/commons/net/io/FromNetASCIIOutputStream.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/***
+ * This class wraps an output stream, replacing all occurrences
+ * of <CR><LF> (carriage return followed by a linefeed),
+ * which is the NETASCII standard for representing a newline, with the
+ * local line separator representation. You would use this class to
+ * implement ASCII file transfers requiring conversion from NETASCII.
+ *
+ * Because of the translation process, a call to
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class FromNetASCIIOutputStream extends FilterOutputStream
+{
+ private boolean __lastWasCR;
+
+ /***
+ * Creates a FromNetASCIIOutputStream instance that wraps an existing
+ * OutputStream.
+ *
+ * @param output The OutputStream to wrap.
+ ***/
+ public FromNetASCIIOutputStream(OutputStream output)
+ {
+ super(output);
+ __lastWasCR = false;
+ }
+
+
+ private void __write(int ch) throws IOException
+ {
+ switch (ch)
+ {
+ case '\r':
+ __lastWasCR = true;
+ // Don't write anything. We need to see if next one is linefeed
+ break;
+ case '\n':
+ if (__lastWasCR)
+ {
+ out.write(FromNetASCIIInputStream._lineSeparatorBytes);
+ __lastWasCR = false;
+ break;
+ }
+ __lastWasCR = false;
+ out.write('\n');
+ break;
+ default:
+ if (__lastWasCR)
+ {
+ out.write('\r');
+ __lastWasCR = false;
+ }
+ out.write(ch);
+ break;
+ }
+ }
+
+
+ /***
+ * Writes a byte to the stream. Note that a call to this method
+ * might not actually write a byte to the underlying stream until a
+ * subsequent character is written, from which it can be determined if
+ * a NETASCII line separator was encountered.
+ * This is transparent to the programmer and is only mentioned for
+ * completeness.
+ *
+ * @param ch The byte to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(int ch)
+ throws IOException
+ {
+ if (FromNetASCIIInputStream._noConversionRequired)
+ {
+ out.write(ch);
+ return ;
+ }
+
+ __write(ch);
+ }
+
+
+ /***
+ * Writes a byte array to the stream.
+ *
+ * @param buffer The byte array to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(byte buffer[])
+ throws IOException
+ {
+ write(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Writes a number of bytes from a byte array to the stream starting from
+ * a given offset.
+ *
+ * @param buffer The byte array to write.
+ * @param offset The offset into the array at which to start copying data.
+ * @param length The number of bytes to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(byte buffer[], int offset, int length)
+ throws IOException
+ {
+ if (FromNetASCIIInputStream._noConversionRequired)
+ {
+ // FilterOutputStream method is very slow.
+ //super.write(buffer, offset, length);
+ out.write(buffer, offset, length);
+ return ;
+ }
+
+ while (length-- > 0)
+ __write(buffer[offset++]);
+ }
+
+
+ /***
+ * Closes the stream, writing all pending data.
+ *
+ * @exception IOException If an error occurs while closing the stream.
+ ***/
+ @Override
+ public synchronized void close()
+ throws IOException
+ {
+ if (FromNetASCIIInputStream._noConversionRequired)
+ {
+ super.close();
+ return ;
+ }
+
+ if (__lastWasCR)
+ out.write('\r');
+ super.close();
+ }
+}
diff --git a/org/apache/commons/net/io/SocketInputStream.class b/org/apache/commons/net/io/SocketInputStream.class
new file mode 100644
index 0000000..97657e8
Binary files /dev/null and b/org/apache/commons/net/io/SocketInputStream.class differ
diff --git a/org/apache/commons/net/io/SocketInputStream.java b/org/apache/commons/net/io/SocketInputStream.java
new file mode 100644
index 0000000..673f434
--- /dev/null
+++ b/org/apache/commons/net/io/SocketInputStream.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+
+/***
+ * This class wraps an input stream, storing a reference to its originating
+ * socket. When the stream is closed, it will also close the socket
+ * immediately afterward. This class is useful for situations where you
+ * are dealing with a stream originating from a socket, but do not have
+ * a reference to the socket, and want to make sure it closes when the
+ * stream closes.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SocketOutputStream
+ ***/
+
+public class SocketInputStream extends FilterInputStream
+{
+ private Socket __socket;
+
+ /***
+ * Creates a SocketInputStream instance wrapping an input stream and
+ * storing a reference to a socket that should be closed on closing
+ * the stream.
+ *
+ * @param socket The socket to close on closing the stream.
+ * @param stream The input stream to wrap.
+ ***/
+ public SocketInputStream(Socket socket, InputStream stream)
+ {
+ super(stream);
+ __socket = socket;
+ }
+
+ /***
+ * Closes the stream and immediately afterward closes the referenced
+ * socket.
+ *
+ * @exception IOException If there is an error in closing the stream
+ * or socket.
+ ***/
+ @Override
+ public void close() throws IOException
+ {
+ super.close();
+ __socket.close();
+ }
+}
diff --git a/org/apache/commons/net/io/SocketOutputStream.class b/org/apache/commons/net/io/SocketOutputStream.class
new file mode 100644
index 0000000..41a30e5
Binary files /dev/null and b/org/apache/commons/net/io/SocketOutputStream.class differ
diff --git a/org/apache/commons/net/io/SocketOutputStream.java b/org/apache/commons/net/io/SocketOutputStream.java
new file mode 100644
index 0000000..abd7f5d
--- /dev/null
+++ b/org/apache/commons/net/io/SocketOutputStream.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/***
+ * This class wraps an output stream, storing a reference to its originating
+ * socket. When the stream is closed, it will also close the socket
+ * immediately afterward. This class is useful for situations where you
+ * are dealing with a stream originating from a socket, but do not have
+ * a reference to the socket, and want to make sure it closes when the
+ * stream closes.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SocketInputStream
+ ***/
+
+public class SocketOutputStream extends FilterOutputStream
+{
+ private Socket __socket;
+
+ /***
+ * Creates a SocketOutputStream instance wrapping an output stream and
+ * storing a reference to a socket that should be closed on closing
+ * the stream.
+ *
+ * @param socket The socket to close on closing the stream.
+ * @param stream The input stream to wrap.
+ ***/
+ public SocketOutputStream(Socket socket, OutputStream stream)
+ {
+ super(stream);
+ __socket = socket;
+ }
+
+
+ /***
+ * Writes a number of bytes from a byte array to the stream starting from
+ * a given offset. This method bypasses the equivalent method in
+ * FilterOutputStream because the FilterOutputStream implementation is
+ * very inefficient.
+ *
+ * @param buffer The byte array to write.
+ * @param offset The offset into the array at which to start copying data.
+ * @param length The number of bytes to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public void write(byte buffer[], int offset, int length) throws IOException
+ {
+ out.write(buffer, offset, length);
+ }
+
+
+ /***
+ * Closes the stream and immediately afterward closes the referenced
+ * socket.
+ *
+ * @exception IOException If there is an error in closing the stream
+ * or socket.
+ ***/
+ @Override
+ public void close() throws IOException
+ {
+ super.close();
+ __socket.close();
+ }
+}
diff --git a/org/apache/commons/net/io/ToNetASCIIInputStream.java b/org/apache/commons/net/io/ToNetASCIIInputStream.java
new file mode 100644
index 0000000..55e4735
--- /dev/null
+++ b/org/apache/commons/net/io/ToNetASCIIInputStream.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/***
+ * This class wraps an input stream, replacing all singly occurring
+ * <LF> (linefeed) characters with <CR><LF> (carriage return
+ * followed by linefeed), which is the NETASCII standard for representing
+ * a newline.
+ * You would use this class to implement ASCII file transfers requiring
+ * conversion to NETASCII.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class ToNetASCIIInputStream extends FilterInputStream
+{
+ private static final int __NOTHING_SPECIAL = 0;
+ private static final int __LAST_WAS_CR = 1;
+ private static final int __LAST_WAS_NL = 2;
+ private int __status;
+
+ /***
+ * Creates a ToNetASCIIInputStream instance that wraps an existing
+ * InputStream.
+ *
+ * @param input The InputStream to .
+ ***/
+ public ToNetASCIIInputStream(InputStream input)
+ {
+ super(input);
+ __status = __NOTHING_SPECIAL;
+ }
+
+
+ /***
+ * Reads and returns the next byte in the stream. If the end of the
+ * message has been reached, returns -1.
+ *
+ * @return The next character in the stream. Returns -1 if the end of the
+ * stream has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read() throws IOException
+ {
+ int ch;
+
+ if (__status == __LAST_WAS_NL)
+ {
+ __status = __NOTHING_SPECIAL;
+ return '\n';
+ }
+
+ ch = in.read();
+
+ switch (ch)
+ {
+ case '\r':
+ __status = __LAST_WAS_CR;
+ return '\r';
+ case '\n':
+ if (__status != __LAST_WAS_CR)
+ {
+ __status = __LAST_WAS_NL;
+ return '\r';
+ }
+ // else fall through
+ default:
+ __status = __NOTHING_SPECIAL;
+ return ch;
+ }
+ // statement not reached
+ //return ch;
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and
+ * returns the number of bytes read. Returns -1 if the end of the
+ * stream has been reached.
+ *
+ * @param buffer The byte array in which to store the data.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the message has been reached.
+ * @exception IOException If an error occurs in reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[]) throws IOException
+ {
+ return read(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and returns
+ * the number of bytes read. Returns -1 if the end of the
+ * message has been reached. The characters are stored in the array
+ * starting from the given offset and up to the length specified.
+ *
+ * @param buffer The byte array in which to store the data.
+ * @param offset The offset into the array at which to start storing data.
+ * @param length The number of bytes to read.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the stream has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[], int offset, int length) throws IOException
+ {
+ int ch, off;
+
+ if (length < 1)
+ return 0;
+
+ ch = available();
+
+ if (length > ch)
+ length = ch;
+
+ // If nothing is available, block to read only one character
+ if (length < 1)
+ length = 1;
+
+ if ((ch = read()) == -1)
+ return -1;
+
+ off = offset;
+
+ do
+ {
+ buffer[offset++] = (byte)ch;
+ }
+ while (--length > 0 && (ch = read()) != -1);
+
+ return (offset - off);
+ }
+
+ /*** Returns false. Mark is not supported. ***/
+ @Override
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ int result;
+
+ result = in.available();
+
+ if (__status == __LAST_WAS_NL)
+ return (result + 1);
+
+ return result;
+ }
+}
diff --git a/org/apache/commons/net/io/ToNetASCIIOutputStream.class b/org/apache/commons/net/io/ToNetASCIIOutputStream.class
new file mode 100644
index 0000000..62185e4
Binary files /dev/null and b/org/apache/commons/net/io/ToNetASCIIOutputStream.class differ
diff --git a/org/apache/commons/net/io/ToNetASCIIOutputStream.java b/org/apache/commons/net/io/ToNetASCIIOutputStream.java
new file mode 100644
index 0000000..aeacc98
--- /dev/null
+++ b/org/apache/commons/net/io/ToNetASCIIOutputStream.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/***
+ * This class wraps an output stream, replacing all singly occurring
+ * <LF> (linefeed) characters with <CR><LF> (carriage return
+ * followed by linefeed), which is the NETASCII standard for representing
+ * a newline.
+ * You would use this class to implement ASCII file transfers requiring
+ * conversion to NETASCII.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class ToNetASCIIOutputStream extends FilterOutputStream
+{
+ private boolean __lastWasCR;
+
+ /***
+ * Creates a ToNetASCIIOutputStream instance that wraps an existing
+ * OutputStream.
+ *
+ * @param output The OutputStream to wrap.
+ ***/
+ public ToNetASCIIOutputStream(OutputStream output)
+ {
+ super(output);
+ __lastWasCR = false;
+ }
+
+
+ /***
+ * Writes a byte to the stream. Note that a call to this method
+ * may result in multiple writes to the underlying input stream in order
+ * to convert naked newlines to NETASCII line separators.
+ * This is transparent to the programmer and is only mentioned for
+ * completeness.
+ *
+ * @param ch The byte to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(int ch)
+ throws IOException
+ {
+ switch (ch)
+ {
+ case '\r':
+ __lastWasCR = true;
+ out.write('\r');
+ return ;
+ case '\n':
+ if (!__lastWasCR)
+ out.write('\r');
+ // Fall through
+ default:
+ __lastWasCR = false;
+ out.write(ch);
+ return ;
+ }
+ }
+
+
+ /***
+ * Writes a byte array to the stream.
+ *
+ * @param buffer The byte array to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(byte buffer[])
+ throws IOException
+ {
+ write(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Writes a number of bytes from a byte array to the stream starting from
+ * a given offset.
+ *
+ * @param buffer The byte array to write.
+ * @param offset The offset into the array at which to start copying data.
+ * @param length The number of bytes to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(byte buffer[], int offset, int length)
+ throws IOException
+ {
+ while (length-- > 0)
+ write(buffer[offset++]);
+ }
+
+}
diff --git a/org/apache/commons/net/io/Util.class b/org/apache/commons/net/io/Util.class
new file mode 100644
index 0000000..7509801
Binary files /dev/null and b/org/apache/commons/net/io/Util.class differ
diff --git a/org/apache/commons/net/io/Util.java b/org/apache/commons/net/io/Util.java
new file mode 100644
index 0000000..4e85a93
--- /dev/null
+++ b/org/apache/commons/net/io/Util.java
@@ -0,0 +1,334 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+
+/***
+ * The Util class cannot be instantiated and stores short static convenience
+ * methods that are often quite useful.
+ *
+ *
+ * @see CopyStreamException
+ * @see CopyStreamListener
+ * @see CopyStreamAdapter
+ * @author Daniel F. Savarese
+ ***/
+
+public final class Util
+{
+ /***
+ * The default buffer size used by {@link #copyStream copyStream }
+ * and {@link #copyReader copyReader }. It's value is 1024.
+ ***/
+ public static final int DEFAULT_COPY_BUFFER_SIZE = 1024;
+
+ // Cannot be instantiated
+ private Util()
+ { }
+
+
+ /***
+ * Copies the contents of an InputStream to an OutputStream using a
+ * copy buffer of a given size and notifies the provided
+ * CopyStreamListener of the progress of the copy operation by calling
+ * its bytesTransferred(long, int) method after each write to the
+ * destination. If you wish to notify more than one listener you should
+ * use a CopyStreamAdapter as the listener and register the additional
+ * listeners with the CopyStreamAdapter.
+ *
+ * The contents of the InputStream are
+ * read until the end of the stream is reached, but neither the
+ * source nor the destination are closed. You must do this yourself
+ * outside of the method call. The number of bytes read/written is
+ * returned.
+ *
+ * @param source The source InputStream.
+ * @param dest The destination OutputStream.
+ * @param bufferSize The number of bytes to buffer during the copy.
+ * @param streamSize The number of bytes in the stream being copied.
+ * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
+ * @param listener The CopyStreamListener to notify of progress. If
+ * this parameter is null, notification is not attempted.
+ * @param flush Whether to flush the output stream after every
+ * write. This is necessary for interactive sessions that rely on
+ * buffered streams. If you don't flush, the data will stay in
+ * the stream buffer.
+ * @exception CopyStreamException If an error occurs while reading from the
+ * source or writing to the destination. The CopyStreamException
+ * will contain the number of bytes confirmed to have been
+ * transferred before an
+ * IOException occurred, and it will also contain the IOException
+ * that caused the error. These values can be retrieved with
+ * the CopyStreamException getTotalBytesTransferred() and
+ * getIOException() methods.
+ ***/
+ public static final long copyStream(InputStream source, OutputStream dest,
+ int bufferSize, long streamSize,
+ CopyStreamListener listener,
+ boolean flush)
+ throws CopyStreamException
+ {
+ int bytes;
+ long total;
+ byte[] buffer;
+
+ buffer = new byte[bufferSize];
+ total = 0;
+
+ try
+ {
+ while ((bytes = source.read(buffer)) != -1)
+ {
+ // Technically, some read(byte[]) methods may return 0 and we cannot
+ // accept that as an indication of EOF.
+
+ if (bytes == 0)
+ {
+ bytes = source.read();
+ if (bytes < 0)
+ break;
+ dest.write(bytes);
+ if(flush)
+ dest.flush();
+ ++total;
+ if (listener != null)
+ listener.bytesTransferred(total, 1, streamSize);
+ continue;
+ }
+
+ dest.write(buffer, 0, bytes);
+ if(flush)
+ dest.flush();
+ total += bytes;
+ if (listener != null)
+ listener.bytesTransferred(total, bytes, streamSize);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new CopyStreamException("IOException caught while copying.",
+ total, e);
+ }
+
+ return total;
+ }
+
+
+ /***
+ * Copies the contents of an InputStream to an OutputStream using a
+ * copy buffer of a given size and notifies the provided
+ * CopyStreamListener of the progress of the copy operation by calling
+ * its bytesTransferred(long, int) method after each write to the
+ * destination. If you wish to notify more than one listener you should
+ * use a CopyStreamAdapter as the listener and register the additional
+ * listeners with the CopyStreamAdapter.
+ *
+ * The contents of the InputStream are
+ * read until the end of the stream is reached, but neither the
+ * source nor the destination are closed. You must do this yourself
+ * outside of the method call. The number of bytes read/written is
+ * returned.
+ *
+ * @param source The source InputStream.
+ * @param dest The destination OutputStream.
+ * @param bufferSize The number of bytes to buffer during the copy.
+ * @param streamSize The number of bytes in the stream being copied.
+ * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
+ * @param listener The CopyStreamListener to notify of progress. If
+ * this parameter is null, notification is not attempted.
+ * @exception CopyStreamException If an error occurs while reading from the
+ * source or writing to the destination. The CopyStreamException
+ * will contain the number of bytes confirmed to have been
+ * transferred before an
+ * IOException occurred, and it will also contain the IOException
+ * that caused the error. These values can be retrieved with
+ * the CopyStreamException getTotalBytesTransferred() and
+ * getIOException() methods.
+ ***/
+ public static final long copyStream(InputStream source, OutputStream dest,
+ int bufferSize, long streamSize,
+ CopyStreamListener listener)
+ throws CopyStreamException
+ {
+ return copyStream(source, dest, bufferSize, streamSize, listener,
+ true);
+ }
+
+
+ /***
+ * Copies the contents of an InputStream to an OutputStream using a
+ * copy buffer of a given size. The contents of the InputStream are
+ * read until the end of the stream is reached, but neither the
+ * source nor the destination are closed. You must do this yourself
+ * outside of the method call. The number of bytes read/written is
+ * returned.
+ *
+ * @param source The source InputStream.
+ * @param dest The destination OutputStream.
+ * @return The number of bytes read/written in the copy operation.
+ * @exception CopyStreamException If an error occurs while reading from the
+ * source or writing to the destination. The CopyStreamException
+ * will contain the number of bytes confirmed to have been
+ * transferred before an
+ * IOException occurred, and it will also contain the IOException
+ * that caused the error. These values can be retrieved with
+ * the CopyStreamException getTotalBytesTransferred() and
+ * getIOException() methods.
+ ***/
+ public static final long copyStream(InputStream source, OutputStream dest,
+ int bufferSize)
+ throws CopyStreamException
+ {
+ return copyStream(source, dest, bufferSize,
+ CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
+ }
+
+
+ /***
+ * Same as
+ * The contents of the Reader are
+ * read until its end is reached, but neither the source nor the
+ * destination are closed. You must do this yourself outside of the
+ * method call. The number of characters read/written is returned.
+ *
+ * @param source The source Reader.
+ * @param dest The destination writer.
+ * @param bufferSize The number of characters to buffer during the copy.
+ * @param streamSize The number of characters in the stream being copied.
+ * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
+ * @param listener The CopyStreamListener to notify of progress. If
+ * this parameter is null, notification is not attempted.
+ * @return The number of characters read/written in the copy operation.
+ * @exception CopyStreamException If an error occurs while reading from the
+ * source or writing to the destination. The CopyStreamException
+ * will contain the number of bytes confirmed to have been
+ * transferred before an
+ * IOException occurred, and it will also contain the IOException
+ * that caused the error. These values can be retrieved with
+ * the CopyStreamException getTotalBytesTransferred() and
+ * getIOException() methods.
+ ***/
+ public static final long copyReader(Reader source, Writer dest,
+ int bufferSize, long streamSize,
+ CopyStreamListener listener)
+ throws CopyStreamException
+ {
+ int chars;
+ long total;
+ char[] buffer;
+
+ buffer = new char[bufferSize];
+ total = 0;
+
+ try
+ {
+ while ((chars = source.read(buffer)) != -1)
+ {
+ // Technically, some read(char[]) methods may return 0 and we cannot
+ // accept that as an indication of EOF.
+ if (chars == 0)
+ {
+ chars = source.read();
+ if (chars < 0)
+ break;
+ dest.write(chars);
+ dest.flush();
+ ++total;
+ if (listener != null)
+ listener.bytesTransferred(total, chars, streamSize);
+ continue;
+ }
+
+ dest.write(buffer, 0, chars);
+ dest.flush();
+ total += chars;
+ if (listener != null)
+ listener.bytesTransferred(total, chars, streamSize);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new CopyStreamException("IOException caught while copying.",
+ total, e);
+ }
+
+ return total;
+ }
+
+
+ /***
+ * Copies the contents of a Reader to a Writer using a
+ * copy buffer of a given size. The contents of the Reader are
+ * read until its end is reached, but neither the source nor the
+ * destination are closed. You must do this yourself outside of the
+ * method call. The number of characters read/written is returned.
+ *
+ * @param source The source Reader.
+ * @param dest The destination writer.
+ * @param bufferSize The number of characters to buffer during the copy.
+ * @return The number of characters read/written in the copy operation.
+ * @exception CopyStreamException If an error occurs while reading from the
+ * source or writing to the destination. The CopyStreamException
+ * will contain the number of bytes confirmed to have been
+ * transferred before an
+ * IOException occurred, and it will also contain the IOException
+ * that caused the error. These values can be retrieved with
+ * the CopyStreamException getTotalBytesTransferred() and
+ * getIOException() methods.
+ ***/
+ public static final long copyReader(Reader source, Writer dest,
+ int bufferSize)
+ throws CopyStreamException
+ {
+ return copyReader(source, dest, bufferSize,
+ CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
+ }
+
+
+ /***
+ * Same as
+ * You should keep in mind that the NNTP server may choose to prematurely
+ * close a connection if the client has been idle for longer than a
+ * given time period or if the server is being shutdown by the operator or
+ * some other reason. The NNTP class will detect a
+ * premature NNTP server connection closing when it receives a
+ * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED }
+ * response to a command.
+ * When that occurs, the NNTP class method encountering that reply will throw
+ * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
+ * .
+ *
+ * Rather than list it separately for each method, we mention here that
+ * every method communicating with the server and throwing an IOException
+ * can also throw a
+ * {@link org.apache.commons.net.MalformedServerReplyException}
+ * , which is a subclass
+ * of IOException. A MalformedServerReplyException will be thrown when
+ * the reply received from the server deviates enough from the protocol
+ * specification that it cannot be interpreted in a useful manner despite
+ * attempts to be as lenient as possible.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @author Rory Winston
+ * @author Ted Wise
+ * @see NNTPClient
+ * @see NNTPConnectionClosedException
+ * @see org.apache.commons.net.MalformedServerReplyException
+ ***/
+
+public class NNTP extends SocketClient
+{
+ /*** The default NNTP port. Its value is 119 according to RFC 977. ***/
+ public static final int DEFAULT_PORT = 119;
+
+ // We have to ensure that the protocol communication is in ASCII
+ // but we use ISO-8859-1 just in case 8-bit characters cross
+ // the wire.
+ private static final String __DEFAULT_ENCODING = "ISO-8859-1";
+
+ private StringBuffer __commandBuffer;
+
+ boolean _isAllowedToPost;
+ int _replyCode;
+ String _replyString;
+
+ /**
+ * Wraps {@link SocketClient#_input_}
+ * to communicate with server. Initialized by {@link #_connectAction_}.
+ * All server reads should be done through this variable.
+ */
+ protected BufferedReader _reader_;
+
+ /**
+ * Wraps {@link SocketClient#_output_}
+ * to communicate with server. Initialized by {@link #_connectAction_}.
+ * All server reads should be done through this variable.
+ */
+ protected BufferedWriter _writer_;
+
+ /***
+ * A ProtocolCommandSupport object used to manage the registering of
+ * ProtocolCommandListeners and te firing of ProtocolCommandEvents.
+ ***/
+ protected ProtocolCommandSupport _commandSupport_;
+
+ /***
+ * The default NNTP constructor. Sets the default port to
+ *
+ * @param listener The ProtocolCommandListener to add.
+ ***/
+ public void addProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ _commandSupport_.addProtocolCommandListener(listener);
+ }
+
+ /***
+ * Removes a ProtocolCommandListener. Delegates this task to
+ * {@link #_commandSupport_ _commandSupport_ }.
+ *
+ * @param listener The ProtocolCommandListener to remove.
+ ***/
+ public void removeProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ _commandSupport_.removeProtocolCommandListener(listener);
+ }
+
+ /***
+ * Closes the connection to the NNTP server and sets to null
+ * some internal data so that the memory may be reclaimed by the
+ * garbage collector. The reply text and code information from the
+ * last command is voided so that the memory it used may be reclaimed.
+ *
+ * @exception IOException If an error occurs while disconnecting.
+ ***/
+ @Override
+ public void disconnect() throws IOException
+ {
+ super.disconnect();
+ _reader_ = null;
+ _writer_ = null;
+ _replyString = null;
+ _isAllowedToPost = false;
+ }
+
+
+ /***
+ * Indicates whether or not the client is allowed to post articles to
+ * the server it is currently connected to.
+ *
+ * @return True if the client can post articles to the server, false
+ * otherwise.
+ ***/
+ public boolean isAllowedToPost()
+ {
+ return _isAllowedToPost;
+ }
+
+
+ /***
+ * Sends an NNTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString }.
+ *
+ * @param command The text representation of the NNTP command to send.
+ * @param args The arguments to the NNTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the NNTP reply code returned by the server
+ * in response to the command.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(String command, String args) throws IOException
+ {
+ String message;
+
+ __commandBuffer.setLength(0);
+ __commandBuffer.append(command);
+
+ if (args != null)
+ {
+ __commandBuffer.append(' ');
+ __commandBuffer.append(args);
+ }
+ __commandBuffer.append(SocketClient.NETASCII_EOL);
+
+ _writer_.write(message = __commandBuffer.toString());
+ _writer_.flush();
+
+ if (_commandSupport_.getListenerCount() > 0)
+ _commandSupport_.fireCommandSent(command, message);
+
+ __getReply();
+ return _replyCode;
+ }
+
+
+ /***
+ * Sends an NNTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString }.
+ *
+ * @param command The NNTPCommand constant corresponding to the NNTP command
+ * to send.
+ * @param args The arguments to the NNTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the NNTP reply code returned by the server
+ * in response to the command.
+ * in response to the command.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(int command, String args) throws IOException
+ {
+ return sendCommand(NNTPCommand._commands[command], args);
+ }
+
+
+ /***
+ * Sends an NNTP command with no arguments to the server, waits for a
+ * reply and returns the numerical response code. After invocation, for
+ * more detailed information, the actual reply text can be accessed by
+ * calling {@link #getReplyString getReplyString }.
+ *
+ * @param command The text representation of the NNTP command to send.
+ * @return The integer value of the NNTP reply code returned by the server
+ * in response to the command.
+ * in response to the command.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(String command) throws IOException
+ {
+ return sendCommand(command, null);
+ }
+
+
+ /***
+ * Sends an NNTP command with no arguments to the server, waits for a
+ * reply and returns the numerical response code. After invocation, for
+ * more detailed information, the actual reply text can be accessed by
+ * calling {@link #getReplyString getReplyString }.
+ *
+ * @param command The NNTPCommand constant corresponding to the NNTP command
+ * to send.
+ * @return The integer value of the NNTP reply code returned by the server
+ * in response to the command.
+ * in response to the command.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(int command) throws IOException
+ {
+ return sendCommand(command, null);
+ }
+
+
+ /***
+ * Returns the integer value of the reply code of the last NNTP reply.
+ * You will usually only use this method after you connect to the
+ * NNTP server to check that the connection was successful since
+ *
+ * @return The integer value of the reply code of the last NNTP reply.
+ ***/
+ public int getReplyCode()
+ {
+ return _replyCode;
+ }
+
+ /***
+ * Fetches a reply from the NNTP server and returns the integer reply
+ * code. After calling this method, the actual reply text can be accessed
+ * from {@link #getReplyString getReplyString }. Only use this
+ * method if you are implementing your own NNTP client or if you need to
+ * fetch a secondary response from the NNTP server.
+ *
+ * @return The integer value of the reply code of the fetched NNTP reply.
+ * in response to the command.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while
+ * receiving the server reply.
+ ***/
+ public int getReply() throws IOException
+ {
+ __getReply();
+ return _replyCode;
+ }
+
+
+ /***
+ * Returns the entire text of the last NNTP server response exactly
+ * as it was received, not including the end of line marker.
+ *
+ * @return The entire text from the last NNTP response as a String.
+ ***/
+ public String getReplyString()
+ {
+ return _replyString;
+ }
+
+
+ /***
+ * A convenience method to send the NNTP ARTICLE command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @param messageId The message identifier of the requested article,
+ * including the encapsulating < and > characters.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int article(String messageId) throws IOException
+ {
+ return sendCommand(NNTPCommand.ARTICLE, messageId);
+ }
+
+ /***
+ * A convenience method to send the NNTP ARTICLE command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @param articleNumber The number of the article to request from the
+ * currently selected newsgroup.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int article(int articleNumber) throws IOException
+ {
+ return sendCommand(NNTPCommand.ARTICLE, Integer.toString(articleNumber));
+ }
+
+ /***
+ * A convenience method to send the NNTP ARTICLE command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int article() throws IOException
+ {
+ return sendCommand(NNTPCommand.ARTICLE);
+ }
+
+
+
+ /***
+ * A convenience method to send the NNTP BODY command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @param messageId The message identifier of the requested article,
+ * including the encapsulating < and > characters.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int body(String messageId) throws IOException
+ {
+ return sendCommand(NNTPCommand.BODY, messageId);
+ }
+
+ /***
+ * A convenience method to send the NNTP BODY command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @param articleNumber The number of the article to request from the
+ * currently selected newsgroup.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int body(int articleNumber) throws IOException
+ {
+ return sendCommand(NNTPCommand.BODY, Integer.toString(articleNumber));
+ }
+
+ /***
+ * A convenience method to send the NNTP BODY command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int body() throws IOException
+ {
+ return sendCommand(NNTPCommand.BODY);
+ }
+
+
+
+ /***
+ * A convenience method to send the NNTP HEAD command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @param messageId The message identifier of the requested article,
+ * including the encapsulating < and > characters.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int head(String messageId) throws IOException
+ {
+ return sendCommand(NNTPCommand.HEAD, messageId);
+ }
+
+ /***
+ * A convenience method to send the NNTP HEAD command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @param articleNumber The number of the article to request from the
+ * currently selected newsgroup.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int head(int articleNumber) throws IOException
+ {
+ return sendCommand(NNTPCommand.HEAD, Integer.toString(articleNumber));
+ }
+
+ /***
+ * A convenience method to send the NNTP HEAD command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int head() throws IOException
+ {
+ return sendCommand(NNTPCommand.HEAD);
+ }
+
+
+
+ /***
+ * A convenience method to send the NNTP STAT command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @param messageId The message identifier of the requested article,
+ * including the encapsulating < and > characters.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stat(String messageId) throws IOException
+ {
+ return sendCommand(NNTPCommand.STAT, messageId);
+ }
+
+ /***
+ * A convenience method to send the NNTP STAT command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @param articleNumber The number of the article to request from the
+ * currently selected newsgroup.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stat(int articleNumber) throws IOException
+ {
+ return sendCommand(NNTPCommand.STAT, Integer.toString(articleNumber));
+ }
+
+ /***
+ * A convenience method to send the NNTP STAT command to the server,
+ * receive the initial reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stat() throws IOException
+ {
+ return sendCommand(NNTPCommand.STAT);
+ }
+
+
+ /***
+ * A convenience method to send the NNTP GROUP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param newsgroup The name of the newsgroup to select.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int group(String newsgroup) throws IOException
+ {
+ return sendCommand(NNTPCommand.GROUP, newsgroup);
+ }
+
+
+ /***
+ * A convenience method to send the NNTP HELP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int help() throws IOException
+ {
+ return sendCommand(NNTPCommand.HELP);
+ }
+
+
+ /***
+ * A convenience method to send the NNTP IHAVE command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param messageId The article identifier,
+ * including the encapsulating < and > characters.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int ihave(String messageId) throws IOException
+ {
+ return sendCommand(NNTPCommand.IHAVE, messageId);
+ }
+
+
+ /***
+ * A convenience method to send the NNTP LAST command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int last() throws IOException
+ {
+ return sendCommand(NNTPCommand.LAST);
+ }
+
+
+
+ /***
+ * A convenience method to send the NNTP LIST command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int list() throws IOException
+ {
+ return sendCommand(NNTPCommand.LIST);
+ }
+
+
+
+ /***
+ * A convenience method to send the NNTP NEXT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int next() throws IOException
+ {
+ return sendCommand(NNTPCommand.NEXT);
+ }
+
+
+ /***
+ * A convenience method to send the NNTP NEWGROUPS command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param date The date after which to check for new groups.
+ * Date format is YYMMDD
+ * @param time The time after which to check for new groups.
+ * Time format is HHMMSS using a 24-hour clock.
+ * @param GMT True if the time is in GMT, false if local server time.
+ * @param distributions Comma-separated distribution list to check for
+ * new groups. Set to null if no distributions.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int newgroups(String date, String time, boolean GMT,
+ String distributions) throws IOException
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append(date);
+ buffer.append(' ');
+ buffer.append(time);
+
+ if (GMT)
+ {
+ buffer.append(' ');
+ buffer.append("GMT");
+ }
+
+ if (distributions != null)
+ {
+ buffer.append(" <");
+ buffer.append(distributions);
+ buffer.append('>');
+ }
+
+ return sendCommand(NNTPCommand.NEWGROUPS, buffer.toString());
+ }
+
+
+ /***
+ * A convenience method to send the NNTP NEWGROUPS command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param newsgroups A comma-separated list of newsgroups to check for new
+ * news.
+ * @param date The date after which to check for new news.
+ * Date format is YYMMDD
+ * @param time The time after which to check for new news.
+ * Time format is HHMMSS using a 24-hour clock.
+ * @param GMT True if the time is in GMT, false if local server time.
+ * @param distributions Comma-separated distribution list to check for
+ * new news. Set to null if no distributions.
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int newnews(String newsgroups, String date, String time, boolean GMT,
+ String distributions) throws IOException
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append(newsgroups);
+ buffer.append(' ');
+ buffer.append(date);
+ buffer.append(' ');
+ buffer.append(time);
+
+ if (GMT)
+ {
+ buffer.append(' ');
+ buffer.append("GMT");
+ }
+
+ if (distributions != null)
+ {
+ buffer.append(" <");
+ buffer.append(distributions);
+ buffer.append('>');
+ }
+
+ return sendCommand(NNTPCommand.NEWNEWS, buffer.toString());
+ }
+
+
+
+ /***
+ * A convenience method to send the NNTP POST command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int post() throws IOException
+ {
+ return sendCommand(NNTPCommand.POST);
+ }
+
+
+
+ /***
+ * A convenience method to send the NNTP QUIT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int quit() throws IOException
+ {
+ return sendCommand(NNTPCommand.QUIT);
+ }
+
+ /***
+ * A convenience method to send the AUTHINFO USER command to the server,
+ * receive the reply, and return the reply code. (See RFC 2980)
+ *
+ * @param username A valid username.
+ * @return The reply code received from the server. The server should
+ * return a 381 or 281 for this command.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int authinfoUser(String username) throws IOException {
+ String userParameter = "USER " + username;
+ return sendCommand(NNTPCommand.AUTHINFO, userParameter);
+ }
+
+ /***
+ * A convenience method to send the AUTHINFO PASS command to the server,
+ * receive the reply, and return the reply code. If this step is
+ * required, it should immediately follow the AUTHINFO USER command
+ * (See RFC 2980)
+ *
+ * @param password a valid password.
+ * @return The reply code received from the server. The server should
+ * return a 281 or 502 for this command.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int authinfoPass(String password) throws IOException {
+ String passParameter = "PASS " + password;
+ return sendCommand(NNTPCommand.AUTHINFO, passParameter);
+ }
+
+ /***
+ * A convenience method to send the NNTP XOVER command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param selectedArticles a String representation of the range of
+ * article headers required. This may be an article number, or a
+ * range of article numbers in the form "XXXX-YYYY", where XXXX
+ * and YYYY are valid article numbers in the current group. It
+ * also may be of the form "XXX-", meaning "return XXX and all
+ * following articles" In this revision, the last format is not
+ * possible (yet).
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int xover(String selectedArticles) throws IOException {
+ return sendCommand(NNTPCommand.XOVER, selectedArticles);
+ }
+
+ /***
+ * A convenience method to send the NNTP XHDR command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param header a String naming a header line (e.g., "subject"). See
+ * RFC-1036 for a list of valid header lines.
+ * @param selectedArticles a String representation of the range of
+ * article headers required. This may be an article number, or a
+ * range of article numbers in the form "XXXX-YYYY", where XXXX
+ * and YYYY are valid article numbers in the current group. It
+ * also may be of the form "XXX-", meaning "return XXX and all
+ * following articles" In this revision, the last format is not
+ * possible (yet).
+ * @return The reply code received from the server.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int xhdr(String header, String selectedArticles) throws IOException {
+ StringBuffer command = new StringBuffer(header);
+ command.append(" ");
+ command.append(selectedArticles);
+ return sendCommand(NNTPCommand.XHDR, command.toString());
+ }
+
+ /**
+ * A convenience wrapper for the extended LIST command that takes
+ * an argument, allowing us to selectively list multiple groups.
+ *
+ * @param wildmat A wildmat (pseudo-regex) pattern. See RFC 2980 for
+ * details.
+ * @return the reply code received from the server.
+ * @throws IOException
+ */
+ public int listActive(String wildmat) throws IOException {
+ StringBuffer command = new StringBuffer("ACTIVE ");
+ command.append(wildmat);
+ return sendCommand(NNTPCommand.LIST, command.toString());
+ }
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/org/apache/commons/net/nntp/NNTPClient.java b/org/apache/commons/net/nntp/NNTPClient.java
new file mode 100644
index 0000000..e10ce90
--- /dev/null
+++ b/org/apache/commons/net/nntp/NNTPClient.java
@@ -0,0 +1,1285 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.nntp;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.commons.net.MalformedServerReplyException;
+import org.apache.commons.net.io.DotTerminatedMessageReader;
+import org.apache.commons.net.io.DotTerminatedMessageWriter;
+import org.apache.commons.net.io.Util;
+
+/***
+ * NNTPClient encapsulates all the functionality necessary to post and
+ * retrieve articles from an NNTP server. As with all classes derived
+ * from {@link org.apache.commons.net.SocketClient},
+ * you must first connect to the server with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * before doing anything, and finally
+ * {@link org.apache.commons.net.nntp.NNTP#disconnect disconnect() }
+ * after you're completely finished interacting with the server.
+ * Remember that the
+ * {@link org.apache.commons.net.nntp.NNTP#isAllowedToPost isAllowedToPost()}
+ * method is defined in
+ * {@link org.apache.commons.net.nntp.NNTP}.
+ *
+ * You should keep in mind that the NNTP server may choose to prematurely
+ * close a connection if the client has been idle for longer than a
+ * given time period or if the server is being shutdown by the operator or
+ * some other reason. The NNTP class will detect a
+ * premature NNTP server connection closing when it receives a
+ * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED }
+ * response to a command.
+ * When that occurs, the NNTP class method encountering that reply will throw
+ * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
+ * .
+ *
+ * Rather than list it separately for each method, we mention here that
+ * every method communicating with the server and throwing an IOException
+ * can also throw a
+ * {@link org.apache.commons.net.MalformedServerReplyException}
+ * , which is a subclass
+ * of IOException. A MalformedServerReplyException will be thrown when
+ * the reply received from the server deviates enough from the protocol
+ * specification that it cannot be interpreted in a useful manner despite
+ * attempts to be as lenient as possible.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @author Rory Winston
+ * @author Ted Wise
+ * @see NNTP
+ * @see NNTPConnectionClosedException
+ * @see org.apache.commons.net.MalformedServerReplyException
+ ***/
+
+public class NNTPClient extends NNTP
+{
+
+ private void __parseArticlePointer(String reply, ArticlePointer pointer)
+ throws MalformedServerReplyException
+ {
+ StringTokenizer tokenizer;
+
+ // Do loop is a kluge to simulate goto
+ do
+ {
+ tokenizer = new StringTokenizer(reply);
+
+ if (tokenizer.countTokens() < 3)
+ break;
+
+ // Skip numeric response value
+ tokenizer.nextToken();
+ // Get article number
+ try
+ {
+ pointer.articleNumber = Integer.parseInt(tokenizer.nextToken());
+ }
+ catch (NumberFormatException e)
+ {
+ break;
+ }
+
+ // Get article id
+ pointer.articleId = tokenizer.nextToken();
+ return ;
+ }
+ while (false);
+
+ throw new MalformedServerReplyException(
+ "Could not parse article pointer.\nServer reply: " + reply);
+ }
+
+
+ private void __parseGroupReply(String reply, NewsgroupInfo info)
+ throws MalformedServerReplyException
+ {
+ String count, first, last;
+ StringTokenizer tokenizer;
+
+ // Do loop is a kluge to simulate goto
+ do
+ {
+ tokenizer = new StringTokenizer(reply);
+
+ if (tokenizer.countTokens() < 5)
+ break;
+
+ // Skip numeric response value
+ tokenizer.nextToken();
+ // Get estimated article count
+ count = tokenizer.nextToken();
+ // Get first article number
+ first = tokenizer.nextToken();
+ // Get last article number
+ last = tokenizer.nextToken();
+ // Get newsgroup name
+ info._setNewsgroup(tokenizer.nextToken());
+
+ try
+ {
+ info._setArticleCount(Integer.parseInt(count));
+ info._setFirstArticle(Integer.parseInt(first));
+ info._setLastArticle(Integer.parseInt(last));
+ }
+ catch (NumberFormatException e)
+ {
+ break;
+ }
+
+ info._setPostingPermission(NewsgroupInfo.UNKNOWN_POSTING_PERMISSION);
+ return ;
+ }
+ while (false);
+
+ throw new MalformedServerReplyException(
+ "Could not parse newsgroup info.\nServer reply: " + reply);
+ }
+
+
+ private NewsgroupInfo __parseNewsgroupListEntry(String entry)
+ {
+ NewsgroupInfo result;
+ StringTokenizer tokenizer;
+ int lastNum, firstNum;
+ String last, first, permission;
+
+ result = new NewsgroupInfo();
+ tokenizer = new StringTokenizer(entry);
+
+ if (tokenizer.countTokens() < 4)
+ return null;
+
+ result._setNewsgroup(tokenizer.nextToken());
+ last = tokenizer.nextToken();
+ first = tokenizer.nextToken();
+ permission = tokenizer.nextToken();
+
+ try
+ {
+ lastNum = Integer.parseInt(last);
+ firstNum = Integer.parseInt(first);
+ result._setFirstArticle(firstNum);
+ result._setLastArticle(lastNum);
+
+ if((firstNum == 0) && (lastNum == 0))
+ result._setArticleCount(0);
+ else
+ result._setArticleCount(lastNum - firstNum + 1);
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+
+ switch (permission.charAt(0))
+ {
+ case 'y':
+ case 'Y':
+ result._setPostingPermission(
+ NewsgroupInfo.PERMITTED_POSTING_PERMISSION);
+ break;
+ case 'n':
+ case 'N':
+ result._setPostingPermission(
+ NewsgroupInfo.PROHIBITED_POSTING_PERMISSION);
+ break;
+ case 'm':
+ case 'M':
+ result._setPostingPermission(
+ NewsgroupInfo.MODERATED_POSTING_PERMISSION);
+ break;
+ default:
+ result._setPostingPermission(
+ NewsgroupInfo.UNKNOWN_POSTING_PERMISSION);
+ break;
+ }
+
+ return result;
+ }
+
+ private NewsgroupInfo[] __readNewsgroupListing() throws IOException
+ {
+ int size;
+ String line;
+ Vector
+ * A DotTerminatedMessageReader is returned from which the article can
+ * be read. If the article does not exist, null is returned.
+ *
+ * You must not issue any commands to the NNTP server (i.e., call any
+ * other methods) until you finish reading the message from the returned
+ * Reader instance.
+ * The NNTP protocol uses the same stream for issuing commands as it does
+ * for returning results. Therefore the returned Reader actually reads
+ * directly from the NNTP connection. After the end of message has been
+ * reached, new commands can be executed and their replies read. If
+ * you do not follow these requirements, your program will not work
+ * properly.
+ *
+ * @param articleId The unique article identifier of the article to
+ * retrieve. If this parameter is null, the currently selected
+ * article is retrieved.
+ * @param pointer A parameter through which to return the article's
+ * number and unique id. The articleId field cannot always be trusted
+ * because of server deviations from RFC 977 reply formats. You may
+ * set this parameter to null if you do not desire to retrieve the
+ * returned article information.
+ * @return A DotTerminatedMessageReader instance from which the article
+ * be read. null if the article does not exist.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public Reader retrieveArticle(String articleId, ArticlePointer pointer)
+ throws IOException
+ {
+ return __retrieve(NNTPCommand.ARTICLE, articleId, pointer);
+
+ }
+
+ /*** Same as
+ * A DotTerminatedMessageReader is returned from which the article can
+ * be read. If the article does not exist, null is returned.
+ *
+ * You must not issue any commands to the NNTP server (i.e., call any
+ * other methods) until you finish reading the message from the returned
+ * Reader instance.
+ * The NNTP protocol uses the same stream for issuing commands as it does
+ * for returning results. Therefore the returned Reader actually reads
+ * directly from the NNTP connection. After the end of message has been
+ * reached, new commands can be executed and their replies read. If
+ * you do not follow these requirements, your program will not work
+ * properly.
+ *
+ * @param articleNumber The number of the the article to
+ * retrieve.
+ * @param pointer A parameter through which to return the article's
+ * number and unique id. The articleId field cannot always be trusted
+ * because of server deviations from RFC 977 reply formats. You may
+ * set this parameter to null if you do not desire to retrieve the
+ * returned article information.
+ * @return A DotTerminatedMessageReader instance from which the article
+ * be read. null if the article does not exist.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public Reader retrieveArticle(int articleNumber, ArticlePointer pointer)
+ throws IOException
+ {
+ return __retrieve(NNTPCommand.ARTICLE, articleNumber, pointer);
+ }
+
+ /*** Same as
+ * A DotTerminatedMessageReader is returned from which the article can
+ * be read. If the article does not exist, null is returned.
+ *
+ * You must not issue any commands to the NNTP server (i.e., call any
+ * other methods) until you finish reading the message from the returned
+ * Reader instance.
+ * The NNTP protocol uses the same stream for issuing commands as it does
+ * for returning results. Therefore the returned Reader actually reads
+ * directly from the NNTP connection. After the end of message has been
+ * reached, new commands can be executed and their replies read. If
+ * you do not follow these requirements, your program will not work
+ * properly.
+ *
+ * @param articleId The unique article identifier of the article whose
+ * header is being retrieved. If this parameter is null, the
+ * header of the currently selected article is retrieved.
+ * @param pointer A parameter through which to return the article's
+ * number and unique id. The articleId field cannot always be trusted
+ * because of server deviations from RFC 977 reply formats. You may
+ * set this parameter to null if you do not desire to retrieve the
+ * returned article information.
+ * @return A DotTerminatedMessageReader instance from which the article
+ * header can be read. null if the article does not exist.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public Reader retrieveArticleHeader(String articleId, ArticlePointer pointer)
+ throws IOException
+ {
+ return __retrieve(NNTPCommand.HEAD, articleId, pointer);
+
+ }
+
+ /*** Same as
+ * A DotTerminatedMessageReader is returned from which the article can
+ * be read. If the article does not exist, null is returned.
+ *
+ * You must not issue any commands to the NNTP server (i.e., call any
+ * other methods) until you finish reading the message from the returned
+ * Reader instance.
+ * The NNTP protocol uses the same stream for issuing commands as it does
+ * for returning results. Therefore the returned Reader actually reads
+ * directly from the NNTP connection. After the end of message has been
+ * reached, new commands can be executed and their replies read. If
+ * you do not follow these requirements, your program will not work
+ * properly.
+ *
+ * @param articleNumber The number of the the article whose header is
+ * being retrieved.
+ * @param pointer A parameter through which to return the article's
+ * number and unique id. The articleId field cannot always be trusted
+ * because of server deviations from RFC 977 reply formats. You may
+ * set this parameter to null if you do not desire to retrieve the
+ * returned article information.
+ * @return A DotTerminatedMessageReader instance from which the article
+ * header can be read. null if the article does not exist.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public Reader retrieveArticleHeader(int articleNumber,
+ ArticlePointer pointer)
+ throws IOException
+ {
+ return __retrieve(NNTPCommand.HEAD, articleNumber, pointer);
+ }
+
+
+ /*** Same as
+ * A DotTerminatedMessageReader is returned from which the article can
+ * be read. If the article does not exist, null is returned.
+ *
+ * You must not issue any commands to the NNTP server (i.e., call any
+ * other methods) until you finish reading the message from the returned
+ * Reader instance.
+ * The NNTP protocol uses the same stream for issuing commands as it does
+ * for returning results. Therefore the returned Reader actually reads
+ * directly from the NNTP connection. After the end of message has been
+ * reached, new commands can be executed and their replies read. If
+ * you do not follow these requirements, your program will not work
+ * properly.
+ *
+ * @param articleId The unique article identifier of the article whose
+ * body is being retrieved. If this parameter is null, the
+ * body of the currently selected article is retrieved.
+ * @param pointer A parameter through which to return the article's
+ * number and unique id. The articleId field cannot always be trusted
+ * because of server deviations from RFC 977 reply formats. You may
+ * set this parameter to null if you do not desire to retrieve the
+ * returned article information.
+ * @return A DotTerminatedMessageReader instance from which the article
+ * body can be read. null if the article does not exist.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public Reader retrieveArticleBody(String articleId, ArticlePointer pointer)
+ throws IOException
+ {
+ return __retrieve(NNTPCommand.BODY, articleId, pointer);
+
+ }
+
+ /*** Same as
+ * A DotTerminatedMessageReader is returned from which the article can
+ * be read. If the article does not exist, null is returned.
+ *
+ * You must not issue any commands to the NNTP server (i.e., call any
+ * other methods) until you finish reading the message from the returned
+ * Reader instance.
+ * The NNTP protocol uses the same stream for issuing commands as it does
+ * for returning results. Therefore the returned Reader actually reads
+ * directly from the NNTP connection. After the end of message has been
+ * reached, new commands can be executed and their replies read. If
+ * you do not follow these requirements, your program will not work
+ * properly.
+ *
+ * @param articleNumber The number of the the article whose body is
+ * being retrieved.
+ * @param pointer A parameter through which to return the article's
+ * number and unique id. The articleId field cannot always be trusted
+ * because of server deviations from RFC 977 reply formats. You may
+ * set this parameter to null if you do not desire to retrieve the
+ * returned article information.
+ * @return A DotTerminatedMessageReader instance from which the article
+ * body can be read. null if the article does not exist.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public Reader retrieveArticleBody(int articleNumber,
+ ArticlePointer pointer)
+ throws IOException
+ {
+ return __retrieve(NNTPCommand.BODY, articleNumber, pointer);
+ }
+
+
+ /*** Same as
+ * @param newsgroup The newsgroup to select.
+ * @param info A parameter through which the newsgroup information of
+ * the selected newsgroup contained in the server reply is returned.
+ * Set this to null if you do not desire this information.
+ * @return True if the newsgroup exists and was selected, false otherwise.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean selectNewsgroup(String newsgroup, NewsgroupInfo info)
+ throws IOException
+ {
+ if (!NNTPReply.isPositiveCompletion(group(newsgroup)))
+ return false;
+
+ if (info != null)
+ __parseGroupReply(getReplyString(), info);
+
+ return true;
+ }
+
+ /*** Same as
+ * @return The sever help information.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String listHelp() throws IOException
+ {
+ StringWriter help;
+ Reader reader;
+
+ if (!NNTPReply.isInformational(help()))
+ return null;
+
+ help = new StringWriter();
+ reader = new DotTerminatedMessageReader(_reader_);
+ Util.copyReader(reader, help);
+ reader.close();
+ help.close();
+ return help.toString();
+ }
+
+
+ /***
+ * Select an article by its unique identifier (including enclosing
+ * < and >) and return its article number and id through the
+ * pointer parameter. This is achieved through the STAT command.
+ * According to RFC 977, this will NOT set the current article pointer
+ * on the server. To do that, you must reference the article by its
+ * number.
+ *
+ * @param articleId The unique article identifier of the article that
+ * is being selectedd. If this parameter is null, the
+ * body of the current article is selected
+ * @param pointer A parameter through which to return the article's
+ * number and unique id. The articleId field cannot always be trusted
+ * because of server deviations from RFC 977 reply formats. You may
+ * set this parameter to null if you do not desire to retrieve the
+ * returned article information.
+ * @return True if successful, false if not.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean selectArticle(String articleId, ArticlePointer pointer)
+ throws IOException
+ {
+ if (articleId != null)
+ {
+ if (!NNTPReply.isPositiveCompletion(stat(articleId)))
+ return false;
+ }
+ else
+ {
+ if (!NNTPReply.isPositiveCompletion(stat()))
+ return false;
+ }
+
+ if (pointer != null)
+ __parseArticlePointer(getReplyString(), pointer);
+
+ return true;
+ }
+
+ /**** Same as
+ * @param articleNumber The number of the article to select from the
+ * currently selected newsgroup.
+ * @param pointer A parameter through which to return the article's
+ * number and unique id. Although the articleId field cannot always
+ * be trusted because of server deviations from RFC 977 reply formats,
+ * we haven't found a server that misformats this information in response
+ * to this particular command. You may set this parameter to null if
+ * you do not desire to retrieve the returned article information.
+ * @return True if successful, false if not.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean selectArticle(int articleNumber, ArticlePointer pointer)
+ throws IOException
+ {
+ if (!NNTPReply.isPositiveCompletion(stat(articleNumber)))
+ return false;
+
+ if (pointer != null)
+ __parseArticlePointer(getReplyString(), pointer);
+
+ return true;
+ }
+
+
+ /*** Same as
+ * @param pointer A parameter through which to return the article's
+ * number and unique id. The articleId field cannot always be trusted
+ * because of server deviations from RFC 977 reply formats. You may
+ * set this parameter to null if you do not desire to retrieve the
+ * returned article information.
+ * @return True if successful, false if not (e.g., there is no previous
+ * article).
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean selectPreviousArticle(ArticlePointer pointer)
+ throws IOException
+ {
+ if (!NNTPReply.isPositiveCompletion(last()))
+ return false;
+
+ if (pointer != null)
+ __parseArticlePointer(getReplyString(), pointer);
+
+ return true;
+ }
+
+ /*** Same as
+ * @param pointer A parameter through which to return the article's
+ * number and unique id. The articleId field cannot always be trusted
+ * because of server deviations from RFC 977 reply formats. You may
+ * set this parameter to null if you do not desire to retrieve the
+ * returned article information.
+ * @return True if successful, false if not (e.g., there is no following
+ * article).
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean selectNextArticle(ArticlePointer pointer) throws IOException
+ {
+ if (!NNTPReply.isPositiveCompletion(next()))
+ return false;
+
+ if (pointer != null)
+ __parseArticlePointer(getReplyString(), pointer);
+
+ return true;
+ }
+
+
+ /*** Same as
+ * @return An array of NewsgroupInfo instances containing the information
+ * for each newsgroup served by the NNTP server. If no newsgroups
+ * are served, a zero length array will be returned. If the command
+ * fails, null will be returned.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public NewsgroupInfo[] listNewsgroups() throws IOException
+ {
+ if (!NNTPReply.isPositiveCompletion(list()))
+ return null;
+
+ return __readNewsgroupListing();
+ }
+
+ /**
+ * An overloaded listNewsgroups() command that allows us to
+ * specify with a pattern what groups we want to list. Wraps the
+ * LIST ACTIVE command.
+ *
+ * @param wildmat a pseudo-regex pattern (cf. RFC 2980)
+ * @return An array of NewsgroupInfo instances containing the information
+ * for each newsgroup served by the NNTP server corresponding to the
+ * supplied pattern. If no such newsgroups are served, a zero length
+ * array will be returned. If the command fails, null will be returned.
+ * @throws IOException
+ */
+ public NewsgroupInfo[] listNewsgroups(String wildmat) throws IOException
+ {
+ if(!NNTPReply.isPositiveCompletion(listActive(wildmat)))
+ return null;
+ return __readNewsgroupListing();
+ }
+
+
+ /***
+ * List all new newsgroups added to the NNTP server since a particular
+ * date subject to the conditions of the specified query. If no new
+ * newsgroups were added, a zero length array will be returned. If the
+ * command fails, null will be returned.
+ *
+ * @param query The query restricting how to search for new newsgroups.
+ * @return An array of NewsgroupInfo instances containing the information
+ * for each new newsgroup added to the NNTP server. If no newsgroups
+ * were added, a zero length array will be returned. If the command
+ * fails, null will be returned.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public NewsgroupInfo[] listNewNewsgroups(NewGroupsOrNewsQuery query)
+ throws IOException
+ {
+ if (!NNTPReply.isPositiveCompletion(newgroups(
+ query.getDate(), query.getTime(),
+ query.isGMT(), query.getDistributions())))
+ return null;
+
+ return __readNewsgroupListing();
+ }
+
+
+ /***
+ * List all new articles added to the NNTP server since a particular
+ * date subject to the conditions of the specified query. If no new
+ * new news is found, a zero length array will be returned. If the
+ * command fails, null will be returned. You must add at least one
+ * newsgroup to the query, else the command will fail. Each String
+ * in the returned array is a unique message identifier including the
+ * enclosing < and >.
+ *
+ * @param query The query restricting how to search for new news. You
+ * must add at least one newsgroup to the query.
+ * @return An array of String instances containing the unique message
+ * identifiers for each new article added to the NNTP server. If no
+ * new news is found, a zero length array will be returned. If the
+ * command fails, null will be returned.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String[] listNewNews(NewGroupsOrNewsQuery query)
+ throws IOException
+ {
+ int size;
+ String line;
+ Vector
+ * For example
+ *
+ * @return True if successfully completed, false if not.
+ * @exception NNTPConnectionClosedException
+ * If the NNTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send NNTP reply code 400. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean completePendingCommand() throws IOException
+ {
+ return NNTPReply.isPositiveCompletion(getReply());
+ }
+
+ /***
+ * Post an article to the NNTP server. This method returns a
+ * DotTerminatedMessageWriter instance to which the article can be
+ * written. Null is returned if the posting attempt fails. You
+ * should check {@link NNTP#isAllowedToPost isAllowedToPost() }
+ * before trying to post. However, a posting
+ * attempt can fail due to malformed headers.
+ *
+ * You must not issue any commands to the NNTP server (i.e., call any
+ * (other methods) until you finish writing to the returned Writer
+ * instance and close it. The NNTP protocol uses the same stream for
+ * issuing commands as it does for returning results. Therefore the
+ * returned Writer actually writes directly to the NNTP connection.
+ * After you close the writer, you can execute new commands. If you
+ * do not follow these requirements your program will not work properly.
+ *
+ * Different NNTP servers will require different header formats, but
+ * you can use the provided
+ * {@link org.apache.commons.net.nntp.SimpleNNTPHeader}
+ * class to construct the bare minimum acceptable header for most
+ * news readers. To construct more complicated headers you should
+ * refer to RFC 822. When the Java Mail API is finalized, you will be
+ * able to use it to compose fully compliant Internet text messages.
+ * The DotTerminatedMessageWriter takes care of doubling line-leading
+ * dots and ending the message with a single dot upon closing, so all
+ * you have to worry about is writing the header and the message.
+ *
+ * Upon closing the returned Writer, you need to call
+ * {@link #completePendingCommand completePendingCommand() }
+ * to finalize the posting and verify its success or failure from
+ * the server reply.
+ *
+ * @return A DotTerminatedMessageWriter to which the article (including
+ * header) can be written. Returns null if the command fails.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+
+ public Writer postArticle() throws IOException
+ {
+ if (!NNTPReply.isPositiveIntermediate(post()))
+ return null;
+
+ return new DotTerminatedMessageWriter(_writer_);
+ }
+
+
+ public Writer forwardArticle(String articleId) throws IOException
+ {
+ if (!NNTPReply.isPositiveIntermediate(ihave(articleId)))
+ return null;
+
+ return new DotTerminatedMessageWriter(_writer_);
+ }
+
+
+ /***
+ * Logs out of the news server gracefully by sending the QUIT command.
+ * However, you must still disconnect from the server before you can open
+ * a new connection.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean logout() throws IOException
+ {
+ return NNTPReply.isPositiveCompletion(quit());
+ }
+
+
+ /**
+ * Log into a news server by sending the AUTHINFO USER/AUTHINFO
+ * PASS command sequence. This is usually sent in response to a
+ * 480 reply code from the NNTP server.
+ *
+ * @param username a valid username
+ * @param password the corresponding password
+ * @return True for successful login, false for a failure
+ * @throws IOException
+ */
+ public boolean authenticate(String username, String password)
+ throws IOException
+ {
+ int replyCode = authinfoUser(username);
+
+ if (replyCode == NNTPReply.MORE_AUTH_INFO_REQUIRED)
+ {
+ replyCode = authinfoPass(password);
+
+ if (replyCode == NNTPReply.AUTHENTICATION_ACCEPTED)
+ {
+ _isAllowedToPost = true;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /***
+ * Private implementation of XOVER functionality.
+ *
+ * See {@link NNTP#xover}
+ * for legal agument formats. Alternatively, read RFC 2980 :-)
+ *
+ * @param articleRange
+ * @return Returns a DotTerminatedMessageReader if successful, null
+ * otherwise
+ * @exception IOException
+ */
+ private Reader __retrieveArticleInfo(String articleRange)
+ throws IOException
+ {
+ if (!NNTPReply.isPositiveCompletion(xover(articleRange)))
+ return null;
+
+ return new DotTerminatedMessageReader(_reader_);
+ }
+
+ /**
+ * Return article headers for a specified post.
+ *
+ * @param articleNumber the article to retrieve headers for
+ * @return a DotTerminatedReader if successful, null otherwise
+ * @throws IOException
+ */
+ public Reader retrieveArticleInfo(int articleNumber) throws IOException
+ {
+ return __retrieveArticleInfo(Integer.toString(articleNumber));
+ }
+
+ /**
+ * Return article headers for all articles between lowArticleNumber
+ * and highArticleNumber, inclusively.
+ *
+ * @param lowArticleNumber
+ * @param highArticleNumber
+ * @return a DotTerminatedReader if successful, null otherwise
+ * @throws IOException
+ */
+ public Reader retrieveArticleInfo(int lowArticleNumber,
+ int highArticleNumber)
+ throws IOException
+ {
+ return
+ __retrieveArticleInfo(lowArticleNumber + "-" +
+ highArticleNumber);
+ }
+
+ /***
+ * Private implementation of XHDR functionality.
+ *
+ * See {@link NNTP#xhdr}
+ * for legal agument formats. Alternatively, read RFC 1036.
+ *
+ * @param header
+ * @param articleRange
+ * @return Returns a DotTerminatedMessageReader if successful, null
+ * otherwise
+ * @exception IOException
+ */
+ private Reader __retrieveHeader(String header, String articleRange)
+ throws IOException
+ {
+ if (!NNTPReply.isPositiveCompletion(xhdr(header, articleRange)))
+ return null;
+
+ return new DotTerminatedMessageReader(_reader_);
+ }
+
+ /**
+ * Return an article header for a specified post.
+ *
+ * @param header the header to retrieve
+ * @param articleNumber the article to retrieve the header for
+ * @return a DotTerminatedReader if successful, null otherwise
+ * @throws IOException
+ */
+ public Reader retrieveHeader(String header, int articleNumber)
+ throws IOException
+ {
+ return __retrieveHeader(header, Integer.toString(articleNumber));
+ }
+
+ /**
+ * Return an article header for all articles between lowArticleNumber
+ * and highArticleNumber, inclusively.
+ *
+ * @param header
+ * @param lowArticleNumber
+ * @param highArticleNumber
+ * @return a DotTerminatedReader if successful, null otherwise
+ * @throws IOException
+ */
+ public Reader retrieveHeader(String header, int lowArticleNumber,
+ int highArticleNumber)
+ throws IOException
+ {
+ return
+ __retrieveHeader(header,lowArticleNumber + "-" + highArticleNumber);
+ }
+}
+
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/org/apache/commons/net/nntp/NNTPCommand.java b/org/apache/commons/net/nntp/NNTPCommand.java
new file mode 100644
index 0000000..09f4015
--- /dev/null
+++ b/org/apache/commons/net/nntp/NNTPCommand.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.nntp;
+
+/***
+ * NNTPCommand stores a set of constants for NNTP command codes. To interpret
+ * the meaning of the codes, familiarity with RFC 977 is assumed.
+ *
+ * @author Daniel F. Savarese
+ * @author Rory Winston
+ * @author Ted Wise
+ ***/
+
+public final class NNTPCommand
+{
+
+ public static final int ARTICLE = 0;
+ public static final int BODY = 1;
+ public static final int GROUP = 2;
+ public static final int HEAD = 3;
+ public static final int HELP = 4;
+ public static final int IHAVE = 5;
+ public static final int LAST = 6;
+ public static final int LIST = 7;
+ public static final int NEWGROUPS = 8;
+ public static final int NEWNEWS = 9;
+ public static final int NEXT = 10;
+ public static final int POST = 11;
+ public static final int QUIT = 12;
+ public static final int SLAVE = 13;
+ public static final int STAT = 14;
+ public static final int AUTHINFO = 15;
+ public static final int XOVER = 16;
+ public static final int XHDR = 17;
+
+ // Cannot be instantiated
+ private NNTPCommand()
+ {}
+
+ static final String[] _commands = {
+ "ARTICLE", "BODY", "GROUP", "HEAD", "HELP", "IHAVE", "LAST", "LIST",
+ "NEWGROUPS", "NEWNEWS", "NEXT", "POST", "QUIT", "SLAVE", "STAT",
+ "AUTHINFO", "XOVER", "XHDR"
+ };
+
+
+ /***
+ * Retrieve the NNTP protocol command string corresponding to a specified
+ * command code.
+ *
+ * @param command The command code.
+ * @return The NNTP protcol command string corresponding to a specified
+ * command code.
+ ***/
+ public static final String getCommand(int command)
+ {
+ return _commands[command];
+ }
+
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/org/apache/commons/net/nntp/NNTPConnectionClosedException.java b/org/apache/commons/net/nntp/NNTPConnectionClosedException.java
new file mode 100644
index 0000000..948ed12
--- /dev/null
+++ b/org/apache/commons/net/nntp/NNTPConnectionClosedException.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.nntp;
+
+import java.io.IOException;
+
+/***
+ * NNTPConnectionClosedException is used to indicate the premature or
+ * unexpected closing of an NNTP connection resulting from a
+ * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED }
+ * response (NNTP reply code 400) to a
+ * failed NNTP command. This exception is derived from IOException and
+ * therefore may be caught either as an IOException or specifically as an
+ * NNTPConnectionClosedException.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see NNTP
+ * @see NNTPClient
+ ***/
+
+public final class NNTPConnectionClosedException extends IOException
+{
+
+ /*** Constructs a NNTPConnectionClosedException with no message ***/
+ public NNTPConnectionClosedException()
+ {
+ super();
+ }
+
+ /***
+ * Constructs a NNTPConnectionClosedException with a specified message.
+ *
+ * @param message The message explaining the reason for the exception.
+ ***/
+ public NNTPConnectionClosedException(String message)
+ {
+ super(message);
+ }
+
+}
diff --git a/org/apache/commons/net/nntp/NNTPReply.java b/org/apache/commons/net/nntp/NNTPReply.java
new file mode 100644
index 0000000..f7d0fbd
--- /dev/null
+++ b/org/apache/commons/net/nntp/NNTPReply.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.nntp;
+
+/***
+ * NNTPReply stores a set of constants for NNTP reply codes. To interpret
+ * the meaning of the codes, familiarity with RFC 977 is assumed.
+ * The mnemonic constant names are transcriptions from the code descriptions
+ * of RFC 977. For those who think in terms of the actual reply code values,
+ * a set of CODE_NUM constants are provided where NUM is the numerical value
+ * of the code.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class NNTPReply
+{
+
+ public static final int CODE_100 = 100;
+ public static final int CODE_199 = 199;
+ public static final int CODE_200 = 200;
+ public static final int CODE_201 = 201;
+ public static final int CODE_202 = 202;
+ public static final int CODE_205 = 205;
+ public static final int CODE_211 = 211;
+ public static final int CODE_215 = 215;
+ public static final int CODE_220 = 220;
+ public static final int CODE_221 = 221;
+ public static final int CODE_222 = 222;
+ public static final int CODE_223 = 223;
+ public static final int CODE_230 = 230;
+ public static final int CODE_231 = 231;
+ public static final int CODE_235 = 235;
+ public static final int CODE_240 = 240;
+ public static final int CODE_281 = 281;
+ public static final int CODE_335 = 335;
+ public static final int CODE_340 = 340;
+ public static final int CODE_381 = 381;
+ public static final int CODE_400 = 400;
+ public static final int CODE_408 = 408;
+ public static final int CODE_411 = 411;
+ public static final int CODE_412 = 412;
+ public static final int CODE_420 = 420;
+ public static final int CODE_421 = 421;
+ public static final int CODE_422 = 422;
+ public static final int CODE_423 = 423;
+ public static final int CODE_430 = 430;
+ public static final int CODE_435 = 435;
+ public static final int CODE_436 = 436;
+ public static final int CODE_437 = 437;
+ public static final int CODE_440 = 440;
+ public static final int CODE_441 = 441;
+ public static final int CODE_482 = 482;
+ public static final int CODE_500 = 500;
+ public static final int CODE_501 = 501;
+ public static final int CODE_502 = 502;
+ public static final int CODE_503 = 503;
+
+ public static final int HELP_TEXT_FOLLOWS = CODE_100;
+ public static final int DEBUG_OUTPUT = CODE_199;
+ public static final int SERVER_READY_POSTING_ALLOWED = CODE_200;
+ public static final int SERVER_READY_POSTING_NOT_ALLOWED = CODE_201;
+ public static final int SLAVE_STATUS_NOTED = CODE_202;
+ public static final int CLOSING_CONNECTION = CODE_205;
+ public static final int GROUP_SELECTED = CODE_211;
+ public static final int ARTICLE_RETRIEVED_HEAD_AND_BODY_FOLLOW = CODE_220;
+ public static final int ARTICLE_RETRIEVED_HEAD_FOLLOWS = CODE_221;
+ public static final int ARTICLE_RETRIEVED_BODY_FOLLOWS = CODE_222;
+ public static final int
+ ARTICLE_RETRIEVED_REQUEST_TEXT_SEPARATELY = CODE_223;
+ public static final int ARTICLE_LIST_BY_MESSAGE_ID_FOLLOWS = CODE_230;
+ public static final int NEW_NEWSGROUP_LIST_FOLLOWS = CODE_231;
+ public static final int ARTICLE_TRANSFERRED_OK = CODE_235;
+ public static final int ARTICLE_POSTED_OK = CODE_240;
+ public static final int AUTHENTICATION_ACCEPTED = CODE_281;
+ public static final int SEND_ARTICLE_TO_TRANSFER = CODE_335;
+ public static final int SEND_ARTICLE_TO_POST = CODE_340;
+ public static final int MORE_AUTH_INFO_REQUIRED = CODE_381;
+ public static final int SERVICE_DISCONTINUED = CODE_400;
+ public static final int NO_SUCH_NEWSGROUP = CODE_411;
+ public static final int AUTHENTICATION_REQUIRED = CODE_408;
+ public static final int NO_NEWSGROUP_SELECTED = CODE_412;
+ public static final int NO_CURRENT_ARTICLE_SELECTED = CODE_420;
+ public static final int NO_NEXT_ARTICLE = CODE_421;
+ public static final int NO_PREVIOUS_ARTICLE = CODE_422;
+ public static final int NO_SUCH_ARTICLE_NUMBER = CODE_423;
+ public static final int NO_SUCH_ARTICLE_FOUND = CODE_430;
+ public static final int ARTICLE_NOT_WANTED = CODE_435;
+ public static final int TRANSFER_FAILED = CODE_436;
+ public static final int ARTICLE_REJECTED = CODE_437;
+ public static final int POSTING_NOT_ALLOWED = CODE_440;
+ public static final int POSTING_FAILED = CODE_441;
+ public static final int AUTHENTICATION_REJECTED = CODE_482;
+ public static final int COMMAND_NOT_RECOGNIZED = CODE_500;
+ public static final int COMMAND_SYNTAX_ERROR = CODE_501;
+ public static final int PERMISSION_DENIED = CODE_502;
+ public static final int PROGRAM_FAULT = CODE_503;
+
+ // Cannot be instantiated
+
+ private NNTPReply()
+ {}
+
+ /***
+ * Determine if a reply code is an informational response. All
+ * codes beginning with a 1 are positive informational responses.
+ * Informational responses are used to provide human readable
+ * information such as help text.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is an informational response, false
+ * if not.
+ ***/
+ public static boolean isInformational(int reply)
+ {
+ return (reply >= 100 && reply < 200);
+ }
+
+ /***
+ * Determine if a reply code is a positive completion response. All
+ * codes beginning with a 2 are positive completion responses.
+ * The NNTP server will send a positive completion response on the final
+ * successful completion of a command.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive completion response, false
+ * if not.
+ ***/
+ public static boolean isPositiveCompletion(int reply)
+ {
+ return (reply >= 200 && reply < 300);
+ }
+
+ /***
+ * Determine if a reply code is a positive intermediate response. All
+ * codes beginning with a 3 are positive intermediate responses.
+ * The NNTP server will send a positive intermediate response on the
+ * successful completion of one part of a multi-part command or
+ * sequence of commands. For example, after a successful POST command,
+ * a positive intermediate response will be sent to indicate that the
+ * server is ready to receive the article to be posted.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive intermediate response, false
+ * if not.
+ ***/
+ public static boolean isPositiveIntermediate(int reply)
+ {
+ return (reply >= 300 && reply < 400);
+ }
+
+ /***
+ * Determine if a reply code is a negative transient response. All
+ * codes beginning with a 4 are negative transient responses.
+ * The NNTP server will send a negative transient response on the
+ * failure of a correctly formatted command that could not be performed
+ * for some reason. For example, retrieving an article that does not
+ * exist will result in a negative transient response.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a negative transient response, false
+ * if not.
+ ***/
+ public static boolean isNegativeTransient(int reply)
+ {
+ return (reply >= 400 && reply < 500);
+ }
+
+ /***
+ * Determine if a reply code is a negative permanent response. All
+ * codes beginning with a 5 are negative permanent responses.
+ * The NNTP server will send a negative permanent response when
+ * it does not implement a command, a command is incorrectly formatted,
+ * or a serious program error occurs.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a negative permanent response, false
+ * if not.
+ ***/
+ public static boolean isNegativePermanent(int reply)
+ {
+ return (reply >= 500 && reply < 600);
+ }
+
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/org/apache/commons/net/nntp/NewGroupsOrNewsQuery.java b/org/apache/commons/net/nntp/NewGroupsOrNewsQuery.java
new file mode 100644
index 0000000..a0d9aeb
--- /dev/null
+++ b/org/apache/commons/net/nntp/NewGroupsOrNewsQuery.java
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.nntp;
+
+import java.util.Calendar;
+
+/***
+ * The NewGroupsOrNewsQuery class. This is used to issue NNTP NEWGROUPS and
+ * NEWNEWS queries, implemented by
+ * {@link org.apache.commons.net.nntp.NNTPClient#listNewNewsgroups listNewNewsGroups }
+ * and
+ * {@link org.apache.commons.net.nntp.NNTPClient#listNewNews listNewNews }
+ * respectively. It prevents you from having to format
+ * date, time, distribution, and newgroup arguments.
+ *
+ * You might use the class as follows:
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see NNTPClient
+ ***/
+
+public final class NewGroupsOrNewsQuery
+{
+ private String __date, __time;
+ private StringBuffer __distributions;
+ private StringBuffer __newsgroups;
+ private boolean __isGMT;
+
+
+ /***
+ * Creates a new query using the given time as a reference point.
+ *
+ * @param date The date since which new groups or news have arrived.
+ * @param gmt True if the date should be considered as GMT, false if not.
+ ***/
+ public NewGroupsOrNewsQuery(Calendar date, boolean gmt)
+ {
+ int num;
+ String str;
+ StringBuffer buffer;
+
+ __distributions = null;
+ __newsgroups = null;
+ __isGMT = gmt;
+
+ buffer = new StringBuffer();
+
+ // Get year
+ num = date.get(Calendar.YEAR);
+ str = Integer.toString(num);
+ num = str.length();
+
+ if (num >= 2)
+ buffer.append(str.substring(num - 2));
+ else
+ buffer.append("00");
+
+ // Get month
+ num = date.get(Calendar.MONTH) + 1;
+ str = Integer.toString(num);
+ num = str.length();
+
+ if (num == 1)
+ {
+ buffer.append('0');
+ buffer.append(str);
+ }
+ else if (num == 2)
+ buffer.append(str);
+ else
+ buffer.append("01");
+
+ // Get day
+ num = date.get(Calendar.DAY_OF_MONTH);
+ str = Integer.toString(num);
+ num = str.length();
+
+ if (num == 1)
+ {
+ buffer.append('0');
+ buffer.append(str);
+ }
+ else if (num == 2)
+ buffer.append(str);
+ else
+ buffer.append("01");
+
+ __date = buffer.toString();
+
+ buffer.setLength(0);
+
+ // Get hour
+ num = date.get(Calendar.HOUR_OF_DAY);
+ str = Integer.toString(num);
+ num = str.length();
+
+ if (num == 1)
+ {
+ buffer.append('0');
+ buffer.append(str);
+ }
+ else if (num == 2)
+ buffer.append(str);
+ else
+ buffer.append("00");
+
+ // Get minutes
+ num = date.get(Calendar.MINUTE);
+ str = Integer.toString(num);
+ num = str.length();
+
+ if (num == 1)
+ {
+ buffer.append('0');
+ buffer.append(str);
+ }
+ else if (num == 2)
+ buffer.append(str);
+ else
+ buffer.append("00");
+
+
+ // Get seconds
+ num = date.get(Calendar.SECOND);
+ str = Integer.toString(num);
+ num = str.length();
+
+ if (num == 1)
+ {
+ buffer.append('0');
+ buffer.append(str);
+ }
+ else if (num == 2)
+ buffer.append(str);
+ else
+ buffer.append("00");
+
+ __time = buffer.toString();
+ }
+
+
+ /***
+ * Add a newsgroup to the list of newsgroups being queried. Newsgroups
+ * added this way are only meaningful to the NEWNEWS command. Newsgroup
+ * names may include the
+ * @param newsgroup The newsgroup to add to the list of groups to be
+ * checked for new news.
+ ***/
+ public void addNewsgroup(String newsgroup)
+ {
+ if (__newsgroups != null)
+ __newsgroups.append(',');
+ else
+ __newsgroups = new StringBuffer();
+ __newsgroups.append(newsgroup);
+ }
+
+
+ /***
+ * Add a newsgroup to the list of newsgroups being queried, but indicate
+ * that group should not be checked for new news. Newsgroups
+ * added this way are only meaningful to the NEWNEWS command.
+ * Newsgroup names may include the
+ * The following would create a query that searched for new news in
+ * all comp.lang.java newsgroups except for comp.lang.java.advocacy.
+ *
+ * @param newsgroup The newsgroup to add to the list of groups to be
+ * checked for new news, but which should be omitted from
+ * the search for new news..
+ ***/
+ public void omitNewsgroup(String newsgroup)
+ {
+ addNewsgroup("!" + newsgroup);
+ }
+
+
+ /***
+ * Add a distribution group to the query. The distribution part of a
+ * newsgroup is the segment of the name preceding the first dot (e.g.,
+ * comp, alt, rec). Only those newsgroups matching one of the
+ * distributions or, in the case of NEWNEWS, an article in a newsgroup
+ * matching one of the distributions, will be reported as a query result.
+ * Adding distributions is purely optional.
+ *
+ * @param distribution A distribution to add to the query.
+ ***/
+ public void addDistribution(String distribution)
+ {
+ if (__distributions != null)
+ __distributions.append(',');
+ else
+ __distributions = new StringBuffer();
+ __distributions.append(distribution);
+ }
+
+ /***
+ * Return the NNTP query formatted date (year, month, day in the form
+ * YYMMDD.
+ *
+ * @return The NNTP query formatted date.
+ ***/
+ public String getDate()
+ {
+ return __date;
+ }
+
+ /***
+ * Return the NNTP query formatted time (hour, minutes, seconds in the form
+ * HHMMSS.
+ *
+ * @return The NNTP query formatted time.
+ ***/
+ public String getTime()
+ {
+ return __time;
+ }
+
+ /***
+ * Return whether or not the query date should be treated as GMT.
+ *
+ * @return True if the query date is to be treated as GMT, false if not.
+ ***/
+ public boolean isGMT()
+ {
+ return __isGMT;
+ }
+
+ /***
+ * Return the comma separated list of distributions. This may be null
+ * if there are no distributions.
+ *
+ * @return The list of distributions, which may be null if no distributions
+ * have been specified.
+ ***/
+ public String getDistributions()
+ {
+ return (__distributions == null ? null : __distributions.toString());
+ }
+
+ /***
+ * Return the comma separated list of newsgroups. This may be null
+ * if there are no newsgroups
+ *
+ * @return The list of newsgroups, which may be null if no newsgroups
+ * have been specified.
+ ***/
+ public String getNewsgroups()
+ {
+ return (__newsgroups == null ? null : __newsgroups.toString());
+ }
+}
diff --git a/org/apache/commons/net/nntp/NewsgroupInfo.java b/org/apache/commons/net/nntp/NewsgroupInfo.java
new file mode 100644
index 0000000..aa48d16
--- /dev/null
+++ b/org/apache/commons/net/nntp/NewsgroupInfo.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.nntp;
+
+/***
+ * NewsgroupInfo stores information pertaining to a newsgroup returned by
+ * the NNTP GROUP, LIST, and NEWGROUPS commands, implemented by
+ * {@link org.apache.commons.net.nntp.NNTPClient#selectNewsgroup selectNewsgroup }
+ * ,
+ * {@link org.apache.commons.net.nntp.NNTPClient#listNewsgroups listNewsgroups }
+ * , and
+ * {@link org.apache.commons.net.nntp.NNTPClient#listNewNewsgroups listNewNewsgroups }
+ * respectively.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see NNTPClient
+ ***/
+
+public final class NewsgroupInfo
+{
+ /***
+ * A constant indicating that the posting permission of a newsgroup is
+ * unknown. For example, the NNTP GROUP command does not return posting
+ * information, so NewsgroupInfo instances obtained from that command
+ * willhave an UNKNOWN_POSTING_PERMISSION.
+ ***/
+ public static final int UNKNOWN_POSTING_PERMISSION = 0;
+
+ /*** A constant indicating that a newsgroup is moderated. ***/
+ public static final int MODERATED_POSTING_PERMISSION = 1;
+
+ /*** A constant indicating that a newsgroup is public and unmoderated. ***/
+ public static final int PERMITTED_POSTING_PERMISSION = 2;
+
+ /***
+ * A constant indicating that a newsgroup is closed for general posting.
+ ***/
+ public static final int PROHIBITED_POSTING_PERMISSION = 3;
+
+ private String __newsgroup;
+ private int __estimatedArticleCount;
+ private int __firstArticle, __lastArticle;
+ private int __postingPermission;
+
+ void _setNewsgroup(String newsgroup)
+ {
+ __newsgroup = newsgroup;
+ }
+
+ void _setArticleCount(int count)
+ {
+ __estimatedArticleCount = count;
+ }
+
+ void _setFirstArticle(int first)
+ {
+ __firstArticle = first;
+ }
+
+ void _setLastArticle(int last)
+ {
+ __lastArticle = last;
+ }
+
+ void _setPostingPermission(int permission)
+ {
+ __postingPermission = permission;
+ }
+
+ /***
+ * Get the newsgroup name.
+ *
+ * @return The name of the newsgroup.
+ ***/
+ public String getNewsgroup()
+ {
+ return __newsgroup;
+ }
+
+ /***
+ * Get the estimated number of articles in the newsgroup. The
+ * accuracy of this value will depend on the server implementation.
+ *
+ * @return The estimated number of articles in the newsgroup.
+ ***/
+ public int getArticleCount()
+ {
+ return __estimatedArticleCount;
+ }
+
+ /***
+ * Get the number of the first article in the newsgroup.
+ *
+ * @return The number of the first article in the newsgroup.
+ ***/
+ public int getFirstArticle()
+ {
+ return __firstArticle;
+ }
+
+ /***
+ * Get the number of the last article in the newsgroup.
+ *
+ * @return The number of the last article in the newsgroup.
+ ***/
+ public int getLastArticle()
+ {
+ return __lastArticle;
+ }
+
+ /***
+ * Get the posting permission of the newsgroup. This will be one of
+ * the
+ * @return The posting permission status of the newsgroup.
+ ***/
+ public int getPostingPermission()
+ {
+ return __postingPermission;
+ }
+
+ /*
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(__newsgroup);
+ buffer.append(' ');
+ buffer.append(__lastArticle);
+ buffer.append(' ');
+ buffer.append(__firstArticle);
+ buffer.append(' ');
+ switch(__postingPermission) {
+ case 1: buffer.append('m'); break;
+ case 2: buffer.append('y'); break;
+ case 3: buffer.append('n'); break;
+ }
+ return buffer.toString();
+}
+ */
+}
diff --git a/org/apache/commons/net/nntp/SimpleNNTPHeader.java b/org/apache/commons/net/nntp/SimpleNNTPHeader.java
new file mode 100644
index 0000000..d18a8cf
--- /dev/null
+++ b/org/apache/commons/net/nntp/SimpleNNTPHeader.java
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.nntp;
+
+/***
+ * This class is used to construct the bare minimum
+ * acceptable header for most news readers. To construct more
+ * complicated headers you should refer to RFC 822. When the
+ * Java Mail API is finalized, you will be
+ * able to use it to compose fully compliant Internet text messages.
+ *
+ * The main purpose of the class is to faciliatate the article posting
+ * process, by relieving the programmer from having to explicitly format
+ * an article header. For example:
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see NNTPClient
+ ***/
+
+public class SimpleNNTPHeader
+{
+ private String __subject, __from;
+ private StringBuilder __newsgroups;
+ private StringBuilder __headerFields;
+ private int __newsgroupCount;
+
+ /***
+ * Creates a new SimpleNNTPHeader instance initialized with the given
+ * from and subject header field values.
+ *
+ * @param from The value of the
+ * @param newsgroup The newsgroup to add to the article's newsgroup
+ * distribution list.
+ ***/
+ public void addNewsgroup(String newsgroup)
+ {
+ if (__newsgroupCount++ > 0)
+ __newsgroups.append(',');
+ __newsgroups.append(newsgroup);
+ }
+
+ /***
+ * Adds an arbitrary header field with the given value to the article
+ * header. These headers will be written after the From, Newsgroups,
+ * and Subject fields when the SimpleNNTPHeader is convertered to a string.
+ * An example use would be:
+ *
+ * @param headerField The header field to add, not including the colon.
+ * @param value The value of the added header field.
+ ***/
+ public void addHeaderField(String headerField, String value)
+ {
+ __headerFields.append(headerField);
+ __headerFields.append(": ");
+ __headerFields.append(value);
+ __headerFields.append('\n');
+ }
+
+
+ /***
+ * Returns the address used in the
+ * @return The from address.
+ ***/
+ public String getFromAddress()
+ {
+ return __from;
+ }
+
+ /***
+ * Returns the subject used in the
+ * @return The subject.
+ ***/
+ public String getSubject()
+ {
+ return __subject;
+ }
+
+ /***
+ * Returns the contents of the
+ * @return The comma-separated list of newsgroups to which the article
+ * is being posted.
+ ***/
+ public String getNewsgroups()
+ {
+ return __newsgroups.toString();
+ }
+
+ /***
+ * Converts the SimpleNNTPHeader to a properly formatted header in
+ * the form of a String, including the blank line used to separate
+ * the header from the article body.
+ *
+ * @return The article header in the form of a String.
+ ***/
+ @Override
+ public String toString()
+ {
+ StringBuffer header = new StringBuffer();
+
+ header.append("From: ");
+ header.append(__from);
+ header.append("\nNewsgroups: ");
+ header.append(__newsgroups.toString());
+ header.append("\nSubject: ");
+ header.append(__subject);
+ header.append('\n');
+ if (__headerFields.length() > 0)
+ header.append(__headerFields.toString());
+ header.append('\n');
+
+ return header.toString();
+ }
+}
diff --git a/org/apache/commons/net/nntp/Threadable.java b/org/apache/commons/net/nntp/Threadable.java
new file mode 100644
index 0000000..518a9a4
--- /dev/null
+++ b/org/apache/commons/net/nntp/Threadable.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.nntp;
+
+/**
+ * A placeholder interface for threadable message objects
+ * Author: Rory Winston
+ * @param host The address of the server.
+ * @param port The port of the service.
+ * @return The time value retrieved from the server.
+ * @exception IOException If an error occurs while retrieving the time.
+ ***/
+ public TimeInfo getTime(InetAddress host, int port) throws IOException
+ {
+ // if not connected then open to next available UDP port
+ if (!isOpen())
+ {
+ open();
+ }
+
+ NtpV3Packet message = new NtpV3Impl();
+ message.setMode(NtpV3Packet.MODE_CLIENT);
+ message.setVersion(_version);
+ DatagramPacket sendPacket = message.getDatagramPacket();
+ sendPacket.setAddress(host);
+ sendPacket.setPort(port);
+
+ NtpV3Packet recMessage = new NtpV3Impl();
+ DatagramPacket receivePacket = recMessage.getDatagramPacket();
+
+ /*
+ * Must minimize the time between getting the current time,
+ * timestamping the packet, and sending it out which
+ * introduces an error in the delay time.
+ * No extraneous logging and initializations here !!!
+ */
+ TimeStamp now = TimeStamp.getCurrentTime();
+
+ // Note that if you do not set the transmit time field then originating time
+ // in server response is all 0's which is "Thu Feb 07 01:28:16 EST 2036".
+ message.setTransmitTime(now);
+
+ _socket_.send(sendPacket);
+ _socket_.receive(receivePacket);
+
+ long returnTime = System.currentTimeMillis();
+ // create TimeInfo message container but don't pre-compute the details yet
+ TimeInfo info = new TimeInfo(recMessage, returnTime, false);
+
+ return info;
+ }
+
+ /***
+ * Retrieves the time information from the specified server on the
+ * default NTP port and returns it. The time is the number of miliiseconds
+ * since 00:00 (midnight) 1 January 1900 UTC, as specified by RFC 1305.
+ * This method reads the raw NTP packet and constructs a TimeInfo
+ * object that allows access to all the fields of the NTP message header.
+ *
+ * @param host The address of the server.
+ * @return The time value retrieved from the server.
+ * @exception IOException If an error occurs while retrieving the time.
+ ***/
+ public TimeInfo getTime(InetAddress host) throws IOException
+ {
+ return getTime(host, NtpV3Packet.NTP_PORT);
+ }
+
+ /***
+ * Returns the NTP protocol version number that client sets on request packet
+ * that is sent to remote host (e.g. 3=NTP v3, 4=NTP v4, etc.)
+ *
+ * @return the NTP protocol version number that client sets on request packet.
+ * @see #setVersion(int)
+ ***/
+ public int getVersion()
+ {
+ return _version;
+ }
+
+ /***
+ * Sets the NTP protocol version number that client sets on request packet
+ * communicate with remote host.
+ *
+ * @param version the NTP protocol version number
+ ***/
+ public void setVersion(int version)
+ {
+ _version = version;
+ }
+
+}
diff --git a/org/apache/commons/net/ntp/NtpUtils.java b/org/apache/commons/net/ntp/NtpUtils.java
new file mode 100644
index 0000000..ca1fb41
--- /dev/null
+++ b/org/apache/commons/net/ntp/NtpUtils.java
@@ -0,0 +1,113 @@
+package org.apache.commons.net.ntp;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/***
+ * Common NtpUtils Helper class.
+ *
+ * @author Jason Mathews, MITRE Corp
+ *
+ * @version $Revision: 489397 $ $Date: 2006-12-21 16:28:51 +0000 (Thu, 21 Dec 2006) $
+ */
+public final class NtpUtils {
+
+ /***
+ * Returns 32-bit integer address to IPv4 address string "%d.%d.%d.%d" format.
+ *
+ * @param address the 32-bit address
+ * @return the raw IP address in a string format.
+ */
+ public static String getHostAddress(int address)
+ {
+ return ((address >>> 24) & 0xFF) + "." +
+ ((address >>> 16) & 0xFF) + "." +
+ ((address >>> 8) & 0xFF) + "." +
+ ((address >>> 0) & 0xFF);
+ }
+
+ /***
+ * Returns NTP packet reference identifier as IP address.
+ *
+ * @param packet NTP packet
+ * @return the packet reference id (as IP address) in "%d.%d.%d.%d" format.
+ */
+ public static String getRefAddress(NtpV3Packet packet)
+ {
+ int address = (packet == null) ? 0 : packet.getReferenceId();
+ return getHostAddress(address);
+ }
+
+ /***
+ * Get refId as reference clock string (e.g. GPS, WWV, LCL). If string is
+ * invalid (non-ASCII character) then returns empty string "".
+ * For details refer to the Comprehensive
+ * List of Clock Drivers.
+ *
+ * @param message
+ * @return reference clock string if primary NTP server
+ */
+ public static String getReferenceClock(NtpV3Packet message) {
+ if (message == null)
+ return "";
+ int refId = message.getReferenceId();
+ if (refId == 0)
+ return "";
+ StringBuffer buf = new StringBuffer(4);
+ // start at highest-order byte (0x4c434c00 -> LCL)
+ for (int shiftBits = 24; shiftBits >= 0; shiftBits -= 8)
+ {
+ char c = (char) ((refId >>> shiftBits) & 0xff);
+ if (c == 0) break; // 0-terminated ASCII string
+ if (!Character.isLetterOrDigit(c))
+ return "";
+ buf.append(c);
+ }
+ return buf.toString();
+ }
+
+ /***
+ * Return human-readable name of message mode type (RFC 1305).
+ *
+ * @param mode
+ * @return mode name
+ */
+ public static String getModeName(int mode)
+ {
+ switch (mode) {
+ case NtpV3Packet.MODE_RESERVED:
+ return "Reserved";
+ case NtpV3Packet.MODE_SYMMETRIC_ACTIVE:
+ return "Symmetric Active";
+ case NtpV3Packet.MODE_SYMMETRIC_PASSIVE:
+ return "Symmetric Passive";
+ case NtpV3Packet.MODE_CLIENT:
+ return "Client";
+ case NtpV3Packet.MODE_SERVER:
+ return "Server";
+ case NtpV3Packet.MODE_BROADCAST:
+ return "Broadcast";
+ case NtpV3Packet.MODE_CONTROL_MESSAGE:
+ return "Control";
+ case NtpV3Packet.MODE_PRIVATE:
+ return "Private";
+ default:
+ return "Unknown";
+ }
+ }
+
+}
diff --git a/org/apache/commons/net/ntp/NtpV3Impl.java b/org/apache/commons/net/ntp/NtpV3Impl.java
new file mode 100644
index 0000000..4a8569a
--- /dev/null
+++ b/org/apache/commons/net/ntp/NtpV3Impl.java
@@ -0,0 +1,583 @@
+package org.apache.commons.net.ntp;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.net.DatagramPacket;
+
+/***
+ * Implementation of NtpV3Packet with methods converting Java objects to/from
+ * the Network Time Protocol (NTP) data message header format described in RFC-1305.
+ *
+ * @author Naz Irizarry, MITRE Corp
+ * @author Jason Mathews, MITRE Corp
+ *
+ * @version $Revision: 658518 $ $Date: 2008-05-21 02:04:30 +0100 (Wed, 21 May 2008) $
+ */
+public class NtpV3Impl implements NtpV3Packet
+{
+
+ private static final int MODE_INDEX = 0;
+ private static final int MODE_SHIFT = 0;
+
+ private static final int VERSION_INDEX = 0;
+ private static final int VERSION_SHIFT = 3;
+
+ private static final int LI_INDEX = 0;
+ private static final int LI_SHIFT = 6;
+
+ private static final int STRATUM_INDEX = 1;
+ private static final int POLL_INDEX = 2;
+ private static final int PRECISION_INDEX = 3;
+
+ private static final int ROOT_DELAY_INDEX = 4;
+ private static final int ROOT_DISPERSION_INDEX = 8;
+ private static final int REFERENCE_ID_INDEX = 12;
+
+ private static final int REFERENCE_TIMESTAMP_INDEX = 16;
+ private static final int ORIGINATE_TIMESTAMP_INDEX = 24;
+ private static final int RECEIVE_TIMESTAMP_INDEX = 32;
+ private static final int TRANSMIT_TIMESTAMP_INDEX = 40;
+
+ private static final int KEY_IDENTIFIER_INDEX = 48;
+ private static final int MESSAGE_DIGEST = 54; /* len 16 bytes */
+
+ private byte[] buf = new byte[48];
+
+ private volatile DatagramPacket dp;
+
+ /** Creates a new instance of NtpV3Impl */
+ public NtpV3Impl()
+ {
+ }
+
+ /***
+ * Returns mode as defined in RFC-1305 which is a 3-bit integer
+ * whose value is indicated by the MODE_xxx parameters.
+ *
+ * @return mode as defined in RFC-1305.
+ */
+ public int getMode()
+ {
+ return (ui(buf[MODE_INDEX]) >> MODE_SHIFT) & 0x7;
+ }
+
+ /***
+ * Return human-readable name of message mode type as described in
+ * RFC 1305.
+ * @return mode name as string.
+ */
+ public String getModeName()
+ {
+ return NtpUtils.getModeName(getMode());
+ }
+
+ /***
+ * Set mode as defined in RFC-1305.
+ * @param mode
+ */
+ public void setMode(int mode)
+ {
+ buf[MODE_INDEX] = (byte) (buf[MODE_INDEX] & 0xF8 | mode & 0x7);
+ }
+
+ /***
+ * Returns leap indicator as defined in RFC-1305 which is a two-bit code:
+ * 0=no warning
+ * 1=last minute has 61 seconds
+ * 2=last minute has 59 seconds
+ * 3=alarm condition (clock not synchronized)
+ *
+ * @return leap indicator as defined in RFC-1305.
+ */
+ public int getLeapIndicator()
+ {
+ return (ui(buf[LI_INDEX]) >> LI_SHIFT) & 0x3;
+ }
+
+ /***
+ * Set leap indicator as defined in RFC-1305.
+ * @param li leap indicator.
+ */
+ public void setLeapIndicator(int li)
+ {
+ buf[LI_INDEX] = (byte) (buf[LI_INDEX] & 0x3F | ((li & 0x3) << LI_SHIFT));
+ }
+
+ /***
+ * Returns poll interval as defined in RFC-1305, which is an eight-bit
+ * signed integer indicating the maximum interval between successive
+ * messages, in seconds to the nearest power of two (e.g. value of six
+ * indicates an interval of 64 seconds. The values that can appear in
+ * this field range from NTP_MINPOLL to NTP_MAXPOLL inclusive.
+ *
+ * @return poll interval as defined in RFC-1305.
+ */
+ public int getPoll()
+ {
+ return buf[POLL_INDEX];
+ }
+
+ /***
+ * Set poll interval as defined in RFC-1305.
+ *
+ * @param poll poll interval.
+ */
+ public void setPoll(int poll)
+ {
+ buf[POLL_INDEX] = (byte) (poll & 0xFF);
+ }
+
+ /***
+ * Returns precision as defined in RFC-1305 encoded as an 8-bit signed
+ * integer (seconds to nearest power of two).
+ * Values normally range from -6 to -20.
+ *
+ * @return precision as defined in RFC-1305.
+ */
+ public int getPrecision()
+ {
+ return buf[PRECISION_INDEX];
+ }
+
+ /***
+ * Set precision as defined in RFC-1305.
+ * @param precision
+ */
+ public void setPrecision(int precision)
+ {
+ buf[PRECISION_INDEX] = (byte) (precision & 0xFF);
+ }
+
+ /***
+ * Returns NTP version number as defined in RFC-1305.
+ *
+ * @return NTP version number.
+ */
+ public int getVersion()
+ {
+ return (ui(buf[VERSION_INDEX]) >> VERSION_SHIFT) & 0x7;
+ }
+
+ /***
+ * Set NTP version as defined in RFC-1305.
+ *
+ * @param version NTP version.
+ */
+ public void setVersion(int version)
+ {
+ buf[VERSION_INDEX] = (byte) (buf[VERSION_INDEX] & 0xC7 | ((version & 0x7) << VERSION_SHIFT));
+ }
+
+ /***
+ * Returns Stratum as defined in RFC-1305, which indicates the stratum level
+ * of the local clock, with values defined as follows: 0=unspecified,
+ * 1=primary ref clock, and all others a secondary reference (via NTP).
+ *
+ * @return Stratum level as defined in RFC-1305.
+ */
+ public int getStratum()
+ {
+ return ui(buf[STRATUM_INDEX]);
+ }
+
+ /***
+ * Set stratum level as defined in RFC-1305.
+ *
+ * @param stratum stratum level.
+ */
+ public void setStratum(int stratum)
+ {
+ buf[STRATUM_INDEX] = (byte) (stratum & 0xFF);
+ }
+
+ /***
+ * Return root delay as defined in RFC-1305, which is the total roundtrip delay
+ * to the primary reference source, in seconds. Values can take positive and
+ * negative values, depending on clock precision and skew.
+ *
+ * @return root delay as defined in RFC-1305.
+ */
+ public int getRootDelay()
+ {
+ return getInt(ROOT_DELAY_INDEX);
+ }
+
+ /***
+ * Return root delay as defined in RFC-1305 in milliseconds, which is
+ * the total roundtrip delay to the primary reference source, in
+ * seconds. Values can take positive and negative values, depending
+ * on clock precision and skew.
+ *
+ * @return root delay in milliseconds
+ */
+ public double getRootDelayInMillisDouble()
+ {
+ double l = getRootDelay();
+ return l / 65.536;
+ }
+
+ /***
+ * Returns root dispersion as defined in RFC-1305.
+ * @return root dispersion.
+ */
+ public int getRootDispersion()
+ {
+ return getInt(ROOT_DISPERSION_INDEX);
+ }
+
+ /***
+ * Returns root dispersion (as defined in RFC-1305) in milliseconds.
+ *
+ * @return root dispersion in milliseconds
+ */
+ public long getRootDispersionInMillis()
+ {
+ long l = getRootDispersion();
+ return (l * 1000) / 65536L;
+ }
+
+ /***
+ * Returns root dispersion (as defined in RFC-1305) in milliseconds
+ * as double precision value.
+ *
+ * @return root dispersion in milliseconds
+ */
+ public double getRootDispersionInMillisDouble()
+ {
+ double l = getRootDispersion();
+ return l / 65.536;
+ }
+
+ /***
+ * Set reference clock identifier field with 32-bit unsigned integer value.
+ * See RFC-1305 for description.
+ *
+ * @param refId reference clock identifier.
+ */
+ public void setReferenceId(int refId)
+ {
+ for (int i = 3; i >= 0; i--) {
+ buf[REFERENCE_ID_INDEX + i] = (byte) (refId & 0xff);
+ refId >>>= 8; // shift right one-byte
+ }
+ }
+
+ /***
+ * Returns the reference id as defined in RFC-1305, which is
+ * a 32-bit integer whose value is dependent on several criteria.
+ *
+ * @return the reference id as defined in RFC-1305.
+ */
+ public int getReferenceId()
+ {
+ return getInt(REFERENCE_ID_INDEX);
+ }
+
+ /***
+ * Returns the reference id string. String cannot be null but
+ * value is dependent on the version of the NTP spec supported
+ * and stratum level. Value can be an empty string, clock type string,
+ * IP address, or a hex string.
+ *
+ * @return the reference id string.
+ */
+ public String getReferenceIdString()
+ {
+ int version = getVersion();
+ int stratum = getStratum();
+ if (version == VERSION_3 || version == VERSION_4) {
+ if (stratum == 0 || stratum == 1) {
+ return idAsString(); // 4-character ASCII string (e.g. GPS, USNO)
+ }
+ // in NTPv4 servers this is latest transmit timestamp of ref source
+ if (version == VERSION_4)
+ return idAsHex();
+ }
+
+ // Stratum 2 and higher this is a four-octet IPv4 address
+ // of the primary reference host.
+ if (stratum >= 2) {
+ return idAsIPAddress();
+ }
+ return idAsHex();
+ }
+
+ /***
+ * Returns Reference id as dotted IP address.
+ * @return refId as IP address string.
+ */
+ private String idAsIPAddress()
+ {
+ return ui(buf[REFERENCE_ID_INDEX]) + "." +
+ ui(buf[REFERENCE_ID_INDEX + 1]) + "." +
+ ui(buf[REFERENCE_ID_INDEX + 2]) + "." +
+ ui(buf[REFERENCE_ID_INDEX + 3]);
+ }
+
+ private String idAsString()
+ {
+ StringBuilder id = new StringBuilder();
+ for (int i = 0; i <= 3; i++) {
+ char c = (char) buf[REFERENCE_ID_INDEX + i];
+ if (c == 0) break; // 0-terminated string
+ id.append(c);
+ }
+ return id.toString();
+ }
+
+ private String idAsHex()
+ {
+ return Integer.toHexString(getReferenceId());
+ }
+
+ /***
+ * Returns the transmit timestamp as defined in RFC-1305.
+ *
+ * @return the transmit timestamp as defined in RFC-1305.
+ * Never returns a null object.
+ */
+ public TimeStamp getTransmitTimeStamp()
+ {
+ return getTimestamp(TRANSMIT_TIMESTAMP_INDEX);
+ }
+
+ /***
+ * Set transmit time with NTP timestamp.
+ * If
+ * Methods exist to convert NTP timestamps to and from the equivalent Java date
+ * representation, which is the number of milliseconds since the standard base
+ * time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
+ *
+ * Rather than list it separately for each method, we mention here that
+ * every method communicating with the server and throwing an IOException
+ * can also throw a
+ * {@link org.apache.commons.net.MalformedServerReplyException}
+ * , which is a subclass
+ * of IOException. A MalformedServerReplyException will be thrown when
+ * the reply received from the server deviates enough from the protocol
+ * specification that it cannot be interpreted in a useful manner despite
+ * attempts to be as lenient as possible.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see POP3Client
+ * @see org.apache.commons.net.MalformedServerReplyException
+ ***/
+
+public class POP3 extends SocketClient
+{
+ /*** The default POP3 port. Set to 110 according to RFC 1288. ***/
+ public static final int DEFAULT_PORT = 110;
+ /***
+ * A constant representing the state where the client is not yet connected
+ * to a POP3 server.
+ ***/
+ public static final int DISCONNECTED_STATE = -1;
+ /*** A constant representing the POP3 authorization state. ***/
+ public static final int AUTHORIZATION_STATE = 0;
+ /*** A constant representing the POP3 transaction state. ***/
+ public static final int TRANSACTION_STATE = 1;
+ /*** A constant representing the POP3 update state. ***/
+ public static final int UPDATE_STATE = 2;
+
+ static final String _OK = "+OK";
+ static final String _ERROR = "-ERR";
+
+ // We have to ensure that the protocol communication is in ASCII
+ // but we use ISO-8859-1 just in case 8-bit characters cross
+ // the wire.
+ private static final String __DEFAULT_ENCODING = "ISO-8859-1";
+
+ private int __popState;
+ private BufferedWriter __writer;
+ private StringBuffer __commandBuffer;
+
+ BufferedReader _reader;
+ int _replyCode;
+ String _lastReplyLine;
+ Vector
+ * @param listener The ProtocolCommandListener to add.
+ ***/
+ public void addProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ _commandSupport_.addProtocolCommandListener(listener);
+ }
+
+ /***
+ * Removes a ProtocolCommandListener. Delegates this task to
+ * {@link #_commandSupport_ _commandSupport_ }.
+ *
+ * @param listener The ProtocolCommandListener to remove.
+ ***/
+ public void removeProtocolCommandistener(ProtocolCommandListener listener)
+ {
+ _commandSupport_.removeProtocolCommandListener(listener);
+ }
+
+
+ /***
+ * Sets POP3 client state. This must be one of the
+ *
+ * @param state The new state.
+ ***/
+ public void setState(int state)
+ {
+ __popState = state;
+ }
+
+
+ /***
+ * Returns the current POP3 client state.
+ *
+ * @return The current POP3 client state.
+ ***/
+ public int getState()
+ {
+ return __popState;
+ }
+
+
+ /***
+ * Retrieves the additional lines of a multi-line server reply.
+ ***/
+ public void getAdditionalReply() throws IOException
+ {
+ String line;
+
+ line = _reader.readLine();
+ while (line != null)
+ {
+ _replyLines.addElement(line);
+ if (line.equals("."))
+ break;
+ line = _reader.readLine();
+ }
+ }
+
+
+ /***
+ * Disconnects the client from the server, and sets the state to
+ *
+ * @exception IOException If there is an error in disconnecting.
+ ***/
+ @Override
+ public void disconnect() throws IOException
+ {
+ super.disconnect();
+ _reader = null;
+ __writer = null;
+ _lastReplyLine = null;
+ _replyLines.setSize(0);
+ setState(DISCONNECTED_STATE);
+ }
+
+
+ /***
+ * Sends a command an arguments to the server and returns the reply code.
+ *
+ * @param command The POP3 command to send.
+ * @param args The command arguments.
+ * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
+ ***/
+ public int sendCommand(String command, String args) throws IOException
+ {
+ String message;
+
+ __commandBuffer.setLength(0);
+ __commandBuffer.append(command);
+
+ if (args != null)
+ {
+ __commandBuffer.append(' ');
+ __commandBuffer.append(args);
+ }
+ __commandBuffer.append(SocketClient.NETASCII_EOL);
+
+ __writer.write(message = __commandBuffer.toString());
+ __writer.flush();
+
+ if (_commandSupport_.getListenerCount() > 0)
+ _commandSupport_.fireCommandSent(command, message);
+
+ __getReply();
+ return _replyCode;
+ }
+
+ /***
+ * Sends a command with no arguments to the server and returns the
+ * reply code.
+ *
+ * @param command The POP3 command to send.
+ * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
+ ***/
+ public int sendCommand(String command) throws IOException
+ {
+ return sendCommand(command, null);
+ }
+
+ /***
+ * Sends a command an arguments to the server and returns the reply code.
+ *
+ * @param command The POP3 command to send
+ * (one of the POP3Command constants).
+ * @param args The command arguments.
+ * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
+ ***/
+ public int sendCommand(int command, String args) throws IOException
+ {
+ return sendCommand(POP3Command._commands[command], args);
+ }
+
+ /***
+ * Sends a command with no arguments to the server and returns the
+ * reply code.
+ *
+ * @param command The POP3 command to send
+ * (one of the POP3Command constants).
+ * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
+ ***/
+ public int sendCommand(int command) throws IOException
+ {
+ return sendCommand(POP3Command._commands[command], null);
+ }
+
+
+ /***
+ * Returns an array of lines received as a reply to the last command
+ * sent to the server. The lines have end of lines truncated. If
+ * the reply is a single line, but its format ndicates it should be
+ * a multiline reply, then you must call
+ * {@link #getAdditionalReply getAdditionalReply() } to
+ * fetch the rest of the reply, and then call
+ * @return The last server response.
+ ***/
+ public String[] getReplyStrings()
+ {
+ String[] lines;
+ lines = new String[_replyLines.size()];
+ _replyLines.copyInto(lines);
+ return lines;
+ }
+
+ /***
+ * Returns the reply to the last command sent to the server.
+ * The value is a single string containing all the reply lines including
+ * newlines. If the reply is a single line, but its format ndicates it
+ * should be a multiline reply, then you must call
+ * {@link #getAdditionalReply getAdditionalReply() } to
+ * fetch the rest of the reply, and then call
+ * @return The last server response.
+ ***/
+ public String getReplyString()
+ {
+ Enumeration
+ * Rather than list it separately for each method, we mention here that
+ * every method communicating with the server and throwing an IOException
+ * can also throw a
+ * {@link org.apache.commons.net.MalformedServerReplyException}
+ * , which is a subclass
+ * of IOException. A MalformedServerReplyException will be thrown when
+ * the reply received from the server deviates enough from the protocol
+ * specification that it cannot be interpreted in a useful manner despite
+ * attempts to be as lenient as possible.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see POP3MessageInfo
+ * @see org.apache.commons.net.io.DotTerminatedMessageReader
+ * @see org.apache.commons.net.MalformedServerReplyException
+ ***/
+
+public class POP3Client extends POP3
+{
+
+ private static POP3MessageInfo __parseStatus(String line)
+ {
+ int num, size;
+ StringTokenizer tokenizer;
+
+ tokenizer = new StringTokenizer(line);
+
+ if (!tokenizer.hasMoreElements())
+ return null;
+
+ num = size = 0;
+
+ try
+ {
+ num = Integer.parseInt(tokenizer.nextToken());
+
+ if (!tokenizer.hasMoreElements())
+ return null;
+
+ size = Integer.parseInt(tokenizer.nextToken());
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+
+ return new POP3MessageInfo(num, size);
+ }
+
+ private static POP3MessageInfo __parseUID(String line)
+ {
+ int num;
+ StringTokenizer tokenizer;
+
+ tokenizer = new StringTokenizer(line);
+
+ if (!tokenizer.hasMoreElements())
+ return null;
+
+ num = 0;
+
+ try
+ {
+ num = Integer.parseInt(tokenizer.nextToken());
+
+ if (!tokenizer.hasMoreElements())
+ return null;
+
+ line = tokenizer.nextToken();
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+
+ return new POP3MessageInfo(num, line);
+ }
+
+ /***
+ * Login to the POP3 server with the given username and password. You
+ * must first connect to the server with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * before attempting to login. A login attempt is only valid if
+ * the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#AUTHORIZATION_STATE AUTHORIZATION_STATE }
+ * . After logging in, the client enters the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * .
+ *
+ * @param username The account name being logged in to.
+ * @param password The plain text password of the account.
+ * @return True if the login attempt was successful, false if not.
+ * @exception IOException If a network I/O error occurs in the process of
+ * logging in.
+ ***/
+ public boolean login(String username, String password) throws IOException
+ {
+ if (getState() != AUTHORIZATION_STATE)
+ return false;
+
+ if (sendCommand(POP3Command.USER, username) != POP3Reply.OK)
+ return false;
+
+ if (sendCommand(POP3Command.PASS, password) != POP3Reply.OK)
+ return false;
+
+ setState(TRANSACTION_STATE);
+
+ return true;
+ }
+
+
+ /***
+ * Login to the POP3 server with the given username and authentication
+ * information. Use this method when connecting to a server requiring
+ * authentication using the APOP command. Because the timestamp
+ * produced in the greeting banner varies from server to server, it is
+ * not possible to consistently extract the information. Therefore,
+ * after connecting to the server, you must call
+ * {@link org.apache.commons.net.pop3.POP3#getReplyString getReplyString }
+ * and parse out the timestamp information yourself.
+ *
+ * You must first connect to the server with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * before attempting to login. A login attempt is only valid if
+ * the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#AUTHORIZATION_STATE AUTHORIZATION_STATE }
+ * . After logging in, the client enters the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * . After connecting, you must parse out the
+ * server specific information to use as a timestamp, and pass that
+ * information to this method. The secret is a shared secret known
+ * to you and the server. See RFC 1939 for more details regarding
+ * the APOP command.
+ *
+ * @param username The account name being logged in to.
+ * @param timestamp The timestamp string to combine with the secret.
+ * @param secret The shared secret which produces the MD5 digest when
+ * combined with the timestamp.
+ * @return True if the login attempt was successful, false if not.
+ * @exception IOException If a network I/O error occurs in the process of
+ * logging in.
+ * @exception NoSuchAlgorithmException If the MD5 encryption algorithm
+ * cannot be instantiated by the Java runtime system.
+ ***/
+ public boolean login(String username, String timestamp, String secret)
+ throws IOException, NoSuchAlgorithmException
+ {
+ int i;
+ byte[] digest;
+ StringBuffer buffer, digestBuffer;
+ MessageDigest md5;
+
+ if (getState() != AUTHORIZATION_STATE)
+ return false;
+
+ md5 = MessageDigest.getInstance("MD5");
+ timestamp += secret;
+ digest = md5.digest(timestamp.getBytes());
+ digestBuffer = new StringBuffer(128);
+
+ for (i = 0; i < digest.length; i++)
+ digestBuffer.append(Integer.toHexString(digest[i] & 0xff));
+
+ buffer = new StringBuffer(256);
+ buffer.append(username);
+ buffer.append(' ');
+ buffer.append(digestBuffer.toString());
+
+ if (sendCommand(POP3Command.APOP, buffer.toString()) != POP3Reply.OK)
+ return false;
+
+ setState(TRANSACTION_STATE);
+
+ return true;
+ }
+
+
+ /***
+ * Logout of the POP3 server. To fully disconnect from the server
+ * you must call
+ * {@link org.apache.commons.net.pop3.POP3#disconnect disconnect }.
+ * A logout attempt is valid in any state. If
+ * the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * , it enters the
+ * {@link org.apache.commons.net.pop3.POP3#UPDATE_STATE UPDATE_STATE }
+ * on a successful logout.
+ *
+ * @return True if the logout attempt was successful, false if not.
+ * @exception IOException If a network I/O error occurs in the process
+ * of logging out.
+ ***/
+ public boolean logout() throws IOException
+ {
+ if (getState() == TRANSACTION_STATE)
+ setState(UPDATE_STATE);
+ sendCommand(POP3Command.QUIT);
+ return (_replyCode == POP3Reply.OK);
+ }
+
+
+ /***
+ * Send a NOOP command to the POP3 server. This is useful for keeping
+ * a connection alive since most POP3 servers will timeout after 10
+ * minutes of inactivity. A noop attempt will only succeed if
+ * the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * .
+ *
+ * @return True if the noop attempt was successful, false if not.
+ * @exception IOException If a network I/O error occurs in the process of
+ * sending the NOOP command.
+ ***/
+ public boolean noop() throws IOException
+ {
+ if (getState() == TRANSACTION_STATE)
+ return (sendCommand(POP3Command.NOOP) == POP3Reply.OK);
+ return false;
+ }
+
+
+ /***
+ * Delete a message from the POP3 server. The message is only marked
+ * for deletion by the server. If you decide to unmark the message, you
+ * must issuse a {@link #reset reset } command. Messages marked
+ * for deletion are only deleted by the server on
+ * {@link #logout logout }.
+ * A delete attempt can only succeed if the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * .
+ *
+ * @param messageId The message number to delete.
+ * @return True if the deletion attempt was successful, false if not.
+ * @exception IOException If a network I/O error occurs in the process of
+ * sending the delete command.
+ ***/
+ public boolean deleteMessage(int messageId) throws IOException
+ {
+ if (getState() == TRANSACTION_STATE)
+ return (sendCommand(POP3Command.DELE, Integer.toString(messageId))
+ == POP3Reply.OK);
+ return false;
+ }
+
+
+ /***
+ * Reset the POP3 session. This is useful for undoing any message
+ * deletions that may have been performed. A reset attempt can only
+ * succeed if the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * .
+ *
+ * @return True if the reset attempt was successful, false if not.
+ * @exception IOException If a network I/O error occurs in the process of
+ * sending the reset command.
+ ***/
+ public boolean reset() throws IOException
+ {
+ if (getState() == TRANSACTION_STATE)
+ return (sendCommand(POP3Command.RSET) == POP3Reply.OK);
+ return false;
+ }
+
+ /***
+ * Get the mailbox status. A status attempt can only
+ * succeed if the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * . Returns a POP3MessageInfo instance
+ * containing the number of messages in the mailbox and the total
+ * size of the messages in bytes. Returns null if the status the
+ * attempt fails.
+ *
+ * @return A POP3MessageInfo instance containing the number of
+ * messages in the mailbox and the total size of the messages
+ * in bytes. Returns null if the status the attempt fails.
+ * @exception IOException If a network I/O error occurs in the process of
+ * sending the status command.
+ ***/
+ public POP3MessageInfo status() throws IOException
+ {
+ if (getState() != TRANSACTION_STATE)
+ return null;
+ if (sendCommand(POP3Command.STAT) != POP3Reply.OK)
+ return null;
+ return __parseStatus(_lastReplyLine.substring(3));
+ }
+
+
+ /***
+ * List an individual message. A list attempt can only
+ * succeed if the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * . Returns a POP3MessageInfo instance
+ * containing the number of the listed message and the
+ * size of the message in bytes. Returns null if the list
+ * attempt fails (e.g., if the specified message number does
+ * not exist).
+ *
+ * @param messageId The number of the message list.
+ * @return A POP3MessageInfo instance containing the number of the
+ * listed message and the size of the message in bytes. Returns
+ * null if the list attempt fails.
+ * @exception IOException If a network I/O error occurs in the process of
+ * sending the list command.
+ ***/
+ public POP3MessageInfo listMessage(int messageId) throws IOException
+ {
+ if (getState() != TRANSACTION_STATE)
+ return null;
+ if (sendCommand(POP3Command.LIST, Integer.toString(messageId))
+ != POP3Reply.OK)
+ return null;
+ return __parseStatus(_lastReplyLine.substring(3));
+ }
+
+
+ /***
+ * List all messages. A list attempt can only
+ * succeed if the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * . Returns an array of POP3MessageInfo instances,
+ * each containing the number of a message and its size in bytes.
+ * If there are no messages, this method returns a zero length array.
+ * If the list attempt fails, it returns null.
+ *
+ * @return An array of POP3MessageInfo instances representing all messages
+ * in the order they appear in the mailbox,
+ * each containing the number of a message and its size in bytes.
+ * If there are no messages, this method returns a zero length array.
+ * If the list attempt fails, it returns null.
+ * @exception IOException If a network I/O error occurs in the process of
+ * sending the list command.
+ ***/
+ public POP3MessageInfo[] listMessages() throws IOException
+ {
+ POP3MessageInfo[] messages;
+ Enumeration
+ * @param messageId The number of the message list.
+ * @return A POP3MessageInfo instance containing the number of the
+ * listed message and the unique identifier for that message.
+ * Returns null if the list attempt fails.
+ * @exception IOException If a network I/O error occurs in the process of
+ * sending the list unique identifier command.
+ ***/
+ public POP3MessageInfo listUniqueIdentifier(int messageId)
+ throws IOException
+ {
+ if (getState() != TRANSACTION_STATE)
+ return null;
+ if (sendCommand(POP3Command.UIDL, Integer.toString(messageId))
+ != POP3Reply.OK)
+ return null;
+ return __parseUID(_lastReplyLine.substring(3));
+ }
+
+
+ /***
+ * List the unique identifiers for all messages. A list attempt can only
+ * succeed if the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * . Returns an array of POP3MessageInfo instances,
+ * each containing the number of a message and its unique identifier.
+ * If there are no messages, this method returns a zero length array.
+ * If the list attempt fails, it returns null.
+ *
+ * @return An array of POP3MessageInfo instances representing all messages
+ * in the order they appear in the mailbox,
+ * each containing the number of a message and its unique identifier
+ * If there are no messages, this method returns a zero length array.
+ * If the list attempt fails, it returns null.
+ * @exception IOException If a network I/O error occurs in the process of
+ * sending the list unique identifier command.
+ ***/
+ public POP3MessageInfo[] listUniqueIdentifiers() throws IOException
+ {
+ POP3MessageInfo[] messages;
+ Enumeration
+ * You must not issue any commands to the POP3 server (i.e., call any
+ * other methods) until you finish reading the message from the
+ * returned Reader instance.
+ * The POP3 protocol uses the same stream for issuing commands as it does
+ * for returning results. Therefore the returned Reader actually reads
+ * directly from the POP3 connection. After the end of message has been
+ * reached, new commands can be executed and their replies read. If
+ * you do not follow these requirements, your program will not work
+ * properly.
+ *
+ * @param messageId The number of the message to fetch.
+ * @return A DotTerminatedMessageReader instance
+ * from which the entire message can be read.
+ * Returns null if the retrieval attempt fails (e.g., if the specified
+ * message number does not exist).
+ * @exception IOException If a network I/O error occurs in the process of
+ * sending the retrieve message command.
+ ***/
+ public Reader retrieveMessage(int messageId) throws IOException
+ {
+ if (getState() != TRANSACTION_STATE)
+ return null;
+ if (sendCommand(POP3Command.RETR, Integer.toString(messageId))
+ != POP3Reply.OK)
+ return null;
+
+ return new DotTerminatedMessageReader(_reader);
+ }
+
+
+ /***
+ * Retrieve only the specified top number of lines of a message from the
+ * POP3 server. A retrieve top lines attempt
+ * can only succeed if the client is in the
+ * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
+ * . Returns a DotTerminatedMessageReader instance
+ * from which the specified top number of lines of the message can be
+ * read.
+ * Returns null if the retrieval attempt fails (e.g., if the specified
+ * message number does not exist).
+ *
+ * You must not issue any commands to the POP3 server (i.e., call any
+ * other methods) until you finish reading the message from the returned
+ * Reader instance.
+ * The POP3 protocol uses the same stream for issuing commands as it does
+ * for returning results. Therefore the returned Reader actually reads
+ * directly from the POP3 connection. After the end of message has been
+ * reached, new commands can be executed and their replies read. If
+ * you do not follow these requirements, your program will not work
+ * properly.
+ *
+ * @param messageId The number of the message to fetch.
+ * @param numLines The top number of lines to fetch. This must be >= 0.
+ * @return A DotTerminatedMessageReader instance
+ * from which the specified top number of lines of the message can be
+ * read.
+ * Returns null if the retrieval attempt fails (e.g., if the specified
+ * message number does not exist).
+ * @exception IOException If a network I/O error occurs in the process of
+ * sending the top command.
+ ***/
+ public Reader retrieveMessageTop(int messageId, int numLines)
+ throws IOException
+ {
+ if (numLines < 0 || getState() != TRANSACTION_STATE)
+ return null;
+ if (sendCommand(POP3Command.TOP, Integer.toString(messageId) + " " +
+ Integer.toString(numLines)) != POP3Reply.OK)
+ return null;
+
+ return new DotTerminatedMessageReader(_reader);
+ }
+
+
+}
+
diff --git a/org/apache/commons/net/pop3/POP3Command.java b/org/apache/commons/net/pop3/POP3Command.java
new file mode 100644
index 0000000..0f583bc
--- /dev/null
+++ b/org/apache/commons/net/pop3/POP3Command.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.pop3;
+
+/***
+ * POP3Command stores POP3 command code constants.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class POP3Command
+{
+ /*** Send user name. ***/
+ public static final int USER = 0;
+ /*** Send password. ***/
+ public static final int PASS = 1;
+ /*** Quit session. ***/
+ public static final int QUIT = 2;
+ /*** Get status. ***/
+ public static final int STAT = 3;
+ /*** List message(s). ***/
+ public static final int LIST = 4;
+ /*** Retrieve message(s). ***/
+ public static final int RETR = 5;
+ /*** Delete message(s). ***/
+ public static final int DELE = 6;
+ /*** No operation. Used as a session keepalive. ***/
+ public static final int NOOP = 7;
+ /*** Reset session. ***/
+ public static final int RSET = 8;
+ /*** Authorization. ***/
+ public static final int APOP = 9;
+ /*** Retrieve top number lines from message. ***/
+ public static final int TOP = 10;
+ /*** List unique message identifier(s). ***/
+ public static final int UIDL = 11;
+
+ static final String[] _commands = {
+ "USER", "PASS", "QUIT", "STAT", "LIST", "RETR", "DELE", "NOOP", "RSET",
+ "APOP", "TOP", "UIDL"
+ };
+
+ // Cannot be instantiated.
+ private POP3Command()
+ {}
+
+ /***
+ * Get the POP3 protocol string command corresponding to a command code.
+ *
+ * @return The POP3 protocol string command corresponding to a command code.
+ ***/
+ public static final String getCommand(int command)
+ {
+ return _commands[command];
+ }
+}
diff --git a/org/apache/commons/net/pop3/POP3MessageInfo.java b/org/apache/commons/net/pop3/POP3MessageInfo.java
new file mode 100644
index 0000000..070fd69
--- /dev/null
+++ b/org/apache/commons/net/pop3/POP3MessageInfo.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.pop3;
+
+/***
+ * POP3MessageInfo is used to return information about messages stored on
+ * a POP3 server. Its fields are used to mean slightly different things
+ * depending on the information being returned.
+ *
+ * In response to a status command,
+ * In response to a message listings,
+ * In response to unique identifier listings,
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class POP3MessageInfo
+{
+ public int number;
+ public int size;
+ public String identifier;
+
+ /***
+ * Creates a POP3MessageInfo instance with
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class POP3Reply
+{
+ /*** The reply code indicating success of an operation. ***/
+ public static final int OK = 0;
+
+ /*** The reply code indicating failure of an operation. ***/
+ public static final int ERROR = 1;
+
+ // Cannot be instantiated.
+ private POP3Reply()
+ {}
+}
diff --git a/org/apache/commons/net/smtp/RelayPath.java b/org/apache/commons/net/smtp/RelayPath.java
new file mode 100644
index 0000000..62d1098
--- /dev/null
+++ b/org/apache/commons/net/smtp/RelayPath.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.smtp;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+/***
+ * A class used to represent forward and reverse relay paths. The
+ * SMTP MAIL command requires a reverse relay path while the SMTP RCPT
+ * command requires a forward relay path. See RFC 821 for more details.
+ * In general, you will not have to deal with relay paths.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SMTPClient
+ ***/
+
+public final class RelayPath
+{
+ Vector
+ * @param emailAddress The destination email address.
+ ***/
+ public RelayPath(String emailAddress)
+ {
+ _path = new Vector
+ * @param hostname The host to add to the relay path.
+ ***/
+ public void addRelay(String hostname)
+ {
+ _path.addElement(hostname);
+ }
+
+ /***
+ * Return the properly formatted string representation of the relay path.
+ *
+ * @return The properly formatted string representation of the relay path.
+ ***/
+ @Override
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+ Enumeration
+ * You should keep in mind that the SMTP server may choose to prematurely
+ * close a connection for various reasons. The SMTP class will detect a
+ * premature SMTP server connection closing when it receives a
+ * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE }
+ * response to a command.
+ * When that occurs, the SMTP class method encountering that reply will throw
+ * an {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
+ * .
+ *
+ * Rather than list it separately for each method, we mention here that
+ * every method communicating with the server and throwing an IOException
+ * can also throw a
+ * {@link org.apache.commons.net.MalformedServerReplyException}
+ * , which is a subclass
+ * of IOException. A MalformedServerReplyException will be thrown when
+ * the reply received from the server deviates enough from the protocol
+ * specification that it cannot be interpreted in a useful manner despite
+ * attempts to be as lenient as possible.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SMTPClient
+ * @see SMTPConnectionClosedException
+ * @see org.apache.commons.net.MalformedServerReplyException
+ ***/
+
+public class SMTP extends SocketClient
+{
+ /*** The default SMTP port (25). ***/
+ public static final int DEFAULT_PORT = 25;
+
+ // We have to ensure that the protocol communication is in ASCII
+ // but we use ISO-8859-1 just in case 8-bit characters cross
+ // the wire.
+ private static final String __DEFAULT_ENCODING = "ISO-8859-1";
+
+ /** The encoding to use (user-settable) */
+ private String encoding = __DEFAULT_ENCODING;
+
+ private StringBuffer __commandBuffer;
+
+ BufferedReader _reader;
+ BufferedWriter _writer;
+ int _replyCode;
+ ArrayList
+ * @param listener The ProtocolCommandListener to add.
+ ***/
+ public void addProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ _commandSupport_.addProtocolCommandListener(listener);
+ }
+
+ /***
+ * Removes a ProtocolCommandListener. Delegates this task to
+ * {@link #_commandSupport_ _commandSupport_ }.
+ *
+ * @param listener The ProtocolCommandListener to remove.
+ ***/
+ public void removeProtocolCommandistener(ProtocolCommandListener listener)
+ {
+ _commandSupport_.removeProtocolCommandListener(listener);
+ }
+
+
+ /***
+ * Closes the connection to the SMTP server and sets to null
+ * some internal data so that the memory may be reclaimed by the
+ * garbage collector. The reply text and code information from the
+ * last command is voided so that the memory it used may be reclaimed.
+ *
+ * @exception IOException If an error occurs while disconnecting.
+ ***/
+ @Override
+ public void disconnect() throws IOException
+ {
+ super.disconnect();
+ _reader = null;
+ _writer = null;
+ _replyString = null;
+ _replyLines.clear();
+ _newReplyString = false;
+ }
+
+
+ /***
+ * Sends an SMTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The text representation of the SMTP command to send.
+ * @param args The arguments to the SMTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the SMTP reply code returned by the server
+ * in response to the command.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(String command, String args) throws IOException
+ {
+ return __sendCommand(command, args, true);
+ }
+
+
+ /***
+ * Sends an SMTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The SMTPCommand constant corresponding to the SMTP command
+ * to send.
+ * @param args The arguments to the SMTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the SMTP reply code returned by the server
+ * in response to the command.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(int command, String args) throws IOException
+ {
+ return sendCommand(SMTPCommand._commands[command], args);
+ }
+
+
+ /***
+ * Sends an SMTP command with no arguments to the server, waits for a
+ * reply and returns the numerical response code. After invocation, for
+ * more detailed information, the actual reply text can be accessed by
+ * calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The text representation of the SMTP command to send.
+ * @return The integer value of the SMTP reply code returned by the server
+ * in response to the command.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(String command) throws IOException
+ {
+ return sendCommand(command, null);
+ }
+
+
+ /***
+ * Sends an SMTP command with no arguments to the server, waits for a
+ * reply and returns the numerical response code. After invocation, for
+ * more detailed information, the actual reply text can be accessed by
+ * calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The SMTPCommand constant corresponding to the SMTP command
+ * to send.
+ * @return The integer value of the SMTP reply code returned by the server
+ * in response to the command.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(int command) throws IOException
+ {
+ return sendCommand(command, null);
+ }
+
+
+ /***
+ * Returns the integer value of the reply code of the last SMTP reply.
+ * You will usually only use this method after you connect to the
+ * SMTP server to check that the connection was successful since
+ *
+ * @return The integer value of the reply code of the last SMTP reply.
+ ***/
+ public int getReplyCode()
+ {
+ return _replyCode;
+ }
+
+ /***
+ * Fetches a reply from the SMTP server and returns the integer reply
+ * code. After calling this method, the actual reply text can be accessed
+ * from either calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }. Only use this
+ * method if you are implementing your own SMTP client or if you need to
+ * fetch a secondary response from the SMTP server.
+ *
+ * @return The integer value of the reply code of the fetched SMTP reply.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while receiving the
+ * server reply.
+ ***/
+ public int getReply() throws IOException
+ {
+ __getReply();
+ return _replyCode;
+ }
+
+
+ /***
+ * Returns the lines of text from the last SMTP server response as an array
+ * of strings, one entry per line. The end of line markers of each are
+ * stripped from each line.
+ *
+ * @return The lines of text from the last SMTP response as an array.
+ ***/
+ public String[] getReplyStrings()
+ {
+ String[] lines;
+ lines = new String[_replyLines.size()];
+ _replyLines.addAll(Arrays.asList(lines));
+ return lines;
+ }
+
+ /***
+ * Returns the entire text of the last SMTP server response exactly
+ * as it was received, including all end of line markers in NETASCII
+ * format.
+ *
+ * @return The entire text from the last SMTP response as a String.
+ ***/
+ public String getReplyString()
+ {
+ StringBuilder buffer;
+
+ if (!_newReplyString)
+ return _replyString;
+
+ buffer = new StringBuilder();
+
+ for (String line : _replyLines)
+ {
+ buffer.append(line);
+ buffer.append(SocketClient.NETASCII_EOL);
+ }
+
+ _newReplyString = false;
+
+ return (_replyString = buffer.toString());
+ }
+
+
+ /***
+ * A convenience method to send the SMTP HELO command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param hostname The hostname of the sender.
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int helo(String hostname) throws IOException
+ {
+ return sendCommand(SMTPCommand.HELO, hostname);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP MAIL command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param reversePath The reverese path.
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int mail(String reversePath) throws IOException
+ {
+ return __sendCommand(SMTPCommand.MAIL, reversePath, false);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP RCPT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param forwardPath The forward path.
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rcpt(String forwardPath) throws IOException
+ {
+ return __sendCommand(SMTPCommand.RCPT, forwardPath, false);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP DATA command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int data() throws IOException
+ {
+ return sendCommand(SMTPCommand.DATA);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP SEND command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param reversePath The reverese path.
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int send(String reversePath) throws IOException
+ {
+ return sendCommand(SMTPCommand.SEND, reversePath);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP SOML command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param reversePath The reverese path.
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int soml(String reversePath) throws IOException
+ {
+ return sendCommand(SMTPCommand.SOML, reversePath);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP SAML command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param reversePath The reverese path.
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int saml(String reversePath) throws IOException
+ {
+ return sendCommand(SMTPCommand.SAML, reversePath);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP RSET command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rset() throws IOException
+ {
+ return sendCommand(SMTPCommand.RSET);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP VRFY command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param user The user address to verify.
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int vrfy(String user) throws IOException
+ {
+ return sendCommand(SMTPCommand.VRFY, user);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP VRFY command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param name The name to expand.
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int expn(String name) throws IOException
+ {
+ return sendCommand(SMTPCommand.EXPN, name);
+ }
+
+ /***
+ * A convenience method to send the SMTP HELP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int help() throws IOException
+ {
+ return sendCommand(SMTPCommand.HELP);
+ }
+
+ /***
+ * A convenience method to send the SMTP HELP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param command The command name on which to request help.
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int help(String command) throws IOException
+ {
+ return sendCommand(SMTPCommand.HELP, command);
+ }
+
+ /***
+ * A convenience method to send the SMTP NOOP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int noop() throws IOException
+ {
+ return sendCommand(SMTPCommand.NOOP);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP TURN command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int turn() throws IOException
+ {
+ return sendCommand(SMTPCommand.TURN);
+ }
+
+
+ /***
+ * A convenience method to send the SMTP QUIT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int quit() throws IOException
+ {
+ return sendCommand(SMTPCommand.QUIT);
+ }
+
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/org/apache/commons/net/smtp/SMTPClient.java b/org/apache/commons/net/smtp/SMTPClient.java
new file mode 100644
index 0000000..8b9ed45
--- /dev/null
+++ b/org/apache/commons/net/smtp/SMTPClient.java
@@ -0,0 +1,607 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.smtp;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.net.InetAddress;
+
+import org.apache.commons.net.io.DotTerminatedMessageWriter;
+
+/***
+ * SMTPClient encapsulates all the functionality necessary to send files
+ * through an SMTP server. This class takes care of all
+ * low level details of interacting with an SMTP server and provides
+ * a convenient higher level interface. As with all classes derived
+ * from {@link org.apache.commons.net.SocketClient},
+ * you must first connect to the server with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * before doing anything, and finally
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * after you're completely finished interacting with the server.
+ * Then you need to check the SMTP reply code to see if the connection
+ * was successful. For example:
+ *
+ * Immediately after connecting is the only real time you need to check the
+ * reply code (because connect is of type void). The convention for all the
+ * SMTP command methods in SMTPClient is such that they either return a
+ * boolean value or some other value.
+ * The boolean methods return true on a successful completion reply from
+ * the SMTP server and false on a reply resulting in an error condition or
+ * failure. The methods returning a value other than boolean return a value
+ * containing the higher level data produced by the SMTP command, or null if a
+ * reply resulted in an error condition or failure. If you want to access
+ * the exact SMTP reply code causing a success or failure, you must call
+ * {@link org.apache.commons.net.smtp.SMTP#getReplyCode getReplyCode } after
+ * a success or failure.
+ *
+ * You should keep in mind that the SMTP server may choose to prematurely
+ * close a connection for various reasons. The SMTPClient class will detect a
+ * premature SMTP server connection closing when it receives a
+ * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE }
+ * response to a command.
+ * When that occurs, the method encountering that reply will throw
+ * an {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
+ * .
+ *
+ * Rather than list it separately for each method, we mention here that
+ * every method communicating with the server and throwing an IOException
+ * can also throw a
+ * {@link org.apache.commons.net.MalformedServerReplyException}
+ * , which is a subclass
+ * of IOException. A MalformedServerReplyException will be thrown when
+ * the reply received from the server deviates enough from the protocol
+ * specification that it cannot be interpreted in a useful manner despite
+ * attempts to be as lenient as possible.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SMTP
+ * @see SimpleSMTPHeader
+ * @see RelayPath
+ * @see SMTPConnectionClosedException
+ * @see org.apache.commons.net.MalformedServerReplyException
+ ***/
+
+public class SMTPClient extends SMTP
+{
+
+ /**
+ * Default SMTPClient constructor. Creates a new SMTPClient instance.
+ */
+ public SMTPClient() { }
+
+ /**
+ * Overloaded constructor that takes an encoding specification
+ * @param encoding The encoding to use
+ * @since 2.0
+ */
+ public SMTPClient(String encoding) {
+ super(encoding);
+ }
+
+
+ /***
+ * At least one SMTPClient method ({@link #sendMessageData sendMessageData })
+ * does not complete the entire sequence of SMTP commands to complete a
+ * transaction. These types of commands require some action by the
+ * programmer after the reception of a positive intermediate command.
+ * After the programmer's code completes its actions, it must call this
+ * method to receive the completion reply from the server and verify the
+ * success of the entire transaction.
+ *
+ * For example,
+ *
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean completePendingCommand() throws IOException
+ {
+ return SMTPReply.isPositiveCompletion(getReply());
+ }
+
+
+ /***
+ * Login to the SMTP server by sending the HELO command with the
+ * given hostname as an argument. Before performing any mail commands,
+ * you must first login.
+ *
+ * @param hostname The hostname with which to greet the SMTP server.
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean login(String hostname) throws IOException
+ {
+ return SMTPReply.isPositiveCompletion(helo(hostname));
+ }
+
+
+ /***
+ * Login to the SMTP server by sending the HELO command with the
+ * client hostname as an argument. Before performing any mail commands,
+ * you must first login.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean login() throws IOException
+ {
+ String name;
+ InetAddress host;
+
+ host = getLocalAddress();
+ name = host.getHostName();
+
+ if (name == null)
+ return false;
+
+ return SMTPReply.isPositiveCompletion(helo(name));
+ }
+
+
+ /***
+ * Set the sender of a message using the SMTP MAIL command, specifying
+ * a reverse relay path. The sender must be set first before any
+ * recipients may be specified, otherwise the mail server will reject
+ * your commands.
+ *
+ * @param path The reverse relay path pointing back to the sender.
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean setSender(RelayPath path) throws IOException
+ {
+ return SMTPReply.isPositiveCompletion(mail(path.toString()));
+ }
+
+
+ /***
+ * Set the sender of a message using the SMTP MAIL command, specifying
+ * the sender's email address. The sender must be set first before any
+ * recipients may be specified, otherwise the mail server will reject
+ * your commands.
+ *
+ * @param address The sender's email address.
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean setSender(String address) throws IOException
+ {
+ return SMTPReply.isPositiveCompletion(mail("<" + address + ">"));
+ }
+
+
+ /***
+ * Add a recipient for a message using the SMTP RCPT command, specifying
+ * a forward relay path. The sender must be set first before any
+ * recipients may be specified, otherwise the mail server will reject
+ * your commands.
+ *
+ * @param path The forward relay path pointing to the recipient.
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean addRecipient(RelayPath path) throws IOException
+ {
+ return SMTPReply.isPositiveCompletion(rcpt(path.toString()));
+ }
+
+
+ /***
+ * Add a recipient for a message using the SMTP RCPT command, the
+ * recipient's email address. The sender must be set first before any
+ * recipients may be specified, otherwise the mail server will reject
+ * your commands.
+ *
+ * @param address The recipient's email address.
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean addRecipient(String address) throws IOException
+ {
+ return SMTPReply.isPositiveCompletion(rcpt("<" + address + ">"));
+ }
+
+
+
+ /***
+ * Send the SMTP DATA command in preparation to send an email message.
+ * This method returns a DotTerminatedMessageWriter instance to which
+ * the message can be written. Null is returned if the DATA command
+ * fails.
+ *
+ * You must not issue any commands to the SMTP server (i.e., call any
+ * (other methods) until you finish writing to the returned Writer
+ * instance and close it. The SMTP protocol uses the same stream for
+ * issuing commands as it does for returning results. Therefore the
+ * returned Writer actually writes directly to the SMTP connection.
+ * After you close the writer, you can execute new commands. If you
+ * do not follow these requirements your program will not work properly.
+ *
+ * You can use the provided
+ * {@link org.apache.commons.net.smtp.SimpleSMTPHeader}
+ * class to construct a bare minimum header.
+ * To construct more complicated headers you should
+ * refer to RFC 822. When the Java Mail API is finalized, you will be
+ * able to use it to compose fully compliant Internet text messages.
+ * The DotTerminatedMessageWriter takes care of doubling line-leading
+ * dots and ending the message with a single dot upon closing, so all
+ * you have to worry about is writing the header and the message.
+ *
+ * Upon closing the returned Writer, you need to call
+ * {@link #completePendingCommand completePendingCommand() }
+ * to finalize the transaction and verify its success or failure from
+ * the server reply.
+ *
+ * @return A DotTerminatedMessageWriter to which the message (including
+ * header) can be written. Returns null if the command fails.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public Writer sendMessageData() throws IOException
+ {
+ if (!SMTPReply.isPositiveIntermediate(data()))
+ return null;
+
+ return new DotTerminatedMessageWriter(_writer);
+ }
+
+
+ /***
+ * A convenience method for sending short messages. This method fetches
+ * the Writer returned by {@link #sendMessageData sendMessageData() }
+ * and writes the specified String to it. After writing the message,
+ * this method calls {@link #completePendingCommand completePendingCommand() }
+ * to finalize the transaction and returns
+ * its success or failure.
+ *
+ * @param message The short email message to send.
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean sendShortMessageData(String message) throws IOException
+ {
+ Writer writer;
+
+ writer = sendMessageData();
+
+ if (writer == null)
+ return false;
+
+ writer.write(message);
+ writer.close();
+
+ return completePendingCommand();
+ }
+
+
+ /***
+ * A convenience method for a sending short email without having to
+ * explicitly set the sender and recipient(s). This method
+ * sets the sender and recipient using
+ * {@link #setSender setSender } and
+ * {@link #addRecipient addRecipient }, and then sends the
+ * message using {@link #sendShortMessageData sendShortMessageData }.
+ *
+ * @param sender The email address of the sender.
+ * @param recipient The email address of the recipient.
+ * @param message The short email message to send.
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean sendSimpleMessage(String sender, String recipient,
+ String message)
+ throws IOException
+ {
+ if (!setSender(sender))
+ return false;
+
+ if (!addRecipient(recipient))
+ return false;
+
+ return sendShortMessageData(message);
+ }
+
+
+
+ /***
+ * A convenience method for a sending short email without having to
+ * explicitly set the sender and recipient(s). This method
+ * sets the sender and recipients using
+ * {@link #setSender setSender } and
+ * {@link #addRecipient addRecipient }, and then sends the
+ * message using {@link #sendShortMessageData sendShortMessageData }.
+ *
+ * @param sender The email address of the sender.
+ * @param recipients An array of recipient email addresses.
+ * @param message The short email message to send.
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean sendSimpleMessage(String sender, String[] recipients,
+ String message)
+ throws IOException
+ {
+ boolean oneSuccess = false;
+ int count;
+
+ if (!setSender(sender))
+ return false;
+
+ for (count = 0; count < recipients.length; count++)
+ {
+ if (addRecipient(recipients[count]))
+ oneSuccess = true;
+ }
+
+ if (!oneSuccess)
+ return false;
+
+ return sendShortMessageData(message);
+ }
+
+
+ /***
+ * Logout of the SMTP server by sending the QUIT command.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean logout() throws IOException
+ {
+ return SMTPReply.isPositiveCompletion(quit());
+ }
+
+
+
+ /***
+ * Aborts the current mail transaction, resetting all server stored
+ * sender, recipient, and mail data, cleaing all buffers and tables.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean reset() throws IOException
+ {
+ return SMTPReply.isPositiveCompletion(rset());
+ }
+
+
+ /***
+ * Verify that a username or email address is valid, i.e., that mail
+ * can be delivered to that mailbox on the server.
+ *
+ * @param username The username or email address to validate.
+ * @return True if the username is valid, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean verify(String username) throws IOException
+ {
+ int result;
+
+ result = vrfy(username);
+
+ return (result == SMTPReply.ACTION_OK ||
+ result == SMTPReply.USER_NOT_LOCAL_WILL_FORWARD);
+ }
+
+
+ /***
+ * Fetches the system help information from the server and returns the
+ * full string.
+ *
+ * @return The system help string obtained from the server. null if the
+ * information could not be obtained.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String listHelp() throws IOException
+ {
+ if (SMTPReply.isPositiveCompletion(help()))
+ return getReplyString();
+ return null;
+ }
+
+
+ /***
+ * Fetches the help information for a given command from the server and
+ * returns the full string.
+ *
+ * @param command The command on which to ask for help.
+ * @return The command help string obtained from the server. null if the
+ * information could not be obtained.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String listHelp(String command) throws IOException
+ {
+ if (SMTPReply.isPositiveCompletion(help(command)))
+ return getReplyString();
+ return null;
+ }
+
+
+ /***
+ * Sends a NOOP command to the SMTP server. This is useful for preventing
+ * server timeouts.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception SMTPConnectionClosedException
+ * If the SMTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send SMTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean sendNoOp() throws IOException
+ {
+ return SMTPReply.isPositiveCompletion(noop());
+ }
+
+}
diff --git a/org/apache/commons/net/smtp/SMTPCommand.java b/org/apache/commons/net/smtp/SMTPCommand.java
new file mode 100644
index 0000000..04dbf99
--- /dev/null
+++ b/org/apache/commons/net/smtp/SMTPCommand.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.smtp;
+
+/***
+ * SMTPCommand stores a set of constants for SMTP command codes. To interpret
+ * the meaning of the codes, familiarity with RFC 821 is assumed.
+ * The mnemonic constant names are transcriptions from the code descriptions
+ * of RFC 821. For those who think in terms of the actual SMTP commands,
+ * a set of constants such as {@link #HELO HELO } are provided
+ * where the constant name is the same as the SMTP command.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class SMTPCommand
+{
+
+
+ public static final int HELO = 0;
+ public static final int MAIL = 1;
+ public static final int RCPT = 2;
+ public static final int DATA = 3;
+ public static final int SEND = 4;
+ public static final int SOML = 5;
+ public static final int SAML = 6;
+ public static final int RSET = 7;
+ public static final int VRFY = 8;
+ public static final int EXPN = 9;
+ public static final int HELP = 10;
+ public static final int NOOP = 11;
+ public static final int TURN = 12;
+ public static final int QUIT = 13;
+
+ public static final int HELLO = HELO;
+ public static final int LOGIN = HELO;
+ public static final int MAIL_FROM = MAIL;
+ public static final int RECIPIENT = RCPT;
+ public static final int SEND_MESSAGE_DATA = DATA;
+ public static final int SEND_FROM = SEND;
+ public static final int SEND_OR_MAIL_FROM = SOML;
+ public static final int SEND_AND_MAIL_FROM = SAML;
+ public static final int RESET = RSET;
+ public static final int VERIFY = VRFY;
+ public static final int EXPAND = EXPN;
+ // public static final int HELP = HELP;
+ // public static final int NOOP = NOOP;
+ // public static final int TURN = TURN;
+ // public static final int QUIT = QUIT;
+ public static final int LOGOUT = QUIT;
+
+ // Cannot be instantiated
+ private SMTPCommand()
+ {}
+
+ static final String[] _commands = {
+ "HELO", "MAIL FROM:", "RCPT TO:", "DATA", "SEND FROM:", "SOML FROM:",
+ "SAML FROM:", "RSET", "VRFY", "EXPN", "HELP", "NOOP", "TURN", "QUIT"
+ };
+
+
+ /***
+ * Retrieve the SMTP protocol command string corresponding to a specified
+ * command code.
+ *
+ * @param command The command code.
+ * @return The SMTP protcol command string corresponding to a specified
+ * command code.
+ ***/
+ public static final String getCommand(int command)
+ {
+ return _commands[command];
+ }
+
+}
diff --git a/org/apache/commons/net/smtp/SMTPConnectionClosedException.java b/org/apache/commons/net/smtp/SMTPConnectionClosedException.java
new file mode 100644
index 0000000..f9a5762
--- /dev/null
+++ b/org/apache/commons/net/smtp/SMTPConnectionClosedException.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.smtp;
+
+import java.io.IOException;
+
+/***
+ * SMTPConnectionClosedException is used to indicate the premature or
+ * unexpected closing of an SMTP connection resulting from a
+ * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE }
+ * response (SMTP reply code 421) to a
+ * failed SMTP command. This exception is derived from IOException and
+ * therefore may be caught either as an IOException or specifically as an
+ * SMTPConnectionClosedException.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SMTP
+ * @see SMTPClient
+ ***/
+
+public final class SMTPConnectionClosedException extends IOException
+{
+
+ /*** Constructs a SMTPConnectionClosedException with no message ***/
+ public SMTPConnectionClosedException()
+ {
+ super();
+ }
+
+ /***
+ * Constructs a SMTPConnectionClosedException with a specified message.
+ *
+ * @param message The message explaining the reason for the exception.
+ ***/
+ public SMTPConnectionClosedException(String message)
+ {
+ super(message);
+ }
+
+}
diff --git a/org/apache/commons/net/smtp/SMTPReply.java b/org/apache/commons/net/smtp/SMTPReply.java
new file mode 100644
index 0000000..45fd7c8
--- /dev/null
+++ b/org/apache/commons/net/smtp/SMTPReply.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.smtp;
+
+/***
+ * SMTPReply stores a set of constants for SMTP reply codes. To interpret
+ * the meaning of the codes, familiarity with RFC 821 is assumed.
+ * The mnemonic constant names are transcriptions from the code descriptions
+ * of RFC 821. For those who think in terms of the actual reply code values,
+ * a set of CODE_NUM constants are provided where NUM is the numerical value
+ * of the code.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class SMTPReply
+{
+
+ public static final int CODE_211 = 211;
+ public static final int CODE_214 = 214;
+ public static final int CODE_215 = 215;
+ public static final int CODE_220 = 220;
+ public static final int CODE_221 = 221;
+ public static final int CODE_250 = 250;
+ public static final int CODE_251 = 251;
+ public static final int CODE_354 = 354;
+ public static final int CODE_421 = 421;
+ public static final int CODE_450 = 450;
+ public static final int CODE_451 = 451;
+ public static final int CODE_452 = 452;
+ public static final int CODE_500 = 500;
+ public static final int CODE_501 = 501;
+ public static final int CODE_502 = 502;
+ public static final int CODE_503 = 503;
+ public static final int CODE_504 = 504;
+ public static final int CODE_550 = 550;
+ public static final int CODE_551 = 551;
+ public static final int CODE_552 = 552;
+ public static final int CODE_553 = 553;
+ public static final int CODE_554 = 554;
+
+ public static final int SYSTEM_STATUS = CODE_211;
+ public static final int HELP_MESSAGE = CODE_214;
+ public static final int SERVICE_READY = CODE_220;
+ public static final int SERVICE_CLOSING_TRANSMISSION_CHANNEL = CODE_221;
+ public static final int ACTION_OK = CODE_250;
+ public static final int USER_NOT_LOCAL_WILL_FORWARD = CODE_251;
+ public static final int START_MAIL_INPUT = CODE_354;
+ public static final int SERVICE_NOT_AVAILABLE = CODE_421;
+ public static final int ACTION_NOT_TAKEN = CODE_450;
+ public static final int ACTION_ABORTED = CODE_451;
+ public static final int INSUFFICIENT_STORAGE = CODE_452;
+ public static final int UNRECOGNIZED_COMMAND = CODE_500;
+ public static final int SYNTAX_ERROR_IN_ARGUMENTS = CODE_501;
+ public static final int COMMAND_NOT_IMPLEMENTED = CODE_502;
+ public static final int BAD_COMMAND_SEQUENCE = CODE_503;
+ public static final int COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER = CODE_504;
+ public static final int MAILBOX_UNAVAILABLE = CODE_550;
+ public static final int USER_NOT_LOCAL = CODE_551;
+ public static final int STORAGE_ALLOCATION_EXCEEDED = CODE_552;
+ public static final int MAILBOX_NAME_NOT_ALLOWED = CODE_553;
+ public static final int TRANSACTION_FAILED = CODE_554;
+
+ // Cannot be instantiated
+ private SMTPReply()
+ {}
+
+ /***
+ * Determine if a reply code is a positive preliminary response. All
+ * codes beginning with a 1 are positive preliminary responses.
+ * Postitive preliminary responses are used to indicate tentative success.
+ * No further commands can be issued to the SMTP server after a positive
+ * preliminary response until a follow up response is received from the
+ * server.
+ *
+ * Note: No SMTP commands defined in RFC 822 provide this
+ * type of reply.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive preliminary response, false
+ * if not.
+ ***/
+ public static boolean isPositivePreliminary(int reply)
+ {
+ return (reply >= 100 && reply < 200);
+ }
+
+ /***
+ * Determine if a reply code is a positive completion response. All
+ * codes beginning with a 2 are positive completion responses.
+ * The SMTP server will send a positive completion response on the final
+ * successful completion of a command.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive completion response, false
+ * if not.
+ ***/
+ public static boolean isPositiveCompletion(int reply)
+ {
+ return (reply >= 200 && reply < 300);
+ }
+
+ /***
+ * Determine if a reply code is a positive intermediate response. All
+ * codes beginning with a 3 are positive intermediate responses.
+ * The SMTP server will send a positive intermediate response on the
+ * successful completion of one part of a multi-part sequence of
+ * commands. For example, after a successful DATA command, a positive
+ * intermediate response will be sent to indicate that the server is
+ * ready to receive the message data.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive intermediate response, false
+ * if not.
+ ***/
+ public static boolean isPositiveIntermediate(int reply)
+ {
+ return (reply >= 300 && reply < 400);
+ }
+
+ /***
+ * Determine if a reply code is a negative transient response. All
+ * codes beginning with a 4 are negative transient responses.
+ * The SMTP server will send a negative transient response on the
+ * failure of a command that can be reattempted with success.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a negative transient response, false
+ * if not.
+ ***/
+ public static boolean isNegativeTransient(int reply)
+ {
+ return (reply >= 400 && reply < 500);
+ }
+
+ /***
+ * Determine if a reply code is a negative permanent response. All
+ * codes beginning with a 5 are negative permanent responses.
+ * The SMTP server will send a negative permanent response on the
+ * failure of a command that cannot be reattempted with success.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a negative permanent response, false
+ * if not.
+ ***/
+ public static boolean isNegativePermanent(int reply)
+ {
+ return (reply >= 500 && reply < 600);
+ }
+
+}
diff --git a/org/apache/commons/net/smtp/SimpleSMTPHeader.java b/org/apache/commons/net/smtp/SimpleSMTPHeader.java
new file mode 100644
index 0000000..ed0ea4d
--- /dev/null
+++ b/org/apache/commons/net/smtp/SimpleSMTPHeader.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.smtp;
+
+/***
+ * This class is used to construct a bare minimum
+ * acceptable header for an email message. To construct more
+ * complicated headers you should refer to RFC 822. When the
+ * Java Mail API is finalized, you will be
+ * able to use it to compose fully compliant Internet text messages.
+ *
+ * The main purpose of the class is to faciliatate the mail sending
+ * process, by relieving the programmer from having to explicitly format
+ * a simple message header. For example:
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SMTPClient
+ ***/
+
+public class SimpleSMTPHeader
+{
+ private String __subject, __from, __to;
+ private StringBuffer __headerFields, __cc;
+
+ /***
+ * Creates a new SimpleSMTPHeader instance initialized with the given
+ * from, to, and subject header field values.
+ *
+ * @param from The value of the
+ * @param headerField The header field to add, not including the colon.
+ * @param value The value of the added header field.
+ ***/
+ public void addHeaderField(String headerField, String value)
+ {
+ __headerFields.append(headerField);
+ __headerFields.append(": ");
+ __headerFields.append(value);
+ __headerFields.append('\n');
+ }
+
+
+ /***
+ * Add an email address to the CC (carbon copy or courtesy copy) list.
+ *
+ * @param address The email address to add to the CC list.
+ ***/
+ public void addCC(String address)
+ {
+ if (__cc == null)
+ __cc = new StringBuffer();
+ else
+ __cc.append(", ");
+
+ __cc.append(address);
+ }
+
+
+ /***
+ * Converts the SimpleSMTPHeader to a properly formatted header in
+ * the form of a String, including the blank line used to separate
+ * the header from the article body. The header fields CC and Subject
+ * are only included when they are non-null.
+ *
+ * @return The message header in the form of a String.
+ ***/
+ @Override
+ public String toString()
+ {
+ StringBuffer header = new StringBuffer();
+
+ if (__headerFields.length() > 0)
+ header.append(__headerFields.toString());
+
+ header.append("From: ");
+ header.append(__from);
+ header.append("\nTo: ");
+ header.append(__to);
+
+ if (__cc != null)
+ {
+ header.append("\nCc: ");
+ header.append(__cc.toString());
+ }
+
+ if (__subject != null)
+ {
+ header.append("\nSubject: ");
+ header.append(__subject);
+ }
+
+ header.append('\n');
+ header.append('\n');
+
+ return header.toString();
+ }
+}
+
+
+
diff --git a/org/apache/commons/net/telnet/EchoOptionHandler.java b/org/apache/commons/net/telnet/EchoOptionHandler.java
new file mode 100644
index 0000000..8c43f85
--- /dev/null
+++ b/org/apache/commons/net/telnet/EchoOptionHandler.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Implements the telnet echo option RFC 857.
+ *
+ * @author Bruno D'Avanzo
+ ***/
+public class EchoOptionHandler extends TelnetOptionHandler
+{
+ /***
+ * Constructor for the EchoOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ *
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public EchoOptionHandler(boolean initlocal, boolean initremote,
+ boolean acceptlocal, boolean acceptremote)
+ {
+ super(TelnetOption.ECHO, initlocal, initremote,
+ acceptlocal, acceptremote);
+ }
+
+ /***
+ * Constructor for the EchoOptionHandler. Initial and accept
+ * behaviour flags are set to false
+ ***/
+ public EchoOptionHandler()
+ {
+ super(TelnetOption.ECHO, false, false, false, false);
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] answerSubnegotiation(int suboptionData[],
+ int suboptionLength)
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationLocal()
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationRemote()
+ {
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/telnet/InvalidTelnetOptionException.java b/org/apache/commons/net/telnet/InvalidTelnetOptionException.java
new file mode 100644
index 0000000..740d185
--- /dev/null
+++ b/org/apache/commons/net/telnet/InvalidTelnetOptionException.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * The InvalidTelnetOptionException is the exception that is
+ * thrown whenever a TelnetOptionHandler with an invlaid
+ * option code is registered in TelnetClient with addOptionHandler.
+ *
+ * @author Bruno D'Avanzo
+ ***/
+public class InvalidTelnetOptionException extends Exception
+{
+
+ /***
+ * Option code
+ ***/
+ private int optionCode = -1;
+
+ /***
+ * Error message
+ ***/
+ private String msg;
+
+ /***
+ * Constructor for the exception.
+ *
+ * @param message - Error message.
+ * @param optcode - Option code.
+ ***/
+ public InvalidTelnetOptionException(String message, int optcode)
+ {
+ optionCode = optcode;
+ msg = message;
+ }
+
+ /***
+ * Gets the error message of ths exception.
+ *
+ * @return the error message.
+ ***/
+ @Override
+ public String getMessage()
+ {
+ return (msg + ": " + optionCode);
+ }
+}
diff --git a/org/apache/commons/net/telnet/SimpleOptionHandler.java b/org/apache/commons/net/telnet/SimpleOptionHandler.java
new file mode 100644
index 0000000..3395508
--- /dev/null
+++ b/org/apache/commons/net/telnet/SimpleOptionHandler.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Simple option handler that can be used for options
+ * that don't require subnegotiation.
+ *
+ * @author Bruno D'Avanzo
+ ***/
+public class SimpleOptionHandler extends TelnetOptionHandler
+{
+ /***
+ * Constructor for the SimpleOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ *
+ * @param optcode - option code.
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public SimpleOptionHandler(int optcode,
+ boolean initlocal,
+ boolean initremote,
+ boolean acceptlocal,
+ boolean acceptremote)
+ {
+ super(optcode, initlocal, initremote,
+ acceptlocal, acceptremote);
+ }
+
+ /***
+ * Constructor for the SimpleOptionHandler. Initial and accept
+ * behaviour flags are set to false
+ *
+ * @param optcode - option code.
+ ***/
+ public SimpleOptionHandler(int optcode)
+ {
+ super(optcode, false, false, false, false);
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationLocal()
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationRemote()
+ {
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/telnet/SuppressGAOptionHandler.java b/org/apache/commons/net/telnet/SuppressGAOptionHandler.java
new file mode 100644
index 0000000..aa18452
--- /dev/null
+++ b/org/apache/commons/net/telnet/SuppressGAOptionHandler.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Implements the telnet suppress go ahead option RFC 858.
+ *
+ * @author Bruno D'Avanzo
+ ***/
+public class SuppressGAOptionHandler extends TelnetOptionHandler
+{
+ /***
+ * Constructor for the SuppressGAOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ *
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public SuppressGAOptionHandler(boolean initlocal, boolean initremote,
+ boolean acceptlocal, boolean acceptremote)
+ {
+ super(TelnetOption.SUPPRESS_GO_AHEAD, initlocal, initremote,
+ acceptlocal, acceptremote);
+ }
+
+ /***
+ * Constructor for the SuppressGAOptionHandler. Initial and accept
+ * behaviour flags are set to false
+ ***/
+ public SuppressGAOptionHandler()
+ {
+ super(TelnetOption.SUPPRESS_GO_AHEAD, false, false, false, false);
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationLocal()
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationRemote()
+ {
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/telnet/Telnet.java b/org/apache/commons/net/telnet/Telnet.java
new file mode 100644
index 0000000..c05b563
--- /dev/null
+++ b/org/apache/commons/net/telnet/Telnet.java
@@ -0,0 +1,1317 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import org.apache.commons.net.SocketClient;
+
+/**
+ * @author Daniel F. Savarese
+ * @author Bruno D'Avanzo
+ */
+
+class Telnet extends SocketClient
+{
+ static final boolean debug = /*true;*/ false;
+
+ static final boolean debugoptions = /*true;*/ false;
+
+ static final byte[] _COMMAND_DO = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.DO
+ };
+
+ static final byte[] _COMMAND_DONT = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.DONT
+ };
+
+ static final byte[] _COMMAND_WILL = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.WILL
+ };
+
+ static final byte[] _COMMAND_WONT = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.WONT
+ };
+
+ static final byte[] _COMMAND_SB = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.SB
+ };
+
+ static final byte[] _COMMAND_SE = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.SE
+ };
+
+ static final int _WILL_MASK = 0x01, _DO_MASK = 0x02,
+ _REQUESTED_WILL_MASK = 0x04, _REQUESTED_DO_MASK = 0x08;
+
+ /* public */
+ static final int DEFAULT_PORT = 23;
+
+ int[] _doResponse, _willResponse, _options;
+
+ /* TERMINAL-TYPE option (start)*/
+ /***
+ * Terminal type option
+ ***/
+ protected static final int TERMINAL_TYPE = 24;
+
+ /***
+ * Send (for subnegotiation)
+ ***/
+ protected static final int TERMINAL_TYPE_SEND = 1;
+
+ /***
+ * Is (for subnegotiation)
+ ***/
+ protected static final int TERMINAL_TYPE_IS = 0;
+
+ /***
+ * Is sequence (for subnegotiation)
+ ***/
+ static final byte[] _COMMAND_IS = {
+ (byte) TERMINAL_TYPE, (byte) TERMINAL_TYPE_IS
+ };
+
+ /***
+ * Terminal type
+ ***/
+ private String terminalType = null;
+ /* TERMINAL-TYPE option (end)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+ /***
+ * Array of option handlers
+ ***/
+ private TelnetOptionHandler optionHandlers[];
+
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting AYT (start)*/
+ /***
+ * AYT sequence
+ ***/
+ static final byte[] _COMMAND_AYT = {
+ (byte) TelnetCommand.IAC, (byte) TelnetCommand.AYT
+ };
+
+ /***
+ * monitor to wait for AYT
+ ***/
+ private Object aytMonitor = new Object();
+
+ /***
+ * flag for AYT
+ ***/
+ private boolean aytFlag = true;
+ /* Code Section added for supporting AYT (end)*/
+
+ /***
+ * The stream on which to spy
+ ***/
+ private OutputStream spyStream = null;
+
+ /***
+ * The notification handler
+ ***/
+ private TelnetNotificationHandler __notifhand = null;
+ /***
+ * Empty Constructor
+ ***/
+ Telnet()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ optionHandlers =
+ new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
+ }
+
+ /* TERMINAL-TYPE option (start)*/
+ /***
+ * This constructor lets you specify the terminal type.
+ *
+ * @param termtype - terminal type to be negotiated (ej. VT100)
+ ***/
+ Telnet(String termtype)
+ {
+ setDefaultPort(DEFAULT_PORT);
+ _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ terminalType = termtype;
+ optionHandlers =
+ new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
+ }
+ /* TERMINAL-TYPE option (end)*/
+
+ /***
+ * Looks for the state of the option.
+ *
+ * @return returns true if a will has been acknowledged
+ *
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsWill(int option)
+ {
+ return ((_options[option] & _WILL_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ *
+ * @return returns true if a wont has been acknowledged
+ *
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsWont(int option)
+ {
+ return !_stateIsWill(option);
+ }
+
+ /***
+ * Looks for the state of the option.
+ *
+ * @return returns true if a do has been acknowledged
+ *
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsDo(int option)
+ {
+ return ((_options[option] & _DO_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ *
+ * @return returns true if a dont has been acknowledged
+ *
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsDont(int option)
+ {
+ return !_stateIsDo(option);
+ }
+
+ /***
+ * Looks for the state of the option.
+ *
+ * @return returns true if a will has been reuqested
+ *
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedWill(int option)
+ {
+ return ((_options[option] & _REQUESTED_WILL_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ *
+ * @return returns true if a wont has been reuqested
+ *
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedWont(int option)
+ {
+ return !_requestedWill(option);
+ }
+
+ /***
+ * Looks for the state of the option.
+ *
+ * @return returns true if a do has been reuqested
+ *
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedDo(int option)
+ {
+ return ((_options[option] & _REQUESTED_DO_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ *
+ * @return returns true if a dont has been reuqested
+ *
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedDont(int option)
+ {
+ return !_requestedDo(option);
+ }
+
+ /***
+ * Sets the state of the option.
+ *
+ * @param option - option code to be set.
+ ***/
+ void _setWill(int option)
+ {
+ _options[option] |= _WILL_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (_requestedWill(option))
+ {
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setWill(true);
+
+ int subneg[] =
+ optionHandlers[option].startSubnegotiationLocal();
+
+ if (subneg != null)
+ {
+ try
+ {
+ _sendSubnegotiation(subneg);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception in option subnegotiation"
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ *
+ * @param option - option code to be set.
+ ***/
+ void _setDo(int option)
+ {
+ _options[option] |= _DO_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (_requestedDo(option))
+ {
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setDo(true);
+
+ int subneg[] =
+ optionHandlers[option].startSubnegotiationRemote();
+
+ if (subneg != null)
+ {
+ try
+ {
+ _sendSubnegotiation(subneg);
+ }
+ catch (IOException e)
+ {
+ System.err.println("Exception in option subnegotiation"
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ *
+ * @param option - option code to be set.
+ ***/
+ void _setWantWill(int option)
+ {
+ _options[option] |= _REQUESTED_WILL_MASK;
+ }
+
+ /***
+ * Sets the state of the option.
+ *
+ * @param option - option code to be set.
+ ***/
+ void _setWantDo(int option)
+ {
+ _options[option] |= _REQUESTED_DO_MASK;
+ }
+
+ /***
+ * Sets the state of the option.
+ *
+ * @param option - option code to be set.
+ ***/
+ void _setWont(int option)
+ {
+ _options[option] &= ~_WILL_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setWill(false);
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ *
+ * @param option - option code to be set.
+ ***/
+ void _setDont(int option)
+ {
+ _options[option] &= ~_DO_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setDo(false);
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ *
+ * @param option - option code to be set.
+ ***/
+ void _setWantWont(int option)
+ {
+ _options[option] &= ~_REQUESTED_WILL_MASK;
+ }
+
+ /***
+ * Sets the state of the option.
+ *
+ * @param option - option code to be set.
+ ***/
+ void _setWantDont(int option)
+ {
+ _options[option] &= ~_REQUESTED_DO_MASK;
+ }
+
+ /**
+ * Processes a DO request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processDo(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED DO: "
+ + TelnetOption.getOption(option));
+ }
+
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_DO,
+ option);
+ }
+
+ boolean acceptNewState = false;
+
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ acceptNewState = optionHandlers[option].getAcceptLocal();
+ }
+ else
+ {
+ /* open TelnetOptionHandler functionality (end)*/
+ /* TERMINAL-TYPE option (start)*/
+ if (option == TERMINAL_TYPE)
+ {
+ if ((terminalType != null) && (terminalType.length() > 0))
+ {
+ acceptNewState = true;
+ }
+ }
+ /* TERMINAL-TYPE option (end)*/
+ /* open TelnetOptionHandler functionality (start)*/
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ if (_willResponse[option] > 0)
+ {
+ --_willResponse[option];
+ if (_willResponse[option] > 0 && _stateIsWill(option))
+ {
+ --_willResponse[option];
+ }
+ }
+
+ if (_willResponse[option] == 0)
+ {
+ if (_requestedWont(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+
+ if (acceptNewState)
+ {
+ _setWantWill(option);
+ _sendWill(option);
+ }
+ else
+ {
+ ++_willResponse[option];
+ _sendWont(option);
+ }
+ }
+ else
+ {
+ // Other end has acknowledged option.
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+ }
+ }
+
+ _setWill(option);
+ }
+
+ /**
+ * Processes a DONT request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processDont(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED DONT: "
+ + TelnetOption.getOption(option));
+ }
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_DONT,
+ option);
+ }
+ if (_willResponse[option] > 0)
+ {
+ --_willResponse[option];
+ if (_willResponse[option] > 0 && _stateIsWont(option))
+ {
+ --_willResponse[option];
+ }
+ }
+
+ if (_willResponse[option] == 0 && _requestedWill(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+ /* FIX for a BUG in the negotiation (start)*/
+ if ((_stateIsWill(option)) || (_requestedWill(option)))
+ {
+ _sendWont(option);
+ }
+
+ _setWantWont(option);
+ /* FIX for a BUG in the negotiation (end)*/
+ }
+
+ _setWont(option);
+ }
+
+
+ /**
+ * Processes a WILL request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processWill(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED WILL: "
+ + TelnetOption.getOption(option));
+ }
+
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_WILL,
+ option);
+ }
+
+ boolean acceptNewState = false;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ acceptNewState = optionHandlers[option].getAcceptRemote();
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ if (_doResponse[option] > 0)
+ {
+ --_doResponse[option];
+ if (_doResponse[option] > 0 && _stateIsDo(option))
+ {
+ --_doResponse[option];
+ }
+ }
+
+ if (_doResponse[option] == 0 && _requestedDont(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+
+ if (acceptNewState)
+ {
+ _setWantDo(option);
+ _sendDo(option);
+ }
+ else
+ {
+ ++_doResponse[option];
+ _sendDont(option);
+ }
+ }
+
+ _setDo(option);
+ }
+
+ /**
+ * Processes a WONT request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processWont(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED WONT: "
+ + TelnetOption.getOption(option));
+ }
+
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_WONT,
+ option);
+ }
+
+ if (_doResponse[option] > 0)
+ {
+ --_doResponse[option];
+ if (_doResponse[option] > 0 && _stateIsDont(option))
+ {
+ --_doResponse[option];
+ }
+ }
+
+ if (_doResponse[option] == 0 && _requestedDo(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+ /* FIX for a BUG in the negotiation (start)*/
+ if ((_stateIsDo(option)) || (_requestedDo(option)))
+ {
+ _sendDont(option);
+ }
+
+ _setWantDont(option);
+ /* FIX for a BUG in the negotiation (end)*/
+ }
+
+ _setDont(option);
+ }
+
+ /* TERMINAL-TYPE option (start)*/
+ /**
+ * Processes a suboption negotiation.
+ *
+ * @param suboption - subnegotiation data received
+ * @param suboptionLength - length of data received
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processSuboption(int suboption[], int suboptionLength)
+ throws IOException
+ {
+ if (debug)
+ {
+ System.err.println("PROCESS SUBOPTION.");
+ }
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (suboptionLength > 0)
+ {
+ if (optionHandlers[suboption[0]] != null)
+ {
+ int responseSuboption[] =
+ optionHandlers[suboption[0]].answerSubnegotiation(suboption,
+ suboptionLength);
+ _sendSubnegotiation(responseSuboption);
+ }
+ else
+ {
+ if (suboptionLength > 1)
+ {
+ if (debug)
+ {
+ for (int ii = 0; ii < suboptionLength; ii++)
+ {
+ System.err.println("SUB[" + ii + "]: "
+ + suboption[ii]);
+ }
+ }
+ if ((suboption[0] == TERMINAL_TYPE)
+ && (suboption[1] == TERMINAL_TYPE_SEND))
+ {
+ _sendTerminalType();
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sends terminal type information.
+ *
+ * @throws IOException - Exception in I/O.
+ ***/
+ final synchronized void _sendTerminalType()
+ throws IOException
+ {
+ if (debug)
+ {
+ System.err.println("SEND TERMINAL-TYPE: " + terminalType);
+ }
+ if (terminalType != null)
+ {
+ _output_.write(_COMMAND_SB);
+ _output_.write(_COMMAND_IS);
+ _output_.write(terminalType.getBytes());
+ _output_.write(_COMMAND_SE);
+ _output_.flush();
+ }
+ }
+
+ /* TERMINAL-TYPE option (end)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+ /**
+ * Manages subnegotiation for Terminal Type.
+ *
+ * @param subn - subnegotiation data to be sent
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendSubnegotiation(int subn[])
+ throws IOException
+ {
+ if (debug)
+ {
+ System.err.println("SEND SUBNEGOTIATION: ");
+ if (subn != null)
+ {
+ for (int ii = 0; ii < subn.length; ii++)
+ {
+ System.err.println("subn[" + ii + "]=" + subn[ii]);
+ }
+ }
+ }
+ if (subn != null)
+ {
+ byte byteresp[] = new byte[subn.length];
+ for (int ii = 0; ii < subn.length; ii++)
+ {
+ byteresp[ii] = (byte) subn[ii];
+ }
+
+ _output_.write(_COMMAND_SB);
+ _output_.write(byteresp);
+ _output_.write(_COMMAND_SE);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting AYT (start)*/
+ /***
+ * Processes the response of an AYT
+ ***/
+ final synchronized void _processAYTResponse()
+ {
+ if (!aytFlag)
+ {
+ synchronized (aytMonitor)
+ {
+ aytFlag = true;
+ try
+ {
+ aytMonitor.notifyAll();
+ }
+ catch (IllegalMonitorStateException e)
+ {
+ System.err.println("Exception notifying:" + e.getMessage());
+ }
+ }
+ }
+ }
+ /* Code Section added for supporting AYT (end)*/
+
+ /***
+ * Called upon connection.
+ *
+ * @throws IOException - Exception in I/O.
+ ***/
+ @Override
+ protected void _connectAction_() throws IOException
+ {
+ /* (start). BUGFIX: clean the option info for each connection*/
+ for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++)
+ {
+ _doResponse[ii] = 0;
+ _willResponse[ii] = 0;
+ _options[ii] = 0;
+ if (optionHandlers[ii] != null)
+ {
+ optionHandlers[ii].setDo(false);
+ optionHandlers[ii].setWill(false);
+ }
+ }
+ /* (end). BUGFIX: clean the option info for each connection*/
+
+ super._connectAction_();
+ _input_ = new BufferedInputStream(_input_);
+ _output_ = new BufferedOutputStream(_output_);
+
+ /* open TelnetOptionHandler functionality (start)*/
+ for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++)
+ {
+ if (optionHandlers[ii] != null)
+ {
+ if (optionHandlers[ii].getInitLocal())
+ {
+ try
+ {
+ _requestWill(optionHandlers[ii].getOptionCode());
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+
+ if (optionHandlers[ii].getInitRemote())
+ {
+ try
+ {
+ _requestDo(optionHandlers[ii].getOptionCode());
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /**
+ * Sends a DO.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendDo(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("DO: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_DO);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a DO.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestDo(int option)
+ throws IOException
+ {
+ if ((_doResponse[option] == 0 && _stateIsDo(option))
+ || _requestedDo(option))
+ {
+ return ;
+ }
+ _setWantDo(option);
+ ++_doResponse[option];
+ _sendDo(option);
+ }
+
+ /**
+ * Sends a DONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendDont(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("DONT: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_DONT);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a DONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestDont(int option)
+ throws IOException
+ {
+ if ((_doResponse[option] == 0 && _stateIsDont(option))
+ || _requestedDont(option))
+ {
+ return ;
+ }
+ _setWantDont(option);
+ ++_doResponse[option];
+ _sendDont(option);
+ }
+
+
+ /**
+ * Sends a WILL.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendWill(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("WILL: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_WILL);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a WILL.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestWill(int option)
+ throws IOException
+ {
+ if ((_willResponse[option] == 0 && _stateIsWill(option))
+ || _requestedWill(option))
+ {
+ return ;
+ }
+ _setWantWill(option);
+ ++_doResponse[option];
+ _sendWill(option);
+ }
+
+ /**
+ * Sends a WONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendWont(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("WONT: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_WONT);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a WONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestWont(int option)
+ throws IOException
+ {
+ if ((_willResponse[option] == 0 && _stateIsWont(option))
+ || _requestedWont(option))
+ {
+ return ;
+ }
+ _setWantWont(option);
+ ++_doResponse[option];
+ _sendWont(option);
+ }
+
+ /**
+ * Sends a byte.
+ *
+ * @param b - byte to send
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendByte(int b)
+ throws IOException
+ {
+ _output_.write(b);
+
+ /* Code Section added for supporting spystreams (start)*/
+ _spyWrite(b);
+ /* Code Section added for supporting spystreams (end)*/
+
+ }
+
+ /* Code Section added for supporting AYT (start)*/
+ /**
+ * Sends an Are You There sequence and waits for the result.
+ *
+ * @param timeout - Time to wait for a response (millis.)
+ * @throws IOException - Exception in I/O.
+ * @throws IllegalArgumentException - Illegal argument
+ * @throws InterruptedException - Interrupted during wait.
+ * @return true if AYT received a response, false otherwise
+ **/
+ final boolean _sendAYT(long timeout)
+ throws IOException, IllegalArgumentException, InterruptedException
+ {
+ boolean retValue = false;
+ synchronized (aytMonitor)
+ {
+ synchronized (this)
+ {
+ aytFlag = false;
+ _output_.write(_COMMAND_AYT);
+ _output_.flush();
+ }
+
+ try
+ {
+ aytMonitor.wait(timeout);
+ if (aytFlag == false)
+ {
+ retValue = false;
+ aytFlag = true;
+ }
+ else
+ {
+ retValue = true;
+ }
+ }
+ catch (IllegalMonitorStateException e)
+ {
+ System.err.println("Exception processing AYT:"
+ + e.getMessage());
+ }
+ }
+
+ return (retValue);
+ }
+ /* Code Section added for supporting AYT (end)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+
+ /**
+ * Registers a new TelnetOptionHandler for this telnet to use.
+ *
+ * @param opthand - option handler to be registered.
+ * @throws InvalidTelnetOptionException - The option code is invalid.
+ **/
+ void addOptionHandler(TelnetOptionHandler opthand)
+ throws InvalidTelnetOptionException
+ {
+ int optcode = opthand.getOptionCode();
+ if (TelnetOption.isValidOption(optcode))
+ {
+ if (optionHandlers[optcode] == null)
+ {
+ optionHandlers[optcode] = opthand;
+ if (isConnected())
+ {
+ if (opthand.getInitLocal())
+ {
+ try
+ {
+ _requestWill(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+
+ if (opthand.getInitRemote())
+ {
+ try
+ {
+ _requestDo(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ else
+ {
+ throw (new InvalidTelnetOptionException(
+ "Already registered option", optcode));
+ }
+ }
+ else
+ {
+ throw (new InvalidTelnetOptionException(
+ "Invalid Option Code", optcode));
+ }
+ }
+
+ /**
+ * Unregisters a TelnetOptionHandler.
+ *
+ * @param optcode - Code of the option to be unregistered.
+ * @throws InvalidTelnetOptionException - The option code is invalid.
+ **/
+ void deleteOptionHandler(int optcode)
+ throws InvalidTelnetOptionException
+ {
+ if (TelnetOption.isValidOption(optcode))
+ {
+ if (optionHandlers[optcode] == null)
+ {
+ throw (new InvalidTelnetOptionException(
+ "Unregistered option", optcode));
+ }
+ else
+ {
+ TelnetOptionHandler opthand = optionHandlers[optcode];
+ optionHandlers[optcode] = null;
+
+ if (opthand.getWill())
+ {
+ try
+ {
+ _requestWont(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while turning off option: "
+ + e.getMessage());
+ }
+ }
+
+ if (opthand.getDo())
+ {
+ try
+ {
+ _requestDont(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while turning off option: "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ else
+ {
+ throw (new InvalidTelnetOptionException(
+ "Invalid Option Code", optcode));
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting spystreams (start)*/
+ /***
+ * Registers an OutputStream for spying what's going on in
+ * the Telnet session.
+ *
+ * @param spystream - OutputStream on which session activity
+ * will be echoed.
+ ***/
+ void _registerSpyStream(OutputStream spystream)
+ {
+ spyStream = spystream;
+ }
+
+ /***
+ * Stops spying this Telnet.
+ *
+ ***/
+ void _stopSpyStream()
+ {
+ spyStream = null;
+ }
+
+ /***
+ * Sends a read char on the spy stream.
+ *
+ * @param ch - character read from the session
+ ***/
+ void _spyRead(int ch)
+ {
+ if (spyStream != null)
+ {
+ try
+ {
+ if (ch != '\r')
+ {
+ spyStream.write(ch);
+ if (ch == '\n')
+ {
+ spyStream.write('\r');
+ }
+ spyStream.flush();
+ }
+ }
+ catch (IOException e)
+ {
+ spyStream = null;
+ }
+ }
+ }
+
+ /***
+ * Sends a written char on the spy stream.
+ *
+ * @param ch - character written to the session
+ ***/
+ void _spyWrite(int ch)
+ {
+ if (!(_stateIsDo(TelnetOption.ECHO)
+ && _requestedDo(TelnetOption.ECHO)))
+ {
+ if (spyStream != null)
+ {
+ try
+ {
+ spyStream.write(ch);
+ spyStream.flush();
+ }
+ catch (IOException e)
+ {
+ spyStream = null;
+ }
+ }
+ }
+ }
+ /* Code Section added for supporting spystreams (end)*/
+
+ /***
+ * Registers a notification handler to which will be sent
+ * notifications of received telnet option negotiation commands.
+ *
+ * @param notifhand - TelnetNotificationHandler to be registered
+ ***/
+ public void registerNotifHandler(TelnetNotificationHandler notifhand)
+ {
+ __notifhand = notifhand;
+ }
+
+ /***
+ * Unregisters the current notification handler.
+ *
+ ***/
+ public void unregisterNotifHandler()
+ {
+ __notifhand = null;
+ }
+}
diff --git a/org/apache/commons/net/telnet/TelnetClient.java b/org/apache/commons/net/telnet/TelnetClient.java
new file mode 100644
index 0000000..3237779
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetClient.java
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.net.io.FromNetASCIIInputStream;
+import org.apache.commons.net.io.ToNetASCIIOutputStream;
+
+/***
+ * The TelnetClient class implements the simple network virtual
+ * terminal (NVT) for the Telnet protocol according to RFC 854. It
+ * does not implement any of the extra Telnet options because it
+ * is meant to be used within a Java program providing automated
+ * access to Telnet accessible resources.
+ *
+ * The class can be used by first connecting to a server using the
+ * SocketClient
+ * {@link org.apache.commons.net.SocketClient#connect connect}
+ * method. Then an InputStream and OutputStream for sending and
+ * receiving data over the Telnet connection can be obtained by
+ * using the {@link #getInputStream getInputStream() } and
+ * {@link #getOutputStream getOutputStream() } methods.
+ * When you finish using the streams, you must call
+ * {@link #disconnect disconnect } rather than simply
+ * closing the streams.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @author Bruno D'Avanzo
+ ***/
+
+public class TelnetClient extends Telnet
+{
+ private InputStream __input;
+ private OutputStream __output;
+ protected boolean readerThread = true;
+
+ /***
+ * Default TelnetClient constructor.
+ ***/
+ public TelnetClient()
+ {
+ /* TERMINAL-TYPE option (start)*/
+ super ("VT100");
+ /* TERMINAL-TYPE option (end)*/
+ __input = null;
+ __output = null;
+ }
+
+ /* TERMINAL-TYPE option (start)*/
+ public TelnetClient(String termtype)
+ {
+ super (termtype);
+ __input = null;
+ __output = null;
+ }
+ /* TERMINAL-TYPE option (end)*/
+
+ void _flushOutputStream() throws IOException
+ {
+ _output_.flush();
+ }
+ void _closeOutputStream() throws IOException
+ {
+ _output_.close();
+ }
+
+ /***
+ * Handles special connection requirements.
+ *
+ * @exception IOException If an error occurs during connection setup.
+ ***/
+ @Override
+ protected void _connectAction_() throws IOException
+ {
+ super._connectAction_();
+ InputStream input;
+ TelnetInputStream tmp;
+
+ if (FromNetASCIIInputStream.isConversionRequired())
+ input = new FromNetASCIIInputStream(_input_);
+ else
+ input = _input_;
+
+
+ tmp = new TelnetInputStream(input, this, readerThread);
+ if(readerThread)
+ {
+ tmp._start();
+ }
+ // __input CANNOT refer to the TelnetInputStream. We run into
+ // blocking problems when some classes use TelnetInputStream, so
+ // we wrap it with a BufferedInputStream which we know is safe.
+ // This blocking behavior requires further investigation, but right
+ // now it looks like classes like InputStreamReader are not implemented
+ // in a safe manner.
+ __input = new BufferedInputStream(tmp);
+ __output = new ToNetASCIIOutputStream(new TelnetOutputStream(this));
+ }
+
+ /***
+ * Disconnects the telnet session, closing the input and output streams
+ * as well as the socket. If you have references to the
+ * input and output streams of the telnet connection, you should not
+ * close them yourself, but rather call disconnect to properly close
+ * the connection.
+ ***/
+ @Override
+ public void disconnect() throws IOException
+ {
+ if (__input != null)
+ __input.close();
+ if (__output != null)
+ __output.close();
+ super.disconnect();
+ }
+
+ /***
+ * Returns the telnet connection output stream. You should not close the
+ * stream when you finish with it. Rather, you should call
+ * {@link #disconnect disconnect }.
+ *
+ * @return The telnet connection output stream.
+ ***/
+ public OutputStream getOutputStream()
+ {
+ return __output;
+ }
+
+ /***
+ * Returns the telnet connection input stream. You should not close the
+ * stream when you finish with it. Rather, you should call
+ * {@link #disconnect disconnect }.
+ *
+ * @return The telnet connection input stream.
+ ***/
+ public InputStream getInputStream()
+ {
+ return __input;
+ }
+
+ /***
+ * Returns the state of the option on the local side.
+ *
+ * @param option - Option to be checked.
+ *
+ * @return The state of the option on the local side.
+ ***/
+ public boolean getLocalOptionState(int option)
+ {
+ /* BUG (option active when not already acknowledged) (start)*/
+ return (_stateIsWill(option) && _requestedWill(option));
+ /* BUG (option active when not already acknowledged) (end)*/
+ }
+
+ /***
+ * Returns the state of the option on the remote side.
+ *
+ * @param option - Option to be checked.
+ *
+ * @return The state of the option on the remote side.
+ ***/
+ public boolean getRemoteOptionState(int option)
+ {
+ /* BUG (option active when not already acknowledged) (start)*/
+ return (_stateIsDo(option) && _requestedDo(option));
+ /* BUG (option active when not already acknowledged) (end)*/
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting AYT (start)*/
+
+ /***
+ * Sends an Are You There sequence and waits for the result.
+ *
+ * @throws InterruptedException
+ * @throws IllegalArgumentException
+ * @throws IOException
+ *
+ * @param timeout - Time to wait for a response (millis.)
+ *
+ * @return true if AYT received a response, false otherwise
+ ***/
+ public boolean sendAYT(long timeout)
+ throws IOException, IllegalArgumentException, InterruptedException
+ {
+ return (_sendAYT(timeout));
+ }
+ /* Code Section added for supporting AYT (start)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+
+ /***
+ * Registers a new TelnetOptionHandler for this telnet client to use.
+ *
+ * @param opthand - option handler to be registered.
+ *
+ * @throws InvalidTelnetOptionException
+ ***/
+ @Override
+ public void addOptionHandler(TelnetOptionHandler opthand)
+ throws InvalidTelnetOptionException
+ {
+ super.addOptionHandler(opthand);
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /***
+ * Unregisters a TelnetOptionHandler.
+ *
+ * @param optcode - Code of the option to be unregistered.
+ *
+ * @throws InvalidTelnetOptionException
+ ***/
+ @Override
+ public void deleteOptionHandler(int optcode)
+ throws InvalidTelnetOptionException
+ {
+ super.deleteOptionHandler(optcode);
+ }
+
+ /* Code Section added for supporting spystreams (start)*/
+ /***
+ * Registers an OutputStream for spying what's going on in
+ * the TelnetClient session.
+ *
+ * @param spystream - OutputStream on which session activity
+ * will be echoed.
+ ***/
+ public void registerSpyStream(OutputStream spystream)
+ {
+ super._registerSpyStream(spystream);
+ }
+
+ /***
+ * Stops spying this TelnetClient.
+ *
+ ***/
+ public void stopSpyStream()
+ {
+ super._stopSpyStream();
+ }
+ /* Code Section added for supporting spystreams (end)*/
+
+ /***
+ * Registers a notification handler to which will be sent
+ * notifications of received telnet option negotiation commands.
+ *
+ * @param notifhand - TelnetNotificationHandler to be registered
+ ***/
+ @Override
+ public void registerNotifHandler(TelnetNotificationHandler notifhand)
+ {
+ super.registerNotifHandler(notifhand);
+ }
+
+ /***
+ * Unregisters the current notification handler.
+ *
+ ***/
+ @Override
+ public void unregisterNotifHandler()
+ {
+ super.unregisterNotifHandler();
+ }
+
+ /***
+ * Sets the status of the reader thread.
+ * The reader thread status will apply to all subsequent connections
+ *
+ * @param flag - true switches the reader thread on, false switches it off
+ ***/
+ public void setReaderThread(boolean flag)
+ {
+ readerThread = flag;
+ }
+
+ /***
+ * Gets the status of the reader thread.
+ *
+ * @return true if the reader thread is on, false otherwise
+ ***/
+ public boolean getReaderThread()
+ {
+ return (readerThread);
+ }
+}
diff --git a/org/apache/commons/net/telnet/TelnetCommand.java b/org/apache/commons/net/telnet/TelnetCommand.java
new file mode 100644
index 0000000..725057b
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetCommand.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/**
+ * The TelnetCommand class cannot be instantiated and only serves as a
+ * storehouse for telnet command constants.
+ * @author Daniel F. Savarese
+ * @see org.apache.commons.net.telnet.Telnet
+ * @see org.apache.commons.net.telnet.TelnetClient
+ */
+
+public final class TelnetCommand
+{
+ /*** The maximum value a command code can have. This value is 255. ***/
+ public static final int MAX_COMMAND_VALUE = 255;
+
+ /*** Interpret As Command code. Value is 255 according to RFC 854. ***/
+ public static final int IAC = 255;
+
+ /*** Don't use option code. Value is 254 according to RFC 854. ***/
+ public static final int DONT = 254;
+
+ /*** Request to use option code. Value is 253 according to RFC 854. ***/
+ public static final int DO = 253;
+
+ /*** Refuse to use option code. Value is 252 according to RFC 854. ***/
+ public static final int WONT = 252;
+
+ /*** Agree to use option code. Value is 251 according to RFC 854. ***/
+ public static final int WILL = 251;
+
+ /*** Start subnegotiation code. Value is 250 according to RFC 854. ***/
+ public static final int SB = 250;
+
+ /*** Go Ahead code. Value is 249 according to RFC 854. ***/
+ public static final int GA = 249;
+
+ /*** Erase Line code. Value is 248 according to RFC 854. ***/
+ public static final int EL = 248;
+
+ /*** Erase Character code. Value is 247 according to RFC 854. ***/
+ public static final int EC = 247;
+
+ /*** Are You There code. Value is 246 according to RFC 854. ***/
+ public static final int AYT = 246;
+
+ /*** Abort Output code. Value is 245 according to RFC 854. ***/
+ public static final int AO = 245;
+
+ /*** Interrupt Process code. Value is 244 according to RFC 854. ***/
+ public static final int IP = 244;
+
+ /*** Break code. Value is 243 according to RFC 854. ***/
+ public static final int BREAK = 243;
+
+ /*** Data mark code. Value is 242 according to RFC 854. ***/
+ public static final int DM = 242;
+
+ /*** No Operation code. Value is 241 according to RFC 854. ***/
+ public static final int NOP = 241;
+
+ /*** End subnegotiation code. Value is 240 according to RFC 854. ***/
+ public static final int SE = 240;
+
+ /*** End of record code. Value is 239. ***/
+ public static final int EOR = 239;
+
+ /*** Abort code. Value is 238. ***/
+ public static final int ABORT = 238;
+
+ /*** Suspend process code. Value is 237. ***/
+ public static final int SUSP = 237;
+
+ /*** End of file code. Value is 236. ***/
+ public static final int EOF = 236;
+
+ /*** Synchronize code. Value is 242. ***/
+ public static final int SYNCH = 242;
+
+ /*** String representations of commands. ***/
+ private static final String __commandString[] = {
+ "IAC", "DONT", "DO", "WONT", "WILL", "SB", "GA", "EL", "EC", "AYT",
+ "AO", "IP", "BRK", "DMARK", "NOP", "SE", "EOR", "ABORT", "SUSP", "EOF"
+ };
+
+ private static final int __FIRST_COMMAND = IAC;
+ private static final int __LAST_COMMAND = EOF;
+
+ /***
+ * Returns the string representation of the telnet protocol command
+ * corresponding to the given command code.
+ *
+ * @param code The command code of the telnet protocol command.
+ * @return The string representation of the telnet protocol command.
+ ***/
+ public static final String getCommand(int code)
+ {
+ return __commandString[__FIRST_COMMAND - code];
+ }
+
+ /***
+ * Determines if a given command code is valid. Returns true if valid,
+ * false if not.
+ *
+ * @param code The command code to test.
+ * @return True if the command code is valid, false if not.
+ **/
+ public static final boolean isValidCommand(int code)
+ {
+ return (code <= __FIRST_COMMAND && code >= __LAST_COMMAND);
+ }
+
+ // Cannot be instantiated
+ private TelnetCommand()
+ { }
+}
diff --git a/org/apache/commons/net/telnet/TelnetInputStream.java b/org/apache/commons/net/telnet/TelnetInputStream.java
new file mode 100644
index 0000000..8a83b68
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetInputStream.java
@@ -0,0 +1,630 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+
+/***
+ *
+ *
+ *
+ *
+ *
+ * @author Daniel F. Savarese
+ * @author Bruno D'Avanzo
+ ***/
+
+
+final class TelnetInputStream extends BufferedInputStream implements Runnable
+{
+ static final int _STATE_DATA = 0, _STATE_IAC = 1, _STATE_WILL = 2,
+ _STATE_WONT = 3, _STATE_DO = 4, _STATE_DONT = 5,
+ _STATE_SB = 6, _STATE_SE = 7, _STATE_CR = 8, _STATE_IAC_SB = 9;
+
+ private boolean __hasReachedEOF, __isClosed;
+ private boolean __readIsWaiting;
+ private int __receiveState, __queueHead, __queueTail, __bytesAvailable;
+ private int[] __queue;
+ private TelnetClient __client;
+ private Thread __thread;
+ private IOException __ioException;
+
+ /* TERMINAL-TYPE option (start)*/
+ private int __suboption[] = new int[256];
+ private int __suboption_count = 0;
+ /* TERMINAL-TYPE option (end)*/
+
+ private boolean __threaded;
+
+ TelnetInputStream(InputStream input, TelnetClient client,
+ boolean readerThread)
+ {
+ super(input);
+ __client = client;
+ __receiveState = _STATE_DATA;
+ __isClosed = true;
+ __hasReachedEOF = false;
+ // Make it 2049, because when full, one slot will go unused, and we
+ // want a 2048 byte buffer just to have a round number (base 2 that is)
+ __queue = new int[2049];
+ __queueHead = 0;
+ __queueTail = 0;
+ __bytesAvailable = 0;
+ __ioException = null;
+ __readIsWaiting = false;
+ __threaded = false;
+ if(readerThread)
+ __thread = new Thread(this);
+ else
+ __thread = null;
+ }
+
+ TelnetInputStream(InputStream input, TelnetClient client) {
+ this(input, client, true);
+ }
+
+ void _start()
+ {
+ if(__thread == null)
+ return;
+
+ int priority;
+ __isClosed = false;
+ // TODO remove this
+ // Need to set a higher priority in case JVM does not use pre-emptive
+ // threads. This should prevent scheduler induced deadlock (rather than
+ // deadlock caused by a bug in this code).
+ priority = Thread.currentThread().getPriority() + 1;
+ if (priority > Thread.MAX_PRIORITY)
+ priority = Thread.MAX_PRIORITY;
+ __thread.setPriority(priority);
+ __thread.setDaemon(true);
+ __thread.start();
+ __threaded = true;
+ }
+
+
+ // synchronized(__client) critical sections are to protect against
+ // TelnetOutputStream writing through the telnet client at same time
+ // as a processDo/Will/etc. command invoked from TelnetInputStream
+ // tries to write.
+ private int __read(boolean mayBlock) throws IOException
+ {
+ int ch;
+
+_loop:
+ while (true)
+ {
+
+ // If there is no more data AND we were told not to block, just return -2. (More efficient than exception.)
+ if(!mayBlock && super.available() == 0)
+ return -2;
+
+ // Otherwise, exit only when we reach end of stream.
+ if ((ch = super.read()) < 0)
+ return -1;
+
+ ch = (ch & 0xff);
+
+ /* Code Section added for supporting AYT (start)*/
+ synchronized (__client)
+ {
+ __client._processAYTResponse();
+ }
+ /* Code Section added for supporting AYT (end)*/
+
+ /* Code Section added for supporting spystreams (start)*/
+ __client._spyRead(ch);
+ /* Code Section added for supporting spystreams (end)*/
+
+_mainSwitch:
+ switch (__receiveState)
+ {
+
+ case _STATE_CR:
+ if (ch == '\0')
+ {
+ // Strip null
+ continue;
+ }
+ // How do we handle newline after cr?
+ // else if (ch == '\n' && _requestedDont(TelnetOption.ECHO) &&
+
+ // Handle as normal data by falling through to _STATE_DATA case
+
+ case _STATE_DATA:
+ if (ch == TelnetCommand.IAC)
+ {
+ __receiveState = _STATE_IAC;
+ continue;
+ }
+
+
+ if (ch == '\r')
+ {
+ synchronized (__client)
+ {
+ if (__client._requestedDont(TelnetOption.BINARY))
+ __receiveState = _STATE_CR;
+ else
+ __receiveState = _STATE_DATA;
+ }
+ }
+ else
+ __receiveState = _STATE_DATA;
+ break;
+
+ case _STATE_IAC:
+ switch (ch)
+ {
+ case TelnetCommand.WILL:
+ __receiveState = _STATE_WILL;
+ continue;
+ case TelnetCommand.WONT:
+ __receiveState = _STATE_WONT;
+ continue;
+ case TelnetCommand.DO:
+ __receiveState = _STATE_DO;
+ continue;
+ case TelnetCommand.DONT:
+ __receiveState = _STATE_DONT;
+ continue;
+ /* TERMINAL-TYPE option (start)*/
+ case TelnetCommand.SB:
+ __suboption_count = 0;
+ __receiveState = _STATE_SB;
+ continue;
+ /* TERMINAL-TYPE option (end)*/
+ case TelnetCommand.IAC:
+ __receiveState = _STATE_DATA;
+ break;
+ default:
+ break;
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ case _STATE_WILL:
+ synchronized (__client)
+ {
+ __client._processWill(ch);
+ __client._flushOutputStream();
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ case _STATE_WONT:
+ synchronized (__client)
+ {
+ __client._processWont(ch);
+ __client._flushOutputStream();
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ case _STATE_DO:
+ synchronized (__client)
+ {
+ __client._processDo(ch);
+ __client._flushOutputStream();
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ case _STATE_DONT:
+ synchronized (__client)
+ {
+ __client._processDont(ch);
+ __client._flushOutputStream();
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ /* TERMINAL-TYPE option (start)*/
+ case _STATE_SB:
+ switch (ch)
+ {
+ case TelnetCommand.IAC:
+ __receiveState = _STATE_IAC_SB;
+ continue;
+ default:
+ // store suboption char
+ __suboption[__suboption_count++] = ch;
+ break;
+ }
+ __receiveState = _STATE_SB;
+ continue;
+ case _STATE_IAC_SB:
+ switch (ch)
+ {
+ case TelnetCommand.SE:
+ synchronized (__client)
+ {
+ __client._processSuboption(__suboption, __suboption_count);
+ __client._flushOutputStream();
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ default:
+ __receiveState = _STATE_SB;
+ break;
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ /* TERMINAL-TYPE option (end)*/
+ }
+
+ break;
+ }
+
+ return ch;
+ }
+
+ // synchronized(__client) critical sections are to protect against
+ // TelnetOutputStream writing through the telnet client at same time
+ // as a processDo/Will/etc. command invoked from TelnetInputStream
+ // tries to write.
+ private void __processChar(int ch) throws InterruptedException
+ {
+ // Critical section because we're altering __bytesAvailable,
+ // __queueTail, and the contents of _queue.
+ synchronized (__queue)
+ {
+ while (__bytesAvailable >= __queue.length - 1)
+ {
+ // The queue is full. We need to wait before adding any more data to it. Hopefully the stream owner
+ // will consume some data soon!
+ if(__threaded)
+ {
+ __queue.notify();
+ try
+ {
+ __queue.wait();
+ }
+ catch (InterruptedException e)
+ {
+ throw e;
+ }
+ }
+ else
+ {
+ // We've been asked to add another character to the queue, but it is already full and there's
+ // no other thread to drain it. This should not have happened!
+ throw new IllegalStateException("Queue is full! Cannot process another character.");
+ }
+ }
+
+ // Need to do this in case we're not full, but block on a read
+ if (__readIsWaiting && __threaded)
+ {
+ __queue.notify();
+ }
+
+ __queue[__queueTail] = ch;
+ ++__bytesAvailable;
+
+ if (++__queueTail >= __queue.length)
+ __queueTail = 0;
+ }
+ }
+
+ @Override
+ public int read() throws IOException
+ {
+ // Critical section because we're altering __bytesAvailable,
+ // __queueHead, and the contents of _queue in addition to
+ // testing value of __hasReachedEOF.
+ synchronized (__queue)
+ {
+
+ while (true)
+ {
+ if (__ioException != null)
+ {
+ IOException e;
+ e = __ioException;
+ __ioException = null;
+ throw e;
+ }
+
+ if (__bytesAvailable == 0)
+ {
+ // Return -1 if at end of file
+ if (__hasReachedEOF)
+ return -1;
+
+ // Otherwise, we have to wait for queue to get something
+ if(__threaded)
+ {
+ __queue.notify();
+ try
+ {
+ __readIsWaiting = true;
+ __queue.wait();
+ __readIsWaiting = false;
+ }
+ catch (InterruptedException e)
+ {
+ throw new InterruptedIOException("Fatal thread interruption during read.");
+ }
+ }
+ else
+ {
+ //__alreadyread = false;
+ __readIsWaiting = true;
+ int ch;
+ boolean mayBlock = true; // block on the first read only
+
+ do
+ {
+ try
+ {
+ if ((ch = __read(mayBlock)) < 0)
+ if(ch != -2)
+ return (ch);
+ }
+ catch (InterruptedIOException e)
+ {
+ synchronized (__queue)
+ {
+ __ioException = e;
+ __queue.notifyAll();
+ try
+ {
+ __queue.wait(100);
+ }
+ catch (InterruptedException interrupted)
+ {
+ }
+ }
+ return (-1);
+ }
+
+
+ try
+ {
+ if(ch != -2)
+ {
+ __processChar(ch);
+ }
+ }
+ catch (InterruptedException e)
+ {
+ if (__isClosed)
+ return (-1);
+ }
+
+ // Reads should not block on subsequent iterations. Potentially, this could happen if the
+ // remaining buffered socket data consists entirely of Telnet command sequence and no "user" data.
+ mayBlock = false;
+
+ }
+ // Continue reading as long as there is data available and the queue is not full.
+ while (super.available() > 0 && __bytesAvailable < __queue.length - 1);
+
+ __readIsWaiting = false;
+ }
+ continue;
+ }
+ else
+ {
+ int ch;
+
+ ch = __queue[__queueHead];
+
+ if (++__queueHead >= __queue.length)
+ __queueHead = 0;
+
+ --__bytesAvailable;
+
+ // Need to explicitly notify() so available() works properly
+ if(__bytesAvailable == 0 && __threaded) {
+ __queue.notify();
+ }
+
+ return ch;
+ }
+ }
+ }
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and
+ * returns the number of bytes read. Returns -1 if the end of the
+ * stream has been reached.
+ *
+ * @param buffer The byte array in which to store the data.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the message has been reached.
+ * @exception IOException If an error occurs in reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[]) throws IOException
+ {
+ return read(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and returns
+ * the number of bytes read. Returns -1 if the end of the
+ * message has been reached. The characters are stored in the array
+ * starting from the given offset and up to the length specified.
+ *
+ * @param buffer The byte array in which to store the data.
+ * @param offset The offset into the array at which to start storing data.
+ * @param length The number of bytes to read.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the stream has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[], int offset, int length) throws IOException
+ {
+ int ch, off;
+
+ if (length < 1)
+ return 0;
+
+ // Critical section because run() may change __bytesAvailable
+ synchronized (__queue)
+ {
+ if (length > __bytesAvailable)
+ length = __bytesAvailable;
+ }
+
+ if ((ch = read()) == -1)
+ return -1;
+
+ off = offset;
+
+ do
+ {
+ buffer[offset++] = (byte)ch;
+ }
+ while (--length > 0 && (ch = read()) != -1);
+
+ //__client._spyRead(buffer, off, offset - off);
+ return (offset - off);
+ }
+
+
+ /*** Returns false. Mark is not supported. ***/
+ @Override
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ // Critical section because run() may change __bytesAvailable
+ synchronized (__queue)
+ {
+ return __bytesAvailable;
+ }
+ }
+
+
+ // Cannot be synchronized. Will cause deadlock if run() is blocked
+ // in read because BufferedInputStream read() is synchronized.
+ @Override
+ public void close() throws IOException
+ {
+ // Completely disregard the fact thread may still be running.
+ // We can't afford to block on this close by waiting for
+ // thread to terminate because few if any JVM's will actually
+ // interrupt a system read() from the interrupt() method.
+ super.close();
+
+ synchronized (__queue)
+ {
+ __hasReachedEOF = true;
+ __isClosed = true;
+
+ if (__thread != null && __thread.isAlive())
+ {
+ __thread.interrupt();
+ }
+
+ __queue.notifyAll();
+ }
+
+ __threaded = false;
+ }
+
+ public void run()
+ {
+ int ch;
+
+ try
+ {
+_outerLoop:
+ while (!__isClosed)
+ {
+ try
+ {
+ if ((ch = __read(true)) < 0)
+ break;
+ }
+ catch (InterruptedIOException e)
+ {
+ synchronized (__queue)
+ {
+ __ioException = e;
+ __queue.notifyAll();
+ try
+ {
+ __queue.wait(100);
+ }
+ catch (InterruptedException interrupted)
+ {
+ if (__isClosed)
+ break _outerLoop;
+ }
+ continue;
+ }
+ } catch(RuntimeException re) {
+ // We treat any runtime exceptions as though the
+ // stream has been closed. We close the
+ // underlying stream just to be sure.
+ super.close();
+ // Breaking the loop has the effect of setting
+ // the state to closed at the end of the method.
+ break _outerLoop;
+ }
+
+ try
+ {
+ __processChar(ch);
+ }
+ catch (InterruptedException e)
+ {
+ if (__isClosed)
+ break _outerLoop;
+ }
+ }
+ }
+ catch (IOException ioe)
+ {
+ synchronized (__queue)
+ {
+ __ioException = ioe;
+ }
+ }
+
+ synchronized (__queue)
+ {
+ __isClosed = true; // Possibly redundant
+ __hasReachedEOF = true;
+ __queue.notify();
+ }
+
+ __threaded = false;
+ }
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/org/apache/commons/net/telnet/TelnetNotificationHandler.java b/org/apache/commons/net/telnet/TelnetNotificationHandler.java
new file mode 100644
index 0000000..d509021
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetNotificationHandler.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * The TelnetNotificationHandler interface can be used to handle
+ * notification of options negotiation commands received on a telnet
+ * session.
+ *
+ * The user can implement this interface and register a
+ * TelnetNotificationHandler by using the registerNotificationHandler()
+ * of TelnetClient to be notified of option negotiation commands.
+ *
+ *
+ * @author Bruno D'Avanzo
+ ***/
+
+public interface TelnetNotificationHandler
+{
+ /***
+ * The remote party sent a DO command.
+ ***/
+ public static final int RECEIVED_DO = 1;
+
+ /***
+ * The remote party sent a DONT command.
+ ***/
+ public static final int RECEIVED_DONT = 2;
+
+ /***
+ * The remote party sent a WILL command.
+ ***/
+ public static final int RECEIVED_WILL = 3;
+
+ /***
+ * The remote party sent a WONT command.
+ ***/
+ public static final int RECEIVED_WONT = 4;
+
+ /***
+ * Callback method called when TelnetClient receives an option
+ * negotiation command.
+ *
+ * @param negotiation_code - type of negotiation command received
+ * (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT)
+ *
+ * @param option_code - code of the option negotiated
+ *
+ ***/
+ public void receivedNegotiation(int negotiation_code, int option_code);
+}
diff --git a/org/apache/commons/net/telnet/TelnetOption.java b/org/apache/commons/net/telnet/TelnetOption.java
new file mode 100644
index 0000000..77799b6
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetOption.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * The TelnetOption class cannot be instantiated and only serves as a
+ * storehouse for telnet option constants.
+ *
+ * Details regarding Telnet option specification can be found in RFC 855.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see org.apache.commons.net.telnet.Telnet
+ * @see org.apache.commons.net.telnet.TelnetClient
+ ***/
+
+public class TelnetOption
+{
+ /*** The maximum value an option code can have. This value is 255. ***/
+ public static final int MAX_OPTION_VALUE = 255;
+
+ public static final int BINARY = 0;
+
+ public static final int ECHO = 1;
+
+ public static final int PREPARE_TO_RECONNECT = 2;
+
+ public static final int SUPPRESS_GO_AHEAD = 3;
+
+ public static final int APPROXIMATE_MESSAGE_SIZE = 4;
+
+ public static final int STATUS = 5;
+
+ public static final int TIMING_MARK = 6;
+
+ public static final int REMOTE_CONTROLLED_TRANSMISSION = 7;
+
+ public static final int NEGOTIATE_OUTPUT_LINE_WIDTH = 8;
+
+ public static final int NEGOTIATE_OUTPUT_PAGE_SIZE = 9;
+
+ public static final int NEGOTIATE_CARRIAGE_RETURN = 10;
+
+ public static final int NEGOTIATE_HORIZONTAL_TAB_STOP = 11;
+
+ public static final int NEGOTIATE_HORIZONTAL_TAB = 12;
+
+ public static final int NEGOTIATE_FORMFEED = 13;
+
+ public static final int NEGOTIATE_VERTICAL_TAB_STOP = 14;
+
+ public static final int NEGOTIATE_VERTICAL_TAB = 15;
+
+ public static final int NEGOTIATE_LINEFEED = 16;
+
+ public static final int EXTENDED_ASCII = 17;
+
+ public static final int FORCE_LOGOUT = 18;
+
+ public static final int BYTE_MACRO = 19;
+
+ public static final int DATA_ENTRY_TERMINAL = 20;
+
+ public static final int SUPDUP = 21;
+
+ public static final int SUPDUP_OUTPUT = 22;
+
+ public static final int SEND_LOCATION = 23;
+
+ public static final int TERMINAL_TYPE = 24;
+
+ public static final int END_OF_RECORD = 25;
+
+ public static final int TACACS_USER_IDENTIFICATION = 26;
+
+ public static final int OUTPUT_MARKING = 27;
+
+ public static final int TERMINAL_LOCATION_NUMBER = 28;
+
+ public static final int REGIME_3270 = 29;
+
+ public static final int X3_PAD = 30;
+
+ public static final int WINDOW_SIZE = 31;
+
+ public static final int TERMINAL_SPEED = 32;
+
+ public static final int REMOTE_FLOW_CONTROL = 33;
+
+ public static final int LINEMODE = 34;
+
+ public static final int X_DISPLAY_LOCATION = 35;
+
+ public static final int OLD_ENVIRONMENT_VARIABLES = 36;
+
+ public static final int AUTHENTICATION = 37;
+
+ public static final int ENCRYPTION = 38;
+
+ public static final int NEW_ENVIRONMENT_VARIABLES = 39;
+
+ public static final int EXTENDED_OPTIONS_LIST = 255;
+
+ private static final int __FIRST_OPTION = BINARY;
+ private static final int __LAST_OPTION = EXTENDED_OPTIONS_LIST;
+
+ private static final String __optionString[] = {
+ "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS",
+ "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD",
+ "NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT",
+ "BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
+ "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID",
+ "OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED",
+ "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
+ "ENCRYPT", "NEW-ENVIRON", "TN3270E", "XAUTH", "CHARSET", "RSP",
+ "Com Port Control", "Suppress Local Echo", "Start TLS",
+ "KERMIT", "SEND-URL", "FORWARD_X", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "TELOPT PRAGMA LOGON", "TELOPT SSPI LOGON",
+ "TELOPT PRAGMA HEARTBEAT", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "Extended-Options-List"
+ };
+
+
+ /***
+ * Returns the string representation of the telnet protocol option
+ * corresponding to the given option code.
+ *
+ * @param code The option code of the telnet protocol option
+ * @return The string representation of the telnet protocol option.
+ ***/
+ public static final String getOption(int code)
+ {
+ if(__optionString[code].length() == 0)
+ {
+ return "UNASSIGNED";
+ }
+ else
+ {
+ return __optionString[code];
+ }
+ }
+
+
+ /***
+ * Determines if a given option code is valid. Returns true if valid,
+ * false if not.
+ *
+ * @param code The option code to test.
+ * @return True if the option code is valid, false if not.
+ **/
+ public static final boolean isValidOption(int code)
+ {
+ return (code <= __LAST_OPTION);
+ }
+
+ // Cannot be instantiated
+ private TelnetOption()
+ { }
+}
diff --git a/org/apache/commons/net/telnet/TelnetOptionHandler.java b/org/apache/commons/net/telnet/TelnetOptionHandler.java
new file mode 100644
index 0000000..52486ba
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetOptionHandler.java
@@ -0,0 +1,272 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * The TelnetOptionHandler class is the base class to be used
+ * for implementing handlers for telnet options.
+ *
+ * TelnetOptionHandler implements basic option handling
+ * functionality and defines abstract methods that must be
+ * implemented to define subnegotiation behaviour.
+ *
+ * @author Bruno D'Avanzo
+ ***/
+public abstract class TelnetOptionHandler
+{
+ /***
+ * Option code
+ ***/
+ private int optionCode = -1;
+
+ /***
+ * true if the option should be activated on the local side
+ ***/
+ private boolean initialLocal = false;
+
+ /***
+ * true if the option should be activated on the remote side
+ ***/
+ private boolean initialRemote = false;
+
+ /***
+ * true if the option should be accepted on the local side
+ ***/
+ private boolean acceptLocal = false;
+
+ /***
+ * true if the option should be accepted on the remote side
+ ***/
+ private boolean acceptRemote = false;
+
+ /***
+ * true if the option is active on the local side
+ ***/
+ private boolean doFlag = false;
+
+ /***
+ * true if the option is active on the remote side
+ ***/
+ private boolean willFlag = false;
+
+ /***
+ * Constructor for the TelnetOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ *
+ * @param optcode - Option code.
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public TelnetOptionHandler(int optcode,
+ boolean initlocal,
+ boolean initremote,
+ boolean acceptlocal,
+ boolean acceptremote)
+ {
+ optionCode = optcode;
+ initialLocal = initlocal;
+ initialRemote = initremote;
+ acceptLocal = acceptlocal;
+ acceptRemote = acceptremote;
+ }
+
+
+ /***
+ * Returns the option code for this option.
+ *
+ * @return Option code.
+ ***/
+ public int getOptionCode()
+ {
+ return (optionCode);
+ }
+
+ /***
+ * Returns a boolean indicating whether to accept a DO
+ * request coming from the other end.
+ *
+ * @return true if a DO request shall be accepted.
+ ***/
+ public boolean getAcceptLocal()
+ {
+ return (acceptLocal);
+ }
+
+ /***
+ * Returns a boolean indicating whether to accept a WILL
+ * request coming from the other end.
+ *
+ * @return true if a WILL request shall be accepted.
+ ***/
+ public boolean getAcceptRemote()
+ {
+ return (acceptRemote);
+ }
+
+ /***
+ * Set behaviour of the option for DO requests coming from
+ * the other end.
+ *
+ * @param accept - if true, subsequent DO requests will be accepted.
+ ***/
+ public void setAcceptLocal(boolean accept)
+ {
+ acceptLocal = accept;
+ }
+
+ /***
+ * Set behaviour of the option for WILL requests coming from
+ * the other end.
+ *
+ * @param accept - if true, subsequent WILL requests will be accepted.
+ ***/
+ public void setAcceptRemote(boolean accept)
+ {
+ acceptRemote = accept;
+ }
+
+ /***
+ * Returns a boolean indicating whether to send a WILL request
+ * to the other end upon connection.
+ *
+ * @return true if a WILL request shall be sent upon connection.
+ ***/
+ public boolean getInitLocal()
+ {
+ return (initialLocal);
+ }
+
+ /***
+ * Returns a boolean indicating whether to send a DO request
+ * to the other end upon connection.
+ *
+ * @return true if a DO request shall be sent upon connection.
+ ***/
+ public boolean getInitRemote()
+ {
+ return (initialRemote);
+ }
+
+ /***
+ * Tells this option whether to send a WILL request upon connection.
+ *
+ * @param init - if true, a WILL request will be sent upon subsequent
+ * connections.
+ ***/
+ public void setInitLocal(boolean init)
+ {
+ initialLocal = init;
+ }
+
+ /***
+ * Tells this option whether to send a DO request upon connection.
+ *
+ * @param init - if true, a DO request will be sent upon subsequent
+ * connections.
+ ***/
+ public void setInitRemote(boolean init)
+ {
+ initialRemote = init;
+ }
+
+ /***
+ * Method called upon reception of a subnegotiation for this option
+ * coming from the other end.
+ * Must be implemented by the actual TelnetOptionHandler to specify
+ * which response must be sent for the subnegotiation request.
+ *
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ *
+ * @return response to be sent to the subnegotiation sequence. TelnetClient
+ * will add IAC SB & IAC SE. null means no response
+ ***/
+ public abstract int[] answerSubnegotiation(int suboptionData[],
+ int suboptionLength);
+
+ /***
+ * This method is invoked whenever this option is acknowledged active on
+ * the local end (TelnetClient sent a WILL, remote side sent a DO).
+ * The method is used to specify a subnegotiation sequence that will be
+ * sent by TelnetClient when the option is activated.
+ *
+ * @return subnegotiation sequence to be sent by TelnetClient. TelnetClient
+ * will add IAC SB & IAC SE. null means no subnegotiation.
+ ***/
+ public abstract int[] startSubnegotiationLocal();
+
+ /***
+ * This method is invoked whenever this option is acknowledged active on
+ * the remote end (TelnetClient sent a DO, remote side sent a WILL).
+ * The method is used to specify a subnegotiation sequence that will be
+ * sent by TelnetClient when the option is activated.
+ *
+ * @return subnegotiation sequence to be sent by TelnetClient. TelnetClient
+ * will add IAC SB & IAC SE. null means no subnegotiation.
+ ***/
+ public abstract int[] startSubnegotiationRemote();
+
+ /***
+ * Returns a boolean indicating whether a WILL request sent to the other
+ * side has been acknowledged.
+ *
+ * @return true if a WILL sent to the other side has been acknowledged.
+ ***/
+ boolean getWill()
+ {
+ return willFlag;
+ }
+
+ /***
+ * Tells this option whether a WILL request sent to the other
+ * side has been acknowledged (invoked by TelnetClient).
+ *
+ * @param state - if true, a WILL request has been acknowledged.
+ ***/
+ void setWill(boolean state)
+ {
+ willFlag = state;
+ }
+
+ /***
+ * Returns a boolean indicating whether a DO request sent to the other
+ * side has been acknowledged.
+ *
+ * @return true if a DO sent to the other side has been acknowledged.
+ ***/
+ boolean getDo()
+ {
+ return doFlag;
+ }
+
+
+ /***
+ * Tells this option whether a DO request sent to the other
+ * side has been acknowledged (invoked by TelnetClient).
+ *
+ * @param state - if true, a DO request has been acknowledged.
+ ***/
+ void setDo(boolean state)
+ {
+ doFlag = state;
+ }
+}
diff --git a/org/apache/commons/net/telnet/TelnetOutputStream.java b/org/apache/commons/net/telnet/TelnetOutputStream.java
new file mode 100644
index 0000000..fd796d1
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetOutputStream.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/***
+ *
+ *
+ *
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+
+final class TelnetOutputStream extends OutputStream
+{
+ private TelnetClient __client;
+ private boolean __convertCRtoCRLF = true;
+ private boolean __lastWasCR = false;
+
+ TelnetOutputStream(TelnetClient client)
+ {
+ __client = client;
+ }
+
+
+ /***
+ * Writes a byte to the stream.
+ *
+ * @param ch The byte to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public void write(int ch) throws IOException
+ {
+
+ synchronized (__client)
+ {
+ ch &= 0xff;
+
+ if (__client._requestedWont(TelnetOption.BINARY))
+ {
+ if (__lastWasCR)
+ {
+ if (__convertCRtoCRLF)
+ {
+ __client._sendByte('\n');
+ if (ch == '\n')
+ {
+ __lastWasCR = false;
+ return ;
+ }
+ }
+ else if (ch != '\n')
+ __client._sendByte('\0');
+ }
+
+ __lastWasCR = false;
+
+ switch (ch)
+ {
+ case '\r':
+ __client._sendByte('\r');
+ __lastWasCR = true;
+ break;
+ case TelnetCommand.IAC:
+ __client._sendByte(TelnetCommand.IAC);
+ __client._sendByte(TelnetCommand.IAC);
+ break;
+ default:
+ __client._sendByte(ch);
+ break;
+ }
+ }
+ else if (ch == TelnetCommand.IAC)
+ {
+ __client._sendByte(ch);
+ __client._sendByte(TelnetCommand.IAC);
+ }
+ else
+ __client._sendByte(ch);
+ }
+ }
+
+
+ /***
+ * Writes a byte array to the stream.
+ *
+ * @param buffer The byte array to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public void write(byte buffer[]) throws IOException
+ {
+ write(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Writes a number of bytes from a byte array to the stream starting from
+ * a given offset.
+ *
+ * @param buffer The byte array to write.
+ * @param offset The offset into the array at which to start copying data.
+ * @param length The number of bytes to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public void write(byte buffer[], int offset, int length) throws IOException
+ {
+ synchronized (__client)
+ {
+ while (length-- > 0)
+ write(buffer[offset++]);
+ }
+ }
+
+ /*** Flushes the stream. ***/
+ @Override
+ public void flush() throws IOException
+ {
+ __client._flushOutputStream();
+ }
+
+ /*** Closes the stream. ***/
+ @Override
+ public void close() throws IOException
+ {
+ __client._closeOutputStream();
+ }
+}
diff --git a/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java b/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java
new file mode 100644
index 0000000..0cbe0c0
--- /dev/null
+++ b/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Implements the telnet terminal type option RFC 1091.
+ *
+ * @author Bruno D'Avanzo
+ ***/
+public class TerminalTypeOptionHandler extends TelnetOptionHandler
+{
+ /***
+ * Terminal type
+ ***/
+ private String termType = null;
+
+ /***
+ * Terminal type option
+ ***/
+ protected static final int TERMINAL_TYPE = 24;
+
+ /***
+ * Send (for subnegotiation)
+ ***/
+ protected static final int TERMINAL_TYPE_SEND = 1;
+
+ /***
+ * Is (for subnegotiation)
+ ***/
+ protected static final int TERMINAL_TYPE_IS = 0;
+
+ /***
+ * Constructor for the TerminalTypeOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ *
+ * @param termtype - terminal type that will be negotiated.
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public TerminalTypeOptionHandler(String termtype,
+ boolean initlocal,
+ boolean initremote,
+ boolean acceptlocal,
+ boolean acceptremote)
+ {
+ super(TelnetOption.TERMINAL_TYPE, initlocal, initremote,
+ acceptlocal, acceptremote);
+ termType = termtype;
+ }
+
+ /***
+ * Constructor for the TerminalTypeOptionHandler. Initial and accept
+ * behaviour flags are set to false
+ *
+ * @param termtype - terminal type that will be negotiated.
+ ***/
+ public TerminalTypeOptionHandler(String termtype)
+ {
+ super(TelnetOption.TERMINAL_TYPE, false, false, false, false);
+ termType = termtype;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ *
+ * @return terminal type information
+ ***/
+ @Override
+ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
+ {
+ if ((suboptionData != null) && (suboptionLength > 1)
+ && (termType != null))
+ {
+ if ((suboptionData[0] == TERMINAL_TYPE)
+ && (suboptionData[1] == TERMINAL_TYPE_SEND))
+ {
+ int response[] = new int[termType.length() + 2];
+
+ response[0] = TERMINAL_TYPE;
+ response[1] = TERMINAL_TYPE_IS;
+
+ for (int ii = 0; ii < termType.length(); ii++)
+ {
+ response[ii + 2] = termType.charAt(ii);
+ }
+
+ return response;
+ }
+ }
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationLocal()
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationRemote()
+ {
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/telnet/WindowSizeOptionHandler.java b/org/apache/commons/net/telnet/WindowSizeOptionHandler.java
new file mode 100644
index 0000000..34bb46f
--- /dev/null
+++ b/org/apache/commons/net/telnet/WindowSizeOptionHandler.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Implements the telnet window size option RFC 1073.
+ *
+ * @author Yuval Kashtan
+ * @version $Id: WindowSizeOptionHandler.java 658520 2008-05-21 01:14:11Z sebb $
+ * @since 2.0
+ ***/
+public class WindowSizeOptionHandler extends TelnetOptionHandler
+{
+ /***
+ * Horizontal Size
+ ***/
+ private int m_nWidth = 80;
+
+ /***
+ * Vertical Size
+ ***/
+ private int m_nHeight = 24;
+
+ /***
+ * Window size option
+ ***/
+ protected static final int WINDOW_SIZE = 31;
+
+ /***
+ * Constructor for the WindowSizeOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ *
+ * @param nWidth - Window width.
+ * @param nHeight - Window Height
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public WindowSizeOptionHandler(
+ int nWidth,
+ int nHeight,
+ boolean initlocal,
+ boolean initremote,
+ boolean acceptlocal,
+ boolean acceptremote
+ ) {
+ super (
+ TelnetOption.WINDOW_SIZE,
+ initlocal,
+ initremote,
+ acceptlocal,
+ acceptremote
+ );
+
+ m_nWidth = nWidth;
+ m_nHeight = nHeight;
+ }
+
+ /***
+ * Constructor for the WindowSizeOptionHandler. Initial and accept
+ * behaviour flags are set to false
+ *
+ * @param nWidth - Window width.
+ * @param nHeight - Window Height
+ ***/
+ public WindowSizeOptionHandler(
+ int nWidth,
+ int nHeight
+ ) {
+ super (
+ TelnetOption.WINDOW_SIZE,
+ false,
+ false,
+ false,
+ false
+ );
+
+ m_nWidth = nWidth;
+ m_nHeight = nHeight;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ *
+ * @return terminal type information
+ ***/
+ @Override
+ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * This will send the client Height and Width to the server.
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationLocal()
+ {
+ int nCompoundWindowSize = m_nWidth * 0x10000 + m_nHeight;
+ int nResponseSize = 5;
+ int nIndex;
+ int nShift;
+ int nTurnedOnBits;
+
+ if ((m_nWidth % 0x100) == 0xFF) {
+ nResponseSize += 1;
+ }
+
+ if ((m_nWidth / 0x100) == 0xFF) {
+ nResponseSize += 1;
+ }
+
+ if ((m_nHeight % 0x100) == 0xFF) {
+ nResponseSize += 1;
+ }
+
+ if ((m_nHeight / 0x100) == 0xFF) {
+ nResponseSize += 1;
+ }
+
+ //
+ // allocate response array
+ //
+ int response[] = new int[nResponseSize];
+
+ //
+ // Build response array.
+ // ---------------------
+ // 1. put option name.
+ // 2. loop through Window size and fill the values,
+ // 3. duplicate 'ff' if needed.
+ //
+
+ response[0] = WINDOW_SIZE; // 1 //
+
+ for ( // 2 //
+ nIndex=1, nShift = 24;
+ nIndex < nResponseSize;
+ nIndex++, nShift -=8
+ ) {
+ nTurnedOnBits = 0xFF;
+ nTurnedOnBits <<= nShift;
+ response[nIndex] = (nCompoundWindowSize & nTurnedOnBits) >>> nShift;
+
+ if (response[nIndex] == 0xff) { // 3 //
+ nIndex++;
+ response[nIndex] = 0xff;
+ }
+ }
+
+ return response;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ *
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationRemote()
+ {
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/tftp/TFTP.java b/org/apache/commons/net/tftp/TFTP.java
new file mode 100644
index 0000000..662da11
--- /dev/null
+++ b/org/apache/commons/net/tftp/TFTP.java
@@ -0,0 +1,301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.tftp;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.DatagramPacket;
+import java.net.SocketException;
+
+import org.apache.commons.net.DatagramSocketClient;
+
+/***
+ * The TFTP class exposes a set of methods to allow you to deal with the TFTP
+ * protocol directly, in case you want to write your own TFTP client or
+ * server. However, almost every user should only be concerend with
+ * the {@link org.apache.commons.net.DatagramSocketClient#open open() },
+ * and {@link org.apache.commons.net.DatagramSocketClient#close close() },
+ * methods. Additionally,the a
+ * {@link org.apache.commons.net.DatagramSocketClient#setDefaultTimeout setDefaultTimeout() }
+ * method may be of importance for performance tuning.
+ *
+ * Details regarding the TFTP protocol and the format of TFTP packets can
+ * be found in RFC 783. But the point of these classes is to keep you
+ * from having to worry about the internals.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see org.apache.commons.net.DatagramSocketClient
+ * @see TFTPPacket
+ * @see TFTPPacketException
+ * @see TFTPClient
+ ***/
+
+public class TFTP extends DatagramSocketClient
+{
+ /***
+ * The ascii transfer mode. Its value is 0 and equivalent to NETASCII_MODE
+ ***/
+ public static final int ASCII_MODE = 0;
+
+ /***
+ * The netascii transfer mode. Its value is 0.
+ ***/
+ public static final int NETASCII_MODE = 0;
+
+ /***
+ * The binary transfer mode. Its value is 1 and equivalent to OCTET_MODE.
+ ***/
+ public static final int BINARY_MODE = 1;
+
+ /***
+ * The image transfer mode. Its value is 1 and equivalent to OCTET_MODE.
+ ***/
+ public static final int IMAGE_MODE = 1;
+
+ /***
+ * The octet transfer mode. Its value is 1.
+ ***/
+ public static final int OCTET_MODE = 1;
+
+ /***
+ * The default number of milliseconds to wait to receive a datagram
+ * before timing out. The default is 5000 milliseconds (5 seconds).
+ ***/
+ public static final int DEFAULT_TIMEOUT = 5000;
+
+ /***
+ * The default TFTP port according to RFC 783 is 69.
+ ***/
+ public static final int DEFAULT_PORT = 69;
+
+ /***
+ * The size to use for TFTP packet buffers. Its 4 plus the
+ * TFTPPacket.SEGMENT_SIZE, i.e. 516.
+ ***/
+ static final int PACKET_SIZE = TFTPPacket.SEGMENT_SIZE + 4;
+
+ /*** A buffer used to accelerate receives in bufferedReceive() ***/
+ private byte[] __receiveBuffer;
+
+ /*** A datagram used to minimize memory allocation in bufferedReceive() ***/
+ private DatagramPacket __receiveDatagram;
+
+ /*** A datagram used to minimize memory allocation in bufferedSend() ***/
+ private DatagramPacket __sendDatagram;
+
+ /***
+ * A buffer used to accelerate sends in bufferedSend().
+ * It is left package visible so that TFTPClient may be slightly more
+ * efficient during file sends. It saves the creation of an
+ * additional buffer and prevents a buffer copy in _newDataPcket().
+ ***/
+ byte[] _sendBuffer;
+
+
+ /***
+ * Returns the TFTP string representation of a TFTP transfer mode.
+ * Will throw an ArrayIndexOutOfBoundsException if an invalid transfer
+ * mode is specified.
+ *
+ * @param mode The TFTP transfer mode. One of the MODE constants.
+ * @return The TFTP string representation of the TFTP transfer mode.
+ ***/
+ public static final String getModeName(int mode)
+ {
+ return TFTPRequestPacket._modeStrings[mode];
+ }
+
+ /***
+ * Creates a TFTP instance with a default timeout of DEFAULT_TIMEOUT,
+ * a null socket, and buffered operations disabled.
+ ***/
+ public TFTP()
+ {
+ setDefaultTimeout(DEFAULT_TIMEOUT);
+ __receiveBuffer = null;
+ __receiveDatagram = null;
+ }
+
+ /***
+ * This method synchronizes a connection by discarding all packets that
+ * may be in the local socket buffer. This method need only be called
+ * when you implement your own TFTP client or server.
+ *
+ * @exception IOException if an I/O error occurs.
+ ***/
+ public final void discardPackets() throws IOException
+ {
+ int to;
+ DatagramPacket datagram;
+
+ datagram = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE);
+
+ to = getSoTimeout();
+ setSoTimeout(1);
+
+ try
+ {
+ while (true)
+ _socket_.receive(datagram);
+ }
+ catch (SocketException e)
+ {
+ // Do nothing. We timed out so we hope we're caught up.
+ }
+ catch (InterruptedIOException e)
+ {
+ // Do nothing. We timed out so we hope we're caught up.
+ }
+
+ setSoTimeout(to);
+ }
+
+
+ /***
+ * This is a special method to perform a more efficient packet receive.
+ * It should only be used after calling
+ * {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps()
+ * initializes a set of buffers used internally that prevent the new
+ * allocation of a DatagramPacket and byte array for each send and receive.
+ * To use these buffers you must call the bufferedReceive() and
+ * bufferedSend() methods instead of send() and receive(). You must
+ * also be certain that you don't manipulate the resulting packet in
+ * such a way that it interferes with future buffered operations.
+ * For example, a TFTPDataPacket received with bufferedReceive() will
+ * have a reference to the internal byte buffer. You must finish using
+ * this data before calling bufferedReceive() again, or else the data
+ * will be overwritten by the the call.
+ *
+ * @return The TFTPPacket received.
+ * @exception InterruptedIOException If a socket timeout occurs. The
+ * Java documentation claims an InterruptedIOException is thrown
+ * on a DatagramSocket timeout, but in practice we find a
+ * SocketException is thrown. You should catch both to be safe.
+ * @exception SocketException If a socket timeout occurs. The
+ * Java documentation claims an InterruptedIOException is thrown
+ * on a DatagramSocket timeout, but in practice we find a
+ * SocketException is thrown. You should catch both to be safe.
+ * @exception IOException If some other I/O error occurs.
+ * @exception TFTPPacketException If an invalid TFTP packet is received.
+ ***/
+ public final TFTPPacket bufferedReceive() throws IOException,
+ InterruptedIOException, SocketException, TFTPPacketException
+ {
+ __receiveDatagram.setData(__receiveBuffer);
+ __receiveDatagram.setLength(__receiveBuffer.length);
+ _socket_.receive(__receiveDatagram);
+
+ return TFTPPacket.newTFTPPacket(__receiveDatagram);
+ }
+
+ /***
+ * This is a special method to perform a more efficient packet send.
+ * It should only be used after calling
+ * {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps()
+ * initializes a set of buffers used internally that prevent the new
+ * allocation of a DatagramPacket and byte array for each send and receive.
+ * To use these buffers you must call the bufferedReceive() and
+ * bufferedSend() methods instead of send() and receive(). You must
+ * also be certain that you don't manipulate the resulting packet in
+ * such a way that it interferes with future buffered operations.
+ * For example, a TFTPDataPacket received with bufferedReceive() will
+ * have a reference to the internal byte buffer. You must finish using
+ * this data before calling bufferedReceive() again, or else the data
+ * will be overwritten by the the call.
+ *
+ * @param packet The TFTP packet to send.
+ * @exception IOException If some I/O error occurs.
+ ***/
+ public final void bufferedSend(TFTPPacket packet) throws IOException
+ {
+ _socket_.send(packet._newDatagram(__sendDatagram, _sendBuffer));
+ }
+
+
+ /***
+ * Initializes the internal buffers. Buffers are used by
+ * {@link #bufferedSend bufferedSend() } and
+ * {@link #bufferedReceive bufferedReceive() }. This
+ * method must be called before calling either one of those two
+ * methods. When you finish using buffered operations, you must
+ * call {@link #endBufferedOps endBufferedOps() }.
+ ***/
+ public final void beginBufferedOps()
+ {
+ __receiveBuffer = new byte[PACKET_SIZE];
+ __receiveDatagram =
+ new DatagramPacket(__receiveBuffer, __receiveBuffer.length);
+ _sendBuffer = new byte[PACKET_SIZE];
+ __sendDatagram =
+ new DatagramPacket(_sendBuffer, _sendBuffer.length);
+ }
+
+ /***
+ * Releases the resources used to perform buffered sends and receives.
+ ***/
+ public final void endBufferedOps()
+ {
+ __receiveBuffer = null;
+ __receiveDatagram = null;
+ _sendBuffer = null;
+ __sendDatagram = null;
+ }
+
+
+ /***
+ * Sends a TFTP packet to its destination.
+ *
+ * @param packet The TFTP packet to send.
+ * @exception IOException If some I/O error occurs.
+ ***/
+ public final void send(TFTPPacket packet) throws IOException
+ {
+ _socket_.send(packet.newDatagram());
+ }
+
+
+ /***
+ * Receives a TFTPPacket.
+ *
+ * @return The TFTPPacket received.
+ * @exception InterruptedIOException If a socket timeout occurs. The
+ * Java documentation claims an InterruptedIOException is thrown
+ * on a DatagramSocket timeout, but in practice we find a
+ * SocketException is thrown. You should catch both to be safe.
+ * @exception SocketException If a socket timeout occurs. The
+ * Java documentation claims an InterruptedIOException is thrown
+ * on a DatagramSocket timeout, but in practice we find a
+ * SocketException is thrown. You should catch both to be safe.
+ * @exception IOException If some other I/O error occurs.
+ * @exception TFTPPacketException If an invalid TFTP packet is received.
+ ***/
+ public final TFTPPacket receive() throws IOException, InterruptedIOException,
+ SocketException, TFTPPacketException
+ {
+ DatagramPacket packet;
+
+ packet = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE);
+
+ _socket_.receive(packet);
+
+ return TFTPPacket.newTFTPPacket(packet);
+ }
+
+
+}
diff --git a/org/apache/commons/net/tftp/TFTPAckPacket.java b/org/apache/commons/net/tftp/TFTPAckPacket.java
new file mode 100644
index 0000000..a0fe7f9
--- /dev/null
+++ b/org/apache/commons/net/tftp/TFTPAckPacket.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.tftp;
+
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+/***
+ * A final class derived from TFTPPacket definiing the TFTP Acknowledgement
+ * packet type.
+ *
+ * Details regarding the TFTP protocol and the format of TFTP packets can
+ * be found in RFC 783. But the point of these classes is to keep you
+ * from having to worry about the internals. Additionally, only very
+ * few people should have to care about any of the TFTPPacket classes
+ * or derived classes. Almost all users should only be concerned with the
+ * {@link org.apache.commons.net.tftp.TFTPClient} class
+ * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
+ * and
+ * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
+ * methods.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TFTPPacket
+ * @see TFTPPacketException
+ * @see TFTP
+ ***/
+
+public final class TFTPAckPacket extends TFTPPacket
+{
+ /*** The block number being acknowledged by the packet. ***/
+ int _blockNumber;
+
+ /***
+ * Creates an acknowledgment packet to be sent to a host at a given port
+ * acknowledging receipt of a block.
+ *
+ * @param destination The host to which the packet is going to be sent.
+ * @param port The port to which the packet is going to be sent.
+ * @param blockNumber The block number being acknowledged.
+ ***/
+ public TFTPAckPacket(InetAddress destination, int port, int blockNumber)
+ {
+ super(TFTPPacket.ACKNOWLEDGEMENT, destination, port);
+ _blockNumber = blockNumber;
+ }
+
+ /***
+ * Creates an acknowledgement packet based from a received
+ * datagram. Assumes the datagram is at least length 4, else an
+ * ArrayIndexOutOfBoundsException may be thrown.
+ *
+ * @param datagram The datagram containing the received acknowledgement.
+ * @throws TFTPPacketException If the datagram isn't a valid TFTP
+ * acknowledgement packet.
+ ***/
+ TFTPAckPacket(DatagramPacket datagram) throws TFTPPacketException
+ {
+ super(TFTPPacket.ACKNOWLEDGEMENT, datagram.getAddress(),
+ datagram.getPort());
+ byte[] data;
+
+ data = datagram.getData();
+
+ if (getType() != data[1])
+ throw new TFTPPacketException("TFTP operator code does not match type.");
+
+ _blockNumber = (((data[2] & 0xff) << 8) | (data[3] & 0xff));
+ }
+
+ /***
+ * This is a method only available within the package for
+ * implementing efficient datagram transport by elminating buffering.
+ * It takes a datagram as an argument, and a byte buffer in which
+ * to store the raw datagram data. Inside the method, the data
+ * is set as the datagram's data and the datagram returned.
+ *
+ * @param datagram The datagram to create.
+ * @param data The buffer to store the packet and to use in the datagram.
+ * @return The datagram argument.
+ ***/
+ @Override
+ DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data)
+ {
+ data[0] = 0;
+ data[1] = (byte)_type;
+ data[2] = (byte)((_blockNumber & 0xffff) >> 8);
+ data[3] = (byte)(_blockNumber & 0xff);
+
+ datagram.setAddress(_address);
+ datagram.setPort(_port);
+ datagram.setData(data);
+ datagram.setLength(4);
+
+ return datagram;
+ }
+
+
+ /***
+ * Creates a UDP datagram containing all the TFTP
+ * acknowledgement packet data in the proper format.
+ * This is a method exposed to the programmer in case he
+ * wants to implement his own TFTP client instead of using
+ * the {@link org.apache.commons.net.tftp.TFTPClient}
+ * class. Under normal circumstances, you should not have a need to call this
+ * method.
+ *
+ * @return A UDP datagram containing the TFTP acknowledgement packet.
+ ***/
+ @Override
+ public DatagramPacket newDatagram()
+ {
+ byte[] data;
+
+ data = new byte[4];
+ data[0] = 0;
+ data[1] = (byte)_type;
+ data[2] = (byte)((_blockNumber & 0xffff) >> 8);
+ data[3] = (byte)(_blockNumber & 0xff);
+
+ return new DatagramPacket(data, data.length, _address, _port);
+ }
+
+
+ /***
+ * Returns the block number of the acknowledgement.
+ *
+ * @return The block number of the acknowledgement.
+ ***/
+ public int getBlockNumber()
+ {
+ return _blockNumber;
+ }
+
+
+ /*** Sets the block number of the acknowledgement. ***/
+ public void setBlockNumber(int blockNumber)
+ {
+ _blockNumber = blockNumber;
+ }
+}
+
diff --git a/org/apache/commons/net/tftp/TFTPClient.java b/org/apache/commons/net/tftp/TFTPClient.java
new file mode 100644
index 0000000..71d4ec6
--- /dev/null
+++ b/org/apache/commons/net/tftp/TFTPClient.java
@@ -0,0 +1,610 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.tftp;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import org.apache.commons.net.io.FromNetASCIIOutputStream;
+import org.apache.commons.net.io.ToNetASCIIInputStream;
+
+/***
+ * The TFTPClient class encapsulates all the aspects of the TFTP protocol
+ * necessary to receive and send files through TFTP. It is derived from
+ * the {@link org.apache.commons.net.tftp.TFTP} because
+ * it is more convenient than using aggregation, and as a result exposes
+ * the same set of methods to allow you to deal with the TFTP protocol
+ * directly. However, almost every user should only be concerend with the
+ * the {@link org.apache.commons.net.DatagramSocketClient#open open() },
+ * {@link org.apache.commons.net.DatagramSocketClient#close close() },
+ * {@link #sendFile sendFile() }, and
+ * {@link #receiveFile receiveFile() } methods. Additionally, the
+ * {@link #setMaxTimeouts setMaxTimeouts() } and
+ * {@link org.apache.commons.net.DatagramSocketClient#setDefaultTimeout setDefaultTimeout() }
+ * methods may be of importance for performance
+ * tuning.
+ *
+ * Details regarding the TFTP protocol and the format of TFTP packets can
+ * be found in RFC 783. But the point of these classes is to keep you
+ * from having to worry about the internals.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TFTP
+ * @see TFTPPacket
+ * @see TFTPPacketException
+ ***/
+
+public class TFTPClient extends TFTP
+{
+ /***
+ * The default number of times a receive attempt is allowed to timeout
+ * before ending attempts to retry the receive and failing. The default
+ * is 5 timeouts.
+ ***/
+ public static final int DEFAULT_MAX_TIMEOUTS = 5;
+
+ /*** The maximum number of timeouts allowed before failing. ***/
+ private int __maxTimeouts;
+
+ /***
+ * Creates a TFTPClient instance with a default timeout of DEFAULT_TIMEOUT,
+ * maximum timeouts value of DEFAULT_MAX_TIMEOUTS, a null socket,
+ * and buffered operations disabled.
+ ***/
+ public TFTPClient()
+ {
+ __maxTimeouts = DEFAULT_MAX_TIMEOUTS;
+ }
+
+ /***
+ * Sets the maximum number of times a receive attempt is allowed to
+ * timeout during a receiveFile() or sendFile() operation before ending
+ * attempts to retry the receive and failing.
+ * The default is DEFAULT_MAX_TIMEOUTS.
+ *
+ * @param numTimeouts The maximum number of timeouts to allow. Values
+ * less than 1 should not be used, but if they are, they are
+ * treated as 1.
+ ***/
+ public void setMaxTimeouts(int numTimeouts)
+ {
+ if (numTimeouts < 1)
+ __maxTimeouts = 1;
+ else
+ __maxTimeouts = numTimeouts;
+ }
+
+ /***
+ * Returns the maximum number of times a receive attempt is allowed to
+ * timeout before ending attempts to retry the receive and failing.
+ *
+ * @return The maximum number of timeouts allowed.
+ ***/
+ public int getMaxTimeouts()
+ {
+ return __maxTimeouts;
+ }
+
+
+ /***
+ * Requests a named file from a remote host, writes the
+ * file to an OutputStream, closes the connection, and returns the number
+ * of bytes read. A local UDP socket must first be created by
+ * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
+ * invoking this method. This method will not close the OutputStream
+ * containing the file; you must close it after the method invocation.
+ *
+ * @param filename The name of the file to receive.
+ * @param mode The TFTP mode of the transfer (one of the MODE constants).
+ * @param output The OutputStream to which the file should be written.
+ * @param host The remote host serving the file.
+ * @param port The port number of the remote TFTP server.
+ * @exception IOException If an I/O error occurs. The nature of the
+ * error will be reported in the message.
+ ***/
+ public int receiveFile(String filename, int mode, OutputStream output,
+ InetAddress host, int port) throws IOException
+ {
+ int bytesRead, timeouts, lastBlock, block, hostPort, dataLength;
+ TFTPPacket sent, received = null;
+ TFTPErrorPacket error;
+ TFTPDataPacket data;
+ TFTPAckPacket ack = new TFTPAckPacket(host, port, 0);
+
+ beginBufferedOps();
+
+ dataLength = lastBlock = hostPort = bytesRead = 0;
+ block = 1;
+
+ if (mode == TFTP.ASCII_MODE)
+ output = new FromNetASCIIOutputStream(output);
+
+ sent =
+ new TFTPReadRequestPacket(host, port, filename, mode);
+
+_sendPacket:
+ do
+ {
+ bufferedSend(sent);
+
+_receivePacket:
+ while (true)
+ {
+ timeouts = 0;
+ while (timeouts < __maxTimeouts)
+ {
+ try
+ {
+ received = bufferedReceive();
+ break;
+ }
+ catch (SocketException e)
+ {
+ if (++timeouts >= __maxTimeouts)
+ {
+ endBufferedOps();
+ throw new IOException("Connection timed out.");
+ }
+ continue;
+ }
+ catch (InterruptedIOException e)
+ {
+ if (++timeouts >= __maxTimeouts)
+ {
+ endBufferedOps();
+ throw new IOException("Connection timed out.");
+ }
+ continue;
+ }
+ catch (TFTPPacketException e)
+ {
+ endBufferedOps();
+ throw new IOException("Bad packet: " + e.getMessage());
+ }
+ }
+
+ // The first time we receive we get the port number and
+ // answering host address (for hosts with multiple IPs)
+ if (lastBlock == 0)
+ {
+ hostPort = received.getPort();
+ ack.setPort(hostPort);
+ if(!host.equals(received.getAddress()))
+ {
+ host = received.getAddress();
+ ack.setAddress(host);
+ sent.setAddress(host);
+ }
+ }
+
+ // Comply with RFC 783 indication that an error acknowledgement
+ // should be sent to originator if unexpected TID or host.
+ if (host.equals(received.getAddress()) &&
+ received.getPort() == hostPort)
+ {
+
+ switch (received.getType())
+ {
+ case TFTPPacket.ERROR:
+ error = (TFTPErrorPacket)received;
+ endBufferedOps();
+ throw new IOException("Error code " + error.getError() +
+ " received: " + error.getMessage());
+ case TFTPPacket.DATA:
+ data = (TFTPDataPacket)received;
+ dataLength = data.getDataLength();
+
+ lastBlock = data.getBlockNumber();
+
+ if (lastBlock == block)
+ {
+ try
+ {
+ output.write(data.getData(), data.getDataOffset(),
+ dataLength);
+ }
+ catch (IOException e)
+ {
+ error = new TFTPErrorPacket(host, hostPort,
+ TFTPErrorPacket.OUT_OF_SPACE,
+ "File write failed.");
+ bufferedSend(error);
+ endBufferedOps();
+ throw e;
+ }
+ ++block;
+ if (block > 65535)
+ {
+ // wrap the block number
+ block = 0;
+ }
+
+ break _receivePacket;
+ }
+ else
+ {
+ discardPackets();
+
+ if (lastBlock == (block == 0 ? 65535 : (block - 1)))
+ continue _sendPacket; // Resend last acknowledgement.
+
+ continue _receivePacket; // Start fetching packets again.
+ }
+ //break;
+
+ default:
+ endBufferedOps();
+ throw new IOException("Received unexpected packet type.");
+ }
+ }
+ else
+ {
+ error = new TFTPErrorPacket(received.getAddress(),
+ received.getPort(),
+ TFTPErrorPacket.UNKNOWN_TID,
+ "Unexpected host or port.");
+ bufferedSend(error);
+ continue _sendPacket;
+ }
+
+ // We should never get here, but this is a safety to avoid
+ // infinite loop. If only Java had the goto statement.
+ //break;
+ }
+
+ ack.setBlockNumber(lastBlock);
+ sent = ack;
+ bytesRead += dataLength;
+ } // First data packet less than 512 bytes signals end of stream.
+
+ while (dataLength == TFTPPacket.SEGMENT_SIZE);
+
+ bufferedSend(sent);
+ endBufferedOps();
+
+ return bytesRead;
+ }
+
+
+ /***
+ * Requests a named file from a remote host, writes the
+ * file to an OutputStream, closes the connection, and returns the number
+ * of bytes read. A local UDP socket must first be created by
+ * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
+ * invoking this method. This method will not close the OutputStream
+ * containing the file; you must close it after the method invocation.
+ *
+ * @param filename The name of the file to receive.
+ * @param mode The TFTP mode of the transfer (one of the MODE constants).
+ * @param output The OutputStream to which the file should be written.
+ * @param hostname The name of the remote host serving the file.
+ * @param port The port number of the remote TFTP server.
+ * @exception IOException If an I/O error occurs. The nature of the
+ * error will be reported in the message.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ ***/
+ public int receiveFile(String filename, int mode, OutputStream output,
+ String hostname, int port)
+ throws UnknownHostException, IOException
+ {
+ return receiveFile(filename, mode, output, InetAddress.getByName(hostname),
+ port);
+ }
+
+
+ /***
+ * Same as calling receiveFile(filename, mode, output, host, TFTP.DEFAULT_PORT).
+ *
+ * @param filename The name of the file to receive.
+ * @param mode The TFTP mode of the transfer (one of the MODE constants).
+ * @param output The OutputStream to which the file should be written.
+ * @param host The remote host serving the file.
+ * @exception IOException If an I/O error occurs. The nature of the
+ * error will be reported in the message.
+ ***/
+ public int receiveFile(String filename, int mode, OutputStream output,
+ InetAddress host)
+ throws IOException
+ {
+ return receiveFile(filename, mode, output, host, DEFAULT_PORT);
+ }
+
+ /***
+ * Same as calling receiveFile(filename, mode, output, hostname, TFTP.DEFAULT_PORT).
+ *
+ * @param filename The name of the file to receive.
+ * @param mode The TFTP mode of the transfer (one of the MODE constants).
+ * @param output The OutputStream to which the file should be written.
+ * @param hostname The name of the remote host serving the file.
+ * @exception IOException If an I/O error occurs. The nature of the
+ * error will be reported in the message.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ ***/
+ public int receiveFile(String filename, int mode, OutputStream output,
+ String hostname)
+ throws UnknownHostException, IOException
+ {
+ return receiveFile(filename, mode, output, InetAddress.getByName(hostname),
+ DEFAULT_PORT);
+ }
+
+
+ /***
+ * Requests to send a file to a remote host, reads the file from an
+ * InputStream, sends the file to the remote host, and closes the
+ * connection. A local UDP socket must first be created by
+ * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
+ * invoking this method. This method will not close the InputStream
+ * containing the file; you must close it after the method invocation.
+ *
+ * @param filename The name the remote server should use when creating
+ * the file on its file system.
+ * @param mode The TFTP mode of the transfer (one of the MODE constants).
+ * @param host The remote host receiving the file.
+ * @param port The port number of the remote TFTP server.
+ * @exception IOException If an I/O error occurs. The nature of the
+ * error will be reported in the message.
+ ***/
+ public void sendFile(String filename, int mode, InputStream input,
+ InetAddress host, int port) throws IOException
+ {
+ int bytesRead, timeouts, lastBlock, block, hostPort, dataLength, offset, totalThisPacket;
+ TFTPPacket sent, received = null;
+ TFTPErrorPacket error;
+ TFTPDataPacket data =
+ new TFTPDataPacket(host, port, 0, _sendBuffer, 4, 0);
+ TFTPAckPacket ack;
+
+ boolean justStarted = true;
+
+ beginBufferedOps();
+
+ dataLength = lastBlock = hostPort = bytesRead = totalThisPacket = 0;
+ block = 0;
+ boolean lastAckWait = false;
+
+ if (mode == TFTP.ASCII_MODE)
+ input = new ToNetASCIIInputStream(input);
+
+ sent =
+ new TFTPWriteRequestPacket(host, port, filename, mode);
+
+_sendPacket:
+ do
+ {
+ // first time: block is 0, lastBlock is 0, send a request packet.
+ // subsequent: block is integer starting at 1, send data packet.
+ bufferedSend(sent);
+
+ // this is trying to receive an ACK
+_receivePacket:
+ while (true)
+ {
+
+
+ timeouts = 0;
+ while (timeouts < __maxTimeouts)
+ {
+ try
+ {
+ received = bufferedReceive();
+ break;
+ }
+ catch (SocketException e)
+ {
+ if (++timeouts >= __maxTimeouts)
+ {
+ endBufferedOps();
+ throw new IOException("Connection timed out.");
+ }
+ continue;
+ }
+ catch (InterruptedIOException e)
+ {
+ if (++timeouts >= __maxTimeouts)
+ {
+ endBufferedOps();
+ throw new IOException("Connection timed out.");
+ }
+ continue;
+ }
+ catch (TFTPPacketException e)
+ {
+ endBufferedOps();
+ throw new IOException("Bad packet: " + e.getMessage());
+ }
+ } // end of while loop over tries to receive
+
+ // The first time we receive we get the port number and
+ // answering host address (for hosts with multiple IPs)
+ if (justStarted)
+ {
+ justStarted = false;
+ hostPort = received.getPort();
+ data.setPort(hostPort);
+ if(!host.equals(received.getAddress()))
+ {
+ host = received.getAddress();
+ data.setAddress(host);
+ sent.setAddress(host);
+ }
+ }
+
+ // Comply with RFC 783 indication that an error acknowledgement
+ // should be sent to originator if unexpected TID or host.
+ if (host.equals(received.getAddress()) &&
+ received.getPort() == hostPort)
+ {
+
+ switch (received.getType())
+ {
+ case TFTPPacket.ERROR:
+ error = (TFTPErrorPacket)received;
+ endBufferedOps();
+ throw new IOException("Error code " + error.getError() +
+ " received: " + error.getMessage());
+ case TFTPPacket.ACKNOWLEDGEMENT:
+ ack = (TFTPAckPacket)received;
+
+ lastBlock = ack.getBlockNumber();
+
+ if (lastBlock == block)
+ {
+ ++block;
+ if (block > 65535)
+ {
+ // wrap the block number
+ block = 0;
+ }
+ if (lastAckWait) {
+
+ break _sendPacket;
+ }
+ else {
+ break _receivePacket;
+ }
+ }
+ else
+ {
+ discardPackets();
+
+ if (lastBlock == (block == 0 ? 65535 : (block - 1)))
+ continue _sendPacket; // Resend last acknowledgement.
+
+ continue _receivePacket; // Start fetching packets again.
+ }
+ //break;
+
+ default:
+ endBufferedOps();
+ throw new IOException("Received unexpected packet type.");
+ }
+ }
+ else
+ {
+ error = new TFTPErrorPacket(received.getAddress(),
+ received.getPort(),
+ TFTPErrorPacket.UNKNOWN_TID,
+ "Unexpected host or port.");
+ bufferedSend(error);
+ continue _sendPacket;
+ }
+
+ // We should never get here, but this is a safety to avoid
+ // infinite loop. If only Java had the goto statement.
+ //break;
+ }
+
+ // OK, we have just gotten ACK about the last data we sent. Make another
+ // and send it
+
+ dataLength = TFTPPacket.SEGMENT_SIZE;
+ offset = 4;
+ totalThisPacket = 0;
+ while (dataLength > 0 &&
+ (bytesRead = input.read(_sendBuffer, offset, dataLength)) > 0)
+ {
+ offset += bytesRead;
+ dataLength -= bytesRead;
+ totalThisPacket += bytesRead;
+ }
+
+ if( totalThisPacket < TFTPPacket.SEGMENT_SIZE ) {
+ /* this will be our last packet -- send, wait for ack, stop */
+ lastAckWait = true;
+ }
+ data.setBlockNumber(block);
+ data.setData(_sendBuffer, 4, totalThisPacket);
+ sent = data;
+ }
+ while ( totalThisPacket > 0 || lastAckWait );
+ // Note: this was looping while dataLength == 0 || lastAckWait,
+ // which was discarding the last packet if it was not full size
+ // Should send the packet.
+
+ endBufferedOps();
+ }
+
+
+ /***
+ * Requests to send a file to a remote host, reads the file from an
+ * InputStream, sends the file to the remote host, and closes the
+ * connection. A local UDP socket must first be created by
+ * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
+ * invoking this method. This method will not close the InputStream
+ * containing the file; you must close it after the method invocation.
+ *
+ * @param filename The name the remote server should use when creating
+ * the file on its file system.
+ * @param mode The TFTP mode of the transfer (one of the MODE constants).
+ * @param hostname The name of the remote host receiving the file.
+ * @param port The port number of the remote TFTP server.
+ * @exception IOException If an I/O error occurs. The nature of the
+ * error will be reported in the message.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ ***/
+ public void sendFile(String filename, int mode, InputStream input,
+ String hostname, int port)
+ throws UnknownHostException, IOException
+ {
+ sendFile(filename, mode, input, InetAddress.getByName(hostname), port);
+ }
+
+
+ /***
+ * Same as calling sendFile(filename, mode, input, host, TFTP.DEFAULT_PORT).
+ *
+ * @param filename The name the remote server should use when creating
+ * the file on its file system.
+ * @param mode The TFTP mode of the transfer (one of the MODE constants).
+ * @param host The name of the remote host receiving the file.
+ * @exception IOException If an I/O error occurs. The nature of the
+ * error will be reported in the message.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ ***/
+ public void sendFile(String filename, int mode, InputStream input,
+ InetAddress host)
+ throws IOException
+ {
+ sendFile(filename, mode, input, host, DEFAULT_PORT);
+ }
+
+ /***
+ * Same as calling sendFile(filename, mode, input, hostname, TFTP.DEFAULT_PORT).
+ *
+ * @param filename The name the remote server should use when creating
+ * the file on its file system.
+ * @param mode The TFTP mode of the transfer (one of the MODE constants).
+ * @param hostname The name of the remote host receiving the file.
+ * @exception IOException If an I/O error occurs. The nature of the
+ * error will be reported in the message.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ ***/
+ public void sendFile(String filename, int mode, InputStream input,
+ String hostname)
+ throws UnknownHostException, IOException
+ {
+ sendFile(filename, mode, input, InetAddress.getByName(hostname),
+ DEFAULT_PORT);
+ }
+}
diff --git a/org/apache/commons/net/tftp/TFTPDataPacket.java b/org/apache/commons/net/tftp/TFTPDataPacket.java
new file mode 100644
index 0000000..24c0dd3
--- /dev/null
+++ b/org/apache/commons/net/tftp/TFTPDataPacket.java
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.tftp;
+
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+/***
+ * A final class derived from TFTPPacket definiing the TFTP Data
+ * packet type.
+ *
+ * Details regarding the TFTP protocol and the format of TFTP packets can
+ * be found in RFC 783. But the point of these classes is to keep you
+ * from having to worry about the internals. Additionally, only very
+ * few people should have to care about any of the TFTPPacket classes
+ * or derived classes. Almost all users should only be concerned with the
+ * {@link org.apache.commons.net.tftp.TFTPClient} class
+ * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
+ * and
+ * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
+ * methods.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TFTPPacket
+ * @see TFTPPacketException
+ * @see TFTP
+ ***/
+
+public final class TFTPDataPacket extends TFTPPacket
+{
+ /*** The maximum number of bytes in a TFTP data packet (512) ***/
+ public static final int MAX_DATA_LENGTH = 512;
+
+ /*** The minimum number of bytes in a TFTP data packet (0) ***/
+ public static final int MIN_DATA_LENGTH = 0;
+
+ /*** The block number of the packet. ***/
+ int _blockNumber;
+
+ /*** The length of the data. ***/
+ int _length;
+
+ /*** The offset into the _data array at which the data begins. ***/
+ int _offset;
+
+ /*** The data stored in the packet. ***/
+ byte[] _data;
+
+ /***
+ * Creates a data packet to be sent to a host at a given port
+ * with a given block number. The actual data to be sent is passed as
+ * an array, an offset, and a length. The offset is the offset into
+ * the byte array where the data starts. The length is the length of
+ * the data. If the length is greater than MAX_DATA_LENGTH, it is
+ * truncated.
+ *
+ * @param destination The host to which the packet is going to be sent.
+ * @param port The port to which the packet is going to be sent.
+ * @param blockNumber The block number of the data.
+ * @param data The byte array containing the data.
+ * @param offset The offset into the array where the data starts.
+ * @param length The length of the data.
+ ***/
+ public TFTPDataPacket(InetAddress destination, int port, int blockNumber,
+ byte[] data, int offset, int length)
+ {
+ super(TFTPPacket.DATA, destination, port);
+
+ _blockNumber = blockNumber;
+ _data = data;
+ _offset = offset;
+
+ if (length > MAX_DATA_LENGTH)
+ _length = MAX_DATA_LENGTH;
+ else
+ _length = length;
+ }
+
+ public TFTPDataPacket(InetAddress destination, int port, int blockNumber,
+ byte[] data)
+ {
+ this(destination, port, blockNumber, data, 0, data.length);
+ }
+
+
+ /***
+ * Creates a data packet based from a received
+ * datagram. Assumes the datagram is at least length 4, else an
+ * ArrayIndexOutOfBoundsException may be thrown.
+ *
+ * @param datagram The datagram containing the received data.
+ * @throws TFTPPacketException If the datagram isn't a valid TFTP
+ * data packet.
+ ***/
+ TFTPDataPacket(DatagramPacket datagram) throws TFTPPacketException
+ {
+ super(TFTPPacket.DATA, datagram.getAddress(), datagram.getPort());
+
+ _data = datagram.getData();
+ _offset = 4;
+
+ if (getType() != _data[1])
+ throw new TFTPPacketException("TFTP operator code does not match type.");
+
+ _blockNumber = (((_data[2] & 0xff) << 8) | (_data[3] & 0xff));
+
+ _length = datagram.getLength() - 4;
+
+ if (_length > MAX_DATA_LENGTH)
+ _length = MAX_DATA_LENGTH;
+ }
+
+ /***
+ * This is a method only available within the package for
+ * implementing efficient datagram transport by elminating buffering.
+ * It takes a datagram as an argument, and a byte buffer in which
+ * to store the raw datagram data. Inside the method, the data
+ * is set as the datagram's data and the datagram returned.
+ *
+ * @param datagram The datagram to create.
+ * @param data The buffer to store the packet and to use in the datagram.
+ * @return The datagram argument.
+ ***/
+ @Override
+ DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data)
+ {
+ data[0] = 0;
+ data[1] = (byte)_type;
+ data[2] = (byte)((_blockNumber & 0xffff) >> 8);
+ data[3] = (byte)(_blockNumber & 0xff);
+
+ // Doublecheck we're not the same
+ if (data != _data)
+ System.arraycopy(_data, _offset, data, 4, _length);
+
+ datagram.setAddress(_address);
+ datagram.setPort(_port);
+ datagram.setData(data);
+ datagram.setLength(_length + 4);
+
+ return datagram;
+ }
+
+ /***
+ * Creates a UDP datagram containing all the TFTP
+ * data packet data in the proper format.
+ * This is a method exposed to the programmer in case he
+ * wants to implement his own TFTP client instead of using
+ * the {@link org.apache.commons.net.tftp.TFTPClient}
+ * class.
+ * Under normal circumstances, you should not have a need to call this
+ * method.
+ *
+ * @return A UDP datagram containing the TFTP data packet.
+ ***/
+ @Override
+ public DatagramPacket newDatagram()
+ {
+ byte[] data;
+
+ data = new byte[_length + 4];
+ data[0] = 0;
+ data[1] = (byte)_type;
+ data[2] = (byte)((_blockNumber & 0xffff) >> 8);
+ data[3] = (byte)(_blockNumber & 0xff);
+
+ System.arraycopy(_data, _offset, data, 4, _length);
+
+ return new DatagramPacket(data, _length + 4, _address, _port);
+ }
+
+ /***
+ * Returns the block number of the data packet.
+ *
+ * @return The block number of the data packet.
+ ***/
+ public int getBlockNumber()
+ {
+ return _blockNumber;
+ }
+
+ /*** Sets the block number of the data packet. ***/
+ public void setBlockNumber(int blockNumber)
+ {
+ _blockNumber = blockNumber;
+ }
+
+ /***
+ * Sets the data for the data packet.
+ *
+ * @param data The byte array containing the data.
+ * @param offset The offset into the array where the data starts.
+ * @param length The length of the data.
+ ***/
+ public void setData(byte[] data, int offset, int length)
+ {
+ _data = data;
+ _offset = offset;
+ _length = length;
+
+ if (length > MAX_DATA_LENGTH)
+ _length = MAX_DATA_LENGTH;
+ else
+ _length = length;
+ }
+
+ /***
+ * Returns the length of the data part of the data packet.
+ *
+ * @return The length of the data part of the data packet.
+ ***/
+ public int getDataLength()
+ {
+ return _length;
+ }
+
+ /***
+ * Returns the offset into the byte array where the packet data actually
+ * starts.
+ *
+ * @return The offset into the byte array where the packet data actually
+ * starts.
+ ***/
+ public int getDataOffset()
+ {
+ return _offset;
+ }
+
+ /***
+ * Returns the byte array containing the packet data.
+ *
+ * @return The byte array containing the packet data.
+ ***/
+ public byte[] getData()
+ {
+ return _data;
+ }
+}
diff --git a/org/apache/commons/net/tftp/TFTPErrorPacket.java b/org/apache/commons/net/tftp/TFTPErrorPacket.java
new file mode 100644
index 0000000..2e7aec2
--- /dev/null
+++ b/org/apache/commons/net/tftp/TFTPErrorPacket.java
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.tftp;
+
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+/***
+ * A final class derived from TFTPPacket definiing the TFTP Error
+ * packet type.
+ *
+ * Details regarding the TFTP protocol and the format of TFTP packets can
+ * be found in RFC 783. But the point of these classes is to keep you
+ * from having to worry about the internals. Additionally, only very
+ * few people should have to care about any of the TFTPPacket classes
+ * or derived classes. Almost all users should only be concerned with the
+ * {@link org.apache.commons.net.tftp.TFTPClient} class
+ * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
+ * and
+ * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
+ * methods.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TFTPPacket
+ * @see TFTPPacketException
+ * @see TFTP
+ ***/
+
+public final class TFTPErrorPacket extends TFTPPacket
+{
+ /*** The undefined error code according to RFC 783, value 0. ***/
+ public static final int UNDEFINED = 0;
+
+ /*** The file not found error code according to RFC 783, value 1. ***/
+ public static final int FILE_NOT_FOUND = 1;
+
+ /*** The access violation error code according to RFC 783, value 2. ***/
+ public static final int ACCESS_VIOLATION = 2;
+
+ /*** The disk full error code according to RFC 783, value 3. ***/
+ public static final int OUT_OF_SPACE = 3;
+
+ /***
+ * The illegal TFTP operation error code according to RFC 783, value 4.
+ ***/
+ public static final int ILLEGAL_OPERATION = 4;
+
+ /*** The unknown transfer id error code according to RFC 783, value 5. ***/
+ public static final int UNKNOWN_TID = 5;
+
+ /*** The file already exists error code according to RFC 783, value 6. ***/
+ public static final int FILE_EXISTS = 6;
+
+ /*** The no such user error code according to RFC 783, value 7. ***/
+ public static final int NO_SUCH_USER = 7;
+
+ /*** The error code of this packet. ***/
+ int _error;
+
+ /*** The error message of this packet. ***/
+ String _message;
+
+ /***
+ * Creates an error packet to be sent to a host at a given port
+ * with an error code and error message.
+ *
+ * @param destination The host to which the packet is going to be sent.
+ * @param port The port to which the packet is going to be sent.
+ * @param error The error code of the packet.
+ * @param message The error message of the packet.
+ ***/
+ public TFTPErrorPacket(InetAddress destination, int port,
+ int error, String message)
+ {
+ super(TFTPPacket.ERROR, destination, port);
+
+ _error = error;
+ _message = message;
+ }
+
+ /***
+ * Creates an error packet based from a received
+ * datagram. Assumes the datagram is at least length 4, else an
+ * ArrayIndexOutOfBoundsException may be thrown.
+ *
+ * @param datagram The datagram containing the received error.
+ * @throws TFTPPacketException If the datagram isn't a valid TFTP
+ * error packet.
+ ***/
+ TFTPErrorPacket(DatagramPacket datagram) throws TFTPPacketException
+ {
+ super(TFTPPacket.ERROR, datagram.getAddress(), datagram.getPort());
+ int index, length;
+ byte[] data;
+ StringBuffer buffer;
+
+ data = datagram.getData();
+ length = datagram.getLength();
+
+ if (getType() != data[1])
+ throw new TFTPPacketException("TFTP operator code does not match type.");
+
+ _error = (((data[2] & 0xff) << 8) | (data[3] & 0xff));
+
+ if (length < 5)
+ throw new TFTPPacketException("Bad error packet. No message.");
+
+ index = 4;
+ buffer = new StringBuffer();
+
+ while (index < length && data[index] != 0)
+ {
+ buffer.append((char)data[index]);
+ ++index;
+ }
+
+ _message = buffer.toString();
+ }
+
+ /***
+ * This is a method only available within the package for
+ * implementing efficient datagram transport by elminating buffering.
+ * It takes a datagram as an argument, and a byte buffer in which
+ * to store the raw datagram data. Inside the method, the data
+ * is set as the datagram's data and the datagram returned.
+ *
+ * @param datagram The datagram to create.
+ * @param data The buffer to store the packet and to use in the datagram.
+ * @return The datagram argument.
+ ***/
+ @Override
+ DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data)
+ {
+ int length;
+
+ length = _message.length();
+
+ data[0] = 0;
+ data[1] = (byte)_type;
+ data[2] = (byte)((_error & 0xffff) >> 8);
+ data[3] = (byte)(_error & 0xff);
+
+ System.arraycopy(_message.getBytes(), 0, data, 4, length);
+
+ data[length + 4] = 0;
+
+ datagram.setAddress(_address);
+ datagram.setPort(_port);
+ datagram.setData(data);
+ datagram.setLength(length + 4);
+
+ return datagram;
+ }
+
+
+ /***
+ * Creates a UDP datagram containing all the TFTP
+ * error packet data in the proper format.
+ * This is a method exposed to the programmer in case he
+ * wants to implement his own TFTP client instead of using
+ * the {@link org.apache.commons.net.tftp.TFTPClient}
+ * class.
+ * Under normal circumstances, you should not have a need to call this
+ * method.
+ *
+ * @return A UDP datagram containing the TFTP error packet.
+ ***/
+ @Override
+ public DatagramPacket newDatagram()
+ {
+ byte[] data;
+ int length;
+
+ length = _message.length();
+
+ data = new byte[length + 5];
+ data[0] = 0;
+ data[1] = (byte)_type;
+ data[2] = (byte)((_error & 0xffff) >> 8);
+ data[3] = (byte)(_error & 0xff);
+
+ System.arraycopy(_message.getBytes(), 0, data, 4, length);
+
+ data[length + 4] = 0;
+
+ return new DatagramPacket(data, data.length, _address, _port);
+ }
+
+
+ /***
+ * Returns the error code of the packet.
+ *
+ * @return The error code of the packet.
+ ***/
+ public int getError()
+ {
+ return _error;
+ }
+
+
+ /***
+ * Returns the error message of the packet.
+ *
+ * @return The error message of the packet.
+ ***/
+ public String getMessage()
+ {
+ return _message;
+ }
+}
diff --git a/org/apache/commons/net/tftp/TFTPPacket.java b/org/apache/commons/net/tftp/TFTPPacket.java
new file mode 100644
index 0000000..e1dc5f1
--- /dev/null
+++ b/org/apache/commons/net/tftp/TFTPPacket.java
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.tftp;
+
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+/***
+ * TFTPPacket is an abstract class encapsulating the functionality common
+ * to the 5 types of TFTP packets. It also provides a static factory
+ * method that will create the correct TFTP packet instance from a
+ * datagram. This relieves the programmer from having to figure out what
+ * kind of TFTP packet is contained in a datagram and create it himself.
+ *
+ * Details regarding the TFTP protocol and the format of TFTP packets can
+ * be found in RFC 783. But the point of these classes is to keep you
+ * from having to worry about the internals. Additionally, only very
+ * few people should have to care about any of the TFTPPacket classes
+ * or derived classes. Almost all users should only be concerned with the
+ * {@link org.apache.commons.net.tftp.TFTPClient} class
+ * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
+ * and
+ * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
+ * methods.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TFTPPacketException
+ * @see TFTP
+ ***/
+
+public abstract class TFTPPacket
+{
+ /***
+ * The minimum size of a packet. This is 4 bytes. It is enough
+ * to store the opcode and blocknumber or other required data
+ * depending on the packet type.
+ ***/
+ static final int MIN_PACKET_SIZE = 4;
+
+ /***
+ * This is the actual TFTP spec
+ * identifier and is equal to 1.
+ * Identifier returned by {@link #getType getType()}
+ * indicating a read request packet.
+ ***/
+ public static final int READ_REQUEST = 1;
+
+ /***
+ * This is the actual TFTP spec
+ * identifier and is equal to 2.
+ * Identifier returned by {@link #getType getType()}
+ * indicating a write request packet.
+ ***/
+ public static final int WRITE_REQUEST = 2;
+
+ /***
+ * This is the actual TFTP spec
+ * identifier and is equal to 3.
+ * Identifier returned by {@link #getType getType()}
+ * indicating a data packet.
+ ***/
+ public static final int DATA = 3;
+
+ /***
+ * This is the actual TFTP spec
+ * identifier and is equal to 4.
+ * Identifier returned by {@link #getType getType()}
+ * indicating an acknowledgement packet.
+ ***/
+ public static final int ACKNOWLEDGEMENT = 4;
+
+ /***
+ * This is the actual TFTP spec
+ * identifier and is equal to 5.
+ * Identifier returned by {@link #getType getType()}
+ * indicating an error packet.
+ ***/
+ public static final int ERROR = 5;
+
+ /***
+ * The TFTP data packet maximum segment size in bytes. This is 512
+ * and is useful for those familiar with the TFTP protocol who want
+ * to use the {@link org.apache.commons.net.tftp.TFTP}
+ * class methods to implement their own TFTP servers or clients.
+ ***/
+ public static final int SEGMENT_SIZE = 512;
+
+ /*** The type of packet. ***/
+ int _type;
+
+ /*** The port the packet came from or is going to. ***/
+ int _port;
+
+ /*** The host the packet is going to be sent or where it came from. ***/
+ InetAddress _address;
+
+ /***
+ * When you receive a datagram that you expect to be a TFTP packet, you use
+ * this factory method to create the proper TFTPPacket object
+ * encapsulating the data contained in that datagram. This method is the
+ * only way you can instantiate a TFTPPacket derived class from a
+ * datagram.
+ *
+ * @param datagram The datagram containing a TFTP packet.
+ * @return The TFTPPacket object corresponding to the datagram.
+ * @exception TFTPPacketException If the datagram does not contain a valid
+ * TFTP packet.
+ ***/
+ public final static TFTPPacket newTFTPPacket(DatagramPacket datagram)
+ throws TFTPPacketException
+ {
+ byte[] data;
+ TFTPPacket packet = null;
+
+ if (datagram.getLength() < MIN_PACKET_SIZE)
+ throw new TFTPPacketException(
+ "Bad packet. Datagram data length is too short.");
+
+ data = datagram.getData();
+
+ switch (data[1])
+ {
+ case READ_REQUEST:
+ packet = new TFTPReadRequestPacket(datagram);
+ break;
+ case WRITE_REQUEST:
+ packet = new TFTPWriteRequestPacket(datagram);
+ break;
+ case DATA:
+ packet = new TFTPDataPacket(datagram);
+ break;
+ case ACKNOWLEDGEMENT:
+ packet = new TFTPAckPacket(datagram);
+ break;
+ case ERROR:
+ packet = new TFTPErrorPacket(datagram);
+ break;
+ default:
+ throw new TFTPPacketException(
+ "Bad packet. Invalid TFTP operator code.");
+ }
+
+ return packet;
+ }
+
+ /***
+ * This constructor is not visible outside of the package. It is used
+ * by subclasses within the package to initialize base data.
+ *
+ * @param type The type of the packet.
+ * @param address The host the packet came from or is going to be sent.
+ * @param port The port the packet came from or is going to be sent.
+ **/
+ TFTPPacket(int type, InetAddress address, int port)
+ {
+ _type = type;
+ _address = address;
+ _port = port;
+ }
+
+ /***
+ * This is an abstract method only available within the package for
+ * implementing efficient datagram transport by elminating buffering.
+ * It takes a datagram as an argument, and a byte buffer in which
+ * to store the raw datagram data. Inside the method, the data
+ * should be set as the datagram's data and the datagram returned.
+ *
+ * @param datagram The datagram to create.
+ * @param data The buffer to store the packet and to use in the datagram.
+ * @return The datagram argument.
+ ***/
+ abstract DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data);
+
+ /***
+ * Creates a UDP datagram containing all the TFTP packet
+ * data in the proper format.
+ * This is an abstract method, exposed to the programmer in case he
+ * wants to implement his own TFTP client instead of using
+ * the {@link org.apache.commons.net.tftp.TFTPClient}
+ * class.
+ * Under normal circumstances, you should not have a need to call this
+ * method.
+ *
+ * @return A UDP datagram containing the TFTP packet.
+ ***/
+ public abstract DatagramPacket newDatagram();
+
+ /***
+ * Returns the type of the packet.
+ *
+ * @return The type of the packet.
+ ***/
+ public final int getType()
+ {
+ return _type;
+ }
+
+ /***
+ * Returns the address of the host where the packet is going to be sent
+ * or where it came from.
+ *
+ * @return The type of the packet.
+ ***/
+ public final InetAddress getAddress()
+ {
+ return _address;
+ }
+
+ /***
+ * Returns the port where the packet is going to be sent
+ * or where it came from.
+ *
+ * @return The port where the packet came from or where it is going.
+ ***/
+ public final int getPort()
+ {
+ return _port;
+ }
+
+ /*** Sets the port where the packet is going to be sent. ***/
+ public final void setPort(int port)
+ {
+ _port = port;
+ }
+
+ /*** Sets the host address where the packet is going to be sent. ***/
+ public final void setAddress(InetAddress address)
+ {
+ _address = address;
+ }
+}
diff --git a/org/apache/commons/net/tftp/TFTPPacketException.java b/org/apache/commons/net/tftp/TFTPPacketException.java
new file mode 100644
index 0000000..286fa3a
--- /dev/null
+++ b/org/apache/commons/net/tftp/TFTPPacketException.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.tftp;
+
+/***
+ * A class used to signify the occurrence of an error in the creation of
+ * a TFTP packet. It is not declared final so that it may be subclassed
+ * to identify more specific errors. You would only want to do this if
+ * you were building your own TFTP client or server on top of the
+ * {@link org.apache.commons.net.tftp.TFTP}
+ * class if you
+ * wanted more functionality than the
+ * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
+ * and
+ * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
+ * methods provide.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TFTPPacket
+ * @see TFTP
+ ***/
+
+public class TFTPPacketException extends Exception
+{
+
+ /***
+ * Simply calls the corresponding constructor of its superclass.
+ ***/
+ public TFTPPacketException()
+ {
+ super();
+ }
+
+ /***
+ * Simply calls the corresponding constructor of its superclass.
+ ***/
+ public TFTPPacketException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/org/apache/commons/net/tftp/TFTPReadRequestPacket.java b/org/apache/commons/net/tftp/TFTPReadRequestPacket.java
new file mode 100644
index 0000000..2669df6
--- /dev/null
+++ b/org/apache/commons/net/tftp/TFTPReadRequestPacket.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.tftp;
+
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+/***
+ * A class derived from TFTPRequestPacket definiing a TFTP read request
+ * packet type.
+ *
+ * Details regarding the TFTP protocol and the format of TFTP packets can
+ * be found in RFC 783. But the point of these classes is to keep you
+ * from having to worry about the internals. Additionally, only very
+ * few people should have to care about any of the TFTPPacket classes
+ * or derived classes. Almost all users should only be concerned with the
+ * {@link org.apache.commons.net.tftp.TFTPClient} class
+ * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
+ * and
+ * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
+ * methods.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TFTPPacket
+ * @see TFTPRequestPacket
+ * @see TFTPPacketException
+ * @see TFTP
+ ***/
+
+public final class TFTPReadRequestPacket extends TFTPRequestPacket
+{
+
+ /***
+ * Creates a read request packet to be sent to a host at a
+ * given port with a filename and transfer mode request.
+ *
+ * @param destination The host to which the packet is going to be sent.
+ * @param port The port to which the packet is going to be sent.
+ * @param filename The requested filename.
+ * @param mode The requested transfer mode. This should be on of the TFTP
+ * class MODE constants (e.g., TFTP.NETASCII_MODE).
+ ***/
+ public TFTPReadRequestPacket(InetAddress destination, int port,
+ String filename, int mode)
+ {
+ super(destination, port, TFTPPacket.READ_REQUEST, filename, mode);
+ }
+
+ /***
+ * Creates a read request packet of based on a received
+ * datagram and assumes the datagram has already been identified as a
+ * read request. Assumes the datagram is at least length 4, else an
+ * ArrayIndexOutOfBoundsException may be thrown.
+ *
+ * @param datagram The datagram containing the received request.
+ * @throws TFTPPacketException If the datagram isn't a valid TFTP
+ * request packet.
+ ***/
+ TFTPReadRequestPacket(DatagramPacket datagram) throws TFTPPacketException
+ {
+ super(TFTPPacket.READ_REQUEST, datagram);
+ }
+
+}
diff --git a/org/apache/commons/net/tftp/TFTPRequestPacket.java b/org/apache/commons/net/tftp/TFTPRequestPacket.java
new file mode 100644
index 0000000..a0f4407
--- /dev/null
+++ b/org/apache/commons/net/tftp/TFTPRequestPacket.java
@@ -0,0 +1,253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.tftp;
+
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+/***
+ * An abstract class derived from TFTPPacket definiing a TFTP Request
+ * packet type. It is subclassed by the
+ * {@link org.apache.commons.net.tftp.TFTPReadRequestPacket}
+ * and
+ * {@link org.apache.commons.net.tftp.TFTPWriteRequestPacket}
+ * classes.
+ *
+ * Details regarding the TFTP protocol and the format of TFTP packets can
+ * be found in RFC 783. But the point of these classes is to keep you
+ * from having to worry about the internals. Additionally, only very
+ * few people should have to care about any of the TFTPPacket classes
+ * or derived classes. Almost all users should only be concerned with the
+ * {@link org.apache.commons.net.tftp.TFTPClient} class
+ * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
+ * and
+ * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
+ * methods.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TFTPPacket
+ * @see TFTPReadRequestPacket
+ * @see TFTPWriteRequestPacket
+ * @see TFTPPacketException
+ * @see TFTP
+ ***/
+
+public abstract class TFTPRequestPacket extends TFTPPacket
+{
+ /***
+ * An array containing the string names of the transfer modes and indexed
+ * by the transfer mode constants.
+ ***/
+ static final String[] _modeStrings = { "netascii", "octet" };
+
+ /***
+ * A null terminated byte array representation of the ascii names of the
+ * transfer mode constants. This is convenient for creating the TFTP
+ * request packets.
+ ***/
+ static final byte[] _modeBytes[] = {
+ { (byte)'n', (byte)'e', (byte)'t', (byte)'a', (byte)'s', (byte)'c',
+ (byte)'i', (byte)'i', 0 },
+ { (byte)'o', (byte)'c', (byte)'t', (byte)'e', (byte)'t', 0 }
+ };
+
+ /*** The transfer mode of the request. ***/
+ int _mode;
+
+ /*** The filename of the request. ***/
+ String _filename;
+
+ /***
+ * Creates a request packet of a given type to be sent to a host at a
+ * given port with a filename and transfer mode request.
+ *
+ * @param destination The host to which the packet is going to be sent.
+ * @param port The port to which the packet is going to be sent.
+ * @param type The type of the request (either TFTPPacket.READ_REQUEST or
+ * TFTPPacket.WRITE_REQUEST).
+ * @param filename The requested filename.
+ * @param mode The requested transfer mode. This should be on of the TFTP
+ * class MODE constants (e.g., TFTP.NETASCII_MODE).
+ ***/
+ TFTPRequestPacket(InetAddress destination, int port,
+ int type, String filename, int mode)
+ {
+ super(type, destination, port);
+
+ _filename = filename;
+ _mode = mode;
+ }
+
+ /***
+ * Creates a request packet of a given type based on a received
+ * datagram. Assumes the datagram is at least length 4, else an
+ * ArrayIndexOutOfBoundsException may be thrown.
+ *
+ * @param type The type of the request (either TFTPPacket.READ_REQUEST or
+ * TFTPPacket.WRITE_REQUEST).
+ * @param datagram The datagram containing the received request.
+ * @throws TFTPPacketException If the datagram isn't a valid TFTP
+ * request packet of the appropriate type.
+ ***/
+ TFTPRequestPacket(int type, DatagramPacket datagram)
+ throws TFTPPacketException
+ {
+ super(type, datagram.getAddress(), datagram.getPort());
+
+ byte[] data;
+ int index, length;
+ String mode;
+ StringBuffer buffer;
+
+ data = datagram.getData();
+
+ if (getType() != data[1])
+ throw new TFTPPacketException("TFTP operator code does not match type.");
+
+ buffer = new StringBuffer();
+
+ index = 2;
+ length = datagram.getLength();
+
+ while (index < length && data[index] != 0)
+ {
+ buffer.append((char)data[index]);
+ ++index;
+ }
+
+ _filename = buffer.toString();
+
+ if (index >= length)
+ throw new TFTPPacketException("Bad filename and mode format.");
+
+ buffer.setLength(0);
+ ++index; // need to advance beyond the end of string marker
+ while (index < length && data[index] != 0)
+ {
+ buffer.append((char)data[index]);
+ ++index;
+ }
+
+ mode = buffer.toString().toLowerCase(java.util.Locale.ENGLISH);
+ length = _modeStrings.length;
+
+ for (index = 0; index < length; index++)
+ {
+ if (mode.equals(_modeStrings[index]))
+ {
+ _mode = index;
+ break;
+ }
+ }
+
+ if (index >= length)
+ {
+ throw new TFTPPacketException("Unrecognized TFTP transfer mode: " + mode);
+ // May just want to default to binary mode instead of throwing
+ // exception.
+ //_mode = TFTP.OCTET_MODE;
+ }
+ }
+
+
+ /***
+ * This is a method only available within the package for
+ * implementing efficient datagram transport by elminating buffering.
+ * It takes a datagram as an argument, and a byte buffer in which
+ * to store the raw datagram data. Inside the method, the data
+ * is set as the datagram's data and the datagram returned.
+ *
+ * @param datagram The datagram to create.
+ * @param data The buffer to store the packet and to use in the datagram.
+ * @return The datagram argument.
+ ***/
+ @Override
+ final DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data)
+ {
+ int fileLength, modeLength;
+
+ fileLength = _filename.length();
+ modeLength = _modeBytes[_mode].length;
+
+ data[0] = 0;
+ data[1] = (byte)_type;
+ System.arraycopy(_filename.getBytes(), 0, data, 2, fileLength);
+ data[fileLength + 2] = 0;
+ System.arraycopy(_modeBytes[_mode], 0, data, fileLength + 3,
+ modeLength);
+
+ datagram.setAddress(_address);
+ datagram.setPort(_port);
+ datagram.setData(data);
+ datagram.setLength(fileLength + modeLength + 3);
+
+ return datagram;
+ }
+
+ /***
+ * Creates a UDP datagram containing all the TFTP
+ * request packet data in the proper format.
+ * This is a method exposed to the programmer in case he
+ * wants to implement his own TFTP client instead of using
+ * the {@link org.apache.commons.net.tftp.TFTPClient}
+ * class. Under normal circumstances, you should not have a need to call
+ * this method.
+ *
+ * @return A UDP datagram containing the TFTP request packet.
+ ***/
+ @Override
+ public final DatagramPacket newDatagram()
+ {
+ int fileLength, modeLength;
+ byte[] data;
+
+ fileLength = _filename.length();
+ modeLength = _modeBytes[_mode].length;
+
+ data = new byte[fileLength + modeLength + 4];
+ data[0] = 0;
+ data[1] = (byte)_type;
+ System.arraycopy(_filename.getBytes(), 0, data, 2, fileLength);
+ data[fileLength + 2] = 0;
+ System.arraycopy(_modeBytes[_mode], 0, data, fileLength + 3,
+ modeLength);
+
+ return new DatagramPacket(data, data.length, _address, _port);
+ }
+
+ /***
+ * Returns the transfer mode of the request.
+ *
+ * @return The transfer mode of the request.
+ ***/
+ public final int getMode()
+ {
+ return _mode;
+ }
+
+ /***
+ * Returns the requested filename.
+ *
+ * @return The requested filename.
+ ***/
+ public final String getFilename()
+ {
+ return _filename;
+ }
+}
diff --git a/org/apache/commons/net/tftp/TFTPWriteRequestPacket.java b/org/apache/commons/net/tftp/TFTPWriteRequestPacket.java
new file mode 100644
index 0000000..b545b2d
--- /dev/null
+++ b/org/apache/commons/net/tftp/TFTPWriteRequestPacket.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.tftp;
+
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+
+/***
+ * A class derived from TFTPRequestPacket definiing a TFTP write request
+ * packet type.
+ *
+ * Details regarding the TFTP protocol and the format of TFTP packets can
+ * be found in RFC 783. But the point of these classes is to keep you
+ * from having to worry about the internals. Additionally, only very
+ * few people should have to care about any of the TFTPPacket classes
+ * or derived classes. Almost all users should only be concerned with the
+ * {@link org.apache.commons.net.tftp.TFTPClient} class
+ * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
+ * and
+ * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
+ * methods.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TFTPPacket
+ * @see TFTPRequestPacket
+ * @see TFTPPacketException
+ * @see TFTP
+ ***/
+
+public final class TFTPWriteRequestPacket extends TFTPRequestPacket
+{
+
+ /***
+ * Creates a write request packet to be sent to a host at a
+ * given port with a filename and transfer mode request.
+ *
+ * @param destination The host to which the packet is going to be sent.
+ * @param port The port to which the packet is going to be sent.
+ * @param filename The requested filename.
+ * @param mode The requested transfer mode. This should be on of the TFTP
+ * class MODE constants (e.g., TFTP.NETASCII_MODE).
+ ***/
+ public TFTPWriteRequestPacket(InetAddress destination, int port,
+ String filename, int mode)
+ {
+ super(destination, port, TFTPPacket.WRITE_REQUEST, filename, mode);
+ }
+
+ /***
+ * Creates a write request packet of based on a received
+ * datagram and assumes the datagram has already been identified as a
+ * write request. Assumes the datagram is at least length 4, else an
+ * ArrayIndexOutOfBoundsException may be thrown.
+ *
+ * @param datagram The datagram containing the received request.
+ * @throws TFTPPacketException If the datagram isn't a valid TFTP
+ * request packet.
+ ***/
+ TFTPWriteRequestPacket(DatagramPacket datagram) throws TFTPPacketException
+ {
+ super(TFTPPacket.WRITE_REQUEST, datagram);
+ }
+}
diff --git a/org/apache/commons/net/time/TimeTCPClient.java b/org/apache/commons/net/time/TimeTCPClient.java
new file mode 100644
index 0000000..ad10ba5
--- /dev/null
+++ b/org/apache/commons/net/time/TimeTCPClient.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.time;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.Date;
+
+import org.apache.commons.net.SocketClient;
+
+/***
+ * The TimeTCPClient class is a TCP implementation of a client for the
+ * Time protocol described in RFC 868. To use the class, merely
+ * establish a connection with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * and call either {@link #getTime getTime() } or
+ * {@link #getDate getDate() } to retrieve the time, then
+ * call {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * to close the connection properly.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TimeUDPClient
+ ***/
+
+public final class TimeTCPClient extends SocketClient
+{
+ /*** The default time port. It is set to 37 according to RFC 868. ***/
+ public static final int DEFAULT_PORT = 37;
+
+ /***
+ * The number of seconds between 00:00 1 January 1900 and
+ * 00:00 1 January 1970. This value can be useful for converting
+ * time values to other formats.
+ ***/
+ public static final long SECONDS_1900_TO_1970 = 2208988800L;
+
+ /***
+ * The default TimeTCPClient constructor. It merely sets the default
+ * port to
+ * The server will have closed the connection at this point, so you should
+ * call
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * after calling this method. To retrieve another time, you must
+ * initiate another connection with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * before calling
+ * @return The time value retrieved from the server.
+ * @exception IOException If an error occurs while fetching the time.
+ ***/
+ public long getTime() throws IOException
+ {
+ DataInputStream input;
+ input = new DataInputStream(_input_);
+ return (input.readInt() & 0xffffffffL);
+ }
+
+ /***
+ * Retrieves the time from the server and returns a Java Date
+ * containing the time converted to the local timezone.
+ *
+ * The server will have closed the connection at this point, so you should
+ * call
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * after calling this method. To retrieve another time, you must
+ * initiate another connection with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * before calling
+ * @return A Date value containing the time retrieved from the server
+ * converted to the local timezone.
+ * @exception IOException If an error occurs while fetching the time.
+ ***/
+ public Date getDate() throws IOException
+ {
+ return new Date((getTime() - SECONDS_1900_TO_1970)*1000L);
+ }
+
+}
+
diff --git a/org/apache/commons/net/time/TimeUDPClient.java b/org/apache/commons/net/time/TimeUDPClient.java
new file mode 100644
index 0000000..f58d96e
--- /dev/null
+++ b/org/apache/commons/net/time/TimeUDPClient.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.time;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.InetAddress;
+import java.util.Date;
+
+import org.apache.commons.net.DatagramSocketClient;
+
+/***
+ * The TimeUDPClient class is a UDP implementation of a client for the
+ * Time protocol described in RFC 868. To use the class, merely
+ * open a local datagram socket with
+ * {@link org.apache.commons.net.DatagramSocketClient#open open }
+ * and call {@link #getTime getTime } or
+ * {@link #getTime getDate } to retrieve the time. Then call
+ * {@link org.apache.commons.net.DatagramSocketClient#close close }
+ * to close the connection properly. Unlike
+ * {@link org.apache.commons.net.time.TimeTCPClient},
+ * successive calls to {@link #getTime getTime } or
+ * {@link #getDate getDate } are permitted
+ * without re-establishing a connection. That is because UDP is a
+ * connectionless protocol and the Time protocol is stateless.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see TimeTCPClient
+ ***/
+
+public final class TimeUDPClient extends DatagramSocketClient
+{
+ /*** The default time port. It is set to 37 according to RFC 868. ***/
+ public static final int DEFAULT_PORT = 37;
+
+ /***
+ * The number of seconds between 00:00 1 January 1900 and
+ * 00:00 1 January 1970. This value can be useful for converting
+ * time values to other formats.
+ ***/
+ public static final long SECONDS_1900_TO_1970 = 2208988800L;
+
+ private byte[] __dummyData = new byte[1];
+ private byte[] __timeData = new byte[4];
+
+ /***
+ * Retrieves the time from the specified server and port and
+ * returns it. The time is the number of seconds since
+ * 00:00 (midnight) 1 January 1900 GMT, as specified by RFC 868.
+ * This method reads the raw 32-bit big-endian
+ * unsigned integer from the server, converts it to a Java long, and
+ * returns the value.
+ *
+ * @param host The address of the server.
+ * @param port The port of the service.
+ * @return The time value retrieved from the server.
+ * @exception IOException If an error occurs while retrieving the time.
+ ***/
+ public long getTime(InetAddress host, int port) throws IOException
+ {
+ long time;
+ DatagramPacket sendPacket, receivePacket;
+
+ sendPacket =
+ new DatagramPacket(__dummyData, __dummyData.length, host, port);
+ receivePacket = new DatagramPacket(__timeData, __timeData.length);
+
+ _socket_.send(sendPacket);
+ _socket_.receive(receivePacket);
+
+ time = 0L;
+ time |= (((__timeData[0] & 0xff) << 24) & 0xffffffffL);
+ time |= (((__timeData[1] & 0xff) << 16) & 0xffffffffL);
+ time |= (((__timeData[2] & 0xff) << 8) & 0xffffffffL);
+ time |= ((__timeData[3] & 0xff) & 0xffffffffL);
+
+ return time;
+ }
+
+ /*** Same as
+ * @param host The address of the server.
+ * @param port The port of the service.
+ * @return A Date value containing the time retrieved from the server
+ * converted to the local timezone.
+ * @exception IOException If an error occurs while fetching the time.
+ ***/
+ public Date getDate(InetAddress host, int port) throws IOException
+ {
+ return new Date((getTime(host, port) - SECONDS_1900_TO_1970)*1000L);
+ }
+
+
+ /*** Same as
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class WhoisClient extends FingerClient
+{
+ /***
+ * The default whois host to query. It is set to whois.internic.net.
+ ***/
+ public static final String DEFAULT_HOST = "whois.internic.net";
+
+ /***
+ * The default whois port. It is set to 43 according to RFC 954.
+ ***/
+ public static final int DEFAULT_PORT = 43;
+
+
+ /***
+ * The default whois constructor. Initializes the
+ * default port to
+ * @param handle The handle to lookup.
+ * @return The result of the whois query.
+ * @exception IOException If an I/O error occurs during the operation.
+ ***/
+ public String query(String handle) throws IOException
+ {
+ return query(false, handle);
+ }
+
+
+ /***
+ * Queries the connected whois server for information regarding
+ * the given handle and returns the InputStream of the network connection.
+ * It is up to the programmer to be familiar with the handle syntax
+ * of the whois server. You must first connect to a finger server before
+ * calling this method, and you should disconnect after finishing reading
+ * the stream.
+ *
+ * @param handle The handle to lookup.
+ * @return The InputStream of the network connection of the whois query.
+ * Can be read to obtain whois results.
+ * @exception IOException If an I/O error occurs during the operation.
+ ***/
+ public InputStream getInputStream(String handle) throws IOException
+ {
+ return getInputStream(false, handle);
+ }
+
+}
+
diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
Binary files /dev/null and b/res/drawable-hdpi/icon.png differ
diff --git a/res/drawable-ldpi/icon.png b/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
Binary files /dev/null and b/res/drawable-ldpi/icon.png differ
diff --git a/res/drawable-mdpi/icon.png b/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
Binary files /dev/null and b/res/drawable-mdpi/icon.png differ
diff --git a/res/layout/filerow.xml b/res/layout/filerow.xml
new file mode 100644
index 0000000..7f12ffa
--- /dev/null
+++ b/res/layout/filerow.xml
@@ -0,0 +1,7 @@
+
+
+ *
+ * @author Daniel F. Savarese
+ * @see DatagramSocketFactory
+ ***/
+
+public abstract class DatagramSocketClient
+{
+ /***
+ * The default DatagramSocketFactory shared by all DatagramSocketClient
+ * instances.
+ ***/
+ private static final DatagramSocketFactory __DEFAULT_SOCKET_FACTORY =
+ new DefaultDatagramSocketFactory();
+
+ /*** The timeout to use after opening a socket. ***/
+ protected int _timeout_;
+
+ /*** The datagram socket used for the connection. ***/
+ protected DatagramSocket _socket_;
+
+ /***
+ * A status variable indicating if the client's socket is currently open.
+ ***/
+ protected boolean _isOpen_;
+
+ /*** The datagram socket's DatagramSocketFactory. ***/
+ protected DatagramSocketFactory _socketFactory_;
+
+ /***
+ * Default constructor for DatagramSocketClient. Initializes
+ * _socket_ to null, _timeout_ to 0, and _isOpen_ to false.
+ ***/
+ public DatagramSocketClient()
+ {
+ _socket_ = null;
+ _timeout_ = 0;
+ _isOpen_ = false;
+ _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
+ }
+
+
+ /***
+ * Opens a DatagramSocket on the local host at the first available port.
+ * Also sets the timeout on the socket to the default timeout set
+ * by {@link #setDefaultTimeout setDefaultTimeout() }.
+ *
+ * _isOpen_ is set to true after calling this method and _socket_
+ * is set to the newly opened socket.
+ *
+ * @exception SocketException If the socket could not be opened or the
+ * timeout could not be set.
+ ***/
+ public void open() throws SocketException
+ {
+ _socket_ = _socketFactory_.createDatagramSocket();
+ _socket_.setSoTimeout(_timeout_);
+ _isOpen_ = true;
+ }
+
+
+ /***
+ * Opens a DatagramSocket on the local host at a specified port.
+ * Also sets the timeout on the socket to the default timeout set
+ * by {@link #setDefaultTimeout setDefaultTimeout() }.
+ *
+ * _isOpen_ is set to true after calling this method and _socket_
+ * is set to the newly opened socket.
+ *
+ * @param port The port to use for the socket.
+ * @exception SocketException If the socket could not be opened or the
+ * timeout could not be set.
+ ***/
+ public void open(int port) throws SocketException
+ {
+ _socket_ = _socketFactory_.createDatagramSocket(port);
+ _socket_.setSoTimeout(_timeout_);
+ _isOpen_ = true;
+ }
+
+
+ /***
+ * Opens a DatagramSocket at the specified address on the local host
+ * at a specified port.
+ * Also sets the timeout on the socket to the default timeout set
+ * by {@link #setDefaultTimeout setDefaultTimeout() }.
+ *
+ * _isOpen_ is set to true after calling this method and _socket_
+ * is set to the newly opened socket.
+ *
+ * @param port The port to use for the socket.
+ * @param laddr The local address to use.
+ * @exception SocketException If the socket could not be opened or the
+ * timeout could not be set.
+ ***/
+ public void open(int port, InetAddress laddr) throws SocketException
+ {
+ _socket_ = _socketFactory_.createDatagramSocket(port, laddr);
+ _socket_.setSoTimeout(_timeout_);
+ _isOpen_ = true;
+ }
+
+
+
+ /***
+ * Closes the DatagramSocket used for the connection.
+ * You should call this method after you've finished using the class
+ * instance and also before you call {@link #open open() }
+ * again. _isOpen_ is set to false and _socket_ is set to null.
+ * If you call this method when the client socket is not open,
+ * a NullPointerException is thrown.
+ ***/
+ public void close()
+ {
+ _socket_.close();
+ _socket_ = null;
+ _isOpen_ = false;
+ }
+
+
+ /***
+ * Returns true if the client has a currently open socket.
+ *
+ * @return True if the client has a curerntly open socket, false otherwise.
+ ***/
+ public boolean isOpen()
+ {
+ return _isOpen_;
+ }
+
+
+ /***
+ * Set the default timeout in milliseconds to use when opening a socket.
+ * After a call to open, the timeout for the socket is set using this value.
+ * This method should be used prior to a call to {@link #open open()}
+ * and should not be confused with {@link #setSoTimeout setSoTimeout()}
+ * which operates on the currently open socket. _timeout_ contains
+ * the new timeout value.
+ *
+ * @param timeout The timeout in milliseconds to use for the datagram socket
+ * connection.
+ ***/
+ public void setDefaultTimeout(int timeout)
+ {
+ _timeout_ = timeout;
+ }
+
+
+ /***
+ * Returns the default timeout in milliseconds that is used when
+ * opening a socket.
+ *
+ * @return The default timeout in milliseconds that is used when
+ * opening a socket.
+ ***/
+ public int getDefaultTimeout()
+ {
+ return _timeout_;
+ }
+
+
+ /***
+ * Set the timeout in milliseconds of a currently open connection.
+ * Only call this method after a connection has been opened
+ * by {@link #open open()}.
+ *
+ * @param timeout The timeout in milliseconds to use for the currently
+ * open datagram socket connection.
+ ***/
+ public void setSoTimeout(int timeout) throws SocketException
+ {
+ _socket_.setSoTimeout(timeout);
+ }
+
+
+ /***
+ * Returns the timeout in milliseconds of the currently opened socket.
+ * If you call this method when the client socket is not open,
+ * a NullPointerException is thrown.
+ *
+ * @return The timeout in milliseconds of the currently opened socket.
+ ***/
+ public int getSoTimeout() throws SocketException
+ {
+ return _socket_.getSoTimeout();
+ }
+
+
+ /***
+ * Returns the port number of the open socket on the local host used
+ * for the connection. If you call this method when the client socket
+ * is not open, a NullPointerException is thrown.
+ *
+ * @return The port number of the open socket on the local host used
+ * for the connection.
+ ***/
+ public int getLocalPort()
+ {
+ return _socket_.getLocalPort();
+ }
+
+
+ /***
+ * Returns the local address to which the client's socket is bound.
+ * If you call this method when the client socket is not open, a
+ * NullPointerException is thrown.
+ *
+ * @return The local address to which the client's socket is bound.
+ ***/
+ public InetAddress getLocalAddress()
+ {
+ return _socket_.getLocalAddress();
+ }
+
+
+ /***
+ * Sets the DatagramSocketFactory used by the DatagramSocketClient
+ * to open DatagramSockets. If the factory value is null, then a default
+ * factory is used (only do this to reset the factory after having
+ * previously altered it).
+ *
+ * @param factory The new DatagramSocketFactory the DatagramSocketClient
+ * should use.
+ ***/
+ public void setDatagramSocketFactory(DatagramSocketFactory factory)
+ {
+ if (factory == null)
+ _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
+ else
+ _socketFactory_ = factory;
+ }
+}
diff --git a/src/org/apache/commons/net/DatagramSocketFactory.java b/src/org/apache/commons/net/DatagramSocketFactory.java
new file mode 100644
index 0000000..c152eb2
--- /dev/null
+++ b/src/org/apache/commons/net/DatagramSocketFactory.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+
+/***
+ * The DatagramSocketFactory interface provides a means for the
+ * programmer to control the creation of datagram sockets and
+ * provide his own DatagramSocket implementations for use by all
+ * classes derived from
+ * {@link org.apache.commons.net.DatagramSocketClient}
+ * .
+ * This allows you to provide your own DatagramSocket implementations and
+ * to perform security checks or browser capability requests before
+ * creating a DatagramSocket.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public interface DatagramSocketFactory
+{
+
+ /***
+ * Creates a DatagramSocket on the local host at the first available port.
+ *
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket() throws SocketException;
+
+ /***
+ * Creates a DatagramSocket on the local host at a specified port.
+ *
+ * @param port The port to use for the socket.
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket(int port) throws SocketException;
+
+ /***
+ * Creates a DatagramSocket at the specified address on the local host
+ * at a specified port.
+ *
+ * @param port The port to use for the socket.
+ * @param laddr The local address to use.
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket(int port, InetAddress laddr)
+ throws SocketException;
+}
diff --git a/src/org/apache/commons/net/DefaultDatagramSocketFactory.java b/src/org/apache/commons/net/DefaultDatagramSocketFactory.java
new file mode 100644
index 0000000..3983fcb
--- /dev/null
+++ b/src/org/apache/commons/net/DefaultDatagramSocketFactory.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+
+/***
+ * DefaultDatagramSocketFactory implements the DatagramSocketFactory
+ * interface by simply wrapping the java.net.DatagramSocket
+ * constructors. It is the default DatagramSocketFactory used by
+ * {@link org.apache.commons.net.DatagramSocketClient}
+ * implementations.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see DatagramSocketFactory
+ * @see DatagramSocketClient
+ * @see DatagramSocketClient#setDatagramSocketFactory
+ ***/
+
+public class DefaultDatagramSocketFactory implements DatagramSocketFactory
+{
+
+ /***
+ * Creates a DatagramSocket on the local host at the first available port.
+ *
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket() throws SocketException
+ {
+ return new DatagramSocket();
+ }
+
+ /***
+ * Creates a DatagramSocket on the local host at a specified port.
+ *
+ * @param port The port to use for the socket.
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket(int port) throws SocketException
+ {
+ return new DatagramSocket(port);
+ }
+
+ /***
+ * Creates a DatagramSocket at the specified address on the local host
+ * at a specified port.
+ *
+ * @param port The port to use for the socket.
+ * @param laddr The local address to use.
+ * @exception SocketException If the socket could not be created.
+ ***/
+ public DatagramSocket createDatagramSocket(int port, InetAddress laddr)
+ throws SocketException
+ {
+ return new DatagramSocket(port, laddr);
+ }
+}
diff --git a/src/org/apache/commons/net/DefaultSocketFactory.java b/src/org/apache/commons/net/DefaultSocketFactory.java
new file mode 100644
index 0000000..e809f84
--- /dev/null
+++ b/src/org/apache/commons/net/DefaultSocketFactory.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import javax.net.SocketFactory;
+
+/***
+ * DefaultSocketFactory implements the SocketFactory interface by
+ * simply wrapping the java.net.Socket and java.net.ServerSocket
+ * constructors. It is the default SocketFactory used by
+ * {@link org.apache.commons.net.SocketClient}
+ * implementations.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SocketFactory
+ * @see SocketClient
+ * @see SocketClient#setSocketFactory
+ ***/
+
+public class DefaultSocketFactory extends SocketFactory
+{
+
+ /***
+ * Creates a Socket connected to the given host and port.
+ *
+ * @param host The hostname to connect to.
+ * @param port The port to connect to.
+ * @return A Socket connected to the given host and port.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ * @exception IOException If an I/O error occurs while creating the Socket.
+ ***/
+ @Override
+ public Socket createSocket(String host, int port)
+ throws UnknownHostException, IOException
+ {
+ return new Socket(host, port);
+ }
+
+ /***
+ * Creates a Socket connected to the given host and port.
+ *
+ * @param address The address of the host to connect to.
+ * @param port The port to connect to.
+ * @return A Socket connected to the given host and port.
+ * @exception IOException If an I/O error occurs while creating the Socket.
+ ***/
+ @Override
+ public Socket createSocket(InetAddress address, int port)
+ throws IOException
+ {
+ return new Socket(address, port);
+ }
+
+ /***
+ * Creates a Socket connected to the given host and port and
+ * originating from the specified local address and port.
+ *
+ * @param host The hostname to connect to.
+ * @param port The port to connect to.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
+ * @return A Socket connected to the given host and port.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ * @exception IOException If an I/O error occurs while creating the Socket.
+ ***/
+ @Override
+ public Socket createSocket(String host, int port,
+ InetAddress localAddr, int localPort)
+ throws UnknownHostException, IOException
+ {
+ return new Socket(host, port, localAddr, localPort);
+ }
+
+ /***
+ * Creates a Socket connected to the given host and port and
+ * originating from the specified local address and port.
+ *
+ * @param address The address of the host to connect to.
+ * @param port The port to connect to.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
+ * @return A Socket connected to the given host and port.
+ * @exception IOException If an I/O error occurs while creating the Socket.
+ ***/
+ @Override
+ public Socket createSocket(InetAddress address, int port,
+ InetAddress localAddr, int localPort)
+ throws IOException
+ {
+ return new Socket(address, port, localAddr, localPort);
+ }
+
+ /***
+ * Creates a ServerSocket bound to a specified port. A port
+ * of 0 will create the ServerSocket on a system-determined free port.
+ *
+ * @param port The port on which to listen, or 0 to use any free port.
+ * @return A ServerSocket that will listen on a specified port.
+ * @exception IOException If an I/O error occurs while creating
+ * the ServerSocket.
+ ***/
+ public ServerSocket createServerSocket(int port) throws IOException
+ {
+ return new ServerSocket(port);
+ }
+
+ /***
+ * Creates a ServerSocket bound to a specified port with a given
+ * maximum queue length for incoming connections. A port of 0 will
+ * create the ServerSocket on a system-determined free port.
+ *
+ * @param port The port on which to listen, or 0 to use any free port.
+ * @param backlog The maximum length of the queue for incoming connections.
+ * @return A ServerSocket that will listen on a specified port.
+ * @exception IOException If an I/O error occurs while creating
+ * the ServerSocket.
+ ***/
+ public ServerSocket createServerSocket(int port, int backlog)
+ throws IOException
+ {
+ return new ServerSocket(port, backlog);
+ }
+
+ /***
+ * Creates a ServerSocket bound to a specified port on a given local
+ * address with a given maximum queue length for incoming connections.
+ * A port of 0 will
+ * create the ServerSocket on a system-determined free port.
+ *
+ * @param port The port on which to listen, or 0 to use any free port.
+ * @param backlog The maximum length of the queue for incoming connections.
+ * @param bindAddr The local address to which the ServerSocket should bind.
+ * @return A ServerSocket that will listen on a specified port.
+ * @exception IOException If an I/O error occurs while creating
+ * the ServerSocket.
+ ***/
+ public ServerSocket createServerSocket(int port, int backlog,
+ InetAddress bindAddr)
+ throws IOException
+ {
+ return new ServerSocket(port, backlog, bindAddr);
+ }
+}
diff --git a/src/org/apache/commons/net/MalformedServerReplyException.java b/src/org/apache/commons/net/MalformedServerReplyException.java
new file mode 100644
index 0000000..3cad5f0
--- /dev/null
+++ b/src/org/apache/commons/net/MalformedServerReplyException.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.io.IOException;
+
+/***
+ * This exception is used to indicate that the reply from a server
+ * could not be interpreted. Most of the NetComponents classes attempt
+ * to be as lenient as possible when receiving server replies. Many
+ * server implementations deviate from IETF protocol specifications, making
+ * it necessary to be as flexible as possible. However, there will be
+ * certain situations where it is not possible to continue an operation
+ * because the server reply could not be interpreted in a meaningful manner.
+ * In these cases, a MalformedServerReplyException should be thrown.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public class MalformedServerReplyException extends IOException
+{
+
+ /*** Constructs a MalformedServerReplyException with no message ***/
+ public MalformedServerReplyException()
+ {
+ super();
+ }
+
+ /***
+ * Constructs a MalformedServerReplyException with a specified message.
+ *
+ * @param message The message explaining the reason for the exception.
+ ***/
+ public MalformedServerReplyException(String message)
+ {
+ super(message);
+ }
+
+}
diff --git a/src/org/apache/commons/net/PrintCommandListener.java b/src/org/apache/commons/net/PrintCommandListener.java
new file mode 100644
index 0000000..d8e7a68
--- /dev/null
+++ b/src/org/apache/commons/net/PrintCommandListener.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.io.PrintWriter;
+import org.apache.commons.net.ProtocolCommandEvent;
+import org.apache.commons.net.ProtocolCommandListener;
+
+/***
+ * This is a support class for some of the example programs. It is
+ * a sample implementation of the ProtocolCommandListener interface
+ * which just prints out to a specified stream all command/reply traffic.
+ *
+ *
+ * @since 2.0
+ ***/
+
+public class PrintCommandListener implements ProtocolCommandListener
+{
+ private PrintWriter __writer;
+
+ public PrintCommandListener(PrintWriter writer)
+ {
+ __writer = writer;
+ }
+
+ public void protocolCommandSent(ProtocolCommandEvent event)
+ {
+ __writer.print(event.getMessage());
+ __writer.flush();
+ }
+
+ public void protocolReplyReceived(ProtocolCommandEvent event)
+ {
+ __writer.print(event.getMessage());
+ __writer.flush();
+ }
+}
+
diff --git a/src/org/apache/commons/net/ProtocolCommandEvent.java b/src/org/apache/commons/net/ProtocolCommandEvent.java
new file mode 100644
index 0000000..8977c03
--- /dev/null
+++ b/src/org/apache/commons/net/ProtocolCommandEvent.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+import java.util.EventObject;
+
+/***
+ * There exists a large class of IETF protocols that work by sending an
+ * ASCII text command and arguments to a server, and then receiving an
+ * ASCII text reply. For debugging and other purposes, it is extremely
+ * useful to log or keep track of the contents of the protocol messages.
+ * The ProtocolCommandEvent class coupled with the
+ * {@link org.apache.commons.net.ProtocolCommandListener}
+ * interface facilitate this process.
+ *
+ *
+ * @see ProtocolCommandListener
+ * @see ProtocolCommandSupport
+ * @author Daniel F. Savarese
+ ***/
+
+public class ProtocolCommandEvent extends EventObject
+{
+ private int __replyCode;
+ private boolean __isCommand;
+ private String __message, __command;
+
+ /***
+ * Creates a ProtocolCommandEvent signalling a command was sent to
+ * the server. ProtocolCommandEvents created with this constructor
+ * should only be sent after a command has been sent, but before the
+ * reply has been received.
+ *
+ * @param source The source of the event.
+ * @param command The string representation of the command type sent, not
+ * including the arguments (e.g., "STAT" or "GET").
+ * @param message The entire command string verbatim as sent to the server,
+ * including all arguments.
+ ***/
+ public ProtocolCommandEvent(Object source, String command, String message)
+ {
+ super(source);
+ __replyCode = 0;
+ __message = message;
+ __isCommand = true;
+ __command = command;
+ }
+
+
+ /***
+ * Creates a ProtocolCommandEvent signalling a reply to a command was
+ * received. ProtocolCommandEvents created with this constructor
+ * should only be sent after a complete command reply has been received
+ * fromt a server.
+ *
+ * @param source The source of the event.
+ * @param replyCode The integer code indicating the natureof the reply.
+ * This will be the protocol integer value for protocols
+ * that use integer reply codes, or the reply class constant
+ * corresponding to the reply for protocols like POP3 that use
+ * strings like OK rather than integer codes (i.e., POP3Repy.OK).
+ * @param message The entire reply as received from the server.
+ ***/
+ public ProtocolCommandEvent(Object source, int replyCode, String message)
+ {
+ super(source);
+ __replyCode = replyCode;
+ __message = message;
+ __isCommand = false;
+ __command = null;
+ }
+
+ /***
+ * Returns the string representation of the command type sent (e.g., "STAT"
+ * or "GET"). If the ProtocolCommandEvent is a reply event, then null
+ * is returned.
+ *
+ * @return The string representation of the command type sent, or null
+ * if this is a reply event.
+ ***/
+ public String getCommand()
+ {
+ return __command;
+ }
+
+
+ /***
+ * Returns the reply code of the received server reply. Undefined if
+ * this is not a reply event.
+ *
+ * @return The reply code of the received server reply. Undefined if
+ * not a reply event.
+ ***/
+ public int getReplyCode()
+ {
+ return __replyCode;
+ }
+
+ /***
+ * Returns true if the ProtocolCommandEvent was generated as a result
+ * of sending a command.
+ *
+ * @return true If the ProtocolCommandEvent was generated as a result
+ * of sending a command. False otherwise.
+ ***/
+ public boolean isCommand()
+ {
+ return __isCommand;
+ }
+
+ /***
+ * Returns true if the ProtocolCommandEvent was generated as a result
+ * of receiving a reply.
+ *
+ * @return true If the ProtocolCommandEvent was generated as a result
+ * of receiving a reply. False otherwise.
+ ***/
+ public boolean isReply()
+ {
+ return !isCommand();
+ }
+
+ /***
+ * Returns the entire message sent to or received from the server.
+ *
+ * @return The entire message sent to or received from the server.
+ ***/
+ public String getMessage()
+ {
+ return __message;
+ }
+}
diff --git a/src/org/apache/commons/net/ProtocolCommandListener.java b/src/org/apache/commons/net/ProtocolCommandListener.java
new file mode 100644
index 0000000..8089926
--- /dev/null
+++ b/src/org/apache/commons/net/ProtocolCommandListener.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+import java.util.EventListener;
+
+/***
+ * There exists a large class of IETF protocols that work by sending an
+ * ASCII text command and arguments to a server, and then receiving an
+ * ASCII text reply. For debugging and other purposes, it is extremely
+ * useful to log or keep track of the contents of the protocol messages.
+ * The ProtocolCommandListener interface coupled with the
+ * {@link ProtocolCommandEvent} class facilitate this process.
+ *
+ * To receive ProtocolCommandEvents, you merely implement the
+ * ProtocolCommandListener interface and register the class as a listener
+ * with a ProtocolCommandEvent source such as
+ * {@link org.apache.commons.net.ftp.FTPClient}.
+ *
+ *
+ * @see ProtocolCommandEvent
+ * @see ProtocolCommandSupport
+ * @author Daniel F. Savarese
+ ***/
+
+public interface ProtocolCommandListener extends EventListener
+{
+
+ /***
+ * This method is invoked by a ProtocolCommandEvent source after
+ * sending a protocol command to a server.
+ *
+ * @param event The ProtocolCommandEvent fired.
+ ***/
+ public void protocolCommandSent(ProtocolCommandEvent event);
+
+ /***
+ * This method is invoked by a ProtocolCommandEvent source after
+ * receiving a reply from a server.
+ *
+ * @param event The ProtocolCommandEvent fired.
+ ***/
+ public void protocolReplyReceived(ProtocolCommandEvent event);
+
+}
diff --git a/src/org/apache/commons/net/ProtocolCommandSupport.java b/src/org/apache/commons/net/ProtocolCommandSupport.java
new file mode 100644
index 0000000..1a51fb6
--- /dev/null
+++ b/src/org/apache/commons/net/ProtocolCommandSupport.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.io.Serializable;
+import java.util.EventListener;
+
+import org.apache.commons.net.util.ListenerList;
+
+/***
+ * ProtocolCommandSupport is a convenience class for managing a list of
+ * ProtocolCommandListeners and firing ProtocolCommandEvents. You can
+ * simply delegate ProtocolCommandEvent firing and listener
+ * registering/unregistering tasks to this class.
+ *
+ *
+ * @see ProtocolCommandEvent
+ * @see ProtocolCommandListener
+ * @author Daniel F. Savarese
+ ***/
+
+public class ProtocolCommandSupport implements Serializable
+{
+ private Object __source;
+ private ListenerList __listeners;
+
+ /***
+ * Creates a ProtocolCommandSupport instant using the indicated source
+ * as the source of fired ProtocolCommandEvents.
+ *
+ * @param source The source to use for all generated ProtocolCommandEvents.
+ ***/
+ public ProtocolCommandSupport(Object source)
+ {
+ __listeners = new ListenerList();
+ __source = source;
+ }
+
+
+ /***
+ * Fires a ProtocolCommandEvent signalling the sending of a command to all
+ * registered listeners, invoking their
+ * {@link org.apache.commons.net.ProtocolCommandListener#protocolCommandSent protocolCommandSent() }
+ * methods.
+ *
+ * @param command The string representation of the command type sent, not
+ * including the arguments (e.g., "STAT" or "GET").
+ * @param message The entire command string verbatim as sent to the server,
+ * including all arguments.
+ ***/
+ public void fireCommandSent(String command, String message)
+ {
+ ProtocolCommandEvent event;
+
+ event = new ProtocolCommandEvent(__source, command, message);
+
+ for (EventListener listener : __listeners)
+ {
+ ((ProtocolCommandListener)listener).protocolCommandSent(event);
+ }
+ }
+
+ /***
+ * Fires a ProtocolCommandEvent signalling the reception of a command reply
+ * to all registered listeners, invoking their
+ * {@link org.apache.commons.net.ProtocolCommandListener#protocolReplyReceived protocolReplyReceived() }
+ * methods.
+ *
+ * @param replyCode The integer code indicating the natureof the reply.
+ * This will be the protocol integer value for protocols
+ * that use integer reply codes, or the reply class constant
+ * corresponding to the reply for protocols like POP3 that use
+ * strings like OK rather than integer codes (i.e., POP3Repy.OK).
+ * @param message The entire reply as received from the server.
+ ***/
+ public void fireReplyReceived(int replyCode, String message)
+ {
+ ProtocolCommandEvent event;
+ event = new ProtocolCommandEvent(__source, replyCode, message);
+
+ for (EventListener listener : __listeners)
+ {
+ ((ProtocolCommandListener)listener).protocolReplyReceived(event);
+ }
+ }
+
+ /***
+ * Adds a ProtocolCommandListener.
+ *
+ * @param listener The ProtocolCommandListener to add.
+ ***/
+ public void addProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ __listeners.addListener(listener);
+ }
+
+ /***
+ * Removes a ProtocolCommandListener.
+ *
+ * @param listener The ProtocolCommandListener to remove.
+ ***/
+ public void removeProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ __listeners.removeListener(listener);
+ }
+
+
+ /***
+ * Returns the number of ProtocolCommandListeners currently registered.
+ *
+ * @return The number of ProtocolCommandListeners currently registered.
+ ***/
+ public int getListenerCount()
+ {
+ return __listeners.getListenerCount();
+ }
+
+}
+
diff --git a/src/org/apache/commons/net/SocketClient.java b/src/org/apache/commons/net/SocketClient.java
new file mode 100644
index 0000000..a5a8ead
--- /dev/null
+++ b/src/org/apache/commons/net/SocketClient.java
@@ -0,0 +1,586 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+
+import javax.net.ServerSocketFactory;
+import javax.net.SocketFactory;
+
+
+/**
+ * The SocketClient provides the basic operations that are required of
+ * client objects accessing sockets. It is meant to be
+ * subclassed to avoid having to rewrite the same code over and over again
+ * to open a socket, close a socket, set timeouts, etc. Of special note
+ * is the {@link #setSocketFactory setSocketFactory }
+ * method, which allows you to control the type of Socket the SocketClient
+ * creates for initiating network connections. This is especially useful
+ * for adding SSL or proxy support as well as better support for applets. For
+ * example, you could create a
+ * {@link org.apache.commons.net.SocketFactory} that
+ * requests browser security capabilities before creating a socket.
+ * All classes derived from SocketClient should use the
+ * {@link #_socketFactory_ _socketFactory_ } member variable to
+ * create Socket and ServerSocket instances rather than instanting
+ * them by directly invoking a constructor. By honoring this contract
+ * you guarantee that a user will always be able to provide his own
+ * Socket implementations by substituting his own SocketFactory.
+ * @author Daniel F. Savarese
+ * @see SocketFactory
+ */
+public abstract class SocketClient
+{
+ /**
+ * The end of line character sequence used by most IETF protocols. That
+ * is a carriage return followed by a newline: "\r\n"
+ */
+ public static final String NETASCII_EOL = "\r\n";
+
+ /** The default SocketFactory shared by all SocketClient instances. */
+ private static final SocketFactory __DEFAULT_SOCKET_FACTORY =
+ SocketFactory.getDefault();
+
+ private static final ServerSocketFactory __DEFAULT_SERVER_SOCKET_FACTORY =
+ ServerSocketFactory.getDefault();
+
+ /** The timeout to use after opening a socket. */
+ protected int _timeout_;
+
+ /** The socket used for the connection. */
+ protected Socket _socket_;
+
+ /** The default port the client should connect to. */
+ protected int _defaultPort_;
+
+ /** The socket's InputStream. */
+ protected InputStream _input_;
+
+ /** The socket's OutputStream. */
+ protected OutputStream _output_;
+
+ /** The socket's SocketFactory. */
+ protected SocketFactory _socketFactory_;
+
+ /** The socket's ServerSocket Factory. */
+ protected ServerSocketFactory _serverSocketFactory_;
+
+ /** The socket's connect timeout (0 = infinite timeout) */
+ private static final int DEFAULT_CONNECT_TIMEOUT = 0;
+ protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
+
+ /**
+ * Default constructor for SocketClient. Initializes
+ * _socket_ to null, _timeout_ to 0, _defaultPort to 0,
+ * _isConnected_ to false, and _socketFactory_ to a shared instance of
+ * {@link org.apache.commons.net.DefaultSocketFactory}.
+ */
+ public SocketClient()
+ {
+ _socket_ = null;
+ _input_ = null;
+ _output_ = null;
+ _timeout_ = 0;
+ _defaultPort_ = 0;
+ _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
+ _serverSocketFactory_ = __DEFAULT_SERVER_SOCKET_FACTORY;
+ }
+
+
+ /**
+ * Because there are so many connect() methods, the _connectAction_()
+ * method is provided as a means of performing some action immediately
+ * after establishing a connection, rather than reimplementing all
+ * of the connect() methods. The last action performed by every
+ * connect() method after opening a socket is to call this method.
+ *
+ * This method sets the timeout on the just opened socket to the default
+ * timeout set by {@link #setDefaultTimeout setDefaultTimeout() },
+ * sets _input_ and _output_ to the socket's InputStream and OutputStream
+ * respectively, and sets _isConnected_ to true.
+ *
+ * Subclasses overriding this method should start by calling
+ *
+ * @param host The remote host.
+ * @param port The port to connect to on the remote host.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ */
+ public void connect(InetAddress host, int port)
+ throws SocketException, IOException
+ {
+ _socket_ = _socketFactory_.createSocket();
+ _socket_.connect(new InetSocketAddress(host, port), connectTimeout);
+
+ _connectAction_();
+ }
+
+ /**
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the current host at a system assigned port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param hostname The name of the remote host.
+ * @param port The port to connect to on the remote host.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ */
+ public void connect(String hostname, int port)
+ throws SocketException, IOException
+ {
+ _socket_= _socketFactory_.createSocket();
+ _socket_.connect(new InetSocketAddress(hostname, port), connectTimeout);
+
+ _connectAction_();
+ }
+
+
+ /**
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the specified local address and port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param host The remote host.
+ * @param port The port to connect to on the remote host.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ */
+ public void connect(InetAddress host, int port,
+ InetAddress localAddr, int localPort)
+ throws SocketException, IOException
+ {
+ _socket_ = _socketFactory_.createSocket();
+ _socket_.bind(new InetSocketAddress(localAddr, localPort));
+ _socket_.connect(new InetSocketAddress(host, port), connectTimeout);
+
+ _connectAction_();
+ }
+
+
+ /**
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the specified local address and port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param hostname The name of the remote host.
+ * @param port The port to connect to on the remote host.
+ * @param localAddr The local address to use.
+ * @param localPort The local port to use.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ */
+ public void connect(String hostname, int port,
+ InetAddress localAddr, int localPort)
+ throws SocketException, IOException
+ {
+ _socket_ =
+ _socketFactory_.createSocket(hostname, port, localAddr, localPort);
+ _connectAction_();
+ }
+
+
+ /**
+ * Opens a Socket connected to a remote host at the current default port
+ * and originating from the current host at a system assigned port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param host The remote host.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ */
+ public void connect(InetAddress host) throws SocketException, IOException
+ {
+ connect(host, _defaultPort_);
+ }
+
+
+ /**
+ * Opens a Socket connected to a remote host at the current default
+ * port and originating from the current host at a system assigned port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ *
+ * @param hostname The name of the remote host.
+ * @exception SocketException If the socket timeout could not be set.
+ * @exception IOException If the socket could not be opened. In most
+ * cases you will only want to catch IOException since SocketException is
+ * derived from it.
+ * @exception UnknownHostException If the hostname cannot be resolved.
+ */
+ public void connect(String hostname) throws SocketException, IOException
+ {
+ connect(hostname, _defaultPort_);
+ }
+
+
+ /**
+ * Disconnects the socket connection.
+ * You should call this method after you've finished using the class
+ * instance and also before you call
+ * {@link #connect connect() }
+ * again. _isConnected_ is set to false, _socket_ is set to null,
+ * _input_ is set to null, and _output_ is set to null.
+ *
+ * @exception IOException If there is an error closing the socket.
+ */
+ public void disconnect() throws IOException
+ {
+ if (_socket_ != null) _socket_.close();
+ if (_input_ != null) _input_.close();
+ if (_output_ != null) _output_.close();
+ if (_socket_ != null) _socket_ = null;
+ _input_ = null;
+ _output_ = null;
+ }
+
+
+ /**
+ * Returns true if the client is currently connected to a server.
+ *
+ * @return True if the client is currently connected to a server,
+ * false otherwise.
+ */
+ public boolean isConnected()
+ {
+ if (_socket_ == null)
+ return false;
+
+ return _socket_.isConnected();
+ }
+
+
+ /**
+ * Sets the default port the SocketClient should connect to when a port
+ * is not specified. The {@link #_defaultPort_ _defaultPort_ }
+ * variable stores this value. If never set, the default port is equal
+ * to zero.
+ *
+ * @param port The default port to set.
+ */
+ public void setDefaultPort(int port)
+ {
+ _defaultPort_ = port;
+ }
+
+ /**
+ * Returns the current value of the default port (stored in
+ * {@link #_defaultPort_ _defaultPort_ }).
+ *
+ * @return The current value of the default port.
+ */
+ public int getDefaultPort()
+ {
+ return _defaultPort_;
+ }
+
+
+ /**
+ * Set the default timeout in milliseconds to use when opening a socket.
+ * This value is only used previous to a call to
+ * {@link #connect connect()}
+ * and should not be confused with {@link #setSoTimeout setSoTimeout()}
+ * which operates on an the currently opened socket. _timeout_ contains
+ * the new timeout value.
+ *
+ * @param timeout The timeout in milliseconds to use for the socket
+ * connection.
+ */
+ public void setDefaultTimeout(int timeout)
+ {
+ _timeout_ = timeout;
+ }
+
+
+ /**
+ * Returns the default timeout in milliseconds that is used when
+ * opening a socket.
+ *
+ * @return The default timeout in milliseconds that is used when
+ * opening a socket.
+ */
+ public int getDefaultTimeout()
+ {
+ return _timeout_;
+ }
+
+
+ /**
+ * Set the timeout in milliseconds of a currently open connection.
+ * Only call this method after a connection has been opened
+ * by {@link #connect connect()}.
+ *
+ * @param timeout The timeout in milliseconds to use for the currently
+ * open socket connection.
+ * @exception SocketException If the operation fails.
+ */
+ public void setSoTimeout(int timeout) throws SocketException
+ {
+ _socket_.setSoTimeout(timeout);
+ }
+
+
+ /**
+ * Set the underlying socket send buffer size.
+ *
+ * @param size The size of the buffer in bytes.
+ * @throws SocketException
+ * @since 2.0
+ */
+ public void setSendBufferSize(int size) throws SocketException {
+ _socket_.setSendBufferSize(size);
+ }
+
+
+ /**
+ * Sets the underlying socket receive buffer size.
+ *
+ * @param size The size of the buffer in bytes.
+ * @throws SocketException
+ * @since 2.0
+ */
+ public void setReceiveBufferSize(int size) throws SocketException {
+ _socket_.setReceiveBufferSize(size);
+ }
+
+
+ /**
+ * Returns the timeout in milliseconds of the currently opened socket.
+ *
+ * @return The timeout in milliseconds of the currently opened socket.
+ * @exception SocketException If the operation fails.
+ */
+ public int getSoTimeout() throws SocketException
+ {
+ return _socket_.getSoTimeout();
+ }
+
+ /**
+ * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the
+ * currently opened socket.
+ *
+ * @param on True if Nagle's algorithm is to be enabled, false if not.
+ * @exception SocketException If the operation fails.
+ */
+ public void setTcpNoDelay(boolean on) throws SocketException
+ {
+ _socket_.setTcpNoDelay(on);
+ }
+
+
+ /**
+ * Returns true if Nagle's algorithm is enabled on the currently opened
+ * socket.
+ *
+ * @return True if Nagle's algorithm is enabled on the currently opened
+ * socket, false otherwise.
+ * @exception SocketException If the operation fails.
+ */
+ public boolean getTcpNoDelay() throws SocketException
+ {
+ return _socket_.getTcpNoDelay();
+ }
+
+
+ /**
+ * Sets the SO_LINGER timeout on the currently opened socket.
+ *
+ * @param on True if linger is to be enabled, false if not.
+ * @param val The linger timeout (in hundredths of a second?)
+ * @exception SocketException If the operation fails.
+ */
+ public void setSoLinger(boolean on, int val) throws SocketException
+ {
+ _socket_.setSoLinger(on, val);
+ }
+
+
+ /**
+ * Returns the current SO_LINGER timeout of the currently opened socket.
+ *
+ * @return The current SO_LINGER timeout. If SO_LINGER is disabled returns
+ * -1.
+ * @exception SocketException If the operation fails.
+ */
+ public int getSoLinger() throws SocketException
+ {
+ return _socket_.getSoLinger();
+ }
+
+
+ /**
+ * Returns the port number of the open socket on the local host used
+ * for the connection.
+ *
+ * @return The port number of the open socket on the local host used
+ * for the connection.
+ */
+ public int getLocalPort()
+ {
+ return _socket_.getLocalPort();
+ }
+
+
+ /**
+ * Returns the local address to which the client's socket is bound.
+ *
+ * @return The local address to which the client's socket is bound.
+ */
+ public InetAddress getLocalAddress()
+ {
+ return _socket_.getLocalAddress();
+ }
+
+ /**
+ * Returns the port number of the remote host to which the client is
+ * connected.
+ *
+ * @return The port number of the remote host to which the client is
+ * connected.
+ */
+ public int getRemotePort()
+ {
+ return _socket_.getPort();
+ }
+
+
+ /**
+ * @return The remote address to which the client is connected.
+ */
+ public InetAddress getRemoteAddress()
+ {
+ return _socket_.getInetAddress();
+ }
+
+
+ /**
+ * Verifies that the remote end of the given socket is connected to the
+ * the same host that the SocketClient is currently connected to. This
+ * is useful for doing a quick security check when a client needs to
+ * accept a connection from a server, such as an FTP data connection or
+ * a BSD R command standard error stream.
+ *
+ * @return True if the remote hosts are the same, false if not.
+ */
+ public boolean verifyRemote(Socket socket)
+ {
+ InetAddress host1, host2;
+
+ host1 = socket.getInetAddress();
+ host2 = getRemoteAddress();
+
+ return host1.equals(host2);
+ }
+
+
+ /**
+ * Sets the SocketFactory used by the SocketClient to open socket
+ * connections. If the factory value is null, then a default
+ * factory is used (only do this to reset the factory after having
+ * previously altered it).
+ *
+ * @param factory The new SocketFactory the SocketClient should use.
+ */
+ public void setSocketFactory(SocketFactory factory)
+ {
+ if (factory == null)
+ _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
+ else
+ _socketFactory_ = factory;
+ }
+
+ /**
+ * Sets the ServerSocketFactory used by the SocketClient to open ServerSocket
+ * connections. If the factory value is null, then a default
+ * factory is used (only do this to reset the factory after having
+ * previously altered it).
+ *
+ * @param factory The new ServerSocketFactory the SocketClient should use.
+ * @since 2.0
+ */
+ public void setServerSocketFactory(ServerSocketFactory factory) {
+ if (factory == null)
+ _serverSocketFactory_ = __DEFAULT_SERVER_SOCKET_FACTORY;
+ else
+ _serverSocketFactory_ = factory;
+ }
+
+ /**
+ * Sets the connection timeout in milliseconds, which will be passed to the {@link Socket} object's
+ * connect() method.
+ * @param connectTimeout The connection timeout to use (in ms)
+ * @since 2.0
+ */
+ public void setConnectTimeout(int connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ }
+
+ /**
+ * Get the underlying socket connection timeout.
+ * @return
+ * @since 2.0
+ */
+ public int getConnectTimeout() {
+ return connectTimeout;
+ }
+
+
+
+}
+
+
diff --git a/src/org/apache/commons/net/ftp/Configurable.java b/src/org/apache/commons/net/ftp/Configurable.java
new file mode 100644
index 0000000..5e8e749
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/Configurable.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+
+
+/**
+ * This interface adds the aspect of configurability by means of
+ * a supplied FTPClientConfig object to other classes in the
+ * system, especially listing parsers.
+ */
+public interface Configurable {
+
+ /**
+ * @param config the object containing the configuration data
+ * @throws IllegalArgumentException if the elements of the
+ *
+ * To derive the full benefits of the FTP class requires some knowledge
+ * of the FTP protocol defined in RFC 959. However, there is no reason
+ * why you should have to use the FTP class. The
+ * {@link org.apache.commons.net.ftp.FTPClient} class,
+ * derived from FTP,
+ * implements all the functionality required of an FTP client. The
+ * FTP class is made public to provide access to various FTP constants
+ * and to make it easier for adventurous programmers (or those with
+ * special needs) to interact with the FTP protocol and implement their
+ * own clients. A set of methods with names corresponding to the FTP
+ * command names are provided to facilitate this interaction.
+ *
+ * You should keep in mind that the FTP server may choose to prematurely
+ * close a connection if the client has been idle for longer than a
+ * given time period (usually 900 seconds). The FTP class will detect a
+ * premature FTP server connection closing when it receives a
+ * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
+ * response to a command.
+ * When that occurs, the FTP class method encountering that reply will throw
+ * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
+ * .
+ * Rather than list it separately for each method, we mention here that
+ * every method communicating with the server and throwing an IOException
+ * can also throw a
+ * {@link org.apache.commons.net.MalformedServerReplyException}
+ * , which is a subclass
+ * of IOException. A MalformedServerReplyException will be thrown when
+ * the reply received from the server deviates enough from the protocol
+ * specification that it cannot be interpreted in a useful manner despite
+ * attempts to be as lenient as possible.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @author Rory Winston
+ * @author Joseph Hindsley
+ * @see FTPClient
+ * @see FTPConnectionClosedException
+ * @see org.apache.commons.net.MalformedServerReplyException
+ * @version $Id: FTP.java 658520 2008-05-21 01:14:11Z sebb $
+ ***/
+
+public class FTP extends SocketClient
+{
+ /*** The default FTP data port (20). ***/
+ public static final int DEFAULT_DATA_PORT = 20;
+ /*** The default FTP control port (21). ***/
+ public static final int DEFAULT_PORT = 21;
+
+ /***
+ * A constant used to indicate the file(s) being transfered should
+ * be treated as ASCII. This is the default file type. All constants
+ * ending in
+ * @param listener The ProtocolCommandListener to add.
+ ***/
+ public void addProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ _commandSupport_.addProtocolCommandListener(listener);
+ }
+
+ /***
+ * Removes a ProtocolCommandListener. Delegates this task to
+ * {@link #_commandSupport_ _commandSupport_ }.
+ *
+ * @param listener The ProtocolCommandListener to remove.
+ ***/
+ public void removeProtocolCommandListener(ProtocolCommandListener listener)
+ {
+ _commandSupport_.removeProtocolCommandListener(listener);
+ }
+
+
+ /***
+ * Closes the control connection to the FTP server and sets to null
+ * some internal data so that the memory may be reclaimed by the
+ * garbage collector. The reply text and code information from the
+ * last command is voided so that the memory it used may be reclaimed.
+ * Also sets {@link #_controlInput_} and {@link #_controlOutput_} to null.
+ *
+ * @exception IOException If an error occurs while disconnecting.
+ ***/
+ @Override
+ public void disconnect() throws IOException
+ {
+ super.disconnect();
+ _controlInput_ = null;
+ _controlOutput_ = null;
+ _newReplyString = false;
+ _replyString = null;
+ }
+
+
+ /***
+ * Sends an FTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The text representation of the FTP command to send.
+ * @param args The arguments to the FTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(String command, String args) throws IOException
+ {
+ String message;
+
+ __commandBuffer.setLength(0);
+ __commandBuffer.append(command);
+
+ if (args != null)
+ {
+ __commandBuffer.append(' ');
+ __commandBuffer.append(args);
+ }
+ __commandBuffer.append(SocketClient.NETASCII_EOL);
+
+ try{
+ _controlOutput_.write(message = __commandBuffer.toString());
+ _controlOutput_.flush();
+ }
+ catch (SocketException e)
+ {
+ if (!isConnected() || !socketIsConnected(_socket_))
+ {
+ throw new FTPConnectionClosedException("Connection unexpectedly closed.");
+ }
+ else
+ {
+ throw e;
+ }
+ }
+
+
+ if (_commandSupport_.getListenerCount() > 0)
+ _commandSupport_.fireCommandSent(command, message);
+
+ __getReply();
+ return _replyCode;
+ }
+
+ /**
+ * Checks if the socket is connected
+ *
+ * @param socket
+ * @return true if connected
+ */
+ private boolean socketIsConnected(Socket socket)
+ {
+ if (socket == null)
+ {
+ return false;
+ }
+
+ return socket.isConnected();
+
+ }
+
+ /***
+ * Sends an FTP command to the server, waits for a reply and returns the
+ * numerical response code. After invocation, for more detailed
+ * information, the actual reply text can be accessed by calling
+ * {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The FTPCommand constant corresponding to the FTP command
+ * to send.
+ * @param args The arguments to the FTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(int command, String args) throws IOException
+ {
+ return sendCommand(FTPCommand._commands[command], args);
+ }
+
+
+ /***
+ * Sends an FTP command with no arguments to the server, waits for a
+ * reply and returns the numerical response code. After invocation, for
+ * more detailed information, the actual reply text can be accessed by
+ * calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The text representation of the FTP command to send.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(String command) throws IOException
+ {
+ return sendCommand(command, null);
+ }
+
+
+ /***
+ * Sends an FTP command with no arguments to the server, waits for a
+ * reply and returns the numerical response code. After invocation, for
+ * more detailed information, the actual reply text can be accessed by
+ * calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }.
+ *
+ * @param command The FTPCommand constant corresponding to the FTP command
+ * to send.
+ * @return The integer value of the FTP reply code returned by the server
+ * in response to the command.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int sendCommand(int command) throws IOException
+ {
+ return sendCommand(command, null);
+ }
+
+
+ /***
+ * Returns the integer value of the reply code of the last FTP reply.
+ * You will usually only use this method after you connect to the
+ * FTP server to check that the connection was successful since
+ *
+ * @return The integer value of the reply code of the last FTP reply.
+ ***/
+ public int getReplyCode()
+ {
+ return _replyCode;
+ }
+
+ /***
+ * Fetches a reply from the FTP server and returns the integer reply
+ * code. After calling this method, the actual reply text can be accessed
+ * from either calling {@link #getReplyString getReplyString } or
+ * {@link #getReplyStrings getReplyStrings }. Only use this
+ * method if you are implementing your own FTP client or if you need to
+ * fetch a secondary response from the FTP server.
+ *
+ * @return The integer value of the reply code of the fetched FTP reply.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while receiving the
+ * server reply.
+ ***/
+ public int getReply() throws IOException
+ {
+ __getReply();
+ return _replyCode;
+ }
+
+
+ /***
+ * Returns the lines of text from the last FTP server response as an array
+ * of strings, one entry per line. The end of line markers of each are
+ * stripped from each line.
+ *
+ * @return The lines of text from the last FTP response as an array.
+ ***/
+ public String[] getReplyStrings()
+ {
+ String[] lines;
+ lines = new String[_replyLines.size()];
+ _replyLines.addAll(Arrays.asList(lines));
+ return lines;
+ }
+
+ /***
+ * Returns the entire text of the last FTP server response exactly
+ * as it was received, including all end of line markers in NETASCII
+ * format.
+ *
+ * @return The entire text from the last FTP response as a String.
+ ***/
+ public String getReplyString()
+ {
+ StringBuilder buffer;
+
+ if (!_newReplyString) {
+ return _replyString;
+ }
+
+ buffer = new StringBuilder(256);
+
+ for (String line : _replyLines) {
+ buffer.append(line);
+ buffer.append(SocketClient.NETASCII_EOL);
+ }
+
+ _newReplyString = false;
+
+ return (_replyString = buffer.toString());
+ }
+
+
+ /***
+ * A convenience method to send the FTP USER command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param username The username to login under.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int user(String username) throws IOException
+ {
+ return sendCommand(FTPCommand.USER, username);
+ }
+
+ /**
+ * A convenience method to send the FTP PASS command to the server,
+ * receive the reply, and return the reply code.
+ * @param password The plain text password of the username being logged into.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int pass(String password) throws IOException
+ {
+ return sendCommand(FTPCommand.PASS, password);
+ }
+
+ /***
+ * A convenience method to send the FTP ACCT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param account The account name to access.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int acct(String account) throws IOException
+ {
+ return sendCommand(FTPCommand.ACCT, account);
+ }
+
+
+ /***
+ * A convenience method to send the FTP ABOR command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int abor() throws IOException
+ {
+ return sendCommand(FTPCommand.ABOR);
+ }
+
+ /***
+ * A convenience method to send the FTP CWD command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param directory The new working directory.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int cwd(String directory) throws IOException
+ {
+ return sendCommand(FTPCommand.CWD, directory);
+ }
+
+ /***
+ * A convenience method to send the FTP CDUP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int cdup() throws IOException
+ {
+ return sendCommand(FTPCommand.CDUP);
+ }
+
+ /***
+ * A convenience method to send the FTP QUIT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int quit() throws IOException
+ {
+ return sendCommand(FTPCommand.QUIT);
+ }
+
+ /***
+ * A convenience method to send the FTP REIN command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rein() throws IOException
+ {
+ return sendCommand(FTPCommand.REIN);
+ }
+
+ /***
+ * A convenience method to send the FTP SMNT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param dir The directory name.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int smnt(String dir) throws IOException
+ {
+ return sendCommand(FTPCommand.SMNT, dir);
+ }
+
+ /***
+ * A convenience method to send the FTP PORT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param host The host owning the port.
+ * @param port The new port.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int port(InetAddress host, int port) throws IOException
+ {
+ int num;
+ StringBuffer info = new StringBuffer(24);
+
+ info.append(host.getHostAddress().replace('.', ','));
+ num = port >>> 8;
+ info.append(',');
+ info.append(num);
+ info.append(',');
+ num = port & 0xff;
+ info.append(num);
+
+ return sendCommand(FTPCommand.PORT, info.toString());
+ }
+
+ /***
+ * A convenience method to send the FTP PASV command to the server,
+ * receive the reply, and return the reply code. Remember, it's up
+ * to you to interpret the reply string containing the host/port
+ * information.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int pasv() throws IOException
+ {
+ return sendCommand(FTPCommand.PASV);
+ }
+
+ /**
+ * A convenience method to send the FTP TYPE command for text files
+ * to the server, receive the reply, and return the reply code.
+ * @param fileType The type of the file (one of the
+ * @param fileType The type of the file (one of the
+ * @param structure The structure of the file (one of the
+ *
+ * @param mode The transfer mode to use (one of the
+ *
+ * @param pathname The pathname of the file to retrieve.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int retr(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.RETR, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP STOR command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @param pathname The pathname to use for the file when stored at
+ * the remote end of the transfer.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stor(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.STOR, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP STOU command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stou() throws IOException
+ {
+ return sendCommand(FTPCommand.STOU);
+ }
+
+ /***
+ * A convenience method to send the FTP STOU command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ * @param pathname The base pathname to use for the file when stored at
+ * the remote end of the transfer. Some FTP servers
+ * require this.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int stou(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.STOU, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP APPE command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @param pathname The pathname to use for the file when stored at
+ * the remote end of the transfer.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int appe(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.APPE, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP ALLO command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param bytes The number of bytes to allocate.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int allo(int bytes) throws IOException
+ {
+ return sendCommand(FTPCommand.ALLO, Integer.toString(bytes));
+ }
+
+ /***
+ * A convenience method to send the FTP ALLO command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param bytes The number of bytes to allocate.
+ * @param recordSize The size of a record.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int allo(int bytes, int recordSize) throws IOException
+ {
+ return sendCommand(FTPCommand.ALLO, Integer.toString(bytes) + " R " +
+ Integer.toString(recordSize));
+ }
+
+ /***
+ * A convenience method to send the FTP REST command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param marker The marker at which to restart a transfer.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rest(String marker) throws IOException
+ {
+ return sendCommand(FTPCommand.REST, marker);
+ }
+
+
+ /**
+ * @since 2.0
+ **/
+ public int mdtm(String file) throws IOException
+ {
+ return sendCommand(FTPCommand.MDTM, file);
+ }
+
+ /***
+ * A convenience method to send the FTP RNFR command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname to rename from.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rnfr(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.RNFR, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP RNTO command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname to rename to
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rnto(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.RNTO, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP DELE command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname to delete.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int dele(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.DELE, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP RMD command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname of the directory to remove.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int rmd(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.RMD, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP MKD command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname The pathname of the new directory to create.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int mkd(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.MKD, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP PWD command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int pwd() throws IOException
+ {
+ return sendCommand(FTPCommand.PWD);
+ }
+
+ /***
+ * A convenience method to send the FTP LIST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int list() throws IOException
+ {
+ return sendCommand(FTPCommand.LIST);
+ }
+
+ /***
+ * A convenience method to send the FTP LIST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @param pathname The pathname to list.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int list(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.LIST, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP NLST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int nlst() throws IOException
+ {
+ return sendCommand(FTPCommand.NLST);
+ }
+
+ /***
+ * A convenience method to send the FTP NLST command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * @param pathname The pathname to list.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int nlst(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.NLST, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP SITE command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param parameters The site parameters to send.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int site(String parameters) throws IOException
+ {
+ return sendCommand(FTPCommand.SITE, parameters);
+ }
+
+ /***
+ * A convenience method to send the FTP SYST command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int syst() throws IOException
+ {
+ return sendCommand(FTPCommand.SYST);
+ }
+
+ /***
+ * A convenience method to send the FTP STAT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stat() throws IOException
+ {
+ return sendCommand(FTPCommand.STAT);
+ }
+
+ /***
+ * A convenience method to send the FTP STAT command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param pathname A pathname to list.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stat(String pathname) throws IOException
+ {
+ return sendCommand(FTPCommand.STAT, pathname);
+ }
+
+ /***
+ * A convenience method to send the FTP HELP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int help() throws IOException
+ {
+ return sendCommand(FTPCommand.HELP);
+ }
+
+ /***
+ * A convenience method to send the FTP HELP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @param command The command name on which to request help.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int help(String command) throws IOException
+ {
+ return sendCommand(FTPCommand.HELP, command);
+ }
+
+ /***
+ * A convenience method to send the FTP NOOP command to the server,
+ * receive the reply, and return the reply code.
+ *
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int noop() throws IOException
+ {
+ return sendCommand(FTPCommand.NOOP);
+ }
+
+ /**
+ * Return whether strict multiline parsing is enabled, as per RFX 959, section 4.2.
+ * @return True if strict, false if lenient
+ * @since 2.0
+ */
+ public boolean isStrictMultilineParsing() {
+ return strictMultilineParsing;
+ }
+
+ /**
+ * Set strict multiline parsing.
+ * @param strictMultilineParsing
+ * @since 2.0
+ */
+ public void setStrictMultilineParsing(boolean strictMultilineParsing) {
+ this.strictMultilineParsing = strictMultilineParsing;
+ }
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/src/org/apache/commons/net/ftp/FTPClient.java b/src/org/apache/commons/net/ftp/FTPClient.java
new file mode 100644
index 0000000..9a2c459
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/FTPClient.java
@@ -0,0 +1,2447 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+
+import org.apache.commons.net.MalformedServerReplyException;
+import org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory;
+import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
+import org.apache.commons.net.ftp.parser.ParserInitializationException;
+import org.apache.commons.net.io.CopyStreamEvent;
+import org.apache.commons.net.io.CopyStreamException;
+import org.apache.commons.net.io.FromNetASCIIInputStream;
+import org.apache.commons.net.io.ToNetASCIIOutputStream;
+import org.apache.commons.net.io.Util;
+
+/***
+ * FTPClient encapsulates all the functionality necessary to store and
+ * retrieve files from an FTP server. This class takes care of all
+ * low level details of interacting with an FTP server and provides
+ * a convenient higher level interface. As with all classes derived
+ * from {@link org.apache.commons.net.SocketClient},
+ * you must first connect to the server with
+ * {@link org.apache.commons.net.SocketClient#connect connect }
+ * before doing anything, and finally
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
+ * after you're completely finished interacting with the server.
+ * Then you need to check the FTP reply code to see if the connection
+ * was successful. For example:
+ *
+ * Immediately after connecting is the only real time you need to check the
+ * reply code (because connect is of type void). The convention for all the
+ * FTP command methods in FTPClient is such that they either return a
+ * boolean value or some other value.
+ * The boolean methods return true on a successful completion reply from
+ * the FTP server and false on a reply resulting in an error condition or
+ * failure. The methods returning a value other than boolean return a value
+ * containing the higher level data produced by the FTP command, or null if a
+ * reply resulted in an error condition or failure. If you want to access
+ * the exact FTP reply code causing a success or failure, you must call
+ * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode } after
+ * a success or failure.
+ *
+ * The default settings for FTPClient are for it to use
+ *
+ *
+ * Because the handling of sockets on different platforms can differ
+ * significantly, the FTPClient automatically issues a new PORT command
+ * prior to every transfer requiring that the server connect to the client's
+ * data port. This ensures identical problem-free behavior on Windows, Unix,
+ * and Macintosh platforms. Additionally, it relieves programmers from
+ * having to issue the PORT command themselves and dealing with platform
+ * dependent issues.
+ *
+ * Additionally, for security purposes, all data connections to the
+ * client are verified to ensure that they originated from the intended
+ * party (host and port). If a data connection is initiated by an unexpected
+ * party, the command will close the socket and throw an IOException. You
+ * may disable this behavior with
+ * {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}.
+ *
+ * You should keep in mind that the FTP server may choose to prematurely
+ * close a connection if the client has been idle for longer than a
+ * given time period (usually 900 seconds). The FTPClient class will detect a
+ * premature FTP server connection closing when it receives a
+ * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
+ * response to a command.
+ * When that occurs, the FTP class method encountering that reply will throw
+ * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
+ * .
+ *
+ * Rather than list it separately for each method, we mention here that
+ * every method communicating with the server and throwing an IOException
+ * can also throw a
+ * {@link org.apache.commons.net.MalformedServerReplyException}
+ * , which is a subclass
+ * of IOException. A MalformedServerReplyException will be thrown when
+ * the reply received from the server deviates enough from the protocol
+ * specification that it cannot be interpreted in a useful manner despite
+ * attempts to be as lenient as possible.
+ *
+ * Listing API Examples
+ * Both paged and unpaged examples of directory listings are available,
+ * as follows:
+ *
+ * Unpaged (whole list) access, using a parser accessible by auto-detect:
+ *
+ * Paged access, using a parser not accessible by auto-detect. The class
+ * defined in the first parameter of initateListParsing should be derived
+ * from org.apache.commons.net.FTPFileEntryParser:
+ *
+ * Paged access, using a parser accessible by auto-detect:
+ *
+ * For examples of using FTPClient on servers whose directory listings
+ *
+ * @author Daniel F. Savarese
+ * @author Rory Winston
+ * @see FTP
+ * @see FTPConnectionClosedException
+ * @see FTPFileEntryParser
+ * @see FTPFileEntryParserFactory
+ * @see DefaultFTPFileEntryParserFactory
+ * @see FTPClientConfig
+ *
+ * @see org.apache.commons.net.MalformedServerReplyException
+ **/
+public class FTPClient extends FTP
+implements Configurable
+{
+ /***
+ * A constant indicating the FTP session is expecting all transfers
+ * to occur between the client (local) and server and that the server
+ * should connect to the client's data port to initiate a data transfer.
+ * This is the default data connection mode when and FTPClient instance
+ * is created.
+ ***/
+ public static final int ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0;
+ /***
+ * A constant indicating the FTP session is expecting all transfers
+ * to occur between two remote servers and that the server
+ * the client is connected to should connect to the other server's
+ * data port to initiate a data transfer.
+ ***/
+ public static final int ACTIVE_REMOTE_DATA_CONNECTION_MODE = 1;
+ /***
+ * A constant indicating the FTP session is expecting all transfers
+ * to occur between the client (local) and server and that the server
+ * is in passive mode, requiring the client to connect to the
+ * server's data port to initiate a transfer.
+ ***/
+ public static final int PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2;
+ /***
+ * A constant indicating the FTP session is expecting all transfers
+ * to occur between two remote servers and that the server
+ * the client is connected to is in passive mode, requiring the other
+ * server to connect to the first server's data port to initiate a data
+ * transfer.
+ ***/
+ public static final int PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3;
+
+ private int __dataConnectionMode, __dataTimeout;
+ private int __passivePort;
+ private String __passiveHost;
+ private int __fileType, __fileFormat, __fileStructure, __fileTransferMode;
+ private boolean __remoteVerificationEnabled;
+ private long __restartOffset;
+ private FTPFileEntryParserFactory __parserFactory;
+ private int __bufferSize;
+ private boolean __listHiddenFiles;
+
+ // __systemName is a cached value that should not be referenced directly
+ // except when assigned in getSystemName and __initDefaults.
+ private String __systemName;
+
+ // __entryParser is a cached value that should not be referenced directly
+ // except when assigned in listFiles(String, String) and __initDefaults.
+ private FTPFileEntryParser __entryParser;
+
+ private FTPClientConfig __configuration;
+
+ /** Pattern for PASV mode responses */
+ private static String __parms = "\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}";
+ private static java.util.regex.Pattern __parms_pat;
+ static {
+ __parms_pat = java.util.regex.Pattern.compile(__parms);
+ }
+
+ /***
+ * Default FTPClient constructor. Creates a new FTPClient instance
+ * with the data connection mode set to
+ *
+ * @param command The text representation of the FTP command to send.
+ * @param arg The arguments to the FTP command. If this parameter is
+ * set to null, then the command is sent with no argument.
+ * @return A Socket corresponding to the established data connection.
+ * Null is returned if an FTP protocol error is reported at
+ * any point during the establishment and initialization of
+ * the connection.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ protected Socket _openDataConnection_(int command, String arg)
+ throws IOException
+ {
+ Socket socket;
+
+ if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE &&
+ __dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE)
+ return null;
+
+ if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE)
+ {
+ ServerSocket server;
+ server = _serverSocketFactory_.createServerSocket(0, 1, getLocalAddress());
+
+ if (!FTPReply.isPositiveCompletion(port(getLocalAddress(),
+ server.getLocalPort())))
+ {
+ server.close();
+ return null;
+ }
+
+ if ((__restartOffset > 0) && !restart(__restartOffset))
+ {
+ server.close();
+ return null;
+ }
+
+ if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
+ {
+ server.close();
+ return null;
+ }
+
+ // For now, let's just use the data timeout value for waiting for
+ // the data connection. It may be desirable to let this be a
+ // separately configurable value. In any case, we really want
+ // to allow preventing the accept from blocking indefinitely.
+ if (__dataTimeout >= 0)
+ server.setSoTimeout(__dataTimeout);
+ try {
+ socket = server.accept();
+ } finally {
+ server.close();
+ }
+ }
+ else
+ { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
+
+ if (pasv() != FTPReply.ENTERING_PASSIVE_MODE)
+ return null;
+
+ __parsePassiveModeReply(_replyLines.get(_replyLines.size() - 1));
+
+ socket = _socketFactory_.createSocket(__passiveHost, __passivePort);
+ if ((__restartOffset > 0) && !restart(__restartOffset))
+ {
+ socket.close();
+ return null;
+ }
+
+ if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
+ {
+ socket.close();
+ return null;
+ }
+ }
+
+ if (__remoteVerificationEnabled && !verifyRemote(socket))
+ {
+ InetAddress host1, host2;
+
+ host1 = socket.getInetAddress();
+ host2 = getRemoteAddress();
+
+ socket.close();
+
+ throw new IOException(
+ "Host attempting data connection " + host1.getHostAddress() +
+ " is not same as server " + host2.getHostAddress());
+ }
+
+ if (__dataTimeout >= 0)
+ socket.setSoTimeout(__dataTimeout);
+
+ return socket;
+ }
+
+
+ @Override
+ protected void _connectAction_() throws IOException
+ {
+ super._connectAction_();
+ __initDefaults();
+ }
+
+
+ /***
+ * Sets the timeout in milliseconds to use when reading from the
+ * data connection. This timeout will be set immediately after
+ * opening the data connection.
+ *
+ * @param timeout The default timeout in milliseconds that is used when
+ * opening a data connection socket.
+ ***/
+ public void setDataTimeout(int timeout)
+ {
+ __dataTimeout = timeout;
+ }
+
+ /**
+ * set the factory used for parser creation to the supplied factory object.
+ *
+ * @param parserFactory
+ * factory object used to create FTPFileEntryParsers
+ *
+ * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
+ * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
+ */
+ public void setParserFactory(FTPFileEntryParserFactory parserFactory) {
+ __parserFactory = parserFactory;
+ }
+
+
+ /***
+ * Closes the connection to the FTP server and restores
+ * connection parameters to the default values.
+ *
+ * @exception IOException If an error occurs while disconnecting.
+ ***/
+ @Override
+ public void disconnect() throws IOException
+ {
+ super.disconnect();
+ __initDefaults();
+ }
+
+
+ /***
+ * Enable or disable verification that the remote host taking part
+ * of a data connection is the same as the host to which the control
+ * connection is attached. The default is for verification to be
+ * enabled. You may set this value at any time, whether the
+ * FTPClient is currently connected or not.
+ *
+ * @param enable True to enable verification, false to disable verification.
+ ***/
+ public void setRemoteVerificationEnabled(boolean enable)
+ {
+ __remoteVerificationEnabled = enable;
+ }
+
+ /***
+ * Return whether or not verification of the remote host participating
+ * in data connections is enabled. The default behavior is for
+ * verification to be enabled.
+ *
+ * @return True if verification is enabled, false if not.
+ ***/
+ public boolean isRemoteVerificationEnabled()
+ {
+ return __remoteVerificationEnabled;
+ }
+
+ /***
+ * Login to the FTP server using the provided username and password.
+ *
+ * @param username The username to login under.
+ * @param password The password to use.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean login(String username, String password) throws IOException
+ {
+ user(username);
+
+ if (FTPReply.isPositiveCompletion(_replyCode))
+ return true;
+
+ // If we get here, we either have an error code, or an intermmediate
+ // reply requesting password.
+ if (!FTPReply.isPositiveIntermediate(_replyCode))
+ return false;
+
+ return FTPReply.isPositiveCompletion(pass(password));
+ }
+
+
+ /***
+ * Login to the FTP server using the provided username, password,
+ * and account. If no account is required by the server, only
+ * the username and password, the account information is not used.
+ *
+ * @param username The username to login under.
+ * @param password The password to use.
+ * @param account The account to use.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean login(String username, String password, String account)
+ throws IOException
+ {
+ user(username);
+
+ if (FTPReply.isPositiveCompletion(_replyCode))
+ return true;
+
+ // If we get here, we either have an error code, or an intermmediate
+ // reply requesting password.
+ if (!FTPReply.isPositiveIntermediate(_replyCode))
+ return false;
+
+ pass(password);
+
+ if (FTPReply.isPositiveCompletion(_replyCode))
+ return true;
+
+ if (!FTPReply.isPositiveIntermediate(_replyCode))
+ return false;
+
+ return FTPReply.isPositiveCompletion(acct(account));
+ }
+
+ /***
+ * Logout of the FTP server by sending the QUIT command.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean logout() throws IOException
+ {
+ return FTPReply.isPositiveCompletion(quit());
+ }
+
+
+ /***
+ * Change the current working directory of the FTP session.
+ *
+ * @param pathname The new current working directory.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean changeWorkingDirectory(String pathname) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(cwd(pathname));
+ }
+
+
+ /***
+ * Change to the parent directory of the current working directory.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean changeToParentDirectory() throws IOException
+ {
+ return FTPReply.isPositiveCompletion(cdup());
+ }
+
+
+ /***
+ * Issue the FTP SMNT command.
+ *
+ * @param pathname The pathname to mount.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean structureMount(String pathname) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(smnt(pathname));
+ }
+
+ /***
+ * Reinitialize the FTP session. Not all FTP servers support this
+ * command, which issues the FTP REIN command.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ boolean reinitialize() throws IOException
+ {
+ rein();
+
+ if (FTPReply.isPositiveCompletion(_replyCode) ||
+ (FTPReply.isPositivePreliminary(_replyCode) &&
+ FTPReply.isPositiveCompletion(getReply())))
+ {
+
+ __initDefaults();
+
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /***
+ * Set the current data connection mode to
+ *
+ * @param host The passive mode server accepting connections for data
+ * transfers.
+ * @param port The passive mode server's data port.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean enterRemoteActiveMode(InetAddress host, int port)
+ throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(port(host, port)))
+ {
+ __dataConnectionMode = ACTIVE_REMOTE_DATA_CONNECTION_MODE;
+ __passiveHost = null;
+ __passivePort = -1;
+ return true;
+ }
+ return false;
+ }
+
+ /***
+ * Set the current data connection mode to
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean enterRemotePassiveMode() throws IOException
+ {
+ if (pasv() != FTPReply.ENTERING_PASSIVE_MODE)
+ return false;
+
+ __dataConnectionMode = PASSIVE_REMOTE_DATA_CONNECTION_MODE;
+ __parsePassiveModeReply(_replyLines.get(0));
+
+ return true;
+ }
+
+ /***
+ * Returns the hostname or IP address (in the form of a string) returned
+ * by the server when entering passive mode. If not in passive mode,
+ * returns null. This method only returns a valid value AFTER a
+ * data connection has been opened after a call to
+ * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
+ * This is because FTPClient sends a PASV command to the server only
+ * just before opening a data connection, and not when you call
+ * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
+ *
+ * @return The passive host name if in passive mode, otherwise null.
+ ***/
+ public String getPassiveHost()
+ {
+ return __passiveHost;
+ }
+
+ /***
+ * If in passive mode, returns the data port of the passive host.
+ * This method only returns a valid value AFTER a
+ * data connection has been opened after a call to
+ * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
+ * This is because FTPClient sends a PASV command to the server only
+ * just before opening a data connection, and not when you call
+ * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
+ *
+ * @return The data port of the passive server. If not in passive
+ * mode, undefined.
+ ***/
+ public int getPassivePort()
+ {
+ return __passivePort;
+ }
+
+
+ /***
+ * Returns the current data connection mode (one of the
+ *
+ * @return The current data connection mode (one of the
+ *
+ * @param fileType The
+ * @param fileType The
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean setFileType(int fileType, int formatOrByteSize)
+ throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(type(fileType, formatOrByteSize)))
+ {
+ __fileType = fileType;
+ __fileFormat = formatOrByteSize;
+ return true;
+ }
+ return false;
+ }
+
+
+ /***
+ * Sets the file structure. The default structure is
+ *
+ * @param structure The structure of the file (one of the FTP class
+ *
+ * @param mode The new transfer mode to use (one of the FTP class
+ *
+ * @param filename The name of the file to retrieve.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean remoteRetrieve(String filename) throws IOException
+ {
+ if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
+ __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
+ return FTPReply.isPositivePreliminary(retr(filename));
+ return false;
+ }
+
+
+ /***
+ * Initiate a server to server file transfer. This method tells the
+ * server to which the client is connected to store a file on
+ * the other server using the given filename. The other server must
+ * have had a
+ * @param filename The name to call the file that is to be stored.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean remoteStore(String filename) throws IOException
+ {
+ if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
+ __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
+ return FTPReply.isPositivePreliminary(stor(filename));
+ return false;
+ }
+
+
+ /***
+ * Initiate a server to server file transfer. This method tells the
+ * server to which the client is connected to store a file on
+ * the other server using a unique filename based on the given filename.
+ * The other server must have had a
+ * @param filename The name on which to base the filename of the file
+ * that is to be stored.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean remoteStoreUnique(String filename) throws IOException
+ {
+ if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
+ __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
+ return FTPReply.isPositivePreliminary(stou(filename));
+ return false;
+ }
+
+
+ /***
+ * Initiate a server to server file transfer. This method tells the
+ * server to which the client is connected to store a file on
+ * the other server using a unique filename.
+ * The other server must have had a
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean remoteStoreUnique() throws IOException
+ {
+ if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
+ __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
+ return FTPReply.isPositivePreliminary(stou());
+ return false;
+ }
+
+ // For server to server transfers
+ /***
+ * Initiate a server to server file transfer. This method tells the
+ * server to which the client is connected to append to a given file on
+ * the other server. The other server must have had a
+ *
+ * @param filename The name of the file to be appended to, or if the
+ * file does not exist, the name to call the file being stored.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean remoteAppend(String filename) throws IOException
+ {
+ if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
+ __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
+ return FTPReply.isPositivePreliminary(stor(filename));
+ return false;
+ }
+
+ /***
+ * There are a few FTPClient methods that do not complete the
+ * entire sequence of FTP commands to complete a transaction. These
+ * commands require some action by the programmer after the reception
+ * of a positive intermediate command. After the programmer's code
+ * completes its actions, it must call this method to receive
+ * the completion reply from the server and verify the success of the
+ * entire transaction.
+ *
+ * For example,
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean completePendingCommand() throws IOException
+ {
+ return FTPReply.isPositiveCompletion(getReply());
+ }
+
+
+ /***
+ * Retrieves a named file from the server and writes it to the given
+ * OutputStream. This method does NOT close the given OutputStream.
+ * If the current file type is ASCII, line separators in the file are
+ * converted to the local representation.
+ *
+ * @param remote The name of the remote file.
+ * @param local The local OutputStream to which to write the file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception CopyStreamException If an I/O error occurs while actually
+ * transferring the file. The CopyStreamException allows you to
+ * determine the number of bytes transferred and the IOException
+ * causing the error. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean retrieveFile(String remote, OutputStream local)
+ throws IOException
+ {
+ InputStream input;
+ Socket socket;
+
+ if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null)
+ return false;
+
+ input = new BufferedInputStream(socket.getInputStream(),
+ getBufferSize());
+ if (__fileType == ASCII_FILE_TYPE)
+ input = new FromNetASCIIInputStream(input);
+ // Treat everything else as binary for now
+ try
+ {
+ Util.copyStream(input, local, getBufferSize(),
+ CopyStreamEvent.UNKNOWN_STREAM_SIZE, null,
+ false);
+ }
+ catch (IOException e)
+ {
+ try
+ {
+ socket.close();
+ }
+ catch (IOException f)
+ {}
+ throw e;
+ }
+ socket.close();
+ return completePendingCommand();
+ }
+
+ /***
+ * Returns an InputStream from which a named file from the server
+ * can be read. If the current file type is ASCII, the returned
+ * InputStream will convert line separators in the file to
+ * the local representation. You must close the InputStream when you
+ * finish reading from it. The InputStream itself will take care of
+ * closing the parent data connection socket upon being closed. To
+ * finalize the file transfer you must call
+ * {@link #completePendingCommand completePendingCommand } and
+ * check its return value to verify success.
+ *
+ * @param remote The name of the remote file.
+ * @return An InputStream from which the remote file can be read. If
+ * the data connection cannot be opened (e.g., the file does not
+ * exist), null is returned (in which case you may check the reply
+ * code to determine the exact reason for failure).
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public InputStream retrieveFileStream(String remote) throws IOException
+ {
+ InputStream input;
+ Socket socket;
+
+ if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null)
+ return null;
+
+ input = socket.getInputStream();
+ if (__fileType == ASCII_FILE_TYPE) {
+ // We buffer ascii transfers because the buffering has to
+ // be interposed between FromNetASCIIOutputSream and the underlying
+ // socket input stream. We don't buffer binary transfers
+ // because we don't want to impose a buffering policy on the
+ // programmer if possible. Programmers can decide on their
+ // own if they want to wrap the SocketInputStream we return
+ // for file types other than ASCII.
+ input = new BufferedInputStream(input,
+ getBufferSize());
+ input = new FromNetASCIIInputStream(input);
+ }
+ return new org.apache.commons.net.io.SocketInputStream(socket, input);
+ }
+
+
+ /***
+ * Stores a file on the server using the given name and taking input
+ * from the given InputStream. This method does NOT close the given
+ * InputStream. If the current file type is ASCII, line separators in
+ * the file are transparently converted to the NETASCII format (i.e.,
+ * you should not attempt to create a special InputStream to do this).
+ *
+ * @param remote The name to give the remote file.
+ * @param local The local InputStream from which to read the file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception CopyStreamException If an I/O error occurs while actually
+ * transferring the file. The CopyStreamException allows you to
+ * determine the number of bytes transferred and the IOException
+ * causing the error. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean storeFile(String remote, InputStream local)
+ throws IOException
+ {
+ return __storeFile(FTPCommand.STOR, remote, local);
+ }
+
+
+ /***
+ * Returns an OutputStream through which data can be written to store
+ * a file on the server using the given name. If the current file type
+ * is ASCII, the returned OutputStream will convert line separators in
+ * the file to the NETASCII format (i.e., you should not attempt to
+ * create a special OutputStream to do this). You must close the
+ * OutputStream when you finish writing to it. The OutputStream itself
+ * will take care of closing the parent data connection socket upon being
+ * closed. To finalize the file transfer you must call
+ * {@link #completePendingCommand completePendingCommand } and
+ * check its return value to verify success.
+ *
+ * @param remote The name to give the remote file.
+ * @return An OutputStream through which the remote file can be written. If
+ * the data connection cannot be opened (e.g., the file does not
+ * exist), null is returned (in which case you may check the reply
+ * code to determine the exact reason for failure).
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public OutputStream storeFileStream(String remote) throws IOException
+ {
+ return __storeFileStream(FTPCommand.STOR, remote);
+ }
+
+ /***
+ * Appends to a file on the server with the given name, taking input
+ * from the given InputStream. This method does NOT close the given
+ * InputStream. If the current file type is ASCII, line separators in
+ * the file are transparently converted to the NETASCII format (i.e.,
+ * you should not attempt to create a special InputStream to do this).
+ *
+ * @param remote The name of the remote file.
+ * @param local The local InputStream from which to read the data to
+ * be appended to the remote file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception CopyStreamException If an I/O error occurs while actually
+ * transferring the file. The CopyStreamException allows you to
+ * determine the number of bytes transferred and the IOException
+ * causing the error. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean appendFile(String remote, InputStream local)
+ throws IOException
+ {
+ return __storeFile(FTPCommand.APPE, remote, local);
+ }
+
+ /***
+ * Returns an OutputStream through which data can be written to append
+ * to a file on the server with the given name. If the current file type
+ * is ASCII, the returned OutputStream will convert line separators in
+ * the file to the NETASCII format (i.e., you should not attempt to
+ * create a special OutputStream to do this). You must close the
+ * OutputStream when you finish writing to it. The OutputStream itself
+ * will take care of closing the parent data connection socket upon being
+ * closed. To finalize the file transfer you must call
+ * {@link #completePendingCommand completePendingCommand } and
+ * check its return value to verify success.
+ *
+ * @param remote The name of the remote file.
+ * @return An OutputStream through which the remote file can be appended.
+ * If the data connection cannot be opened (e.g., the file does not
+ * exist), null is returned (in which case you may check the reply
+ * code to determine the exact reason for failure).
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public OutputStream appendFileStream(String remote) throws IOException
+ {
+ return __storeFileStream(FTPCommand.APPE, remote);
+ }
+
+ /***
+ * Stores a file on the server using a unique name derived from the
+ * given name and taking input
+ * from the given InputStream. This method does NOT close the given
+ * InputStream. If the current file type is ASCII, line separators in
+ * the file are transparently converted to the NETASCII format (i.e.,
+ * you should not attempt to create a special InputStream to do this).
+ *
+ * @param remote The name on which to base the unique name given to
+ * the remote file.
+ * @param local The local InputStream from which to read the file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception CopyStreamException If an I/O error occurs while actually
+ * transferring the file. The CopyStreamException allows you to
+ * determine the number of bytes transferred and the IOException
+ * causing the error. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean storeUniqueFile(String remote, InputStream local)
+ throws IOException
+ {
+ return __storeFile(FTPCommand.STOU, remote, local);
+ }
+
+
+ /***
+ * Returns an OutputStream through which data can be written to store
+ * a file on the server using a unique name derived from the given name.
+ * If the current file type
+ * is ASCII, the returned OutputStream will convert line separators in
+ * the file to the NETASCII format (i.e., you should not attempt to
+ * create a special OutputStream to do this). You must close the
+ * OutputStream when you finish writing to it. The OutputStream itself
+ * will take care of closing the parent data connection socket upon being
+ * closed. To finalize the file transfer you must call
+ * {@link #completePendingCommand completePendingCommand } and
+ * check its return value to verify success.
+ *
+ * @param remote The name on which to base the unique name given to
+ * the remote file.
+ * @return An OutputStream through which the remote file can be written. If
+ * the data connection cannot be opened (e.g., the file does not
+ * exist), null is returned (in which case you may check the reply
+ * code to determine the exact reason for failure).
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public OutputStream storeUniqueFileStream(String remote) throws IOException
+ {
+ return __storeFileStream(FTPCommand.STOU, remote);
+ }
+
+ /**
+ * Stores a file on the server using a unique name assigned by the
+ * server and taking input from the given InputStream. This method does
+ * NOT close the given
+ * InputStream. If the current file type is ASCII, line separators in
+ * the file are transparently converted to the NETASCII format (i.e.,
+ * you should not attempt to create a special InputStream to do this).
+ *
+ * @param local The local InputStream from which to read the file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception CopyStreamException If an I/O error occurs while actually
+ * transferring the file. The CopyStreamException allows you to
+ * determine the number of bytes transferred and the IOException
+ * causing the error. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ public boolean storeUniqueFile(InputStream local) throws IOException
+ {
+ return __storeFile(FTPCommand.STOU, null, local);
+ }
+
+ /**
+ * Returns an OutputStream through which data can be written to store
+ * a file on the server using a unique name assigned by the server.
+ * If the current file type
+ * is ASCII, the returned OutputStream will convert line separators in
+ * the file to the NETASCII format (i.e., you should not attempt to
+ * create a special OutputStream to do this). You must close the
+ * OutputStream when you finish writing to it. The OutputStream itself
+ * will take care of closing the parent data connection socket upon being
+ * closed. To finalize the file transfer you must call
+ * {@link #completePendingCommand completePendingCommand } and
+ * check its return value to verify success.
+ *
+ * @return An OutputStream through which the remote file can be written. If
+ * the data connection cannot be opened (e.g., the file does not
+ * exist), null is returned (in which case you may check the reply
+ * code to determine the exact reason for failure).
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ public OutputStream storeUniqueFileStream() throws IOException
+ {
+ return __storeFileStream(FTPCommand.STOU, null);
+ }
+
+ /***
+ * Reserve a number of bytes on the server for the next file transfer.
+ *
+ * @param bytes The number of bytes which the server should allocate.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean allocate(int bytes) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(allo(bytes));
+ }
+
+
+ /**
+ * Reserve space on the server for the next file transfer.
+ *
+ * @param bytes The number of bytes which the server should allocate.
+ * @param recordSize The size of a file record.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ public boolean allocate(int bytes, int recordSize) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(allo(bytes, recordSize));
+ }
+
+
+ /***
+ * Restart a
+ * @param offset The offset into the remote file at which to start the
+ * next file transfer.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ private boolean restart(long offset) throws IOException
+ {
+ __restartOffset = 0;
+ return FTPReply.isPositiveIntermediate(rest(Long.toString(offset)));
+ }
+
+ /***
+ * Sets the restart offset. The restart command is sent to the server
+ * only before sending the file transfer command. When this is done,
+ * the restart marker is reset to zero.
+ *
+ * @param offset The offset into the remote file at which to start the
+ * next file transfer. This must be a value greater than or
+ * equal to zero.
+ ***/
+ public void setRestartOffset(long offset)
+ {
+ if (offset >= 0)
+ __restartOffset = offset;
+ }
+
+ /***
+ * Fetches the restart offset.
+ *
+ * @return offset The offset into the remote file at which to start the
+ * next file transfer.
+ ***/
+ public long getRestartOffset()
+ {
+ return __restartOffset;
+ }
+
+
+
+ /***
+ * Renames a remote file.
+ *
+ * @param from The name of the remote file to rename.
+ * @param to The new name of the remote file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean rename(String from, String to) throws IOException
+ {
+ if (!FTPReply.isPositiveIntermediate(rnfr(from)))
+ return false;
+
+ return FTPReply.isPositiveCompletion(rnto(to));
+ }
+
+
+ /***
+ * Abort a transfer in progress.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean abort() throws IOException
+ {
+ return FTPReply.isPositiveCompletion(abor());
+ }
+
+ /***
+ * Deletes a file on the FTP server.
+ *
+ * @param pathname The pathname of the file to be deleted.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean deleteFile(String pathname) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(dele(pathname));
+ }
+
+
+ /***
+ * Removes a directory on the FTP server (if empty).
+ *
+ * @param pathname The pathname of the directory to remove.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean removeDirectory(String pathname) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(rmd(pathname));
+ }
+
+
+ /***
+ * Creates a new subdirectory on the FTP server in the current directory
+ * (if a relative pathname is given) or where specified (if an absolute
+ * pathname is given).
+ *
+ * @param pathname The pathname of the directory to create.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean makeDirectory(String pathname) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(mkd(pathname));
+ }
+
+
+ /***
+ * Returns the pathname of the current working directory.
+ *
+ * @return The pathname of the current working directory. If it cannot
+ * be obtained, returns null.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String printWorkingDirectory() throws IOException
+ {
+ if (pwd() != FTPReply.PATHNAME_CREATED)
+ return null;
+
+ return __parsePathname(_replyLines.get( _replyLines.size() - 1));
+ }
+
+
+ /**
+ * Send a site specific command.
+ * @param arguments The site specific command and arguments.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ public boolean sendSiteCommand(String arguments) throws IOException
+ {
+ return FTPReply.isPositiveCompletion(site(arguments));
+ }
+
+
+ /***
+ * Fetches the system type name from the server and returns the string.
+ * This value is cached for the duration of the connection after the
+ * first call to this method. In other words, only the first time
+ * that you invoke this method will it issue a SYST command to the
+ * FTP server. FTPClient will remember the value and return the
+ * cached value until a call to disconnect.
+ *
+ * @return The system type name obtained from the server. null if the
+ * information could not be obtained.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String getSystemName() throws IOException
+ {
+ //if (syst() == FTPReply.NAME_SYSTEM_TYPE)
+ // Technically, we should expect a NAME_SYSTEM_TYPE response, but
+ // in practice FTP servers deviate, so we soften the condition to
+ // a positive completion.
+ if (__systemName == null && FTPReply.isPositiveCompletion(syst()))
+ __systemName = _replyLines.get(_replyLines.size() - 1).substring(4);
+
+ return __systemName;
+ }
+
+
+ /***
+ * Fetches the system help information from the server and returns the
+ * full string.
+ *
+ * @return The system help string obtained from the server. null if the
+ * information could not be obtained.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String listHelp() throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(help()))
+ return getReplyString();
+ return null;
+ }
+
+
+ /**
+ * Fetches the help information for a given command from the server and
+ * returns the full string.
+ * @param command The command on which to ask for help.
+ * @return The command help string obtained from the server. null if the
+ * information could not be obtained.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ */
+ public String listHelp(String command) throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(help(command)))
+ return getReplyString();
+ return null;
+ }
+
+
+ /***
+ * Sends a NOOP command to the FTP server. This is useful for preventing
+ * server timeouts.
+ *
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean sendNoOp() throws IOException
+ {
+ return FTPReply.isPositiveCompletion(noop());
+ }
+
+
+ /***
+ * Obtain a list of filenames in a directory (or just the name of a given
+ * file, which is not particularly useful). This information is obtained
+ * through the NLST command. If the given pathname is a directory and
+ * contains no files, a zero length array is returned only
+ * if the FTP server returned a positive completion code, otherwise
+ * null is returned (the FTP server returned a 550 error No files found.).
+ * If the directory is not empty, an array of filenames in the directory is
+ * returned. If the pathname corresponds
+ * to a file, only that file will be listed. The server may or may not
+ * expand glob expressions.
+ *
+ * @param pathname The file or directory to list.
+ * @return The list of filenames contained in the given path. null if
+ * the list could not be obtained. If there are no filenames in
+ * the directory, a zero-length array is returned.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String[] listNames(String pathname) throws IOException
+ {
+ String line;
+ Socket socket;
+ BufferedReader reader;
+ ArrayList
+ * @return The list of filenames contained in the current working
+ * directory. null if the list could not be obtained.
+ * If there are no filenames in the directory, a zero-length array
+ * is returned.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String[] listNames() throws IOException
+ {
+ return listNames(null);
+ }
+
+
+
+ /**
+ * Using the default system autodetect mechanism, obtain a
+ * list of file information for the current working directory
+ * or for just a single file.
+ *
+ * This information is obtained through the LIST command. The contents of
+ * the returned array is determined by the
+ * @param pathname The file or directory to list. Since the server may
+ * or may not expand glob expressions, using them here
+ * is not recommended and may well cause this method to
+ * fail.
+ *
+ * @return The list of file information contained in the given path in
+ * the format determined by the autodetection mechanism
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection
+ * as a result of the client being idle or some other
+ * reason causing the server to send FTP reply code 421.
+ * This exception may be caught either as an IOException
+ * or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply
+ * from the server.
+ * @exception ParserInitializationException
+ * Thrown if the parserKey parameter cannot be
+ * resolved by the selected parser factory.
+ * In the DefaultFTPEntryParserFactory, this will
+ * happen when parserKey is neither
+ * the fully qualified class name of a class
+ * implementing the interface
+ * org.apache.commons.net.ftp.FTPFileEntryParser
+ * nor a string containing one of the recognized keys
+ * mapping to such a parser or if class loader
+ * security issues prevent its being loaded.
+ * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
+ * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser
+ */
+ public FTPFile[] listFiles(String pathname)
+ throws IOException
+ {
+ String key = null;
+ FTPListParseEngine engine =
+ initiateListParsing(key, pathname);
+ return engine.getFiles();
+
+ }
+ /**
+ * Using the default system autodetect mechanism, obtain a
+ * list of file information for the current working directory.
+ *
+ * This information is obtained through the LIST command. The contents of
+ * the returned array is determined by the
+ * @return The list of file information contained in the current directory
+ * in the format determined by the autodetection mechanism.
+ *
+ * NOTE: This array may contain null members if any of the
+ * individual file listings failed to parse. The caller should
+ * check each entry for null before referencing it.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection
+ * as a result of the client being idle or some other
+ * reason causing the server to send FTP reply code 421.
+ * This exception may be caught either as an IOException
+ * or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply
+ * from the server.
+ * @exception ParserInitializationException
+ * Thrown if the parserKey parameter cannot be
+ * resolved by the selected parser factory.
+ * In the DefaultFTPEntryParserFactory, this will
+ * happen when parserKey is neither
+ * the fully qualified class name of a class
+ * implementing the interface
+ * org.apache.commons.net.ftp.FTPFileEntryParser
+ * nor a string containing one of the recognized keys
+ * mapping to such a parser or if class loader
+ * security issues prevent its being loaded.
+ * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
+ * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser
+ */
+ public FTPFile[] listFiles()
+ throws IOException
+ {
+ return listFiles((String) null);
+ }
+
+ /**
+ * Using the default autodetect mechanism, initialize an FTPListParseEngine
+ * object containing a raw file information for the current working
+ * directory on the server
+ * This information is obtained through the LIST command. This object
+ * is then capable of being iterated to return a sequence of FTPFile
+ * objects with information filled in by the
+ *
+ * This method differs from using the listFiles() methods in that
+ * expensive FTPFile objects are not created until needed which may be
+ * an advantage on large lists.
+ *
+ * @return A FTPListParseEngine object that holds the raw information and
+ * is capable of providing parsed FTPFile objects, one for each file
+ * containing information contained in the given path in the format
+ * determined by the
+ * The server may or may not expand glob expressions. You should avoid
+ * using glob expressions because the return format for glob listings
+ * differs from server to server and will likely cause this method to fail.
+ *
+ * This method differs from using the listFiles() methods in that
+ * expensive FTPFile objects are not created until needed which may be
+ * an advantage on large lists.
+ *
+ *
+ * The server may or may not expand glob expressions. You should avoid
+ * using glob expressions because the return format for glob listings
+ * differs from server to server and will likely cause this method to fail.
+ *
+ * This method differs from using the listFiles() methods in that
+ * expensive FTPFile objects are not created until needed which may be
+ * an advantage on large lists.
+ *
+ * @param parserKey A string representing a designated code or fully-qualified
+ * class name of an
+ * @return The status information returned by the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String getStatus() throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(stat()))
+ return getReplyString();
+ return null;
+ }
+
+
+ /***
+ * Issue the FTP STAT command to the server for a given pathname. This
+ * should produce a listing of the file or directory.
+ *
+ * @return The status information returned by the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public String getStatus(String pathname) throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(stat(pathname)))
+ return getReplyString();
+ return null;
+ }
+
+
+ /**
+ * Issue the FTP MDTM command (not supported by all servers to retrieve the last
+ * modification time of a file. The modification string should be in the
+ * ISO 3077 form "YYYYMMDDhhmmss(.xxx)?". The timestamp represented should also be in
+ * GMT, but not all FTP servers honour this.
+ *
+ * @param pathname The file path to query.
+ * @return A string representing the last file modification time in
+ * This class implements an alternate means of configuring the
+ * {@link org.apache.commons.net.ftp.FTPClient FTPClient} object and
+ * also subordinate objects which it uses. Any class implementing the
+ * {@link org.apache.commons.net.ftp.Configurable Configurable }
+ * interface can be configured by this object.
+ *
+ * In particular this class was designed primarily to support configuration
+ * of FTP servers which express file timestamps in formats and languages
+ * other than those for the US locale, which although it is the most common
+ * is not universal. Unfortunately, nothing in the FTP spec allows this to
+ * be determined in an automated way, so manual configuration such as this
+ * is necessary.
+ *
+ * This functionality was designed to allow existing clients to work exactly
+ * as before without requiring use of this component. This component should
+ * only need to be explicitly invoked by the user of this package for problem
+ * cases that previous implementations could not solve.
+ *
+ * Unpaged (whole list) access on a UNIX server that uses French month names
+ * but uses the "standard"
+ * Paged access on a UNIX server that uses Danish month names
+ * and "European" date formatting in Denmark's time zone, when you
+ * are in some other time zone.
+ *
+ * Unpaged (whole list) access on a VMS server that uses month names
+ * in a language not {@link #getSupportedLanguageCodes() supported} by the system.
+ * but uses the "standard"
+ * Unpaged (whole list) access on a Windows-NT server in a different time zone.
+ * (Note, since the NT Format uses numeric date formatting, language issues
+ * are irrelevant here).
+ *
+ * getter for the {@link #setShortMonthNames(String) shortMonthNames}
+ * property.
+ *
+ * getter for the {@link #setServerLanguageCode(String) serverLanguageCode} property.
+ *
+ * getter for the {@link #setLenientFutureDates(boolean) lenientFutureDates} property.
+ *
+ * setter for the defaultDateFormatStr property. This property
+ * specifies the main date format that will be used by a parser configured
+ * by this configuration to parse file timestamps. If this is not
+ * specified, such a parser will use as a default value, the most commonly
+ * used format which will be in as used in
+ * This should be in the format described for
+ *
+ * setter for the recentDateFormatStr property. This property
+ * specifies a secondary date format that will be used by a parser
+ * configured by this configuration to parse file timestamps, typically
+ * those less than a year old. If this is not specified, such a parser
+ * will not attempt to parse using an alternate format.
+ *
+ * setter for the lenientFutureDates property. This boolean property
+ * (default: false) only has meaning when a
+ * {@link #setRecentDateFormatStr(String) recentDateFormatStr} property
+ * has been set. In that case, if this property is set true, then the
+ * parser, when it encounters a listing parseable with the recent date
+ * format, will only consider a date to belong to the previous year if
+ * it is more than one day in the future. This will allow all
+ * out-of-synch situations (whether based on "slop" - i.e. servers simply
+ * out of synch with one another or because of time zone differences -
+ * but in the latter case it is highly recommended to use the
+ * {@link #setServerTimeZoneId(String) serverTimeZoneId} property
+ * instead) to resolve correctly.
+ *
+ * This is used primarily in unix-based systems.
+ *
+ * setter for the serverTimeZoneId property. This property
+ * allows a time zone to be specified corresponding to that known to be
+ * used by an FTP server in file listings. This might be particularly
+ * useful to clients such as Ant that try to use these timestamps for
+ * dependency checking.
+ *
+ * This should be one of the identifiers used by
+ *
+ * setter for the shortMonthNames property.
+ * This property allows the user to specify a set of month names
+ * used by the server that is different from those that may be
+ * specified using the {@link #setServerLanguageCode(String) serverLanguageCode}
+ * property.
+ *
+ * This should be a string containing twelve strings each composed of
+ * three characters, delimited by pipe (|) characters. Currently,
+ * only 8-bit ASCII characters are known to be supported. For example,
+ * a set of month names used by a hypothetical Icelandic FTP server might
+ * conceivably be specified as
+ *
+ * setter for the serverLanguageCode property. This property allows
+ * user to specify a
+ *
+ * two-letter ISO-639 language code that will be used to
+ * configure the set of month names used by the file timestamp parser.
+ * If neither this nor the {@link #setShortMonthNames(String) shortMonthNames}
+ * is specified, parsing will assume English month names, which may or
+ * may not be significant, depending on whether the date format(s)
+ * specified via {@link #setDefaultDateFormatStr(String) defaultDateFormatStr}
+ * and/or {@link #setRecentDateFormatStr(String) recentDateFormatStr} are using
+ * numeric or alphabetic month names.
+ * If the code supplied is not supported here,
+ * Please note that this attribute will NOT be used to determine a
+ * locale-based date format for the language.
+ * Experience has shown that many if not most FTP servers outside the
+ * United States employ the standard
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class FTPCommand
+{
+
+
+ public static final int USER = 0;
+ public static final int PASS = 1;
+ public static final int ACCT = 2;
+ public static final int CWD = 3;
+ public static final int CDUP = 4;
+ public static final int SMNT = 5;
+ public static final int REIN = 6;
+ public static final int QUIT = 7;
+ public static final int PORT = 8;
+ public static final int PASV = 9;
+ public static final int TYPE = 10;
+ public static final int STRU = 11;
+ public static final int MODE = 12;
+ public static final int RETR = 13;
+ public static final int STOR = 14;
+ public static final int STOU = 15;
+ public static final int APPE = 16;
+ public static final int ALLO = 17;
+ public static final int REST = 18;
+ public static final int RNFR = 19;
+ public static final int RNTO = 20;
+ public static final int ABOR = 21;
+ public static final int DELE = 22;
+ public static final int RMD = 23;
+ public static final int MKD = 24;
+ public static final int PWD = 25;
+ public static final int LIST = 26;
+ public static final int NLST = 27;
+ public static final int SITE = 28;
+ public static final int SYST = 29;
+ public static final int STAT = 30;
+ public static final int HELP = 31;
+ public static final int NOOP = 32;
+ /** @since 2.0 */
+ public static final int MDTM = 33;
+
+ public static final int USERNAME = USER;
+ public static final int PASSWORD = PASS;
+ public static final int ACCOUNT = ACCT;
+ public static final int CHANGE_WORKING_DIRECTORY = CWD;
+ public static final int CHANGE_TO_PARENT_DIRECTORY = CDUP;
+ public static final int STRUCTURE_MOUNT = SMNT;
+ public static final int REINITIALIZE = REIN;
+ public static final int LOGOUT = QUIT;
+ public static final int DATA_PORT = PORT;
+ public static final int PASSIVE = PASV;
+ public static final int REPRESENTATION_TYPE = TYPE;
+ public static final int FILE_STRUCTURE = STRU;
+ public static final int TRANSFER_MODE = MODE;
+ public static final int RETRIEVE = RETR;
+ public static final int STORE = STOR;
+ public static final int STORE_UNIQUE = STOU;
+ public static final int APPEND = APPE;
+ public static final int ALLOCATE = ALLO;
+ public static final int RESTART = REST;
+ public static final int RENAME_FROM = RNFR;
+ public static final int RENAME_TO = RNTO;
+ public static final int ABORT = ABOR;
+ public static final int DELETE = DELE;
+ public static final int REMOVE_DIRECTORY = RMD;
+ public static final int MAKE_DIRECTORY = MKD;
+ public static final int PRINT_WORKING_DIRECTORY = PWD;
+ // public static final int LIST = LIST;
+ public static final int NAME_LIST = NLST;
+ public static final int SITE_PARAMETERS = SITE;
+ public static final int SYSTEM = SYST;
+ public static final int STATUS = STAT;
+ //public static final int HELP = HELP;
+ //public static final int NOOP = NOOP;
+ /** @since 2.0 */
+ public static final int MOD_TIME = MDTM;
+
+ // Cannot be instantiated
+ private FTPCommand()
+ {}
+
+ static final String[] _commands = {
+ "USER", "PASS", "ACCT", "CWD", "CDUP", "SMNT", "REIN", "QUIT", "PORT",
+ "PASV", "TYPE", "STRU", "MODE", "RETR", "STOR", "STOU", "APPE", "ALLO",
+ "REST", "RNFR", "RNTO", "ABOR", "DELE", "RMD", "MKD", "PWD", "LIST",
+ "NLST", "SITE", "SYST", "STAT", "HELP", "NOOP"
+ };
+
+ /**
+ * Retrieve the FTP protocol command string corresponding to a specified
+ * command code.
+ *
+ * @param command The command code.
+ * @return The FTP protcol command string corresponding to a specified
+ * command code.
+ */
+ public static final String getCommand(int command)
+ {
+ return _commands[command];
+ }
+}
diff --git a/src/org/apache/commons/net/ftp/FTPConnectionClosedException.java b/src/org/apache/commons/net/ftp/FTPConnectionClosedException.java
new file mode 100644
index 0000000..3eccbf4
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/FTPConnectionClosedException.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+import java.io.IOException;
+
+/***
+ * FTPConnectionClosedException is used to indicate the premature or
+ * unexpected closing of an FTP connection resulting from a
+ * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
+ * response (FTP reply code 421) to a
+ * failed FTP command. This exception is derived from IOException and
+ * therefore may be caught either as an IOException or specifically as an
+ * FTPConnectionClosedException.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see FTP
+ * @see FTPClient
+ ***/
+
+public class FTPConnectionClosedException extends IOException
+{
+
+ /*** Constructs a FTPConnectionClosedException with no message ***/
+ public FTPConnectionClosedException()
+ {
+ super();
+ }
+
+ /***
+ * Constructs a FTPConnectionClosedException with a specified message.
+ *
+ * @param message The message explaining the reason for the exception.
+ ***/
+ public FTPConnectionClosedException(String message)
+ {
+ super(message);
+ }
+
+}
diff --git a/src/org/apache/commons/net/ftp/FTPFile.java b/src/org/apache/commons/net/ftp/FTPFile.java
new file mode 100644
index 0000000..dd67904
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/FTPFile.java
@@ -0,0 +1,392 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+import java.io.Serializable;
+import java.util.Calendar;
+
+/***
+ * The FTPFile class is used to represent information about files stored
+ * on an FTP server. Because there is no standard representation for
+ * file information on FTP servers, it may not always be possible to
+ * extract all the information that can be represented by FTPFile, or
+ * it may even be possible to extract more information. In cases where
+ * more information can be extracted, you will want to subclass FTPFile
+ * and implement your own {@link org.apache.commons.net.ftp.FTPFileListParser}
+ * to extract the information.
+ * However, most FTP servers return file information in a format that
+ * can be completely parsed by
+ * {@link org.apache.commons.net.ftp.DefaultFTPFileListParser}
+ * and stored in FTPFile.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see FTPFileListParser
+ * @see DefaultFTPFileListParser
+ * @see FTPClient#listFiles
+ ***/
+
+public class FTPFile implements Serializable
+{
+ /** A constant indicating an FTPFile is a file. ***/
+ public static final int FILE_TYPE = 0;
+ /** A constant indicating an FTPFile is a directory. ***/
+ public static final int DIRECTORY_TYPE = 1;
+ /** A constant indicating an FTPFile is a symbolic link. ***/
+ public static final int SYMBOLIC_LINK_TYPE = 2;
+ /** A constant indicating an FTPFile is of unknown type. ***/
+ public static final int UNKNOWN_TYPE = 3;
+
+ /** A constant indicating user access permissions. ***/
+ public static final int USER_ACCESS = 0;
+ /** A constant indicating group access permissions. ***/
+ public static final int GROUP_ACCESS = 1;
+ /** A constant indicating world access permissions. ***/
+ public static final int WORLD_ACCESS = 2;
+
+ /** A constant indicating file/directory read permission. ***/
+ public static final int READ_PERMISSION = 0;
+ /** A constant indicating file/directory write permission. ***/
+ public static final int WRITE_PERMISSION = 1;
+ /**
+ * A constant indicating file execute permission or directory listing
+ * permission.
+ ***/
+ public static final int EXECUTE_PERMISSION = 2;
+
+ int _type, _hardLinkCount;
+ long _size;
+ String _rawListing, _user, _group, _name, _link;
+ Calendar _date;
+ boolean[] _permissions[];
+
+ /*** Creates an empty FTPFile. ***/
+ public FTPFile()
+ {
+ _permissions = new boolean[3][3];
+ _rawListing = null;
+ _type = UNKNOWN_TYPE;
+ _hardLinkCount = 0;
+ _size = 0;
+ _user = null;
+ _group = null;
+ _date = null;
+ _name = null;
+ }
+
+
+ /***
+ * Set the original FTP server raw listing from which the FTPFile was
+ * created.
+ *
+ * @param rawListing The raw FTP server listing.
+ ***/
+ public void setRawListing(String rawListing)
+ {
+ _rawListing = rawListing;
+ }
+
+ /***
+ * Get the original FTP server raw listing used to initialize the FTPFile.
+ *
+ * @return The original FTP server raw listing used to initialize the
+ * FTPFile.
+ ***/
+ public String getRawListing()
+ {
+ return _rawListing;
+ }
+
+
+ /***
+ * Determine if the file is a directory.
+ *
+ * @return True if the file is of type
+ * @return True if the file is of type
+ * @return True if the file is of type
+ * @return True if the file is of type
+ * @param type The integer code representing the type of the file.
+ ***/
+ public void setType(int type)
+ {
+ _type = type;
+ }
+
+
+ /***
+ * Return the type of the file (one of the
+ * @return The type of the file.
+ ***/
+ public int getType()
+ {
+ return _type;
+ }
+
+
+ /***
+ * Set the name of the file.
+ *
+ * @param name The name of the file.
+ ***/
+ public void setName(String name)
+ {
+ _name = name;
+ }
+
+ /***
+ * Return the name of the file.
+ *
+ * @return The name of the file.
+ ***/
+ public String getName()
+ {
+ return _name;
+ }
+
+
+ /**
+ * Set the file size in bytes.
+ * @param size The file size in bytes.
+ */
+ public void setSize(long size)
+ {
+ _size = size;
+ }
+
+
+ /***
+ * Return the file size in bytes.
+ *
+ * @return The file size in bytes.
+ ***/
+ public long getSize()
+ {
+ return _size;
+ }
+
+
+ /***
+ * Set the number of hard links to this file. This is not to be
+ * confused with symbolic links.
+ *
+ * @param links The number of hard links to this file.
+ ***/
+ public void setHardLinkCount(int links)
+ {
+ _hardLinkCount = links;
+ }
+
+
+ /***
+ * Return the number of hard links to this file. This is not to be
+ * confused with symbolic links.
+ *
+ * @return The number of hard links to this file.
+ ***/
+ public int getHardLinkCount()
+ {
+ return _hardLinkCount;
+ }
+
+
+ /***
+ * Set the name of the group owning the file. This may be
+ * a string representation of the group number.
+ *
+ * @param group The name of the group owning the file.
+ ***/
+ public void setGroup(String group)
+ {
+ _group = group;
+ }
+
+
+ /***
+ * Returns the name of the group owning the file. Sometimes this will be
+ * a string representation of the group number.
+ *
+ * @return The name of the group owning the file.
+ ***/
+ public String getGroup()
+ {
+ return _group;
+ }
+
+
+ /***
+ * Set the name of the user owning the file. This may be
+ * a string representation of the user number;
+ *
+ * @param user The name of the user owning the file.
+ ***/
+ public void setUser(String user)
+ {
+ _user = user;
+ }
+
+ /***
+ * Returns the name of the user owning the file. Sometimes this will be
+ * a string representation of the user number.
+ *
+ * @return The name of the user owning the file.
+ ***/
+ public String getUser()
+ {
+ return _user;
+ }
+
+
+ /***
+ * If the FTPFile is a symbolic link, use this method to set the name of the
+ * file being pointed to by the symbolic link.
+ *
+ * @param link The file pointed to by the symbolic link.
+ ***/
+ public void setLink(String link)
+ {
+ _link = link;
+ }
+
+
+ /***
+ * If the FTPFile is a symbolic link, this method returns the name of the
+ * file being pointed to by the symbolic link. Otherwise it returns null.
+ *
+ * @return The file pointed to by the symbolic link (null if the FTPFile
+ * is not a symbolic link).
+ ***/
+ public String getLink()
+ {
+ return _link;
+ }
+
+
+ /***
+ * Set the file timestamp. This usually the last modification time.
+ * The parameter is not cloned, so do not alter its value after calling
+ * this method.
+ *
+ * @param date A Calendar instance representing the file timestamp.
+ ***/
+ public void setTimestamp(Calendar date)
+ {
+ _date = date;
+ }
+
+
+ /***
+ * Returns the file timestamp. This usually the last modification time.
+ *
+ * @return A Calendar instance representing the file timestamp.
+ ***/
+ public Calendar getTimestamp()
+ {
+ return _date;
+ }
+
+
+ /***
+ * Set if the given access group (one of the
+ * @param access The access group (one of the
+ * @param access The access group (one of the
+ * @return A string representation of the FTPFile information.
+ ***/
+ @Override
+ public String toString()
+ {
+ return _rawListing;
+ }
+
+}
diff --git a/src/org/apache/commons/net/ftp/FTPFileEntryParser.java b/src/org/apache/commons/net/ftp/FTPFileEntryParser.java
new file mode 100644
index 0000000..8e6d09c
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/FTPFileEntryParser.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * FTPFileEntryParser defines the interface for parsing a single FTP file
+ * listing and converting that information into an
+ * {@link org.apache.commons.net.ftp.FTPFile} instance.
+ * Sometimes you will want to parse unusual listing formats, in which
+ * case you would create your own implementation of FTPFileEntryParser and
+ * if necessary, subclass FTPFile.
+ *
+ * Here are some examples showing how to use one of the classes that
+ * implement this interface.
+ *
+ * The first example shows how to get an iterable list of files in which the
+ * more expensive
+ * @param listEntry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ FTPFile parseFTPEntry(String listEntry);
+
+ /**
+ * Reads the next entry using the supplied BufferedReader object up to
+ * whatever delemits one entry from the next. Implementors must define
+ * this for the particular ftp system being parsed. In many but not all
+ * cases, this can be defined simply by calling BufferedReader.readLine().
+ *
+ * @param reader The BufferedReader object from which entries are to be
+ * read.
+ *
+ * @return A string representing the next ftp entry or null if none found.
+ * @exception IOException thrown on any IO Error reading from the reader.
+ */
+ String readNextEntry(BufferedReader reader) throws IOException;
+
+
+ /**
+ * This method is a hook for those implementors (such as
+ * VMSVersioningFTPEntryParser, and possibly others) which need to
+ * perform some action upon the FTPFileList after it has been created
+ * from the server stream, but before any clients see the list.
+ *
+ * The default implementation can be a no-op.
+ *
+ * @param original Original list after it has been created from the server stream
+ *
+ * @return Original list as processed by this method.
+ */
+ List
+ * This object defines a two-part parsing mechanism.
+ *
+ * The first part is comprised of reading the raw input into an internal
+ * list of strings. Every item in this list corresponds to an actual
+ * file. All extraneous matter emitted by the server will have been
+ * removed by the end of this phase. This is accomplished in conjunction
+ * with the FTPFileEntryParser associated with this engine, by calling
+ * its methods
+ * The second part is composed of the actual parsing, again in conjunction
+ * with the particular parser used by this engine. This is controlled
+ * by an iterator over the internal list of strings. This may be done
+ * either in block mode, by calling the
+ * Examples:
+ *
+ * Paged access:
+ *
+ * For unpaged access, simply use FTPClient.listFiles(). That method
+ * uses this class transparently.
+ * @version $Id: FTPListParseEngine.java 658518 2008-05-21 01:04:30Z sebb $
+ */
+public class FTPListParseEngine {
+ private List
+ * NOTE: This array may contain null members if any of the
+ * individual file listings failed to parse. The caller should
+ * check each entry for null before referencing it.
+ */
+ public FTPFile[] getNext(int quantityRequested) {
+ List
+ * NOTE: This array may contain null members if any of the
+ * individual file listings failed to parse. The caller should
+ * check each entry for null before referencing it.
+ */
+ public FTPFile[] getPrevious(int quantityRequested) {
+ List
+ * NOTE: This array may contain null members if any of the
+ * individual file listings failed to parse. The caller should
+ * check each entry for null before referencing it.
+ * @exception IOException
+ */
+ public FTPFile[] getFiles()
+ throws IOException
+ {
+ List
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class FTPReply
+{
+
+ public static final int CODE_110 = 110;
+ public static final int CODE_120 = 120;
+ public static final int CODE_125 = 125;
+ public static final int CODE_150 = 150;
+ public static final int CODE_200 = 200;
+ public static final int CODE_202 = 202;
+ public static final int CODE_211 = 211;
+ public static final int CODE_212 = 212;
+ public static final int CODE_213 = 213;
+ public static final int CODE_214 = 214;
+ public static final int CODE_215 = 215;
+ public static final int CODE_220 = 220;
+ public static final int CODE_221 = 221;
+ public static final int CODE_225 = 225;
+ public static final int CODE_226 = 226;
+ public static final int CODE_227 = 227;
+ public static final int CODE_230 = 230;
+ public static final int CODE_250 = 250;
+ public static final int CODE_257 = 257;
+ public static final int CODE_331 = 331;
+ public static final int CODE_332 = 332;
+ public static final int CODE_350 = 350;
+ public static final int CODE_421 = 421;
+ public static final int CODE_425 = 425;
+ public static final int CODE_426 = 426;
+ public static final int CODE_450 = 450;
+ public static final int CODE_451 = 451;
+ public static final int CODE_452 = 452;
+ public static final int CODE_500 = 500;
+ public static final int CODE_501 = 501;
+ public static final int CODE_502 = 502;
+ public static final int CODE_503 = 503;
+ public static final int CODE_504 = 504;
+ public static final int CODE_521 = 521;
+ public static final int CODE_530 = 530;
+ public static final int CODE_532 = 532;
+ public static final int CODE_550 = 550;
+ public static final int CODE_551 = 551;
+ public static final int CODE_552 = 552;
+ public static final int CODE_553 = 553;
+
+ public static final int RESTART_MARKER = CODE_110;
+ public static final int SERVICE_NOT_READY = CODE_120;
+ public static final int DATA_CONNECTION_ALREADY_OPEN = CODE_125;
+ public static final int FILE_STATUS_OK = CODE_150;
+ public static final int COMMAND_OK = CODE_200;
+ public static final int COMMAND_IS_SUPERFLUOUS = CODE_202;
+ public static final int SYSTEM_STATUS = CODE_211;
+ public static final int DIRECTORY_STATUS = CODE_212;
+ public static final int FILE_STATUS = CODE_213;
+ public static final int HELP_MESSAGE = CODE_214;
+ public static final int NAME_SYSTEM_TYPE = CODE_215;
+ public static final int SERVICE_READY = CODE_220;
+ public static final int SERVICE_CLOSING_CONTROL_CONNECTION = CODE_221;
+ public static final int DATA_CONNECTION_OPEN = CODE_225;
+ public static final int CLOSING_DATA_CONNECTION = CODE_226;
+ public static final int ENTERING_PASSIVE_MODE = CODE_227;
+ public static final int USER_LOGGED_IN = CODE_230;
+ public static final int FILE_ACTION_OK = CODE_250;
+ public static final int PATHNAME_CREATED = CODE_257;
+ public static final int NEED_PASSWORD = CODE_331;
+ public static final int NEED_ACCOUNT = CODE_332;
+ public static final int FILE_ACTION_PENDING = CODE_350;
+ public static final int SERVICE_NOT_AVAILABLE = CODE_421;
+ public static final int CANNOT_OPEN_DATA_CONNECTION = CODE_425;
+ public static final int TRANSFER_ABORTED = CODE_426;
+ public static final int FILE_ACTION_NOT_TAKEN = CODE_450;
+ public static final int ACTION_ABORTED = CODE_451;
+ public static final int INSUFFICIENT_STORAGE = CODE_452;
+ public static final int UNRECOGNIZED_COMMAND = CODE_500;
+ public static final int SYNTAX_ERROR_IN_ARGUMENTS = CODE_501;
+ public static final int COMMAND_NOT_IMPLEMENTED = CODE_502;
+ public static final int BAD_COMMAND_SEQUENCE = CODE_503;
+ public static final int COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER = CODE_504;
+ public static final int NOT_LOGGED_IN = CODE_530;
+ public static final int NEED_ACCOUNT_FOR_STORING_FILES = CODE_532;
+ public static final int FILE_UNAVAILABLE = CODE_550;
+ public static final int PAGE_TYPE_UNKNOWN = CODE_551;
+ public static final int STORAGE_ALLOCATION_EXCEEDED = CODE_552;
+ public static final int FILE_NAME_NOT_ALLOWED = CODE_553;
+
+ // FTPS Reply Codes
+ /** @since 2.0 */
+ public static final int CODE_234 = 234;
+ /** @since 2.0 */
+ public static final int CODE_235 = 235;
+ /** @since 2.0 */
+ public static final int CODE_334 = 334;
+ /** @since 2.0 */
+ public static final int CODE_335 = 335;
+ /** @since 2.0 */
+ public static final int CODE_431 = 431;
+ /** @since 2.0 */
+ public static final int CODE_533 = 533;
+ /** @since 2.0 */
+ public static final int CODE_534 = 534;
+ /** @since 2.0 */
+ public static final int CODE_535 = 535;
+ /** @since 2.0 */
+ public static final int CODE_536 = 536;
+
+ /** @since 2.0 */
+ public static final int SECURITY_DATA_EXCHANGE_COMPLETE = CODE_234;
+ /** @since 2.0 */
+ public static final int SECURITY_DATA_EXCHANGE_SUCCESSFULLY = CODE_235;
+ /** @since 2.0 */
+ public static final int SECURITY_MECHANISM_IS_OK = CODE_334;
+ /** @since 2.0 */
+ public static final int SECURITY_DATA_IS_ACCEPTABLE = CODE_335;
+ /** @since 2.0 */
+ public static final int UNAVAILABLE_RESOURCE = CODE_431;
+ /** @since 2.0 */
+ public static final int DENIED_FOR_POLICY_REASONS = CODE_533;
+ /** @since 2.0 */
+ public static final int REQUEST_DENIED = CODE_534;
+ /** @since 2.0 */
+ public static final int FAILED_SECURITY_CHECK = CODE_535;
+ /** @since 2.0 */
+ public static final int REQUESTED_PROT_LEVEL_NOT_SUPPORTED = CODE_536;
+
+
+ // Cannot be instantiated
+ private FTPReply()
+ {}
+
+ /***
+ * Determine if a reply code is a positive preliminary response. All
+ * codes beginning with a 1 are positive preliminary responses.
+ * Postitive preliminary responses are used to indicate tentative success.
+ * No further commands can be issued to the FTP server after a positive
+ * preliminary response until a follow up response is received from the
+ * server.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive preliminary response, false
+ * if not.
+ ***/
+ public static boolean isPositivePreliminary(int reply)
+ {
+ return (reply >= 100 && reply < 200);
+ }
+
+ /***
+ * Determine if a reply code is a positive completion response. All
+ * codes beginning with a 2 are positive completion responses.
+ * The FTP server will send a positive completion response on the final
+ * successful completion of a command.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive completion response, false
+ * if not.
+ ***/
+ public static boolean isPositiveCompletion(int reply)
+ {
+ return (reply >= 200 && reply < 300);
+ }
+
+ /***
+ * Determine if a reply code is a positive intermediate response. All
+ * codes beginning with a 3 are positive intermediate responses.
+ * The FTP server will send a positive intermediate response on the
+ * successful completion of one part of a multi-part sequence of
+ * commands. For example, after a successful USER command, a positive
+ * intermediate response will be sent to indicate that the server is
+ * ready for the PASS command.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a postive intermediate response, false
+ * if not.
+ ***/
+ public static boolean isPositiveIntermediate(int reply)
+ {
+ return (reply >= 300 && reply < 400);
+ }
+
+ /***
+ * Determine if a reply code is a negative transient response. All
+ * codes beginning with a 4 are negative transient responses.
+ * The FTP server will send a negative transient response on the
+ * failure of a command that can be reattempted with success.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a negative transient response, false
+ * if not.
+ ***/
+ public static boolean isNegativeTransient(int reply)
+ {
+ return (reply >= 400 && reply < 500);
+ }
+
+ /***
+ * Determine if a reply code is a negative permanent response. All
+ * codes beginning with a 5 are negative permanent responses.
+ * The FTP server will send a negative permanent response on the
+ * failure of a command that cannot be reattempted with success.
+ *
+ * @param reply The reply code to test.
+ * @return True if a reply code is a negative permanent response, false
+ * if not.
+ ***/
+ public static boolean isNegativePermanent(int reply)
+ {
+ return (reply >= 500 && reply < 600);
+ }
+
+}
diff --git a/src/org/apache/commons/net/ftp/FTPSClient.java b/src/org/apache/commons/net/ftp/FTPSClient.java
new file mode 100644
index 0000000..f809c41
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/FTPSClient.java
@@ -0,0 +1,533 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+/**
+ * FTP over SSL processing. If desired, the JVM property -Djavax.net.debug=all can be used to
+ * see wire-level SSL details.
+ *
+ * @version $Id: FTPSClient.java 658520 2008-05-21 01:14:11Z sebb $
+ * @since 2.0
+ */
+public class FTPSClient extends FTPClient {
+
+ /** keystore algorithm name. */
+ public static String KEYSTORE_ALGORITHM;
+ /** truststore algorithm name. */
+ public static String TRUSTSTORE_ALGORITHM;
+ /** provider name. */
+ public static String PROVIDER;
+ /** truststore type. */
+ public static String STORE_TYPE;
+
+ /** The value that I can set in PROT command */
+ private static final String[] PROT_COMMAND_VALUE = {"C","E","S","P"};
+ /** Default PROT Command */
+ private static final String DEFAULT_PROT = "C";
+ /** Default protocol name */
+ private static final String DEFAULT_PROTOCOL = "TLS";
+
+ /** The security mode. (True - Implicit Mode / False - Explicit Mode) */
+ private boolean isImplicit;
+ /** The use SSL/TLS protocol. */
+ private String protocol = DEFAULT_PROTOCOL;
+ /** The AUTH Command value */
+ private String auth = DEFAULT_PROTOCOL;
+ /** The context object. */
+ private SSLContext context;
+ /** The socket object. */
+ private Socket planeSocket;
+ /** The established socket flag. */
+ private boolean isCreation = true;
+ /** The use client mode flag. */
+ private boolean isClientMode = true;
+ /** The need client auth flag. */
+ private boolean isNeedClientAuth = false;
+ /** The want client auth flag. */
+ private boolean isWantClientAuth = false;
+ /** The cipher suites */
+ private String[] suites = null;
+ /** The protocol versions */
+ private String[] protocols = null;
+
+ /** The FTPS {@link TrustManager} implementation. */
+ private TrustManager trustManager = new FTPSTrustManager();
+
+ /** The {@link KeyManager} */
+ private KeyManager keyManager;
+
+ /**
+ * Constructor for FTPSClient.
+ * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+ * is not available in the environment.
+ */
+ public FTPSClient() throws NoSuchAlgorithmException {
+ this.protocol = DEFAULT_PROTOCOL;
+ this.isImplicit = false;
+ }
+
+ /**
+ * Constructor for FTPSClient.
+ * @param isImplicit The secutiry mode(Implicit/Explicit).
+ * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+ * is not available in the environment.
+ */
+ public FTPSClient(boolean isImplicit) throws NoSuchAlgorithmException {
+ this.protocol = DEFAULT_PROTOCOL;
+ this.isImplicit = isImplicit;
+ }
+
+ /**
+ * Constructor for FTPSClient.
+ * @param protocol the protocol
+ * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+ * is not available in the environment.
+ */
+ public FTPSClient(String protocol) throws NoSuchAlgorithmException {
+ this.protocol = protocol;
+ this.isImplicit = false;
+ }
+
+ /**
+ * Constructor for FTPSClient.
+ * @param protocol the protocol
+ * @param isImplicit The secutiry mode(Implicit/Explicit).
+ * @throws NoSuchAlgorithmException A requested cryptographic algorithm
+ * is not available in the environment.
+ */
+ public FTPSClient(String protocol, boolean isImplicit)
+ throws NoSuchAlgorithmException {
+ this.protocol = protocol;
+ this.isImplicit = isImplicit;
+ }
+
+
+ /**
+ * Set AUTH command use value.
+ * This processing is done before connected processing.
+ * @param auth AUTH command use value.
+ */
+ public void setAuthValue(String auth) {
+ this.auth = auth;
+ }
+
+ /**
+ * Return AUTH command use value.
+ * @return AUTH command use value.
+ */
+ public String getAuthValue() {
+ return this.auth;
+ }
+
+
+ /**
+ * Because there are so many connect() methods,
+ * the _connectAction_() method is provided as a means of performing
+ * some action immediately after establishing a connection,
+ * rather than reimplementing all of the connect() methods.
+ * @throws IOException If it throw by _connectAction_.
+ * @see org.apache.commons.net.SocketClient#_connectAction_()
+ */
+ @Override
+ protected void _connectAction_() throws IOException {
+ // Implicit mode.
+ if (isImplicit) sslNegotiation();
+ super._connectAction_();
+ // Explicit mode.
+ if (!isImplicit) {
+ execAUTH();
+ sslNegotiation();
+ }
+ }
+
+ /**
+ * AUTH command.
+ * @throws SSLException If it server reply code not equal "234" and "334".
+ * @throws IOException If an I/O error occurs while either sending
+ * the command.
+ */
+ private void execAUTH() throws SSLException, IOException {
+ int replyCode = sendCommand(
+ FTPSCommand._commands[FTPSCommand.AUTH], auth);
+ if (FTPReply.SECURITY_MECHANISM_IS_OK == replyCode) {
+ // replyCode = 334
+ // I carry out an ADAT command.
+ } else if (FTPReply.SECURITY_DATA_EXCHANGE_COMPLETE != replyCode) {
+ throw new SSLException(getReplyString());
+ }
+ }
+
+ /**
+ * Performs a lazy init of the SSL context
+ * @throws IOException
+ */
+ private void initSslContext() throws IOException {
+ if(context == null) {
+ try {
+ context = SSLContext.getInstance(protocol);
+
+ context.init(new KeyManager[] { getKeyManager() } , new TrustManager[] { getTrustManager() } , null);
+ } catch (KeyManagementException e) {
+ IOException ioe = new IOException("Could not initialize SSL context");
+ ioe.initCause(e);
+ throw ioe;
+ } catch (NoSuchAlgorithmException e) {
+ IOException ioe = new IOException("Could not initialize SSL context");
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+ }
+
+ /**
+ * SSL/TLS negotiation. Acquires an SSL socket of a control
+ * connection and carries out handshake processing.
+ * @throws IOException A handicap breaks out by sever negotiation.
+ */
+ private void sslNegotiation() throws IOException {
+ // Evacuation not ssl socket.
+ planeSocket = _socket_;
+
+ initSslContext();
+
+ SSLSocketFactory ssf = context.getSocketFactory();
+ String ip = _socket_.getInetAddress().getHostAddress();
+ int port = _socket_.getPort();
+ SSLSocket socket =
+ (SSLSocket) ssf.createSocket(_socket_, ip, port, true);
+ socket.setEnableSessionCreation(isCreation);
+ socket.setUseClientMode(isClientMode);
+ // server mode
+ if (!isClientMode) {
+ socket.setNeedClientAuth(isNeedClientAuth);
+ socket.setWantClientAuth(isWantClientAuth);
+ }
+ if (protocols != null) socket.setEnabledProtocols(protocols);
+ if (suites != null) socket.setEnabledCipherSuites(suites);
+
+ socket.startHandshake();
+
+ _socket_ = socket;
+ _controlInput_ = new BufferedReader(new InputStreamReader(
+ socket .getInputStream(), getControlEncoding()));
+ _controlOutput_ = new BufferedWriter(new OutputStreamWriter(
+ socket.getOutputStream(), getControlEncoding()));
+ }
+
+ /**
+ * Get the {@link KeyManager} instance.
+ * @return The {@link KeyManager} instance
+ */
+ private KeyManager getKeyManager() {
+ return keyManager;
+ }
+
+ /**
+ * Set a {@link KeyManager} to use
+ *
+ * @param keyManager The KeyManager implementation to set.
+ */
+ public void setKeyManager(KeyManager keyManager) {
+ this.keyManager = keyManager;
+ }
+
+ /**
+ * Controls whether new a SSL session may be established by this socket.
+ * @param isCreation The established socket flag.
+ */
+ public void setEnabledSessionCreation(boolean isCreation) {
+ this.isCreation = isCreation;
+ }
+
+ /**
+ * Returns true if new SSL sessions may be established by this socket.
+ * When a socket does not have a ssl socket, This return False.
+ * @return true - Indicates that sessions may be created;
+ * this is the default.
+ * false - indicates that an existing session must be resumed.
+ */
+ public boolean getEnableSessionCreation() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getEnableSessionCreation();
+ return false;
+ }
+
+ /**
+ * Configures the socket to require client authentication.
+ * @param isNeedClientAuth The need client auth flag.
+ */
+ public void setNeedClientAuth(boolean isNeedClientAuth) {
+ this.isNeedClientAuth = isNeedClientAuth;
+ }
+
+ /**
+ * Returns true if the socket will require client authentication.
+ * When a socket does not have a ssl socket, This return False.
+ * @return true - If the server mode socket should request
+ * that the client authenticate itself.
+ */
+ public boolean getNeedClientAuth() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getNeedClientAuth();
+ return false;
+ }
+
+ /**
+ * Configures the socket to request client authentication,
+ * but only if such a request is appropriate to the cipher
+ * suite negotiated.
+ * @param isWantClientAuth The want client auth flag.
+ */
+ public void setWantClientAuth(boolean isWantClientAuth) {
+ this.isWantClientAuth = isWantClientAuth;
+ }
+
+ /**
+ * Returns true if the socket will request client authentication.
+ * When a socket does not have a ssl socket, This return False.
+ * @return true - If the server mode socket should request
+ * that the client authenticate itself.
+ */
+ public boolean getWantClientAuth() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getWantClientAuth();
+ return false;
+ }
+
+ /**
+ * Configures the socket to use client (or server) mode in its first
+ * handshake.
+ * @param isClientMode The use client mode flag.
+ */
+ public void setUseClientMode(boolean isClientMode) {
+ this.isClientMode = isClientMode;
+ }
+
+ /**
+ * Returns true if the socket is set to use client mode
+ * in its first handshake.
+ * When a socket does not have a ssl socket, This return False.
+ * @return true - If the socket should start its first handshake
+ * in "client" mode.
+ */
+ public boolean getUseClientMode() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getUseClientMode();
+ return false;
+ }
+
+ /**
+ * Controls which particular cipher suites are enabled for use on this
+ * connection. I perform setting before a server negotiation.
+ * @param cipherSuites The cipher suites.
+ */
+ public void setEnabledCipherSuites(String[] cipherSuites) {
+ suites = new String[cipherSuites.length];
+ System.arraycopy(cipherSuites, 0, suites, 0, cipherSuites.length);
+ }
+
+ /**
+ * Returns the names of the cipher suites which could be enabled
+ * for use on this connection.
+ * When a socket does not have a ssl socket, This return null.
+ * @return An array of cipher suite names.
+ */
+ public String[] getEnabledCipherSuites() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getEnabledCipherSuites();
+ return null;
+ }
+
+ /**
+ * Controls which particular protocol versions are enabled for use on this
+ * connection. I perform setting before a server negotiation.
+ * @param protocolVersions The protocol versions.
+ */
+ public void setEnabledProtocols(String[] protocolVersions) {
+ protocols = new String[protocolVersions.length];
+ System.arraycopy(protocolVersions, 0, protocols, 0, protocolVersions.length);
+ }
+
+ /**
+ * Returns the names of the protocol versions which are currently
+ * enabled for use on this connection.
+ * When a socket does not have a ssl socket, This return null.
+ * @return An array of protocols.
+ */
+ public String[] getEnabledProtocols() {
+ if (_socket_ instanceof SSLSocket)
+ return ((SSLSocket)_socket_).getEnabledProtocols();
+ return null;
+ }
+
+ /**
+ * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer.
+ * @param pbsz Protection Buffer Size.
+ * @throws SSLException If it server reply code not equal "200".
+ * @throws IOException If an I/O error occurs while either sending
+ * the command.
+ */
+ public void execPBSZ(long pbsz) throws SSLException, IOException {
+ if (pbsz < 0 || 4294967295L < pbsz)
+ throw new IllegalArgumentException();
+ if (FTPReply.COMMAND_OK != sendCommand(
+ FTPSCommand._commands[FTPSCommand.PBSZ],String.valueOf(pbsz)))
+ throw new SSLException(getReplyString());
+ }
+
+ /**
+ * PROT command.
+ * C - Clear
+ * S - Safe(SSL protocol only)
+ * E - Confidential(SSL protocol only)
+ * P - Private
+ * @param prot Data Channel Protection Level.
+ * @throws SSLException If it server reply code not equal "200".
+ * @throws IOException If an I/O error occurs while either sending
+ * the command.
+ */
+ public void execPROT(String prot) throws SSLException, IOException {
+ if (prot == null) prot = DEFAULT_PROT;
+ if (!checkPROTValue(prot)) throw new IllegalArgumentException();
+ if (FTPReply.COMMAND_OK != sendCommand(
+ FTPSCommand._commands[FTPSCommand.PROT], prot))
+ throw new SSLException(getReplyString());
+ if (DEFAULT_PROT.equals(prot)) {
+ setSocketFactory(null);
+ setServerSocketFactory(null);
+ } else {
+ setSocketFactory(new FTPSSocketFactory(context));
+
+ initSslContext();
+
+ SSLServerSocketFactory ssf = context.getServerSocketFactory();
+
+ setServerSocketFactory(ssf);
+ }
+ }
+
+ /**
+ * I check the value that I can set in PROT Command value.
+ * @param prot Data Channel Protection Level.
+ * @return True - A set point is right / False - A set point is not right
+ */
+ private boolean checkPROTValue(String prot) {
+ for (int p = 0; p < PROT_COMMAND_VALUE.length; p++) {
+ if (PROT_COMMAND_VALUE[p].equals(prot)) return true;
+ }
+ return false;
+ }
+
+ /**
+ * I carry out an ftp command.
+ * When a CCC command was carried out, I steep socket and SocketFactory
+ * in a state of not ssl.
+ * @parm command ftp command.
+ * @return server reply.
+ * @throws IOException If an I/O error occurs while either sending
+ * the command.
+ * @see org.apache.commons.net.ftp.FTP#sendCommand(java.lang.String)
+ */
+ @Override
+ public int sendCommand(String command, String args) throws IOException {
+ int repCode = super.sendCommand(command, args);
+ if (FTPSCommand._commands[FTPSCommand.CCC].equals(command)) {
+ if (FTPReply.COMMAND_OK == repCode) {
+ // TODO Check this - is this necessary at all?
+ _socket_ = planeSocket;
+ setSocketFactory(null);
+ } else {
+ throw new SSLException(getReplyString());
+ }
+ }
+ return repCode;
+ }
+
+ /**
+ * Returns a socket of the data connection.
+ * Wrapped as an {@link SSLSocket}, which carries out handshake processing.
+ * @pram command The text representation of the FTP command to send.
+ * @param arg The arguments to the FTP command.
+ * If this parameter is set to null, then the command is sent with
+ * no argument.
+ * @return A Socket corresponding to the established data connection.
+ * Null is returned if an FTP protocol error is reported at any point
+ * during the establishment and initialization of the connection.
+ * @throws IOException If there is any problem with the connection.
+ * @see org.apache.commons.net.ftp.FTPClient#_openDataConnection_(java.lang.String, int)
+ */
+ @Override
+ protected Socket _openDataConnection_(int command, String arg)
+ throws IOException {
+ Socket socket = super._openDataConnection_(command, arg);
+ if (socket != null && socket instanceof SSLSocket) {
+ SSLSocket sslSocket = (SSLSocket)socket;
+ sslSocket.setUseClientMode(isClientMode);
+ sslSocket.setEnableSessionCreation(isCreation);
+ // server mode
+ if (!isClientMode) {
+ sslSocket.setNeedClientAuth(isNeedClientAuth);
+ sslSocket.setWantClientAuth(isWantClientAuth);
+ }
+ if (suites != null)
+ sslSocket.setEnabledCipherSuites(suites);
+ if (protocols != null)
+ sslSocket.setEnabledProtocols(protocols);
+ sslSocket.startHandshake();
+ }
+ return socket;
+ }
+
+ /**
+ * Get the currently configured {@link TrustManager}.
+ *
+ * @return A TrustManager instance.
+ */
+ public TrustManager getTrustManager() {
+ return trustManager;
+ }
+
+ /**
+ * Override the default {@link TrustManager} to use.
+ *
+ * @param trustManager The TrustManager implementation to set.
+ */
+ public void setTrustManager(TrustManager trustManager) {
+ this.trustManager = trustManager;
+ }
+
+
+
+}
diff --git a/src/org/apache/commons/net/ftp/FTPSCommand.java b/src/org/apache/commons/net/ftp/FTPSCommand.java
new file mode 100644
index 0000000..6fd2efa
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/FTPSCommand.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+
+/**
+ * I acquire a command added in FTPS.
+ * @since 2.0
+ */
+public final class FTPSCommand {
+ public static final int AUTH = 0;
+ public static final int ADAT = 1;
+ public static final int PBSZ = 2;
+ public static final int PROT = 3;
+ public static final int CCC = 4;
+
+ public static final int AUTHENTICATION_SECURITY_MECHANISM = AUTH;
+ public static final int AUTHENTICATION_SECURITY_DATA = ADAT;
+ public static final int PROTECTION_BUFFER_SIZE = PBSZ;
+ public static final int DATA_CHANNEL_PROTECTION_LEVEL = PROT;
+ public static final int CLEAR_COMMAND_CHANNEL = CCC;
+
+ static final String[] _commands = {"AUTH","ADAT","PBSZ","PROT","CCC"};
+
+ /**
+ * Retrieve the FTPS command string corresponding to a specified
+ * command code.
+ *
+ * @param command The command code.
+ * @return The FTPS command string corresponding to a specified
+ * command code.
+ */
+ public static final String getCommand(int command) {
+ return _commands[command];
+ }
+}
diff --git a/src/org/apache/commons/net/ftp/FTPSSocketFactory.java b/src/org/apache/commons/net/ftp/FTPSSocketFactory.java
new file mode 100644
index 0000000..b7e1186
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/FTPSSocketFactory.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.net.ftp;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+
+
+/**
+ *
+ * Implementation of org.apache.commons.net.SocketFactory
+ *
+ * @since 2.0
+ */
+public class FTPSSocketFactory extends SocketFactory {
+
+ private SSLContext context;
+
+ public FTPSSocketFactory(SSLContext context) {
+ this.context = context;
+ }
+
+ @Override
+ public Socket createSocket(String address, int port) throws UnknownHostException, IOException {
+ return this.context.getSocketFactory().createSocket(address, port);
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port) throws IOException {
+ return this.context.getSocketFactory().createSocket(address, port);
+ }
+
+ @Override
+ public Socket createSocket(String address, int port, InetAddress localAddress, int localPort) throws UnknownHostException, IOException {
+ return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort);
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
+ return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort);
+ }
+
+ public ServerSocket createServerSocket(int port) throws IOException {
+ return this.init(this.context.getServerSocketFactory().createServerSocket(port));
+ }
+
+ public ServerSocket createServerSocket(int port, int backlog) throws IOException {
+ return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog));
+ }
+
+ public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException {
+ return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog, ifAddress));
+ }
+
+ public ServerSocket init(ServerSocket socket) throws IOException {
+ ((SSLServerSocket) socket).setUseClientMode(true);
+ return socket;
+ }
+}
diff --git a/src/org/apache/commons/net/ftp/FTPSTrustManager.java b/src/org/apache/commons/net/ftp/FTPSTrustManager.java
new file mode 100644
index 0000000..d1a2dd7
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/FTPSTrustManager.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * Custom {@link TrustManager} implementation.
+ *
+ * @version $Id: FTPSTrustManager.java 658520 2008-05-21 01:14:11Z sebb $
+ * @since 2.0
+ */
+public class FTPSTrustManager implements X509TrustManager
+{
+ /**
+ * No-op
+ */
+ public void checkClientTrusted(X509Certificate[] certificates, String authType)
+ {
+ return;
+ }
+
+ public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException
+ {
+ for (int i = 0; i < certificates.length; ++i)
+ {
+ certificates[i].checkValidity();
+ }
+ }
+
+ public X509Certificate[] getAcceptedIssuers()
+ {
+ return null;
+ }
+}
diff --git a/src/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java b/src/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java
new file mode 100644
index 0000000..4977b3f
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.net.ftp.FTPFileEntryParser;
+import org.apache.commons.net.ftp.FTPFileEntryParserImpl;
+
+/**
+ * This implementation allows to pack some FileEntryParsers together
+ * and handle the case where to returned dirstyle isnt clearly defined.
+ * The matching parser will be cached.
+ * If the cached parser wont match due to the server changed the dirstyle,
+ * a new matching parser will be searched.
+ *
+ * @author Mario Ivankovits
+ * This abstract class implements the common timestamp parsing
+ * algorithm for all the concrete parsers. Classes derived from
+ * this one will parse file listings via a supplied regular expression
+ * that pulls out the date portion as a separate string which is
+ * passed to the underlying {@link FTPTimestampParser delegate} to
+ * handle parsing of the file timestamp.
+ *
+ * This class also implements the {@link Configurable Configurable}
+ * interface to allow the parser to be configured from the outside.
+ *
+ * @param timestampStr the timestamp string pulled from the
+ * file listing by the regular expression parser, to be submitted
+ * to the Implementation extracts a key from the supplied
+ * {@link FTPClientConfig FTPClientConfig}
+ * parameter and creates an object implementing the
+ * interface FTPFileEntryParser and uses the supplied configuration
+ * to configure it.
+ *
+ * Note that this method will generally not be called in scenarios
+ * that call for autodetection of parser type but rather, for situations
+ * where the user knows that the server uses a non-default configuration
+ * and knows what that configuration is.
+ *
+ * Note: EnterpriseUnixFTPEntryParser can only be instantiated through the
+ * DefaultFTPParserFactory by classname. It will not be chosen
+ * by the autodetection scheme.
+ *
+ * @version $Id: EnterpriseUnixFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
+ * @author Winston Ojeda
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
+ */
+public class EnterpriseUnixFTPEntryParser extends RegexFTPFileEntryParserImpl
+{
+
+ /**
+ * months abbreviations looked for by this parser. Also used
+ * to determine which month has been matched by the parser.
+ */
+ private static final String MONTHS =
+ "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)";
+
+ /**
+ * this is the regular expression used by this parser.
+ */
+ private static final String REGEX =
+ "(([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])"
+ + "([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z]))"
+ + "(\\S*)\\s*"
+ + "(\\S+)\\s*"
+ + "(\\S*)\\s*"
+ + "(\\d*)\\s*"
+ + "(\\d*)\\s*"
+ + MONTHS
+ + "\\s*"
+ + "((?:[012]\\d*)|(?:3[01]))\\s*"
+ + "((\\d\\d\\d\\d)|((?:[01]\\d)|(?:2[0123])):([012345]\\d))\\s"
+ + "(\\S*)(\\s*.*)";
+
+ /**
+ * The sole constructor for a EnterpriseUnixFTPEntryParser object.
+ *
+ */
+ public EnterpriseUnixFTPEntryParser()
+ {
+ super(REGEX);
+ }
+
+ /**
+ * Parses a line of a unix FTP server file listing and converts it into a
+ * usable format in the form of an
+ * Implementation should be a method that extracts
+ * a key from the supplied {@link FTPClientConfig FTPClientConfig}
+ * parameter and creates an object implementing the
+ * interface FTPFileEntryParser and uses the supplied configuration
+ * to configure it.
+ *
+ * Note that this method will generally not be called in scenarios
+ * that call for autodetection of parser type but rather, for situations
+ * where the user knows that the server uses a non-default configuration
+ * and knows what that configuration is.
+ *
+ * Set up the {@link FTPClientConfig#setDefaultDateFormatStr(java.lang.String) defaultDateFormat}
+ * and optionally the {@link FTPClientConfig#setRecentDateFormatStr(String) recentDateFormat}
+ * to values supplied in the config based on month names configured as follows:
+ *
+ * Finally if a {@link org.apache.commons.net.ftp.FTPClientConfig#setServerTimeZoneId(String) serverTimeZoneId}
+ * has been supplied via the config, set that into all date formats that have
+ * been configured.
+ *
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry)
+ {
+ FTPFile f = new FTPFile();
+ f.setRawListing(entry);
+
+ if (matches(entry))
+ {
+ String datestr = group(1)+" "+group(2);
+ String dirString = group(3);
+ String size = group(4);
+ String name = group(5);
+ try
+ {
+ f.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+ if (null == name || name.equals(".") || name.equals(".."))
+ {
+ return (null);
+ }
+ f.setName(name);
+
+
+ if ("
+ *
+ * Netware file permissions are in the following format: RWCEAFMS, and are explained as follows:
+ *
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry)
+ {
+
+ FTPFile f = new FTPFile();
+ if (matches(entry))
+ {
+ String size = group(1);
+ String attrib = group(2);
+ String dirString = group(3);
+ String datestr = group(4)+" "+group(5);
+ String name = group(6);
+ try
+ {
+ f.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+
+ //is it a DIR or a file
+ if (dirString.trim().equals("DIR") || attrib.trim().equals("DIR"))
+ {
+ f.setType(FTPFile.DIRECTORY_TYPE);
+ }
+ else
+ {
+ f.setType(FTPFile.FILE_TYPE);
+ }
+
+
+ //set the name
+ f.setName(name.trim());
+
+ //set the size
+ f.setSize(Long.parseLong(size.trim()));
+
+ return (f);
+ }
+ return null;
+
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_OS2,
+ DEFAULT_DATE_FORMAT,
+ null, null, null, null);
+ }
+
+}
diff --git a/src/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java b/src/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
new file mode 100644
index 0000000..66c370b
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+
+import java.text.ParseException;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFile;
+
+/**
+ * @version $Id: OS400FTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
+ */
+
+public class OS400FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
+{
+ private static final String DEFAULT_DATE_FORMAT
+ = "yy/MM/dd HH:mm:ss"; //01/11/09 12:30:24
+
+
+
+ private static final String REGEX =
+ "(\\S+)\\s+" // user
+ + "(\\d+)\\s+" // size
+ + "(\\S+)\\s+(\\S+)\\s+" // date stuff
+ + "(\\*\\S+)\\s+" // *STMF/*DIR
+ + "(\\S+/?)\\s*"; // filename
+
+
+ /**
+ * The default constructor for a OS400FTPEntryParser object.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ *
+ * For now end users may specify this format only via
+ *
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry) {
+ FTPFile file = new FTPFile();
+ file.setRawListing(entry);
+ int type;
+ boolean isDevice = false;
+
+ if (matches(entry))
+ {
+ String typeStr = group(1);
+ String hardLinkCount = group(15);
+ String usr = group(16);
+ String grp = group(17);
+ String filesize = group(18);
+ String datestr = group(19) + " " + group(20);
+ String name = group(21);
+ String endtoken = group(22);
+
+ try
+ {
+ file.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+
+ // bcdlfmpSs-
+ switch (typeStr.charAt(0))
+ {
+ case 'd':
+ type = FTPFile.DIRECTORY_TYPE;
+ break;
+ case 'e':
+ type = FTPFile.SYMBOLIC_LINK_TYPE;
+ break;
+ case 'l':
+ type = FTPFile.SYMBOLIC_LINK_TYPE;
+ break;
+ case 'b':
+ case 'c':
+ isDevice = true;
+ // break; - fall through
+ case 'f':
+ case '-':
+ type = FTPFile.FILE_TYPE;
+ break;
+ default:
+ type = FTPFile.UNKNOWN_TYPE;
+ }
+
+ file.setType(type);
+
+ int g = 4;
+ for (int access = 0; access < 3; access++, g += 4)
+ {
+ // Use != '-' to avoid having to check for suid and sticky bits
+ file.setPermission(access, FTPFile.READ_PERMISSION,
+ (!group(g).equals("-")));
+ file.setPermission(access, FTPFile.WRITE_PERMISSION,
+ (!group(g + 1).equals("-")));
+
+ String execPerm = group(g + 2);
+ if (!execPerm.equals("-") && !Character.isUpperCase(execPerm.charAt(0)))
+ {
+ file.setPermission(access, FTPFile.EXECUTE_PERMISSION, true);
+ }
+ else
+ {
+ file.setPermission(access, FTPFile.EXECUTE_PERMISSION, false);
+ }
+ }
+
+ if (!isDevice)
+ {
+ try
+ {
+ file.setHardLinkCount(Integer.parseInt(hardLinkCount));
+ }
+ catch (NumberFormatException e)
+ {
+ // intentionally do nothing
+ }
+ }
+
+ file.setUser(usr);
+ file.setGroup(grp);
+
+ try
+ {
+ file.setSize(Long.parseLong(filesize));
+ }
+ catch (NumberFormatException e)
+ {
+ // intentionally do nothing
+ }
+
+ if (null == endtoken)
+ {
+ file.setName(name);
+ }
+ else
+ {
+ // oddball cases like symbolic links, file names
+ // with spaces in them.
+ name += endtoken;
+ if (type == FTPFile.SYMBOLIC_LINK_TYPE)
+ {
+
+ int end = name.indexOf(" -> ");
+ // Give up if no link indicator is present
+ if (end == -1)
+ {
+ file.setName(name);
+ }
+ else
+ {
+ file.setName(name.substring(0, end));
+ file.setLink(name.substring(end + 4));
+ }
+
+ }
+ else
+ {
+ file.setName(name);
+ }
+ }
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_UNIX,
+ DEFAULT_DATE_FORMAT,
+ DEFAULT_RECENT_DATE_FORMAT,
+ null, null, null);
+ }
+
+}
diff --git a/src/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java b/src/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java
new file mode 100644
index 0000000..1e55ede
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
+import java.util.StringTokenizer;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.net.ftp.FTPListParseEngine;
+
+/**
+ * Implementation FTPFileEntryParser and FTPFileListParser for VMS Systems.
+ * This is a sample of VMS LIST output
+ *
+ * "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ * "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ * "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ *
+ * Note: VMSFTPEntryParser can only be instantiated through the
+ * DefaultFTPParserFactory by classname. It will not be chosen
+ * by the autodetection scheme.
+ *
+ *
+ *
+ * @author Winston Ojeda
+ * @author Steve Cohen
+ * @author Stephane ESTE-GRACIAS
+ * @version $Id: VMSFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
+ *
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
+ */
+public class VMSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
+{
+
+ private static final String DEFAULT_DATE_FORMAT
+ = "d-MMM-yyyy HH:mm:ss"; //9-NOV-2001 12:30:24
+
+ /**
+ * this is the regular expression used by this parser.
+ */
+ private static final String REGEX =
+ "(.*;[0-9]+)\\s*" //1 file and version
+ + "(\\d+)/\\d+\\s*" //2 size/allocated
+ +"(\\S+)\\s+(\\S+)\\s+" //3+4 date and time
+ + "\\[(([0-9$A-Za-z_]+)|([0-9$A-Za-z_]+),([0-9$a-zA-Z_]+))\\]?\\s*" //5(6,7,8) owner
+ + "\\([a-zA-Z]*,([a-zA-Z]*),([a-zA-Z]*),([a-zA-Z]*)\\)"; //9,10,11 Permissions (O,G,W)
+ // TODO - perhaps restrict permissions to [RWED]* ?
+
+
+
+ /**
+ * Constructor for a VMSFTPEntryParser object.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ *
+ * @param listStream The InputStream from which the file list should be
+ * read.
+ * @return The list of file information contained in the given path. null
+ * if the list could not be obtained or if there are no files in
+ * the directory.
+ * @exception IOException If an I/O error occurs reading the listStream.
+ ***/
+ public FTPFile[] parseFileList(InputStream listStream) throws IOException {
+ FTPListParseEngine engine = new FTPListParseEngine(this);
+ engine.readServerList(listStream);
+ return engine.getFiles();
+ }
+
+
+
+ /**
+ * Parses a line of a VMS FTP server file listing and converts it into a
+ * usable format in the form of an
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry)
+ {
+ //one block in VMS equals 512 bytes
+ long longBlock = 512;
+
+ if (matches(entry))
+ {
+ FTPFile f = new FTPFile();
+ f.setRawListing(entry);
+ String name = group(1);
+ String size = group(2);
+ String datestr = group(3)+" "+group(4);
+ String owner = group(5);
+ String permissions[] = new String[3];
+ permissions[0]= group(9);
+ permissions[1]= group(10);
+ permissions[2]= group(11);
+ try
+ {
+ f.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+
+ String grp;
+ String user;
+ StringTokenizer t = new StringTokenizer(owner, ",");
+ switch (t.countTokens()) {
+ case 1:
+ grp = null;
+ user = t.nextToken();
+ break;
+ case 2:
+ grp = t.nextToken();
+ user = t.nextToken();
+ break;
+ default:
+ grp = null;
+ user = null;
+ }
+
+ if (name.lastIndexOf(".DIR") != -1)
+ {
+ f.setType(FTPFile.DIRECTORY_TYPE);
+ }
+ else
+ {
+ f.setType(FTPFile.FILE_TYPE);
+ }
+ //set FTPFile name
+ //Check also for versions to be returned or not
+ if (isVersioning())
+ {
+ f.setName(name);
+ }
+ else
+ {
+ name = name.substring(0, name.lastIndexOf(";"));
+ f.setName(name);
+ }
+ //size is retreived in blocks and needs to be put in bytes
+ //for us humans and added to the FTPFile array
+ long sizeInBytes = Long.parseLong(size) * longBlock;
+ f.setSize(sizeInBytes);
+
+ f.setGroup(grp);
+ f.setUser(user);
+ //set group and owner
+
+ //Set file permission.
+ //VMS has (SYSTEM,OWNER,GROUP,WORLD) users that can contain
+ //R (read) W (write) E (execute) D (delete)
+
+ //iterate for OWNER GROUP WORLD permissions
+ for (int access = 0; access < 3; access++)
+ {
+ String permission = permissions[access];
+
+ f.setPermission(access, FTPFile.READ_PERMISSION, permission.indexOf('R')>=0);
+ f.setPermission(access, FTPFile.WRITE_PERMISSION, permission.indexOf('W')>=0);
+ f.setPermission(access, FTPFile.EXECUTE_PERMISSION, permission.indexOf('E')>=0);
+ }
+
+ return f;
+ }
+ return null;
+ }
+
+
+ /**
+ * Reads the next entry using the supplied BufferedReader object up to
+ * whatever delemits one entry from the next. This parser cannot use
+ * the default implementation of simply calling BufferedReader.readLine(),
+ * because one entry may span multiple lines.
+ *
+ * @param reader The BufferedReader object from which entries are to be
+ * read.
+ *
+ * @return A string representing the next ftp entry or null if none found.
+ * @exception IOException thrown on any IO Error reading from the reader.
+ */
+ @Override
+ public String readNextEntry(BufferedReader reader) throws IOException
+ {
+ String line = reader.readLine();
+ StringBuffer entry = new StringBuffer();
+ while (line != null)
+ {
+ if (line.startsWith("Directory") || line.startsWith("Total")) {
+ line = reader.readLine();
+ continue;
+ }
+
+ entry.append(line);
+ if (line.trim().endsWith(")"))
+ {
+ break;
+ }
+ line = reader.readLine();
+ }
+ return (entry.length() == 0 ? null : entry.toString());
+ }
+
+ protected boolean isVersioning() {
+ return false;
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_VMS,
+ DEFAULT_DATE_FORMAT,
+ null, null, null, null);
+ }
+
+
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/src/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java b/src/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java
new file mode 100644
index 0000000..cb25709
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+
+/**
+ * Special implementation VMSFTPEntryParser with versioning turned on.
+ * This parser removes all duplicates and only leaves the version with the highest
+ * version number for each filename.
+ *
+ * This is a sample of VMS LIST output
+ *
+ * "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ * "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ * "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
+ *
+ *
+ * @author Winston Ojeda
+ * @author Stephane ESTE-GRACIAS
+ * @version $Id: VMSVersioningFTPEntryParser.java 636854 2008-03-13 19:55:01Z sebb $
+ *
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ */
+public class VMSVersioningFTPEntryParser extends VMSFTPEntryParser
+{
+
+ private Matcher _preparse_matcher_;
+ private Pattern _preparse_pattern_;
+ private static final String PRE_PARSE_REGEX =
+ "(.*);([0-9]+)\\s*.*";
+
+ /**
+ * Constructor for a VMSFTPEntryParser object. Sets the versioning member
+ * to the supplied value.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ *
+ *
+ * @see CopyStreamEvent
+ * @see CopyStreamListener
+ * @see Util
+ * @author Daniel F. Savarese
+ * @version $Id: CopyStreamAdapter.java 489397 2006-12-21 16:28:51Z rwinston $
+ */
+public class CopyStreamAdapter implements CopyStreamListener
+{
+ private ListenerList internalListeners;
+
+ /**
+ * Creates a new copyStreamAdapter.
+ */
+ public CopyStreamAdapter()
+ {
+ internalListeners = new ListenerList();
+ }
+
+ /**
+ * This method is invoked by a CopyStreamEvent source after copying
+ * a block of bytes from a stream. The CopyStreamEvent will contain
+ * the total number of bytes transferred so far and the number of bytes
+ * transferred in the last write. The CopyStreamAdapater will relay
+ * the event to all of its registered listeners, listing itself as the
+ * source of the event.
+ * @param event The CopyStreamEvent fired by the copying of a block of
+ * bytes.
+ */
+ public void bytesTransferred(CopyStreamEvent event)
+ {
+ bytesTransferred(event.getTotalBytesTransferred(),
+ event.getBytesTransferred(),
+ event.getStreamSize());
+ }
+
+ /**
+ * This method is not part of the JavaBeans model and is used by the
+ * static methods in the org.apache.commons.io.Util class for efficiency.
+ * It is invoked after a block of bytes to inform the listener of the
+ * transfer. The CopyStreamAdapater will create a CopyStreamEvent
+ * from the arguments and relay the event to all of its registered
+ * listeners, listing itself as the source of the event.
+ * @param totalBytesTransferred The total number of bytes transferred
+ * so far by the copy operation.
+ * @param bytesTransferred The number of bytes copied by the most recent
+ * write.
+ * @param streamSize The number of bytes in the stream being copied.
+ * This may be equal to CopyStreamEvent.UNKNOWN_STREAM_SIZE if
+ * the size is unknown.
+ */
+ public void bytesTransferred(long totalBytesTransferred,
+ int bytesTransferred, long streamSize)
+ {
+ CopyStreamEvent event;
+
+ event = new CopyStreamEvent(this,
+ totalBytesTransferred,
+ bytesTransferred,
+ streamSize);
+
+ for (EventListener listener : internalListeners)
+ {
+ ((CopyStreamListener) (listener)).bytesTransferred(event);
+ }
+ }
+
+ /**
+ * Registers a CopyStreamListener to receive CopyStreamEvents.
+ * Although this method is not declared to be synchronized, it is
+ * implemented in a thread safe manner.
+ * @param listener The CopyStreamlistener to register.
+ */
+ public void addCopyStreamListener(CopyStreamListener listener)
+ {
+ internalListeners.addListener(listener);
+ }
+
+ /**
+ * Unregisters a CopyStreamListener. Although this method is not
+ * synchronized, it is implemented in a thread safe manner.
+ * @param listener The CopyStreamlistener to unregister.
+ */
+ public void removeCopyStreamListener(CopyStreamListener listener)
+ {
+ internalListeners.removeListener(listener);
+ }
+}
diff --git a/src/org/apache/commons/net/io/CopyStreamEvent.java b/src/org/apache/commons/net/io/CopyStreamEvent.java
new file mode 100644
index 0000000..d7d0ec3
--- /dev/null
+++ b/src/org/apache/commons/net/io/CopyStreamEvent.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.util.EventObject;
+
+/**
+ * A CopyStreamEvent is triggered after every write performed by a
+ * stream copying operation. The event stores the number of bytes
+ * transferred by the write triggering the event as well as the total
+ * number of bytes transferred so far by the copy operation.
+ *
+ *
+ * @see CopyStreamListener
+ * @see CopyStreamAdapter
+ * @see Util
+ * @author Daniel F. Savarese
+ * @version $Id: CopyStreamEvent.java 489397 2006-12-21 16:28:51Z rwinston $
+ */
+public class CopyStreamEvent extends EventObject
+{
+ /**
+ * Constant used to indicate the stream size is unknown.
+ */
+ public static final long UNKNOWN_STREAM_SIZE = -1;
+
+ private int bytesTransferred;
+ private long totalBytesTransferred;
+ private long streamSize;
+
+ /**
+ * Creates a new CopyStreamEvent instance.
+ * @param source The source of the event.
+ * @param totalBytesTransferred The total number of bytes transferred so
+ * far during a copy operation.
+ * @param bytesTransferred The number of bytes transferred during the
+ * write that triggered the CopyStreamEvent.
+ * @param streamSize The number of bytes in the stream being copied.
+ * This may be set to
+ *
+ * @see CopyStreamEvent
+ * @see CopyStreamAdapter
+ * @see Util
+ * @author Daniel F. Savarese
+ * @version $Id: CopyStreamListener.java 489397 2006-12-21 16:28:51Z rwinston $
+ */
+public interface CopyStreamListener extends EventListener
+{
+ /**
+ * This method is invoked by a CopyStreamEvent source after copying
+ * a block of bytes from a stream. The CopyStreamEvent will contain
+ * the total number of bytes transferred so far and the number of bytes
+ * transferred in the last write.
+ * @param event The CopyStreamEvent fired by the copying of a block of
+ * bytes.
+ */
+ public void bytesTransferred(CopyStreamEvent event);
+
+
+ /**
+ * This method is not part of the JavaBeans model and is used by the
+ * static methods in the org.apache.commons.io.Util class for efficiency.
+ * It is invoked after a block of bytes to inform the listener of the
+ * transfer.
+ * @param totalBytesTransferred The total number of bytes transferred
+ * so far by the copy operation.
+ * @param bytesTransferred The number of bytes copied by the most recent
+ * write.
+ * @param streamSize The number of bytes in the stream being copied.
+ * This may be equal to CopyStreamEvent.UNKNOWN_STREAM_SIZE if
+ * the size is unknown.
+ */
+ public void bytesTransferred(long totalBytesTransferred,
+ int bytesTransferred,
+ long streamSize);
+}
diff --git a/src/org/apache/commons/net/io/DotTerminatedMessageReader.java b/src/org/apache/commons/net/io/DotTerminatedMessageReader.java
new file mode 100644
index 0000000..c0f344d
--- /dev/null
+++ b/src/org/apache/commons/net/io/DotTerminatedMessageReader.java
@@ -0,0 +1,280 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.Reader;
+
+/**
+ * DotTerminatedMessageReader is a class used to read messages from a
+ * server that are terminated by a single dot followed by a
+ * <CR><LF>
+ * sequence and with double dots appearing at the begining of lines which
+ * do not signal end of message yet start with a dot. Various Internet
+ * protocols such as NNTP and POP3 produce messages of this type.
+ *
+ * This class handles stripping of the duplicate period at the beginning
+ * of lines starting with a period, converts NETASCII newlines to the
+ * local line separator format, truncates the end of message indicator,
+ * and ensures you cannot read past the end of the message.
+ * @author Daniel F. Savarese
+ * @version $Id: DotTerminatedMessageReader.java 636825 2008-03-13 18:34:52Z sebb $
+ */
+public final class DotTerminatedMessageReader extends Reader
+{
+ private static final String LS;
+ private static final char[] LS_CHARS;
+
+ static
+ {
+ LS = System.getProperty("line.separator");
+ LS_CHARS = LS.toCharArray();
+ }
+
+ private boolean atBeginning;
+ private boolean eof;
+ private int pos;
+ private char[] internalBuffer;
+ private PushbackReader internalReader;
+
+ /**
+ * Creates a DotTerminatedMessageReader that wraps an existing Reader
+ * input source.
+ * @param reader The Reader input source containing the message.
+ */
+ public DotTerminatedMessageReader(Reader reader)
+ {
+ super(reader);
+ internalBuffer = new char[LS_CHARS.length + 3];
+ pos = internalBuffer.length;
+ // Assumes input is at start of message
+ atBeginning = true;
+ eof = false;
+ internalReader = new PushbackReader(reader);
+ }
+
+ /**
+ * Reads and returns the next character in the message. If the end of the
+ * message has been reached, returns -1. Note that a call to this method
+ * may result in multiple reads from the underlying input stream to decode
+ * the message properly (removing doubled dots and so on). All of
+ * this is transparent to the programmer and is only mentioned for
+ * completeness.
+ * @return The next character in the message. Returns -1 if the end of the
+ * message has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ */
+ @Override
+ public int read() throws IOException
+ {
+ int ch;
+
+ synchronized (lock)
+ {
+ if (pos < internalBuffer.length)
+ {
+ return internalBuffer[pos++];
+ }
+
+ if (eof)
+ {
+ return -1;
+ }
+
+ if ((ch = internalReader.read()) == -1)
+ {
+ eof = true;
+ return -1;
+ }
+
+ if (atBeginning)
+ {
+ atBeginning = false;
+ if (ch == '.')
+ {
+ ch = internalReader.read();
+
+ if (ch != '.')
+ {
+ // read newline
+ eof = true;
+ internalReader.read();
+ return -1;
+ }
+ else
+ {
+ return '.';
+ }
+ }
+ }
+
+ if (ch == '\r')
+ {
+ ch = internalReader.read();
+
+ if (ch == '\n')
+ {
+ ch = internalReader.read();
+
+ if (ch == '.')
+ {
+ ch = internalReader.read();
+
+ if (ch != '.')
+ {
+ // read newline and indicate end of file
+ internalReader.read();
+ eof = true;
+ }
+ else
+ {
+ internalBuffer[--pos] = (char) ch;
+ }
+ }
+ else
+ {
+ internalReader.unread(ch);
+ }
+
+ pos -= LS_CHARS.length;
+ System.arraycopy(LS_CHARS, 0, internalBuffer, pos,
+ LS_CHARS.length);
+ ch = internalBuffer[pos++];
+ }
+ else
+ {
+ internalBuffer[--pos] = (char) ch;
+ return '\r';
+ }
+ }
+
+ return ch;
+ }
+ }
+
+ /**
+ * Reads the next characters from the message into an array and
+ * returns the number of characters read. Returns -1 if the end of the
+ * message has been reached.
+ * @param buffer The character array in which to store the characters.
+ * @return The number of characters read. Returns -1 if the
+ * end of the message has been reached.
+ * @exception IOException If an error occurs in reading the underlying
+ * stream.
+ */
+ @Override
+ public int read(char[] buffer) throws IOException
+ {
+ return read(buffer, 0, buffer.length);
+ }
+
+ /**
+ * Reads the next characters from the message into an array and
+ * returns the number of characters read. Returns -1 if the end of the
+ * message has been reached. The characters are stored in the array
+ * starting from the given offset and up to the length specified.
+ * @param buffer The character array in which to store the characters.
+ * @param offset The offset into the array at which to start storing
+ * characters.
+ * @param length The number of characters to read.
+ * @return The number of characters read. Returns -1 if the
+ * end of the message has been reached.
+ * @exception IOException If an error occurs in reading the underlying
+ * stream.
+ */
+ @Override
+ public int read(char[] buffer, int offset, int length) throws IOException
+ {
+ int ch, off;
+ synchronized (lock)
+ {
+ if (length < 1)
+ {
+ return 0;
+ }
+ if ((ch = read()) == -1)
+ {
+ return -1;
+ }
+ off = offset;
+
+ do
+ {
+ buffer[offset++] = (char) ch;
+ }
+ while (--length > 0 && (ch = read()) != -1);
+
+ return (offset - off);
+ }
+ }
+
+ /**
+ * Determines if the message is ready to be read.
+ * @return True if the message is ready to be read, false if not.
+ * @exception IOException If an error occurs while checking the underlying
+ * stream.
+ */
+ @Override
+ public boolean ready() throws IOException
+ {
+ synchronized (lock)
+ {
+ return (pos < internalBuffer.length || internalReader.ready());
+ }
+ }
+
+ /**
+ * Closes the message for reading. This doesn't actually close the
+ * underlying stream. The underlying stream may still be used for
+ * communicating with the server and therefore is not closed.
+ *
+ * If the end of the message has not yet been reached, this method
+ * will read the remainder of the message until it reaches the end,
+ * so that the underlying stream may continue to be used properly
+ * for communicating with the server. If you do not fully read
+ * a message, you MUST close it, otherwise your program will likely
+ * hang or behave improperly.
+ * @exception IOException If an error occurs while reading the
+ * underlying stream.
+ */
+ @Override
+ public void close() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (internalReader == null)
+ {
+ return;
+ }
+
+ if (!eof)
+ {
+ while (read() != -1)
+ {
+ ;
+ }
+ }
+ eof = true;
+ atBeginning = false;
+ pos = internalBuffer.length;
+ internalReader = null;
+ }
+ }
+}
diff --git a/src/org/apache/commons/net/io/DotTerminatedMessageWriter.java b/src/org/apache/commons/net/io/DotTerminatedMessageWriter.java
new file mode 100644
index 0000000..853e42f
--- /dev/null
+++ b/src/org/apache/commons/net/io/DotTerminatedMessageWriter.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/***
+ * DotTerminatedMessageWriter is a class used to write messages to a
+ * server that are terminated by a single dot followed by a
+ * <CR><LF>
+ * sequence and with double dots appearing at the begining of lines which
+ * do not signal end of message yet start with a dot. Various Internet
+ * protocols such as NNTP and POP3 produce messages of this type.
+ *
+ * This class handles the doubling of line-starting periods,
+ * converts single linefeeds to NETASCII newlines, and on closing
+ * will send the final message terminator dot and NETASCII newline
+ * sequence.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class DotTerminatedMessageWriter extends Writer
+{
+ private static final int __NOTHING_SPECIAL_STATE = 0;
+ private static final int __LAST_WAS_CR_STATE = 1;
+ private static final int __LAST_WAS_NL_STATE = 2;
+
+ private int __state;
+ private Writer __output;
+
+
+ /***
+ * Creates a DotTerminatedMessageWriter that wraps an existing Writer
+ * output destination.
+ *
+ * @param output The Writer output destination to write the message.
+ ***/
+ public DotTerminatedMessageWriter(Writer output)
+ {
+ super(output);
+ __output = output;
+ __state = __NOTHING_SPECIAL_STATE;
+ }
+
+
+ /***
+ * Writes a character to the output. Note that a call to this method
+ * may result in multiple writes to the underling Writer in order to
+ * convert naked linefeeds to NETASCII line separators and to double
+ * line-leading periods. This is transparent to the programmer and
+ * is only mentioned for completeness.
+ *
+ * @param ch The character to write.
+ * @exception IOException If an error occurs while writing to the
+ * underlying output.
+ ***/
+ @Override
+ public void write(int ch) throws IOException
+ {
+ synchronized (lock)
+ {
+ switch (ch)
+ {
+ case '\r':
+ __state = __LAST_WAS_CR_STATE;
+ __output.write('\r');
+ return ;
+ case '\n':
+ if (__state != __LAST_WAS_CR_STATE)
+ __output.write('\r');
+ __output.write('\n');
+ __state = __LAST_WAS_NL_STATE;
+ return ;
+ case '.':
+ // Double the dot at the beginning of a line
+ if (__state == __LAST_WAS_NL_STATE)
+ __output.write('.');
+ // Fall through
+ default:
+ __state = __NOTHING_SPECIAL_STATE;
+ __output.write(ch);
+ return ;
+ }
+ }
+ }
+
+
+ /***
+ * Writes a number of characters from a character array to the output
+ * starting from a given offset.
+ *
+ * @param buffer The character array to write.
+ * @param offset The offset into the array at which to start copying data.
+ * @param length The number of characters to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * output.
+ ***/
+ @Override
+ public void write(char[] buffer, int offset, int length) throws IOException
+ {
+ synchronized (lock)
+ {
+ while (length-- > 0)
+ write(buffer[offset++]);
+ }
+ }
+
+
+ /***
+ * Writes a character array to the output.
+ *
+ * @param buffer The character array to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * output.
+ ***/
+ @Override
+ public void write(char[] buffer) throws IOException
+ {
+ write(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Writes a String to the output.
+ *
+ * @param string The String to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * output.
+ ***/
+ @Override
+ public void write(String string) throws IOException
+ {
+ write(string.toCharArray());
+ }
+
+
+ /***
+ * Writes part of a String to the output starting from a given offset.
+ *
+ * @param string The String to write.
+ * @param offset The offset into the String at which to start copying data.
+ * @param length The number of characters to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * output.
+ ***/
+ @Override
+ public void write(String string, int offset, int length) throws IOException
+ {
+ write(string.toCharArray(), offset, length);
+ }
+
+
+ /***
+ * Flushes the underlying output, writing all buffered output.
+ *
+ * @exception IOException If an error occurs while writing to the underlying
+ * output.
+ ***/
+ @Override
+ public void flush() throws IOException
+ {
+ synchronized (lock)
+ {
+ __output.flush();
+ }
+ }
+
+
+ /***
+ * Flushes the underlying output, writing all buffered output, but doesn't
+ * actually close the underlying stream. The underlying stream may still
+ * be used for communicating with the server and therefore is not closed.
+ *
+ * @exception IOException If an error occurs while writing to the underlying
+ * output or closing the Writer.
+ ***/
+ @Override
+ public void close() throws IOException
+ {
+ synchronized (lock)
+ {
+ if (__output == null)
+ return ;
+
+ if (__state == __LAST_WAS_CR_STATE)
+ __output.write('\n');
+ else if (__state != __LAST_WAS_NL_STATE)
+ __output.write("\r\n");
+
+ __output.write(".\r\n");
+
+ __output.flush();
+ __output = null;
+ }
+ }
+
+}
diff --git a/src/org/apache/commons/net/io/FromNetASCIIInputStream.java b/src/org/apache/commons/net/io/FromNetASCIIInputStream.java
new file mode 100644
index 0000000..76588ab
--- /dev/null
+++ b/src/org/apache/commons/net/io/FromNetASCIIInputStream.java
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+
+/***
+ * This class wraps an input stream, replacing all occurrences
+ * of <CR><LF> (carriage return followed by a linefeed),
+ * which is the NETASCII standard for representing a newline, with the
+ * local line separator representation. You would use this class to
+ * implement ASCII file transfers requiring conversion from NETASCII.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class FromNetASCIIInputStream extends PushbackInputStream
+{
+ static final boolean _noConversionRequired;
+ static final String _lineSeparator;
+ static final byte[] _lineSeparatorBytes;
+
+ static {
+ _lineSeparator = System.getProperty("line.separator");
+ _noConversionRequired = _lineSeparator.equals("\r\n");
+ _lineSeparatorBytes = _lineSeparator.getBytes();
+ }
+
+ private int __length = 0;
+
+ /***
+ * Returns true if the NetASCII line separator differs from the system
+ * line separator, false if they are the same. This method is useful
+ * to determine whether or not you need to instantiate a
+ * FromNetASCIIInputStream object.
+ *
+ * @return True if the NETASCII line separator differs from the local
+ * system line separator, false if they are the same.
+ ***/
+ public static final boolean isConversionRequired()
+ {
+ return !_noConversionRequired;
+ }
+
+ /***
+ * Creates a FromNetASCIIInputStream instance that wraps an existing
+ * InputStream.
+ ***/
+ public FromNetASCIIInputStream(InputStream input)
+ {
+ super(input, _lineSeparatorBytes.length + 1);
+ }
+
+
+ private int __read() throws IOException
+ {
+ int ch;
+
+ ch = super.read();
+
+ if (ch == '\r')
+ {
+ ch = super.read();
+ if (ch == '\n')
+ {
+ unread(_lineSeparatorBytes);
+ ch = super.read();
+ // This is a kluge for read(byte[], ...) to read the right amount
+ --__length;
+ }
+ else
+ {
+ if (ch != -1)
+ unread(ch);
+ return '\r';
+ }
+ }
+
+ return ch;
+ }
+
+
+ /***
+ * Reads and returns the next byte in the stream. If the end of the
+ * message has been reached, returns -1. Note that a call to this method
+ * may result in multiple reads from the underlying input stream in order
+ * to convert NETASCII line separators to the local line separator format.
+ * This is transparent to the programmer and is only mentioned for
+ * completeness.
+ *
+ * @return The next character in the stream. Returns -1 if the end of the
+ * stream has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read() throws IOException
+ {
+ if (_noConversionRequired)
+ return super.read();
+
+ return __read();
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and
+ * returns the number of bytes read. Returns -1 if the end of the
+ * stream has been reached.
+ *
+ * @param buffer The byte array in which to store the data.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the message has been reached.
+ * @exception IOException If an error occurs in reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[]) throws IOException
+ {
+ return read(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and returns
+ * the number of bytes read. Returns -1 if the end of the
+ * message has been reached. The characters are stored in the array
+ * starting from the given offset and up to the length specified.
+ *
+ * @param buffer The byte array in which to store the data.
+ * @param offset The offset into the array at which to start storing data.
+ * @param length The number of bytes to read.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the stream has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[], int offset, int length) throws IOException
+ {
+ int ch, off;
+
+ if (length < 1)
+ return 0;
+
+ ch = available();
+
+ __length = (length > ch ? ch : length);
+
+ // If nothing is available, block to read only one character
+ if (__length < 1)
+ __length = 1;
+
+ if (_noConversionRequired)
+ return super.read(buffer, offset, __length);
+
+ if ((ch = __read()) == -1)
+ return -1;
+
+ off = offset;
+
+ do
+ {
+ buffer[offset++] = (byte)ch;
+ }
+ while (--__length > 0 && (ch = __read()) != -1);
+
+
+ return (offset - off);
+ }
+
+
+ // PushbackInputStream in JDK 1.1.3 returns the wrong thing
+ /***
+ * Returns the number of bytes that can be read without blocking EXCEPT
+ * when newline conversions have to be made somewhere within the
+ * available block of bytes. In other words, you really should not
+ * rely on the value returned by this method if you are trying to avoid
+ * blocking.
+ ***/
+ @Override
+ public int available() throws IOException
+ {
+ return (buf.length - pos) + in.available();
+ }
+
+}
diff --git a/src/org/apache/commons/net/io/FromNetASCIIOutputStream.java b/src/org/apache/commons/net/io/FromNetASCIIOutputStream.java
new file mode 100644
index 0000000..c025a1b
--- /dev/null
+++ b/src/org/apache/commons/net/io/FromNetASCIIOutputStream.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/***
+ * This class wraps an output stream, replacing all occurrences
+ * of <CR><LF> (carriage return followed by a linefeed),
+ * which is the NETASCII standard for representing a newline, with the
+ * local line separator representation. You would use this class to
+ * implement ASCII file transfers requiring conversion from NETASCII.
+ *
+ * Because of the translation process, a call to
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class FromNetASCIIOutputStream extends FilterOutputStream
+{
+ private boolean __lastWasCR;
+
+ /***
+ * Creates a FromNetASCIIOutputStream instance that wraps an existing
+ * OutputStream.
+ *
+ * @param output The OutputStream to wrap.
+ ***/
+ public FromNetASCIIOutputStream(OutputStream output)
+ {
+ super(output);
+ __lastWasCR = false;
+ }
+
+
+ private void __write(int ch) throws IOException
+ {
+ switch (ch)
+ {
+ case '\r':
+ __lastWasCR = true;
+ // Don't write anything. We need to see if next one is linefeed
+ break;
+ case '\n':
+ if (__lastWasCR)
+ {
+ out.write(FromNetASCIIInputStream._lineSeparatorBytes);
+ __lastWasCR = false;
+ break;
+ }
+ __lastWasCR = false;
+ out.write('\n');
+ break;
+ default:
+ if (__lastWasCR)
+ {
+ out.write('\r');
+ __lastWasCR = false;
+ }
+ out.write(ch);
+ break;
+ }
+ }
+
+
+ /***
+ * Writes a byte to the stream. Note that a call to this method
+ * might not actually write a byte to the underlying stream until a
+ * subsequent character is written, from which it can be determined if
+ * a NETASCII line separator was encountered.
+ * This is transparent to the programmer and is only mentioned for
+ * completeness.
+ *
+ * @param ch The byte to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(int ch)
+ throws IOException
+ {
+ if (FromNetASCIIInputStream._noConversionRequired)
+ {
+ out.write(ch);
+ return ;
+ }
+
+ __write(ch);
+ }
+
+
+ /***
+ * Writes a byte array to the stream.
+ *
+ * @param buffer The byte array to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(byte buffer[])
+ throws IOException
+ {
+ write(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Writes a number of bytes from a byte array to the stream starting from
+ * a given offset.
+ *
+ * @param buffer The byte array to write.
+ * @param offset The offset into the array at which to start copying data.
+ * @param length The number of bytes to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(byte buffer[], int offset, int length)
+ throws IOException
+ {
+ if (FromNetASCIIInputStream._noConversionRequired)
+ {
+ // FilterOutputStream method is very slow.
+ //super.write(buffer, offset, length);
+ out.write(buffer, offset, length);
+ return ;
+ }
+
+ while (length-- > 0)
+ __write(buffer[offset++]);
+ }
+
+
+ /***
+ * Closes the stream, writing all pending data.
+ *
+ * @exception IOException If an error occurs while closing the stream.
+ ***/
+ @Override
+ public synchronized void close()
+ throws IOException
+ {
+ if (FromNetASCIIInputStream._noConversionRequired)
+ {
+ super.close();
+ return ;
+ }
+
+ if (__lastWasCR)
+ out.write('\r');
+ super.close();
+ }
+}
diff --git a/src/org/apache/commons/net/io/SocketInputStream.java b/src/org/apache/commons/net/io/SocketInputStream.java
new file mode 100644
index 0000000..673f434
--- /dev/null
+++ b/src/org/apache/commons/net/io/SocketInputStream.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+
+/***
+ * This class wraps an input stream, storing a reference to its originating
+ * socket. When the stream is closed, it will also close the socket
+ * immediately afterward. This class is useful for situations where you
+ * are dealing with a stream originating from a socket, but do not have
+ * a reference to the socket, and want to make sure it closes when the
+ * stream closes.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SocketOutputStream
+ ***/
+
+public class SocketInputStream extends FilterInputStream
+{
+ private Socket __socket;
+
+ /***
+ * Creates a SocketInputStream instance wrapping an input stream and
+ * storing a reference to a socket that should be closed on closing
+ * the stream.
+ *
+ * @param socket The socket to close on closing the stream.
+ * @param stream The input stream to wrap.
+ ***/
+ public SocketInputStream(Socket socket, InputStream stream)
+ {
+ super(stream);
+ __socket = socket;
+ }
+
+ /***
+ * Closes the stream and immediately afterward closes the referenced
+ * socket.
+ *
+ * @exception IOException If there is an error in closing the stream
+ * or socket.
+ ***/
+ @Override
+ public void close() throws IOException
+ {
+ super.close();
+ __socket.close();
+ }
+}
diff --git a/src/org/apache/commons/net/io/SocketOutputStream.java b/src/org/apache/commons/net/io/SocketOutputStream.java
new file mode 100644
index 0000000..abd7f5d
--- /dev/null
+++ b/src/org/apache/commons/net/io/SocketOutputStream.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/***
+ * This class wraps an output stream, storing a reference to its originating
+ * socket. When the stream is closed, it will also close the socket
+ * immediately afterward. This class is useful for situations where you
+ * are dealing with a stream originating from a socket, but do not have
+ * a reference to the socket, and want to make sure it closes when the
+ * stream closes.
+ *
+ *
+ * @author Daniel F. Savarese
+ * @see SocketInputStream
+ ***/
+
+public class SocketOutputStream extends FilterOutputStream
+{
+ private Socket __socket;
+
+ /***
+ * Creates a SocketOutputStream instance wrapping an output stream and
+ * storing a reference to a socket that should be closed on closing
+ * the stream.
+ *
+ * @param socket The socket to close on closing the stream.
+ * @param stream The input stream to wrap.
+ ***/
+ public SocketOutputStream(Socket socket, OutputStream stream)
+ {
+ super(stream);
+ __socket = socket;
+ }
+
+
+ /***
+ * Writes a number of bytes from a byte array to the stream starting from
+ * a given offset. This method bypasses the equivalent method in
+ * FilterOutputStream because the FilterOutputStream implementation is
+ * very inefficient.
+ *
+ * @param buffer The byte array to write.
+ * @param offset The offset into the array at which to start copying data.
+ * @param length The number of bytes to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public void write(byte buffer[], int offset, int length) throws IOException
+ {
+ out.write(buffer, offset, length);
+ }
+
+
+ /***
+ * Closes the stream and immediately afterward closes the referenced
+ * socket.
+ *
+ * @exception IOException If there is an error in closing the stream
+ * or socket.
+ ***/
+ @Override
+ public void close() throws IOException
+ {
+ super.close();
+ __socket.close();
+ }
+}
diff --git a/src/org/apache/commons/net/io/ToNetASCIIInputStream.java b/src/org/apache/commons/net/io/ToNetASCIIInputStream.java
new file mode 100644
index 0000000..55e4735
--- /dev/null
+++ b/src/org/apache/commons/net/io/ToNetASCIIInputStream.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/***
+ * This class wraps an input stream, replacing all singly occurring
+ * <LF> (linefeed) characters with <CR><LF> (carriage return
+ * followed by linefeed), which is the NETASCII standard for representing
+ * a newline.
+ * You would use this class to implement ASCII file transfers requiring
+ * conversion to NETASCII.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class ToNetASCIIInputStream extends FilterInputStream
+{
+ private static final int __NOTHING_SPECIAL = 0;
+ private static final int __LAST_WAS_CR = 1;
+ private static final int __LAST_WAS_NL = 2;
+ private int __status;
+
+ /***
+ * Creates a ToNetASCIIInputStream instance that wraps an existing
+ * InputStream.
+ *
+ * @param input The InputStream to .
+ ***/
+ public ToNetASCIIInputStream(InputStream input)
+ {
+ super(input);
+ __status = __NOTHING_SPECIAL;
+ }
+
+
+ /***
+ * Reads and returns the next byte in the stream. If the end of the
+ * message has been reached, returns -1.
+ *
+ * @return The next character in the stream. Returns -1 if the end of the
+ * stream has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read() throws IOException
+ {
+ int ch;
+
+ if (__status == __LAST_WAS_NL)
+ {
+ __status = __NOTHING_SPECIAL;
+ return '\n';
+ }
+
+ ch = in.read();
+
+ switch (ch)
+ {
+ case '\r':
+ __status = __LAST_WAS_CR;
+ return '\r';
+ case '\n':
+ if (__status != __LAST_WAS_CR)
+ {
+ __status = __LAST_WAS_NL;
+ return '\r';
+ }
+ // else fall through
+ default:
+ __status = __NOTHING_SPECIAL;
+ return ch;
+ }
+ // statement not reached
+ //return ch;
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and
+ * returns the number of bytes read. Returns -1 if the end of the
+ * stream has been reached.
+ *
+ * @param buffer The byte array in which to store the data.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the message has been reached.
+ * @exception IOException If an error occurs in reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[]) throws IOException
+ {
+ return read(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and returns
+ * the number of bytes read. Returns -1 if the end of the
+ * message has been reached. The characters are stored in the array
+ * starting from the given offset and up to the length specified.
+ *
+ * @param buffer The byte array in which to store the data.
+ * @param offset The offset into the array at which to start storing data.
+ * @param length The number of bytes to read.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the stream has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[], int offset, int length) throws IOException
+ {
+ int ch, off;
+
+ if (length < 1)
+ return 0;
+
+ ch = available();
+
+ if (length > ch)
+ length = ch;
+
+ // If nothing is available, block to read only one character
+ if (length < 1)
+ length = 1;
+
+ if ((ch = read()) == -1)
+ return -1;
+
+ off = offset;
+
+ do
+ {
+ buffer[offset++] = (byte)ch;
+ }
+ while (--length > 0 && (ch = read()) != -1);
+
+ return (offset - off);
+ }
+
+ /*** Returns false. Mark is not supported. ***/
+ @Override
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ int result;
+
+ result = in.available();
+
+ if (__status == __LAST_WAS_NL)
+ return (result + 1);
+
+ return result;
+ }
+}
diff --git a/src/org/apache/commons/net/io/ToNetASCIIOutputStream.java b/src/org/apache/commons/net/io/ToNetASCIIOutputStream.java
new file mode 100644
index 0000000..aeacc98
--- /dev/null
+++ b/src/org/apache/commons/net/io/ToNetASCIIOutputStream.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/***
+ * This class wraps an output stream, replacing all singly occurring
+ * <LF> (linefeed) characters with <CR><LF> (carriage return
+ * followed by linefeed), which is the NETASCII standard for representing
+ * a newline.
+ * You would use this class to implement ASCII file transfers requiring
+ * conversion to NETASCII.
+ *
+ *
+ * @author Daniel F. Savarese
+ ***/
+
+public final class ToNetASCIIOutputStream extends FilterOutputStream
+{
+ private boolean __lastWasCR;
+
+ /***
+ * Creates a ToNetASCIIOutputStream instance that wraps an existing
+ * OutputStream.
+ *
+ * @param output The OutputStream to wrap.
+ ***/
+ public ToNetASCIIOutputStream(OutputStream output)
+ {
+ super(output);
+ __lastWasCR = false;
+ }
+
+
+ /***
+ * Writes a byte to the stream. Note that a call to this method
+ * may result in multiple writes to the underlying input stream in order
+ * to convert naked newlines to NETASCII line separators.
+ * This is transparent to the programmer and is only mentioned for
+ * completeness.
+ *
+ * @param ch The byte to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(int ch)
+ throws IOException
+ {
+ switch (ch)
+ {
+ case '\r':
+ __lastWasCR = true;
+ out.write('\r');
+ return ;
+ case '\n':
+ if (!__lastWasCR)
+ out.write('\r');
+ // Fall through
+ default:
+ __lastWasCR = false;
+ out.write(ch);
+ return ;
+ }
+ }
+
+
+ /***
+ * Writes a byte array to the stream.
+ *
+ * @param buffer The byte array to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(byte buffer[])
+ throws IOException
+ {
+ write(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Writes a number of bytes from a byte array to the stream starting from
+ * a given offset.
+ *
+ * @param buffer The byte array to write.
+ * @param offset The offset into the array at which to start copying data.
+ * @param length The number of bytes to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public synchronized void write(byte buffer[], int offset, int length)
+ throws IOException
+ {
+ while (length-- > 0)
+ write(buffer[offset++]);
+ }
+
+}
diff --git a/src/org/apache/commons/net/io/Util.java b/src/org/apache/commons/net/io/Util.java
new file mode 100644
index 0000000..4e85a93
--- /dev/null
+++ b/src/org/apache/commons/net/io/Util.java
@@ -0,0 +1,334 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+
+/***
+ * The Util class cannot be instantiated and stores short static convenience
+ * methods that are often quite useful.
+ *
+ *
+ * @see CopyStreamException
+ * @see CopyStreamListener
+ * @see CopyStreamAdapter
+ * @author Daniel F. Savarese
+ ***/
+
+public final class Util
+{
+ /***
+ * The default buffer size used by {@link #copyStream copyStream }
+ * and {@link #copyReader copyReader }. It's value is 1024.
+ ***/
+ public static final int DEFAULT_COPY_BUFFER_SIZE = 1024;
+
+ // Cannot be instantiated
+ private Util()
+ { }
+
+
+ /***
+ * Copies the contents of an InputStream to an OutputStream using a
+ * copy buffer of a given size and notifies the provided
+ * CopyStreamListener of the progress of the copy operation by calling
+ * its bytesTransferred(long, int) method after each write to the
+ * destination. If you wish to notify more than one listener you should
+ * use a CopyStreamAdapter as the listener and register the additional
+ * listeners with the CopyStreamAdapter.
+ *
+ * The contents of the InputStream are
+ * read until the end of the stream is reached, but neither the
+ * source nor the destination are closed. You must do this yourself
+ * outside of the method call. The number of bytes read/written is
+ * returned.
+ *
+ * @param source The source InputStream.
+ * @param dest The destination OutputStream.
+ * @param bufferSize The number of bytes to buffer during the copy.
+ * @param streamSize The number of bytes in the stream being copied.
+ * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
+ * @param listener The CopyStreamListener to notify of progress. If
+ * this parameter is null, notification is not attempted.
+ * @param flush Whether to flush the output stream after every
+ * write. This is necessary for interactive sessions that rely on
+ * buffered streams. If you don't flush, the data will stay in
+ * the stream buffer.
+ * @exception CopyStreamException If an error occurs while reading from the
+ * source or writing to the destination. The CopyStreamException
+ * will contain the number of bytes confirmed to have been
+ * transferred before an
+ * IOException occurred, and it will also contain the IOException
+ * that caused the error. These values can be retrieved with
+ * the CopyStreamException getTotalBytesTransferred() and
+ * getIOException() methods.
+ ***/
+ public static final long copyStream(InputStream source, OutputStream dest,
+ int bufferSize, long streamSize,
+ CopyStreamListener listener,
+ boolean flush)
+ throws CopyStreamException
+ {
+ int bytes;
+ long total;
+ byte[] buffer;
+
+ buffer = new byte[bufferSize];
+ total = 0;
+
+ try
+ {
+ while ((bytes = source.read(buffer)) != -1)
+ {
+ // Technically, some read(byte[]) methods may return 0 and we cannot
+ // accept that as an indication of EOF.
+
+ if (bytes == 0)
+ {
+ bytes = source.read();
+ if (bytes < 0)
+ break;
+ dest.write(bytes);
+ if(flush)
+ dest.flush();
+ ++total;
+ if (listener != null)
+ listener.bytesTransferred(total, 1, streamSize);
+ continue;
+ }
+
+ dest.write(buffer, 0, bytes);
+ if(flush)
+ dest.flush();
+ total += bytes;
+ if (listener != null)
+ listener.bytesTransferred(total, bytes, streamSize);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new CopyStreamException("IOException caught while copying.",
+ total, e);
+ }
+
+ return total;
+ }
+
+
+ /***
+ * Copies the contents of an InputStream to an OutputStream using a
+ * copy buffer of a given size and notifies the provided
+ * CopyStreamListener of the progress of the copy operation by calling
+ * its bytesTransferred(long, int) method after each write to the
+ * destination. If you wish to notify more than one listener you should
+ * use a CopyStreamAdapter as the listener and register the additional
+ * listeners with the CopyStreamAdapter.
+ *
+ * The contents of the InputStream are
+ * read until the end of the stream is reached, but neither the
+ * source nor the destination are closed. You must do this yourself
+ * outside of the method call. The number of bytes read/written is
+ * returned.
+ *
+ * @param source The source InputStream.
+ * @param dest The destination OutputStream.
+ * @param bufferSize The number of bytes to buffer during the copy.
+ * @param streamSize The number of bytes in the stream being copied.
+ * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
+ * @param listener The CopyStreamListener to notify of progress. If
+ * this parameter is null, notification is not attempted.
+ * @exception CopyStreamException If an error occurs while reading from the
+ * source or writing to the destination. The CopyStreamException
+ * will contain the number of bytes confirmed to have been
+ * transferred before an
+ * IOException occurred, and it will also contain the IOException
+ * that caused the error. These values can be retrieved with
+ * the CopyStreamException getTotalBytesTransferred() and
+ * getIOException() methods.
+ ***/
+ public static final long copyStream(InputStream source, OutputStream dest,
+ int bufferSize, long streamSize,
+ CopyStreamListener listener)
+ throws CopyStreamException
+ {
+ return copyStream(source, dest, bufferSize, streamSize, listener,
+ true);
+ }
+
+
+ /***
+ * Copies the contents of an InputStream to an OutputStream using a
+ * copy buffer of a given size. The contents of the InputStream are
+ * read until the end of the stream is reached, but neither the
+ * source nor the destination are closed. You must do this yourself
+ * outside of the method call. The number of bytes read/written is
+ * returned.
+ *
+ * @param source The source InputStream.
+ * @param dest The destination OutputStream.
+ * @return The number of bytes read/written in the copy operation.
+ * @exception CopyStreamException If an error occurs while reading from the
+ * source or writing to the destination. The CopyStreamException
+ * will contain the number of bytes confirmed to have been
+ * transferred before an
+ * IOException occurred, and it will also contain the IOException
+ * that caused the error. These values can be retrieved with
+ * the CopyStreamException getTotalBytesTransferred() and
+ * getIOException() methods.
+ ***/
+ public static final long copyStream(InputStream source, OutputStream dest,
+ int bufferSize)
+ throws CopyStreamException
+ {
+ return copyStream(source, dest, bufferSize,
+ CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
+ }
+
+
+ /***
+ * Same as
+ * The contents of the Reader are
+ * read until its end is reached, but neither the source nor the
+ * destination are closed. You must do this yourself outside of the
+ * method call. The number of characters read/written is returned.
+ *
+ * @param source The source Reader.
+ * @param dest The destination writer.
+ * @param bufferSize The number of characters to buffer during the copy.
+ * @param streamSize The number of characters in the stream being copied.
+ * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
+ * @param listener The CopyStreamListener to notify of progress. If
+ * this parameter is null, notification is not attempted.
+ * @return The number of characters read/written in the copy operation.
+ * @exception CopyStreamException If an error occurs while reading from the
+ * source or writing to the destination. The CopyStreamException
+ * will contain the number of bytes confirmed to have been
+ * transferred before an
+ * IOException occurred, and it will also contain the IOException
+ * that caused the error. These values can be retrieved with
+ * the CopyStreamException getTotalBytesTransferred() and
+ * getIOException() methods.
+ ***/
+ public static final long copyReader(Reader source, Writer dest,
+ int bufferSize, long streamSize,
+ CopyStreamListener listener)
+ throws CopyStreamException
+ {
+ int chars;
+ long total;
+ char[] buffer;
+
+ buffer = new char[bufferSize];
+ total = 0;
+
+ try
+ {
+ while ((chars = source.read(buffer)) != -1)
+ {
+ // Technically, some read(char[]) methods may return 0 and we cannot
+ // accept that as an indication of EOF.
+ if (chars == 0)
+ {
+ chars = source.read();
+ if (chars < 0)
+ break;
+ dest.write(chars);
+ dest.flush();
+ ++total;
+ if (listener != null)
+ listener.bytesTransferred(total, chars, streamSize);
+ continue;
+ }
+
+ dest.write(buffer, 0, chars);
+ dest.flush();
+ total += chars;
+ if (listener != null)
+ listener.bytesTransferred(total, chars, streamSize);
+ }
+ }
+ catch (IOException e)
+ {
+ throw new CopyStreamException("IOException caught while copying.",
+ total, e);
+ }
+
+ return total;
+ }
+
+
+ /***
+ * Copies the contents of a Reader to a Writer using a
+ * copy buffer of a given size. The contents of the Reader are
+ * read until its end is reached, but neither the source nor the
+ * destination are closed. You must do this yourself outside of the
+ * method call. The number of characters read/written is returned.
+ *
+ * @param source The source Reader.
+ * @param dest The destination writer.
+ * @param bufferSize The number of characters to buffer during the copy.
+ * @return The number of characters read/written in the copy operation.
+ * @exception CopyStreamException If an error occurs while reading from the
+ * source or writing to the destination. The CopyStreamException
+ * will contain the number of bytes confirmed to have been
+ * transferred before an
+ * IOException occurred, and it will also contain the IOException
+ * that caused the error. These values can be retrieved with
+ * the CopyStreamException getTotalBytesTransferred() and
+ * getIOException() methods.
+ ***/
+ public static final long copyReader(Reader source, Writer dest,
+ int bufferSize)
+ throws CopyStreamException
+ {
+ return copyReader(source, dest, bufferSize,
+ CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
+ }
+
+
+ /***
+ * Same as
- *
- * @author Daniel F. Savarese
- * @see DatagramSocketFactory
- ***/
-
-public abstract class DatagramSocketClient
-{
- /***
- * The default DatagramSocketFactory shared by all DatagramSocketClient
- * instances.
- ***/
- private static final DatagramSocketFactory __DEFAULT_SOCKET_FACTORY =
- new DefaultDatagramSocketFactory();
-
- /*** The timeout to use after opening a socket. ***/
- protected int _timeout_;
-
- /*** The datagram socket used for the connection. ***/
- protected DatagramSocket _socket_;
-
- /***
- * A status variable indicating if the client's socket is currently open.
- ***/
- protected boolean _isOpen_;
-
- /*** The datagram socket's DatagramSocketFactory. ***/
- protected DatagramSocketFactory _socketFactory_;
-
- /***
- * Default constructor for DatagramSocketClient. Initializes
- * _socket_ to null, _timeout_ to 0, and _isOpen_ to false.
- ***/
- public DatagramSocketClient()
- {
- _socket_ = null;
- _timeout_ = 0;
- _isOpen_ = false;
- _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
- }
-
-
- /***
- * Opens a DatagramSocket on the local host at the first available port.
- * Also sets the timeout on the socket to the default timeout set
- * by {@link #setDefaultTimeout setDefaultTimeout() }.
- *
- * _isOpen_ is set to true after calling this method and _socket_
- * is set to the newly opened socket.
- *
- * @exception SocketException If the socket could not be opened or the
- * timeout could not be set.
- ***/
- public void open() throws SocketException
- {
- _socket_ = _socketFactory_.createDatagramSocket();
- _socket_.setSoTimeout(_timeout_);
- _isOpen_ = true;
- }
-
-
- /***
- * Opens a DatagramSocket on the local host at a specified port.
- * Also sets the timeout on the socket to the default timeout set
- * by {@link #setDefaultTimeout setDefaultTimeout() }.
- *
- * _isOpen_ is set to true after calling this method and _socket_
- * is set to the newly opened socket.
- *
- * @param port The port to use for the socket.
- * @exception SocketException If the socket could not be opened or the
- * timeout could not be set.
- ***/
- public void open(int port) throws SocketException
- {
- _socket_ = _socketFactory_.createDatagramSocket(port);
- _socket_.setSoTimeout(_timeout_);
- _isOpen_ = true;
- }
-
-
- /***
- * Opens a DatagramSocket at the specified address on the local host
- * at a specified port.
- * Also sets the timeout on the socket to the default timeout set
- * by {@link #setDefaultTimeout setDefaultTimeout() }.
- *
- * _isOpen_ is set to true after calling this method and _socket_
- * is set to the newly opened socket.
- *
- * @param port The port to use for the socket.
- * @param laddr The local address to use.
- * @exception SocketException If the socket could not be opened or the
- * timeout could not be set.
- ***/
- public void open(int port, InetAddress laddr) throws SocketException
- {
- _socket_ = _socketFactory_.createDatagramSocket(port, laddr);
- _socket_.setSoTimeout(_timeout_);
- _isOpen_ = true;
- }
-
-
-
- /***
- * Closes the DatagramSocket used for the connection.
- * You should call this method after you've finished using the class
- * instance and also before you call {@link #open open() }
- * again. _isOpen_ is set to false and _socket_ is set to null.
- * If you call this method when the client socket is not open,
- * a NullPointerException is thrown.
- ***/
- public void close()
- {
- _socket_.close();
- _socket_ = null;
- _isOpen_ = false;
- }
-
-
- /***
- * Returns true if the client has a currently open socket.
- *
- * @return True if the client has a curerntly open socket, false otherwise.
- ***/
- public boolean isOpen()
- {
- return _isOpen_;
- }
-
-
- /***
- * Set the default timeout in milliseconds to use when opening a socket.
- * After a call to open, the timeout for the socket is set using this value.
- * This method should be used prior to a call to {@link #open open()}
- * and should not be confused with {@link #setSoTimeout setSoTimeout()}
- * which operates on the currently open socket. _timeout_ contains
- * the new timeout value.
- *
- * @param timeout The timeout in milliseconds to use for the datagram socket
- * connection.
- ***/
- public void setDefaultTimeout(int timeout)
- {
- _timeout_ = timeout;
- }
-
-
- /***
- * Returns the default timeout in milliseconds that is used when
- * opening a socket.
- *
- * @return The default timeout in milliseconds that is used when
- * opening a socket.
- ***/
- public int getDefaultTimeout()
- {
- return _timeout_;
- }
-
-
- /***
- * Set the timeout in milliseconds of a currently open connection.
- * Only call this method after a connection has been opened
- * by {@link #open open()}.
- *
- * @param timeout The timeout in milliseconds to use for the currently
- * open datagram socket connection.
- ***/
- public void setSoTimeout(int timeout) throws SocketException
- {
- _socket_.setSoTimeout(timeout);
- }
-
-
- /***
- * Returns the timeout in milliseconds of the currently opened socket.
- * If you call this method when the client socket is not open,
- * a NullPointerException is thrown.
- *
- * @return The timeout in milliseconds of the currently opened socket.
- ***/
- public int getSoTimeout() throws SocketException
- {
- return _socket_.getSoTimeout();
- }
-
-
- /***
- * Returns the port number of the open socket on the local host used
- * for the connection. If you call this method when the client socket
- * is not open, a NullPointerException is thrown.
- *
- * @return The port number of the open socket on the local host used
- * for the connection.
- ***/
- public int getLocalPort()
- {
- return _socket_.getLocalPort();
- }
-
-
- /***
- * Returns the local address to which the client's socket is bound.
- * If you call this method when the client socket is not open, a
- * NullPointerException is thrown.
- *
- * @return The local address to which the client's socket is bound.
- ***/
- public InetAddress getLocalAddress()
- {
- return _socket_.getLocalAddress();
- }
-
-
- /***
- * Sets the DatagramSocketFactory used by the DatagramSocketClient
- * to open DatagramSockets. If the factory value is null, then a default
- * factory is used (only do this to reset the factory after having
- * previously altered it).
- *
- * @param factory The new DatagramSocketFactory the DatagramSocketClient
- * should use.
- ***/
- public void setDatagramSocketFactory(DatagramSocketFactory factory)
- {
- if (factory == null)
- _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
- else
- _socketFactory_ = factory;
- }
-}
diff --git a/org/apache/commons/net/DatagramSocketFactory.java b/org/apache/commons/net/DatagramSocketFactory.java
deleted file mode 100644
index c152eb2..0000000
--- a/org/apache/commons/net/DatagramSocketFactory.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net;
-
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.SocketException;
-
-/***
- * The DatagramSocketFactory interface provides a means for the
- * programmer to control the creation of datagram sockets and
- * provide his own DatagramSocket implementations for use by all
- * classes derived from
- * {@link org.apache.commons.net.DatagramSocketClient}
- * .
- * This allows you to provide your own DatagramSocket implementations and
- * to perform security checks or browser capability requests before
- * creating a DatagramSocket.
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-public interface DatagramSocketFactory
-{
-
- /***
- * Creates a DatagramSocket on the local host at the first available port.
- *
- * @exception SocketException If the socket could not be created.
- ***/
- public DatagramSocket createDatagramSocket() throws SocketException;
-
- /***
- * Creates a DatagramSocket on the local host at a specified port.
- *
- * @param port The port to use for the socket.
- * @exception SocketException If the socket could not be created.
- ***/
- public DatagramSocket createDatagramSocket(int port) throws SocketException;
-
- /***
- * Creates a DatagramSocket at the specified address on the local host
- * at a specified port.
- *
- * @param port The port to use for the socket.
- * @param laddr The local address to use.
- * @exception SocketException If the socket could not be created.
- ***/
- public DatagramSocket createDatagramSocket(int port, InetAddress laddr)
- throws SocketException;
-}
diff --git a/org/apache/commons/net/DefaultDatagramSocketFactory.java b/org/apache/commons/net/DefaultDatagramSocketFactory.java
deleted file mode 100644
index 3983fcb..0000000
--- a/org/apache/commons/net/DefaultDatagramSocketFactory.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net;
-
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.SocketException;
-
-/***
- * DefaultDatagramSocketFactory implements the DatagramSocketFactory
- * interface by simply wrapping the java.net.DatagramSocket
- * constructors. It is the default DatagramSocketFactory used by
- * {@link org.apache.commons.net.DatagramSocketClient}
- * implementations.
- *
- *
- * @author Daniel F. Savarese
- * @see DatagramSocketFactory
- * @see DatagramSocketClient
- * @see DatagramSocketClient#setDatagramSocketFactory
- ***/
-
-public class DefaultDatagramSocketFactory implements DatagramSocketFactory
-{
-
- /***
- * Creates a DatagramSocket on the local host at the first available port.
- *
- * @exception SocketException If the socket could not be created.
- ***/
- public DatagramSocket createDatagramSocket() throws SocketException
- {
- return new DatagramSocket();
- }
-
- /***
- * Creates a DatagramSocket on the local host at a specified port.
- *
- * @param port The port to use for the socket.
- * @exception SocketException If the socket could not be created.
- ***/
- public DatagramSocket createDatagramSocket(int port) throws SocketException
- {
- return new DatagramSocket(port);
- }
-
- /***
- * Creates a DatagramSocket at the specified address on the local host
- * at a specified port.
- *
- * @param port The port to use for the socket.
- * @param laddr The local address to use.
- * @exception SocketException If the socket could not be created.
- ***/
- public DatagramSocket createDatagramSocket(int port, InetAddress laddr)
- throws SocketException
- {
- return new DatagramSocket(port, laddr);
- }
-}
diff --git a/org/apache/commons/net/DefaultSocketFactory.java b/org/apache/commons/net/DefaultSocketFactory.java
deleted file mode 100644
index e809f84..0000000
--- a/org/apache/commons/net/DefaultSocketFactory.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.UnknownHostException;
-
-import javax.net.SocketFactory;
-
-/***
- * DefaultSocketFactory implements the SocketFactory interface by
- * simply wrapping the java.net.Socket and java.net.ServerSocket
- * constructors. It is the default SocketFactory used by
- * {@link org.apache.commons.net.SocketClient}
- * implementations.
- *
- *
- * @author Daniel F. Savarese
- * @see SocketFactory
- * @see SocketClient
- * @see SocketClient#setSocketFactory
- ***/
-
-public class DefaultSocketFactory extends SocketFactory
-{
-
- /***
- * Creates a Socket connected to the given host and port.
- *
- * @param host The hostname to connect to.
- * @param port The port to connect to.
- * @return A Socket connected to the given host and port.
- * @exception UnknownHostException If the hostname cannot be resolved.
- * @exception IOException If an I/O error occurs while creating the Socket.
- ***/
- @Override
- public Socket createSocket(String host, int port)
- throws UnknownHostException, IOException
- {
- return new Socket(host, port);
- }
-
- /***
- * Creates a Socket connected to the given host and port.
- *
- * @param address The address of the host to connect to.
- * @param port The port to connect to.
- * @return A Socket connected to the given host and port.
- * @exception IOException If an I/O error occurs while creating the Socket.
- ***/
- @Override
- public Socket createSocket(InetAddress address, int port)
- throws IOException
- {
- return new Socket(address, port);
- }
-
- /***
- * Creates a Socket connected to the given host and port and
- * originating from the specified local address and port.
- *
- * @param host The hostname to connect to.
- * @param port The port to connect to.
- * @param localAddr The local address to use.
- * @param localPort The local port to use.
- * @return A Socket connected to the given host and port.
- * @exception UnknownHostException If the hostname cannot be resolved.
- * @exception IOException If an I/O error occurs while creating the Socket.
- ***/
- @Override
- public Socket createSocket(String host, int port,
- InetAddress localAddr, int localPort)
- throws UnknownHostException, IOException
- {
- return new Socket(host, port, localAddr, localPort);
- }
-
- /***
- * Creates a Socket connected to the given host and port and
- * originating from the specified local address and port.
- *
- * @param address The address of the host to connect to.
- * @param port The port to connect to.
- * @param localAddr The local address to use.
- * @param localPort The local port to use.
- * @return A Socket connected to the given host and port.
- * @exception IOException If an I/O error occurs while creating the Socket.
- ***/
- @Override
- public Socket createSocket(InetAddress address, int port,
- InetAddress localAddr, int localPort)
- throws IOException
- {
- return new Socket(address, port, localAddr, localPort);
- }
-
- /***
- * Creates a ServerSocket bound to a specified port. A port
- * of 0 will create the ServerSocket on a system-determined free port.
- *
- * @param port The port on which to listen, or 0 to use any free port.
- * @return A ServerSocket that will listen on a specified port.
- * @exception IOException If an I/O error occurs while creating
- * the ServerSocket.
- ***/
- public ServerSocket createServerSocket(int port) throws IOException
- {
- return new ServerSocket(port);
- }
-
- /***
- * Creates a ServerSocket bound to a specified port with a given
- * maximum queue length for incoming connections. A port of 0 will
- * create the ServerSocket on a system-determined free port.
- *
- * @param port The port on which to listen, or 0 to use any free port.
- * @param backlog The maximum length of the queue for incoming connections.
- * @return A ServerSocket that will listen on a specified port.
- * @exception IOException If an I/O error occurs while creating
- * the ServerSocket.
- ***/
- public ServerSocket createServerSocket(int port, int backlog)
- throws IOException
- {
- return new ServerSocket(port, backlog);
- }
-
- /***
- * Creates a ServerSocket bound to a specified port on a given local
- * address with a given maximum queue length for incoming connections.
- * A port of 0 will
- * create the ServerSocket on a system-determined free port.
- *
- * @param port The port on which to listen, or 0 to use any free port.
- * @param backlog The maximum length of the queue for incoming connections.
- * @param bindAddr The local address to which the ServerSocket should bind.
- * @return A ServerSocket that will listen on a specified port.
- * @exception IOException If an I/O error occurs while creating
- * the ServerSocket.
- ***/
- public ServerSocket createServerSocket(int port, int backlog,
- InetAddress bindAddr)
- throws IOException
- {
- return new ServerSocket(port, backlog, bindAddr);
- }
-}
diff --git a/org/apache/commons/net/MalformedServerReplyException.class b/org/apache/commons/net/MalformedServerReplyException.class
deleted file mode 100644
index 6b04dd8..0000000
Binary files a/org/apache/commons/net/MalformedServerReplyException.class and /dev/null differ
diff --git a/org/apache/commons/net/MalformedServerReplyException.java b/org/apache/commons/net/MalformedServerReplyException.java
deleted file mode 100644
index 3cad5f0..0000000
--- a/org/apache/commons/net/MalformedServerReplyException.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net;
-
-import java.io.IOException;
-
-/***
- * This exception is used to indicate that the reply from a server
- * could not be interpreted. Most of the NetComponents classes attempt
- * to be as lenient as possible when receiving server replies. Many
- * server implementations deviate from IETF protocol specifications, making
- * it necessary to be as flexible as possible. However, there will be
- * certain situations where it is not possible to continue an operation
- * because the server reply could not be interpreted in a meaningful manner.
- * In these cases, a MalformedServerReplyException should be thrown.
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-public class MalformedServerReplyException extends IOException
-{
-
- /*** Constructs a MalformedServerReplyException with no message ***/
- public MalformedServerReplyException()
- {
- super();
- }
-
- /***
- * Constructs a MalformedServerReplyException with a specified message.
- *
- * @param message The message explaining the reason for the exception.
- ***/
- public MalformedServerReplyException(String message)
- {
- super(message);
- }
-
-}
diff --git a/org/apache/commons/net/PrintCommandListener.java b/org/apache/commons/net/PrintCommandListener.java
deleted file mode 100644
index d8e7a68..0000000
--- a/org/apache/commons/net/PrintCommandListener.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net;
-
-import java.io.PrintWriter;
-import org.apache.commons.net.ProtocolCommandEvent;
-import org.apache.commons.net.ProtocolCommandListener;
-
-/***
- * This is a support class for some of the example programs. It is
- * a sample implementation of the ProtocolCommandListener interface
- * which just prints out to a specified stream all command/reply traffic.
- *
- *
- * @since 2.0
- ***/
-
-public class PrintCommandListener implements ProtocolCommandListener
-{
- private PrintWriter __writer;
-
- public PrintCommandListener(PrintWriter writer)
- {
- __writer = writer;
- }
-
- public void protocolCommandSent(ProtocolCommandEvent event)
- {
- __writer.print(event.getMessage());
- __writer.flush();
- }
-
- public void protocolReplyReceived(ProtocolCommandEvent event)
- {
- __writer.print(event.getMessage());
- __writer.flush();
- }
-}
-
diff --git a/org/apache/commons/net/ProtocolCommandEvent.class b/org/apache/commons/net/ProtocolCommandEvent.class
deleted file mode 100644
index e558b69..0000000
Binary files a/org/apache/commons/net/ProtocolCommandEvent.class and /dev/null differ
diff --git a/org/apache/commons/net/ProtocolCommandEvent.java b/org/apache/commons/net/ProtocolCommandEvent.java
deleted file mode 100644
index 8977c03..0000000
--- a/org/apache/commons/net/ProtocolCommandEvent.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net;
-import java.util.EventObject;
-
-/***
- * There exists a large class of IETF protocols that work by sending an
- * ASCII text command and arguments to a server, and then receiving an
- * ASCII text reply. For debugging and other purposes, it is extremely
- * useful to log or keep track of the contents of the protocol messages.
- * The ProtocolCommandEvent class coupled with the
- * {@link org.apache.commons.net.ProtocolCommandListener}
- * interface facilitate this process.
- *
- *
- * @see ProtocolCommandListener
- * @see ProtocolCommandSupport
- * @author Daniel F. Savarese
- ***/
-
-public class ProtocolCommandEvent extends EventObject
-{
- private int __replyCode;
- private boolean __isCommand;
- private String __message, __command;
-
- /***
- * Creates a ProtocolCommandEvent signalling a command was sent to
- * the server. ProtocolCommandEvents created with this constructor
- * should only be sent after a command has been sent, but before the
- * reply has been received.
- *
- * @param source The source of the event.
- * @param command The string representation of the command type sent, not
- * including the arguments (e.g., "STAT" or "GET").
- * @param message The entire command string verbatim as sent to the server,
- * including all arguments.
- ***/
- public ProtocolCommandEvent(Object source, String command, String message)
- {
- super(source);
- __replyCode = 0;
- __message = message;
- __isCommand = true;
- __command = command;
- }
-
-
- /***
- * Creates a ProtocolCommandEvent signalling a reply to a command was
- * received. ProtocolCommandEvents created with this constructor
- * should only be sent after a complete command reply has been received
- * fromt a server.
- *
- * @param source The source of the event.
- * @param replyCode The integer code indicating the natureof the reply.
- * This will be the protocol integer value for protocols
- * that use integer reply codes, or the reply class constant
- * corresponding to the reply for protocols like POP3 that use
- * strings like OK rather than integer codes (i.e., POP3Repy.OK).
- * @param message The entire reply as received from the server.
- ***/
- public ProtocolCommandEvent(Object source, int replyCode, String message)
- {
- super(source);
- __replyCode = replyCode;
- __message = message;
- __isCommand = false;
- __command = null;
- }
-
- /***
- * Returns the string representation of the command type sent (e.g., "STAT"
- * or "GET"). If the ProtocolCommandEvent is a reply event, then null
- * is returned.
- *
- * @return The string representation of the command type sent, or null
- * if this is a reply event.
- ***/
- public String getCommand()
- {
- return __command;
- }
-
-
- /***
- * Returns the reply code of the received server reply. Undefined if
- * this is not a reply event.
- *
- * @return The reply code of the received server reply. Undefined if
- * not a reply event.
- ***/
- public int getReplyCode()
- {
- return __replyCode;
- }
-
- /***
- * Returns true if the ProtocolCommandEvent was generated as a result
- * of sending a command.
- *
- * @return true If the ProtocolCommandEvent was generated as a result
- * of sending a command. False otherwise.
- ***/
- public boolean isCommand()
- {
- return __isCommand;
- }
-
- /***
- * Returns true if the ProtocolCommandEvent was generated as a result
- * of receiving a reply.
- *
- * @return true If the ProtocolCommandEvent was generated as a result
- * of receiving a reply. False otherwise.
- ***/
- public boolean isReply()
- {
- return !isCommand();
- }
-
- /***
- * Returns the entire message sent to or received from the server.
- *
- * @return The entire message sent to or received from the server.
- ***/
- public String getMessage()
- {
- return __message;
- }
-}
diff --git a/org/apache/commons/net/ProtocolCommandListener.class b/org/apache/commons/net/ProtocolCommandListener.class
deleted file mode 100644
index 54d6a46..0000000
Binary files a/org/apache/commons/net/ProtocolCommandListener.class and /dev/null differ
diff --git a/org/apache/commons/net/ProtocolCommandListener.java b/org/apache/commons/net/ProtocolCommandListener.java
deleted file mode 100644
index 8089926..0000000
--- a/org/apache/commons/net/ProtocolCommandListener.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net;
-import java.util.EventListener;
-
-/***
- * There exists a large class of IETF protocols that work by sending an
- * ASCII text command and arguments to a server, and then receiving an
- * ASCII text reply. For debugging and other purposes, it is extremely
- * useful to log or keep track of the contents of the protocol messages.
- * The ProtocolCommandListener interface coupled with the
- * {@link ProtocolCommandEvent} class facilitate this process.
- *
- * To receive ProtocolCommandEvents, you merely implement the
- * ProtocolCommandListener interface and register the class as a listener
- * with a ProtocolCommandEvent source such as
- * {@link org.apache.commons.net.ftp.FTPClient}.
- *
- *
- * @see ProtocolCommandEvent
- * @see ProtocolCommandSupport
- * @author Daniel F. Savarese
- ***/
-
-public interface ProtocolCommandListener extends EventListener
-{
-
- /***
- * This method is invoked by a ProtocolCommandEvent source after
- * sending a protocol command to a server.
- *
- * @param event The ProtocolCommandEvent fired.
- ***/
- public void protocolCommandSent(ProtocolCommandEvent event);
-
- /***
- * This method is invoked by a ProtocolCommandEvent source after
- * receiving a reply from a server.
- *
- * @param event The ProtocolCommandEvent fired.
- ***/
- public void protocolReplyReceived(ProtocolCommandEvent event);
-
-}
diff --git a/org/apache/commons/net/ProtocolCommandSupport.class b/org/apache/commons/net/ProtocolCommandSupport.class
deleted file mode 100644
index 70ee4eb..0000000
Binary files a/org/apache/commons/net/ProtocolCommandSupport.class and /dev/null differ
diff --git a/org/apache/commons/net/ProtocolCommandSupport.java b/org/apache/commons/net/ProtocolCommandSupport.java
deleted file mode 100644
index 1a51fb6..0000000
--- a/org/apache/commons/net/ProtocolCommandSupport.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net;
-
-import java.io.Serializable;
-import java.util.EventListener;
-
-import org.apache.commons.net.util.ListenerList;
-
-/***
- * ProtocolCommandSupport is a convenience class for managing a list of
- * ProtocolCommandListeners and firing ProtocolCommandEvents. You can
- * simply delegate ProtocolCommandEvent firing and listener
- * registering/unregistering tasks to this class.
- *
- *
- * @see ProtocolCommandEvent
- * @see ProtocolCommandListener
- * @author Daniel F. Savarese
- ***/
-
-public class ProtocolCommandSupport implements Serializable
-{
- private Object __source;
- private ListenerList __listeners;
-
- /***
- * Creates a ProtocolCommandSupport instant using the indicated source
- * as the source of fired ProtocolCommandEvents.
- *
- * @param source The source to use for all generated ProtocolCommandEvents.
- ***/
- public ProtocolCommandSupport(Object source)
- {
- __listeners = new ListenerList();
- __source = source;
- }
-
-
- /***
- * Fires a ProtocolCommandEvent signalling the sending of a command to all
- * registered listeners, invoking their
- * {@link org.apache.commons.net.ProtocolCommandListener#protocolCommandSent protocolCommandSent() }
- * methods.
- *
- * @param command The string representation of the command type sent, not
- * including the arguments (e.g., "STAT" or "GET").
- * @param message The entire command string verbatim as sent to the server,
- * including all arguments.
- ***/
- public void fireCommandSent(String command, String message)
- {
- ProtocolCommandEvent event;
-
- event = new ProtocolCommandEvent(__source, command, message);
-
- for (EventListener listener : __listeners)
- {
- ((ProtocolCommandListener)listener).protocolCommandSent(event);
- }
- }
-
- /***
- * Fires a ProtocolCommandEvent signalling the reception of a command reply
- * to all registered listeners, invoking their
- * {@link org.apache.commons.net.ProtocolCommandListener#protocolReplyReceived protocolReplyReceived() }
- * methods.
- *
- * @param replyCode The integer code indicating the natureof the reply.
- * This will be the protocol integer value for protocols
- * that use integer reply codes, or the reply class constant
- * corresponding to the reply for protocols like POP3 that use
- * strings like OK rather than integer codes (i.e., POP3Repy.OK).
- * @param message The entire reply as received from the server.
- ***/
- public void fireReplyReceived(int replyCode, String message)
- {
- ProtocolCommandEvent event;
- event = new ProtocolCommandEvent(__source, replyCode, message);
-
- for (EventListener listener : __listeners)
- {
- ((ProtocolCommandListener)listener).protocolReplyReceived(event);
- }
- }
-
- /***
- * Adds a ProtocolCommandListener.
- *
- * @param listener The ProtocolCommandListener to add.
- ***/
- public void addProtocolCommandListener(ProtocolCommandListener listener)
- {
- __listeners.addListener(listener);
- }
-
- /***
- * Removes a ProtocolCommandListener.
- *
- * @param listener The ProtocolCommandListener to remove.
- ***/
- public void removeProtocolCommandListener(ProtocolCommandListener listener)
- {
- __listeners.removeListener(listener);
- }
-
-
- /***
- * Returns the number of ProtocolCommandListeners currently registered.
- *
- * @return The number of ProtocolCommandListeners currently registered.
- ***/
- public int getListenerCount()
- {
- return __listeners.getListenerCount();
- }
-
-}
-
diff --git a/org/apache/commons/net/SocketClient.class b/org/apache/commons/net/SocketClient.class
deleted file mode 100644
index 216f590..0000000
Binary files a/org/apache/commons/net/SocketClient.class and /dev/null differ
diff --git a/org/apache/commons/net/SocketClient.java b/org/apache/commons/net/SocketClient.java
deleted file mode 100644
index a5a8ead..0000000
--- a/org/apache/commons/net/SocketClient.java
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-
-import javax.net.ServerSocketFactory;
-import javax.net.SocketFactory;
-
-
-/**
- * The SocketClient provides the basic operations that are required of
- * client objects accessing sockets. It is meant to be
- * subclassed to avoid having to rewrite the same code over and over again
- * to open a socket, close a socket, set timeouts, etc. Of special note
- * is the {@link #setSocketFactory setSocketFactory }
- * method, which allows you to control the type of Socket the SocketClient
- * creates for initiating network connections. This is especially useful
- * for adding SSL or proxy support as well as better support for applets. For
- * example, you could create a
- * {@link org.apache.commons.net.SocketFactory} that
- * requests browser security capabilities before creating a socket.
- * All classes derived from SocketClient should use the
- * {@link #_socketFactory_ _socketFactory_ } member variable to
- * create Socket and ServerSocket instances rather than instanting
- * them by directly invoking a constructor. By honoring this contract
- * you guarantee that a user will always be able to provide his own
- * Socket implementations by substituting his own SocketFactory.
- * @author Daniel F. Savarese
- * @see SocketFactory
- */
-public abstract class SocketClient
-{
- /**
- * The end of line character sequence used by most IETF protocols. That
- * is a carriage return followed by a newline: "\r\n"
- */
- public static final String NETASCII_EOL = "\r\n";
-
- /** The default SocketFactory shared by all SocketClient instances. */
- private static final SocketFactory __DEFAULT_SOCKET_FACTORY =
- SocketFactory.getDefault();
-
- private static final ServerSocketFactory __DEFAULT_SERVER_SOCKET_FACTORY =
- ServerSocketFactory.getDefault();
-
- /** The timeout to use after opening a socket. */
- protected int _timeout_;
-
- /** The socket used for the connection. */
- protected Socket _socket_;
-
- /** The default port the client should connect to. */
- protected int _defaultPort_;
-
- /** The socket's InputStream. */
- protected InputStream _input_;
-
- /** The socket's OutputStream. */
- protected OutputStream _output_;
-
- /** The socket's SocketFactory. */
- protected SocketFactory _socketFactory_;
-
- /** The socket's ServerSocket Factory. */
- protected ServerSocketFactory _serverSocketFactory_;
-
- /** The socket's connect timeout (0 = infinite timeout) */
- private static final int DEFAULT_CONNECT_TIMEOUT = 0;
- protected int connectTimeout = DEFAULT_CONNECT_TIMEOUT;
-
- /**
- * Default constructor for SocketClient. Initializes
- * _socket_ to null, _timeout_ to 0, _defaultPort to 0,
- * _isConnected_ to false, and _socketFactory_ to a shared instance of
- * {@link org.apache.commons.net.DefaultSocketFactory}.
- */
- public SocketClient()
- {
- _socket_ = null;
- _input_ = null;
- _output_ = null;
- _timeout_ = 0;
- _defaultPort_ = 0;
- _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
- _serverSocketFactory_ = __DEFAULT_SERVER_SOCKET_FACTORY;
- }
-
-
- /**
- * Because there are so many connect() methods, the _connectAction_()
- * method is provided as a means of performing some action immediately
- * after establishing a connection, rather than reimplementing all
- * of the connect() methods. The last action performed by every
- * connect() method after opening a socket is to call this method.
- *
- * This method sets the timeout on the just opened socket to the default
- * timeout set by {@link #setDefaultTimeout setDefaultTimeout() },
- * sets _input_ and _output_ to the socket's InputStream and OutputStream
- * respectively, and sets _isConnected_ to true.
- *
- * Subclasses overriding this method should start by calling
- *
- * @param host The remote host.
- * @param port The port to connect to on the remote host.
- * @exception SocketException If the socket timeout could not be set.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- */
- public void connect(InetAddress host, int port)
- throws SocketException, IOException
- {
- _socket_ = _socketFactory_.createSocket();
- _socket_.connect(new InetSocketAddress(host, port), connectTimeout);
-
- _connectAction_();
- }
-
- /**
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the current host at a system assigned port.
- * Before returning, {@link #_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- *
- * @param hostname The name of the remote host.
- * @param port The port to connect to on the remote host.
- * @exception SocketException If the socket timeout could not be set.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- * @exception UnknownHostException If the hostname cannot be resolved.
- */
- public void connect(String hostname, int port)
- throws SocketException, IOException
- {
- _socket_= _socketFactory_.createSocket();
- _socket_.connect(new InetSocketAddress(hostname, port), connectTimeout);
-
- _connectAction_();
- }
-
-
- /**
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the specified local address and port.
- * Before returning, {@link #_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- *
- * @param host The remote host.
- * @param port The port to connect to on the remote host.
- * @param localAddr The local address to use.
- * @param localPort The local port to use.
- * @exception SocketException If the socket timeout could not be set.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- */
- public void connect(InetAddress host, int port,
- InetAddress localAddr, int localPort)
- throws SocketException, IOException
- {
- _socket_ = _socketFactory_.createSocket();
- _socket_.bind(new InetSocketAddress(localAddr, localPort));
- _socket_.connect(new InetSocketAddress(host, port), connectTimeout);
-
- _connectAction_();
- }
-
-
- /**
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the specified local address and port.
- * Before returning, {@link #_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- *
- * @param hostname The name of the remote host.
- * @param port The port to connect to on the remote host.
- * @param localAddr The local address to use.
- * @param localPort The local port to use.
- * @exception SocketException If the socket timeout could not be set.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- * @exception UnknownHostException If the hostname cannot be resolved.
- */
- public void connect(String hostname, int port,
- InetAddress localAddr, int localPort)
- throws SocketException, IOException
- {
- _socket_ =
- _socketFactory_.createSocket(hostname, port, localAddr, localPort);
- _connectAction_();
- }
-
-
- /**
- * Opens a Socket connected to a remote host at the current default port
- * and originating from the current host at a system assigned port.
- * Before returning, {@link #_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- *
- * @param host The remote host.
- * @exception SocketException If the socket timeout could not be set.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- */
- public void connect(InetAddress host) throws SocketException, IOException
- {
- connect(host, _defaultPort_);
- }
-
-
- /**
- * Opens a Socket connected to a remote host at the current default
- * port and originating from the current host at a system assigned port.
- * Before returning, {@link #_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- *
- * @param hostname The name of the remote host.
- * @exception SocketException If the socket timeout could not be set.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- * @exception UnknownHostException If the hostname cannot be resolved.
- */
- public void connect(String hostname) throws SocketException, IOException
- {
- connect(hostname, _defaultPort_);
- }
-
-
- /**
- * Disconnects the socket connection.
- * You should call this method after you've finished using the class
- * instance and also before you call
- * {@link #connect connect() }
- * again. _isConnected_ is set to false, _socket_ is set to null,
- * _input_ is set to null, and _output_ is set to null.
- *
- * @exception IOException If there is an error closing the socket.
- */
- public void disconnect() throws IOException
- {
- if (_socket_ != null) _socket_.close();
- if (_input_ != null) _input_.close();
- if (_output_ != null) _output_.close();
- if (_socket_ != null) _socket_ = null;
- _input_ = null;
- _output_ = null;
- }
-
-
- /**
- * Returns true if the client is currently connected to a server.
- *
- * @return True if the client is currently connected to a server,
- * false otherwise.
- */
- public boolean isConnected()
- {
- if (_socket_ == null)
- return false;
-
- return _socket_.isConnected();
- }
-
-
- /**
- * Sets the default port the SocketClient should connect to when a port
- * is not specified. The {@link #_defaultPort_ _defaultPort_ }
- * variable stores this value. If never set, the default port is equal
- * to zero.
- *
- * @param port The default port to set.
- */
- public void setDefaultPort(int port)
- {
- _defaultPort_ = port;
- }
-
- /**
- * Returns the current value of the default port (stored in
- * {@link #_defaultPort_ _defaultPort_ }).
- *
- * @return The current value of the default port.
- */
- public int getDefaultPort()
- {
- return _defaultPort_;
- }
-
-
- /**
- * Set the default timeout in milliseconds to use when opening a socket.
- * This value is only used previous to a call to
- * {@link #connect connect()}
- * and should not be confused with {@link #setSoTimeout setSoTimeout()}
- * which operates on an the currently opened socket. _timeout_ contains
- * the new timeout value.
- *
- * @param timeout The timeout in milliseconds to use for the socket
- * connection.
- */
- public void setDefaultTimeout(int timeout)
- {
- _timeout_ = timeout;
- }
-
-
- /**
- * Returns the default timeout in milliseconds that is used when
- * opening a socket.
- *
- * @return The default timeout in milliseconds that is used when
- * opening a socket.
- */
- public int getDefaultTimeout()
- {
- return _timeout_;
- }
-
-
- /**
- * Set the timeout in milliseconds of a currently open connection.
- * Only call this method after a connection has been opened
- * by {@link #connect connect()}.
- *
- * @param timeout The timeout in milliseconds to use for the currently
- * open socket connection.
- * @exception SocketException If the operation fails.
- */
- public void setSoTimeout(int timeout) throws SocketException
- {
- _socket_.setSoTimeout(timeout);
- }
-
-
- /**
- * Set the underlying socket send buffer size.
- *
- * @param size The size of the buffer in bytes.
- * @throws SocketException
- * @since 2.0
- */
- public void setSendBufferSize(int size) throws SocketException {
- _socket_.setSendBufferSize(size);
- }
-
-
- /**
- * Sets the underlying socket receive buffer size.
- *
- * @param size The size of the buffer in bytes.
- * @throws SocketException
- * @since 2.0
- */
- public void setReceiveBufferSize(int size) throws SocketException {
- _socket_.setReceiveBufferSize(size);
- }
-
-
- /**
- * Returns the timeout in milliseconds of the currently opened socket.
- *
- * @return The timeout in milliseconds of the currently opened socket.
- * @exception SocketException If the operation fails.
- */
- public int getSoTimeout() throws SocketException
- {
- return _socket_.getSoTimeout();
- }
-
- /**
- * Enables or disables the Nagle's algorithm (TCP_NODELAY) on the
- * currently opened socket.
- *
- * @param on True if Nagle's algorithm is to be enabled, false if not.
- * @exception SocketException If the operation fails.
- */
- public void setTcpNoDelay(boolean on) throws SocketException
- {
- _socket_.setTcpNoDelay(on);
- }
-
-
- /**
- * Returns true if Nagle's algorithm is enabled on the currently opened
- * socket.
- *
- * @return True if Nagle's algorithm is enabled on the currently opened
- * socket, false otherwise.
- * @exception SocketException If the operation fails.
- */
- public boolean getTcpNoDelay() throws SocketException
- {
- return _socket_.getTcpNoDelay();
- }
-
-
- /**
- * Sets the SO_LINGER timeout on the currently opened socket.
- *
- * @param on True if linger is to be enabled, false if not.
- * @param val The linger timeout (in hundredths of a second?)
- * @exception SocketException If the operation fails.
- */
- public void setSoLinger(boolean on, int val) throws SocketException
- {
- _socket_.setSoLinger(on, val);
- }
-
-
- /**
- * Returns the current SO_LINGER timeout of the currently opened socket.
- *
- * @return The current SO_LINGER timeout. If SO_LINGER is disabled returns
- * -1.
- * @exception SocketException If the operation fails.
- */
- public int getSoLinger() throws SocketException
- {
- return _socket_.getSoLinger();
- }
-
-
- /**
- * Returns the port number of the open socket on the local host used
- * for the connection.
- *
- * @return The port number of the open socket on the local host used
- * for the connection.
- */
- public int getLocalPort()
- {
- return _socket_.getLocalPort();
- }
-
-
- /**
- * Returns the local address to which the client's socket is bound.
- *
- * @return The local address to which the client's socket is bound.
- */
- public InetAddress getLocalAddress()
- {
- return _socket_.getLocalAddress();
- }
-
- /**
- * Returns the port number of the remote host to which the client is
- * connected.
- *
- * @return The port number of the remote host to which the client is
- * connected.
- */
- public int getRemotePort()
- {
- return _socket_.getPort();
- }
-
-
- /**
- * @return The remote address to which the client is connected.
- */
- public InetAddress getRemoteAddress()
- {
- return _socket_.getInetAddress();
- }
-
-
- /**
- * Verifies that the remote end of the given socket is connected to the
- * the same host that the SocketClient is currently connected to. This
- * is useful for doing a quick security check when a client needs to
- * accept a connection from a server, such as an FTP data connection or
- * a BSD R command standard error stream.
- *
- * @return True if the remote hosts are the same, false if not.
- */
- public boolean verifyRemote(Socket socket)
- {
- InetAddress host1, host2;
-
- host1 = socket.getInetAddress();
- host2 = getRemoteAddress();
-
- return host1.equals(host2);
- }
-
-
- /**
- * Sets the SocketFactory used by the SocketClient to open socket
- * connections. If the factory value is null, then a default
- * factory is used (only do this to reset the factory after having
- * previously altered it).
- *
- * @param factory The new SocketFactory the SocketClient should use.
- */
- public void setSocketFactory(SocketFactory factory)
- {
- if (factory == null)
- _socketFactory_ = __DEFAULT_SOCKET_FACTORY;
- else
- _socketFactory_ = factory;
- }
-
- /**
- * Sets the ServerSocketFactory used by the SocketClient to open ServerSocket
- * connections. If the factory value is null, then a default
- * factory is used (only do this to reset the factory after having
- * previously altered it).
- *
- * @param factory The new ServerSocketFactory the SocketClient should use.
- * @since 2.0
- */
- public void setServerSocketFactory(ServerSocketFactory factory) {
- if (factory == null)
- _serverSocketFactory_ = __DEFAULT_SERVER_SOCKET_FACTORY;
- else
- _serverSocketFactory_ = factory;
- }
-
- /**
- * Sets the connection timeout in milliseconds, which will be passed to the {@link Socket} object's
- * connect() method.
- * @param connectTimeout The connection timeout to use (in ms)
- * @since 2.0
- */
- public void setConnectTimeout(int connectTimeout) {
- this.connectTimeout = connectTimeout;
- }
-
- /**
- * Get the underlying socket connection timeout.
- * @return
- * @since 2.0
- */
- public int getConnectTimeout() {
- return connectTimeout;
- }
-
-
-
-}
-
-
diff --git a/org/apache/commons/net/bsd/RCommandClient.java b/org/apache/commons/net/bsd/RCommandClient.java
deleted file mode 100644
index 50cb87a..0000000
--- a/org/apache/commons/net/bsd/RCommandClient.java
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.bsd;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.BindException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketException;
-
-import org.apache.commons.net.io.SocketInputStream;
-
-/***
- * RCommandClient is very similar to
- * {@link org.apache.commons.net.bsd.RExecClient},
- * from which it is derived, and implements the rcmd() facility that
- * first appeared in 4.2BSD Unix. rcmd() is the facility used by the rsh
- * (rshell) and other commands to execute a command on another machine
- * from a trusted host without issuing a password. The trust relationship
- * between two machines is established by the contents of a machine's
- * /etc/hosts.equiv file and a user's .rhosts file. These files specify
- * from which hosts and accounts on those hosts rcmd() requests will be
- * accepted. The only additional measure for establishing trust is that
- * all client connections must originate from a port between 512 and 1023.
- * Consequently, there is an upper limit to the number of rcmd connections
- * that can be running simultaneously. The required ports are reserved
- * ports on Unix systems, and can only be bound by a
- * process running with root permissions (to accomplish this rsh, rlogin,
- * and related commands usualy have the suid bit set). Therefore, on a
- * Unix system, you will only be able to successfully use the RCommandClient
- * class if the process runs as root. However, there is no such restriction
- * on Windows95 and some other systems. The security risks are obvious.
- * However, when carefully used, rcmd() can be very useful when used behind
- * a firewall.
- *
- * As with virtually all of the client classes in org.apache.commons.net, this
- * class derives from SocketClient. But it overrides most of its connection
- * methods so that the local Socket will originate from an acceptable
- * rshell port. The way to use RCommandClient is to first connect
- * to the server, call the {@link #rcommand rcommand() } method,
- * and then
- * fetch the connection's input, output, and optionally error streams.
- * Interaction with the remote command is controlled entirely through the
- * I/O streams. Once you have finished processing the streams, you should
- * invoke {@link org.apache.commons.net.bsd.RExecClient#disconnect disconnect() }
- * to clean up properly.
- *
- * By default the standard output and standard error streams of the
- * remote process are transmitted over the same connection, readable
- * from the input stream returned by
- * {@link org.apache.commons.net.bsd.RExecClient#getInputStream getInputStream() }
- * . However, it is
- * possible to tell the rshd daemon to return the standard error
- * stream over a separate connection, readable from the input stream
- * returned by {@link org.apache.commons.net.bsd.RExecClient#getErrorStream getErrorStream() }
- * . You
- * can specify that a separate connection should be created for standard
- * error by setting the boolean
- *
- * @author Daniel F. Savarese
- * @see org.apache.commons.net.SocketClient
- * @see RExecClient
- * @see RLoginClient
- ***/
-
-public class RCommandClient extends RExecClient
-{
- /***
- * The default rshell port. Set to 514 in BSD Unix.
- ***/
- public static final int DEFAULT_PORT = 514;
-
- /***
- * The smallest port number an rcmd client may use. By BSD convention
- * this number is 512.
- ***/
- public static final int MIN_CLIENT_PORT = 512;
-
- /***
- * The largest port number an rcmd client may use. By BSD convention
- * this number is 1023.
- ***/
- public static final int MAX_CLIENT_PORT = 1023;
-
- // Overrides method in RExecClient in order to implement proper
- // port number limitations.
- @Override
- InputStream _createErrorStream() throws IOException
- {
- int localPort;
- ServerSocket server;
- Socket socket;
-
- localPort = MAX_CLIENT_PORT;
- server = null; // Keep compiler from barfing
-
- for (localPort = MAX_CLIENT_PORT; localPort >= MIN_CLIENT_PORT; --localPort)
- {
- try
- {
- server = _serverSocketFactory_.createServerSocket(localPort, 1,
- getLocalAddress());
- }
- catch (SocketException e)
- {
- continue;
- }
- break;
- }
-
- if (localPort < MIN_CLIENT_PORT)
- throw new BindException("All ports in use.");
-
- _output_.write(Integer.toString(server.getLocalPort()).getBytes());
- _output_.write('\0');
- _output_.flush();
-
- socket = server.accept();
- server.close();
-
- if (isRemoteVerificationEnabled() && !verifyRemote(socket))
- {
- socket.close();
- throw new IOException(
- "Security violation: unexpected connection attempt by " +
- socket.getInetAddress().getHostAddress());
- }
-
- return (new SocketInputStream(socket, socket.getInputStream()));
- }
-
- /***
- * The default RCommandClient constructor. Initializes the
- * default port to
- * @param host The remote host.
- * @param port The port to connect to on the remote host.
- * @param localAddr The local address to use.
- * @exception SocketException If the socket timeout could not be set.
- * @exception BindException If all acceptable rshell ports are in use.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- ***/
- public void connect(InetAddress host, int port, InetAddress localAddr)
- throws SocketException, BindException, IOException
- {
- int localPort;
-
- localPort = MAX_CLIENT_PORT;
-
- for (localPort = MAX_CLIENT_PORT; localPort >= MIN_CLIENT_PORT; --localPort)
- {
- try
- {
- _socket_ =
- _socketFactory_.createSocket(host, port, localAddr, localPort);
- }
- catch (BindException be) {
- continue;
- }
- catch (SocketException e)
- {
- continue;
- }
- break;
- }
-
- if (localPort < MIN_CLIENT_PORT)
- throw new BindException("All ports in use or insufficient permssion.");
-
- _connectAction_();
- }
-
-
-
- /***
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the current host at a port in a range acceptable
- * to the BSD rshell daemon.
- * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- *
- * @param host The remote host.
- * @param port The port to connect to on the remote host.
- * @exception SocketException If the socket timeout could not be set.
- * @exception BindException If all acceptable rshell ports are in use.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- ***/
- @Override
- public void connect(InetAddress host, int port)
- throws SocketException, IOException
- {
- connect(host, port, InetAddress.getLocalHost());
- }
-
-
- /***
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the current host at a port in a range acceptable
- * to the BSD rshell daemon.
- * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- *
- * @param hostname The name of the remote host.
- * @param port The port to connect to on the remote host.
- * @exception SocketException If the socket timeout could not be set.
- * @exception BindException If all acceptable rshell ports are in use.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- @Override
- public void connect(String hostname, int port)
- throws SocketException, IOException
- {
- connect(InetAddress.getByName(hostname), port, InetAddress.getLocalHost());
- }
-
-
- /***
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the specified local address using a port in a range
- * acceptable to the BSD rshell daemon.
- * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- *
- * @param hostname The remote host.
- * @param port The port to connect to on the remote host.
- * @param localAddr The local address to use.
- * @exception SocketException If the socket timeout could not be set.
- * @exception BindException If all acceptable rshell ports are in use.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- ***/
- public void connect(String hostname, int port, InetAddress localAddr)
- throws SocketException, IOException
- {
- connect(InetAddress.getByName(hostname), port, localAddr);
- }
-
-
- /***
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the specified local address and port. The
- * local port must lie between
- * @param host The remote host.
- * @param port The port to connect to on the remote host.
- * @param localAddr The local address to use.
- * @param localPort The local port to use.
- * @exception SocketException If the socket timeout could not be set.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- * @exception IllegalArgumentException If an invalid local port number
- * is specified.
- ***/
- @Override
- public void connect(InetAddress host, int port,
- InetAddress localAddr, int localPort)
- throws SocketException, IOException, IllegalArgumentException
- {
- if (localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT)
- throw new IllegalArgumentException("Invalid port number " + localPort);
- super.connect(host, port, localAddr, localPort);
- }
-
-
- /***
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the specified local address and port. The
- * local port must lie between
- * @param hostname The name of the remote host.
- * @param port The port to connect to on the remote host.
- * @param localAddr The local address to use.
- * @param localPort The local port to use.
- * @exception SocketException If the socket timeout could not be set.
- * @exception IOException If the socket could not be opened. In most
- * cases you will only want to catch IOException since SocketException is
- * derived from it.
- * @exception UnknownHostException If the hostname cannot be resolved.
- * @exception IllegalArgumentException If an invalid local port number
- * is specified.
- ***/
- @Override
- public void connect(String hostname, int port,
- InetAddress localAddr, int localPort)
- throws SocketException, IOException, IllegalArgumentException
- {
- if (localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT)
- throw new IllegalArgumentException("Invalid port number " + localPort);
- super.connect(hostname, port, localAddr, localPort);
- }
-
-
- /***
- * Remotely executes a command through the rshd daemon on the server
- * to which the RCommandClient is connected. After calling this method,
- * you may interact with the remote process through its standard input,
- * output, and error streams. You will typically be able to detect
- * the termination of the remote process after reaching end of file
- * on its standard output (accessible through
- * {@link #getInputStream getInputStream() }. Disconnecting
- * from the server or closing the process streams before reaching
- * end of file will not necessarily terminate the remote process.
- *
- * If a separate error stream is requested, the remote server will
- * connect to a local socket opened by RCommandClient, providing an
- * independent stream through which standard error will be transmitted.
- * The local socket must originate from a secure port (512 - 1023),
- * and rcommand() ensures that this will be so.
- * RCommandClient will also do a simple security check when it accepts a
- * connection for this error stream. If the connection does not originate
- * from the remote server, an IOException will be thrown. This serves as
- * a simple protection against possible hijacking of the error stream by
- * an attacker monitoring the rexec() negotiation. You may disable this
- * behavior with
- * {@link org.apache.commons.net.bsd.RExecClient#setRemoteVerificationEnabled setRemoteVerificationEnabled()}
- * .
- *
- * @param localUsername The user account on the local machine that is
- * requesting the command execution.
- * @param remoteUsername The account name on the server through which to
- * execute the command.
- * @param command The command, including any arguments, to execute.
- * @param separateErrorStream True if you would like the standard error
- * to be transmitted through a different stream than standard output.
- * False if not.
- * @exception IOException If the rcommand() attempt fails. The exception
- * will contain a message indicating the nature of the failure.
- ***/
- public void rcommand(String localUsername, String remoteUsername,
- String command, boolean separateErrorStream)
- throws IOException
- {
- rexec(localUsername, remoteUsername, command, separateErrorStream);
- }
-
-
- /***
- * Same as
- *
- * As with virtually all of the client classes in org.apache.commons.net, this
- * class derives from SocketClient, inheriting its connection methods.
- * The way to use RExecClient is to first connect
- * to the server, call the {@link #rexec rexec() } method, and then
- * fetch the connection's input, output, and optionally error streams.
- * Interaction with the remote command is controlled entirely through the
- * I/O streams. Once you have finished processing the streams, you should
- * invoke {@link #disconnect disconnect() } to clean up properly.
- *
- * By default the standard output and standard error streams of the
- * remote process are transmitted over the same connection, readable
- * from the input stream returned by
- * {@link #getInputStream getInputStream() }. However, it is
- * possible to tell the rexecd daemon to return the standard error
- * stream over a separate connection, readable from the input stream
- * returned by {@link #getErrorStream getErrorStream() }. You
- * can specify that a separate connection should be created for standard
- * error by setting the boolean
- *
- * @author Daniel F. Savarese
- * @see SocketClient
- * @see RCommandClient
- * @see RLoginClient
- ***/
-
-public class RExecClient extends SocketClient
-{
- /***
- * The default rexec port. Set to 512 in BSD Unix.
- ***/
- public static final int DEFAULT_PORT = 512;
-
- private boolean __remoteVerificationEnabled;
-
- /***
- * If a separate error stream is requested,
- * @return The InputStream from which the standard output of the remote
- * process can be read.
- ***/
- public InputStream getInputStream()
- {
- return _input_;
- }
-
-
- /***
- * Returns the OutputStream through which the standard input of the remote
- * process can be written. The output stream will only be set after a
- * successful rexec() invocation.
- *
- * @return The OutputStream through which the standard input of the remote
- * process can be written.
- ***/
- public OutputStream getOutputStream()
- {
- return _output_;
- }
-
-
- /***
- * Returns the InputStream from which the standard error of the remote
- * process can be read if a separate error stream is requested from
- * the server. Otherwise, null will be returned. The error stream
- * will only be set after a successful rexec() invocation.
- *
- * @return The InputStream from which the standard error of the remote
- * process can be read if a separate error stream is requested from
- * the server. Otherwise, null will be returned.
- ***/
- public InputStream getErrorStream()
- {
- return _errorStream_;
- }
-
-
- /***
- * Remotely executes a command through the rexecd daemon on the server
- * to which the RExecClient is connected. After calling this method,
- * you may interact with the remote process through its standard input,
- * output, and error streams. You will typically be able to detect
- * the termination of the remote process after reaching end of file
- * on its standard output (accessible through
- * {@link #getInputStream getInputStream() }. Disconnecting
- * from the server or closing the process streams before reaching
- * end of file will not necessarily terminate the remote process.
- *
- * If a separate error stream is requested, the remote server will
- * connect to a local socket opened by RExecClient, providing an
- * independent stream through which standard error will be transmitted.
- * RExecClient will do a simple security check when it accepts a
- * connection for this error stream. If the connection does not originate
- * from the remote server, an IOException will be thrown. This serves as
- * a simple protection against possible hijacking of the error stream by
- * an attacker monitoring the rexec() negotiation. You may disable this
- * behavior with {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}
- * .
- *
- * @param username The account name on the server through which to execute
- * the command.
- * @param password The plain text password of the user account.
- * @param command The command, including any arguments, to execute.
- * @param separateErrorStream True if you would like the standard error
- * to be transmitted through a different stream than standard output.
- * False if not.
- * @exception IOException If the rexec() attempt fails. The exception
- * will contain a message indicating the nature of the failure.
- ***/
- public void rexec(String username, String password,
- String command, boolean separateErrorStream)
- throws IOException
- {
- int ch;
-
- if (separateErrorStream)
- {
- _errorStream_ = _createErrorStream();
- }
- else
- {
- _output_.write('\0');
- }
-
- _output_.write(username.getBytes());
- _output_.write('\0');
- _output_.write(password.getBytes());
- _output_.write('\0');
- _output_.write(command.getBytes());
- _output_.write('\0');
- _output_.flush();
-
- ch = _input_.read();
- if (ch > 0)
- {
- StringBuffer buffer = new StringBuffer();
-
- while ((ch = _input_.read()) != -1 && ch != '\n')
- buffer.append((char)ch);
-
- throw new IOException(buffer.toString());
- }
- else if (ch < 0)
- {
- throw new IOException("Server closed connection.");
- }
- }
-
-
- /***
- * Same as
- * @exception IOException If there an error occurs while disconnecting.
- ***/
- @Override
- public void disconnect() throws IOException
- {
- if (_errorStream_ != null)
- _errorStream_.close();
- _errorStream_ = null;
- super.disconnect();
- }
-
-
- /***
- * Enable or disable verification that the remote host connecting to
- * create a separate error stream is the same as the host to which
- * the standard out stream is connected. The default is for verification
- * to be enabled. You may set this value at any time, whether the
- * client is currently connected or not.
- *
- * @param enable True to enable verification, false to disable verification.
- ***/
- public final void setRemoteVerificationEnabled(boolean enable)
- {
- __remoteVerificationEnabled = enable;
- }
-
- /***
- * Return whether or not verification of the remote host providing a
- * separate error stream is enabled. The default behavior is for
- * verification to be enabled.
- *
- * @return True if verification is enabled, false if not.
- ***/
- public final boolean isRemoteVerificationEnabled()
- {
- return __remoteVerificationEnabled;
- }
-
-}
-
diff --git a/org/apache/commons/net/bsd/RLoginClient.java b/org/apache/commons/net/bsd/RLoginClient.java
deleted file mode 100644
index 3d7c63c..0000000
--- a/org/apache/commons/net/bsd/RLoginClient.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.bsd;
-
-import java.io.IOException;
-
-/***
- * RLoginClient is very similar to
- * {@link org.apache.commons.net.bsd.RCommandClient},
- * from which it is derived, and uses the rcmd() facility implemented
- * in RCommandClient to implement the functionality of the rlogin command that
- * first appeared in 4.2BSD Unix. rlogin is a command used to login to
- * a remote machine from a trusted host, sometimes without issuing a
- * password. The trust relationship is the same as described in
- * the documentation for
- * {@link org.apache.commons.net.bsd.RCommandClient}.
- *
- * As with virtually all of the client classes in org.apache.commons.net, this
- * class derives from SocketClient. But it relies on the connection
- * methods defined in RcommandClient which ensure that the local Socket
- * will originate from an acceptable rshell port. The way to use
- * RLoginClient is to first connect
- * to the server, call the {@link #rlogin rlogin() } method,
- * and then
- * fetch the connection's input and output streams.
- * Interaction with the remote command is controlled entirely through the
- * I/O streams. Once you have finished processing the streams, you should
- * invoke {@link org.apache.commons.net.bsd.RExecClient#disconnect disconnect() }
- * to clean up properly.
- *
- * The standard output and standard error streams of the
- * remote process are transmitted over the same connection, readable
- * from the input stream returned by
- * {@link org.apache.commons.net.bsd.RExecClient#getInputStream getInputStream() }
- * . Unlike RExecClient and RCommandClient, it is
- * not possible to tell the rlogind daemon to return the standard error
- * stream over a separate connection.
- * {@link org.apache.commons.net.bsd.RExecClient#getErrorStream getErrorStream() }
- * will always return null.
- * The standard input of the remote process can be written to through
- * the output stream returned by
- * {@link org.apache.commons.net.bsd.RExecClient#getOutputStream getOutputSream() }
- * .
- *
- *
- * @author Daniel F. Savarese
- * @see org.apache.commons.net.SocketClient
- * @see RExecClient
- * @see RCommandClient
- ***/
-
-public class RLoginClient extends RCommandClient
-{
- /***
- * The default rlogin port. Set to 513 in BSD Unix and according
- * to RFC 1282.
- ***/
- public static final int DEFAULT_PORT = 513;
-
- /***
- * The default RLoginClient constructor. Initializes the
- * default port to
- * If user authentication fails, the rlogind daemon will request that
- * a password be entered interactively. You will be able to read the
- * prompt from the output stream of the RLoginClient and write the
- * password to the input stream of the RLoginClient.
- *
- * @param localUsername The user account on the local machine that is
- * trying to login to the remote host.
- * @param remoteUsername The account name on the server that is
- * being logged in to.
- * @param terminalType The name of the user's terminal (e.g., "vt100",
- * "network", etc.)
- * @param terminalSpeed The speed of the user's terminal, expressed
- * as a baud rate or bps (e.g., 9600 or 38400)
- * @exception IOException If the rlogin() attempt fails. The exception
- * will contain a message indicating the nature of the failure.
- ***/
- public void rlogin(String localUsername, String remoteUsername,
- String terminalType, int terminalSpeed)
- throws IOException
- {
- rexec(localUsername, remoteUsername, terminalType + "/" + terminalSpeed,
- false);
- }
-
- /***
- * Same as the other rlogin method, but no terminal speed is defined.
- ***/
- public void rlogin(String localUsername, String remoteUsername,
- String terminalType)
- throws IOException
- {
- rexec(localUsername, remoteUsername, terminalType, false);
- }
-
-}
diff --git a/org/apache/commons/net/chargen/CharGenTCPClient.java b/org/apache/commons/net/chargen/CharGenTCPClient.java
deleted file mode 100644
index a023e58..0000000
--- a/org/apache/commons/net/chargen/CharGenTCPClient.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.chargen;
-
-import java.io.InputStream;
-
-import org.apache.commons.net.SocketClient;
-
-/***
- * The CharGenTCPClient class is a TCP implementation of a client for the
- * character generator protocol described in RFC 864. It can also be
- * used for Systat (RFC 866), Quote of the Day (RFC 865), and netstat
- * (port 15). All of these protocols involve connecting to the appropriate
- * port, and reading data from an input stream. The chargen protocol
- * actually sends data until the receiving end closes the connection. All
- * of the others send only a fixed amount of data and then close the
- * connection.
- *
- * To use the CharGenTCPClient class, just establish a
- * connection with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * and call {@link #getInputStream getInputStream() } to access
- * the data. Don't close the input stream when you're done with it. Rather,
- * call {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * to clean up properly.
- *
- *
- * @author Daniel F. Savarese
- * @see CharGenUDPClient
- ***/
-
-public final class CharGenTCPClient extends SocketClient
-{
- /*** The systat port value of 11 according to RFC 866. ***/
- public static final int SYSTAT_PORT = 11;
- /*** The netstat port value of 19. ***/
- public static final int NETSTAT_PORT = 15;
- /*** The quote of the day port value of 17 according to RFC 865. ***/
- public static final int QUOTE_OF_DAY_PORT = 17;
- /*** The character generator port value of 19 according to RFC 864. ***/
- public static final int CHARGEN_PORT = 19;
- /*** The default chargen port. It is set to 19 according to RFC 864. ***/
- public static final int DEFAULT_PORT = 19;
-
- /***
- * The default constructor for CharGenTCPClient. It merely sets the
- * default port to
- * @return An InputStream from which the server generated data can be read.
- ***/
- public InputStream getInputStream()
- {
- return _input_;
- }
-}
-
-
-
-
diff --git a/org/apache/commons/net/chargen/CharGenUDPClient.java b/org/apache/commons/net/chargen/CharGenUDPClient.java
deleted file mode 100644
index f9a349a..0000000
--- a/org/apache/commons/net/chargen/CharGenUDPClient.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.chargen;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-import org.apache.commons.net.DatagramSocketClient;
-
-/***
- * The CharGenUDPClient class is a UDP implementation of a client for the
- * character generator protocol described in RFC 864. It can also be
- * used for Systat (RFC 866), Quote of the Day (RFC 865), and netstat
- * (port 15). All of these protocols involve sending a datagram to the
- * appropriate port, and reading data contained in one or more reply
- * datagrams. The chargen and quote of the day protocols only send
- * one reply datagram containing 512 bytes or less of data. The other
- * protocols may reply with more than one datagram, in which case you
- * must wait for a timeout to determine that all reply datagrams have
- * been sent.
- *
- * To use the CharGenUDPClient class, just open a local UDP port
- * with {@link org.apache.commons.net.DatagramSocketClient#open open }
- * and call {@link #send send } to send the datagram that will
- * initiate the data reply. For chargen or quote of the day, just
- * call {@link #receive receive }, and you're done. For netstat and
- * systat, call receive in a while loop, and catch a SocketException and
- * InterruptedIOException to detect a timeout (don't forget to set the
- * timeout duration beforehand). Don't forget to call
- * {@link org.apache.commons.net.DatagramSocketClient#close close() }
- * to clean up properly.
- *
- *
- * @author Daniel F. Savarese
- * @see CharGenTCPClient
- ***/
-
-public final class CharGenUDPClient extends DatagramSocketClient
-{
- /*** The systat port value of 11 according to RFC 866. ***/
- public static final int SYSTAT_PORT = 11;
- /*** The netstat port value of 19. ***/
- public static final int NETSTAT_PORT = 15;
- /*** The quote of the day port value of 17 according to RFC 865. ***/
- public static final int QUOTE_OF_DAY_PORT = 17;
- /*** The character generator port value of 19 according to RFC 864. ***/
- public static final int CHARGEN_PORT = 19;
- /*** The default chargen port. It is set to 19 according to RFC 864. ***/
- public static final int DEFAULT_PORT = 19;
-
- private byte[] __receiveData;
- private DatagramPacket __receivePacket;
- private DatagramPacket __sendPacket;
-
- /***
- * The default CharGenUDPClient constructor. It initializes some internal
- * data structures for sending and receiving the necessary datagrams for
- * the chargen and related protocols.
- ***/
- public CharGenUDPClient()
- {
- // CharGen return packets have a maximum length of 512
- __receiveData = new byte[512];
- __receivePacket = new DatagramPacket(__receiveData, 512);
- __sendPacket = new DatagramPacket(new byte[0], 0);
- }
-
-
- /***
- * Sends the data initiation datagram. This data in the packet is ignored
- * by the server, and merely serves to signal that the server should send
- * its reply.
- *
- * @param host The address of the server.
- * @param port The port of the service.
- * @exception IOException If an error occurs while sending the datagram.
- ***/
- public void send(InetAddress host, int port) throws IOException
- {
- __sendPacket.setAddress(host);
- __sendPacket.setPort(port);
- _socket_.send(__sendPacket);
- }
-
- /*** Same as
- * @return The reply data from the server.
- * @exception IOException If an error occurs while receiving the datagram.
- ***/
- public byte[] receive() throws IOException
- {
- int length;
- byte[] result;
-
- _socket_.receive(__receivePacket);
-
- result = new byte[length = __receivePacket.getLength()];
- System.arraycopy(__receiveData, 0, result, 0, length);
-
- return result;
- }
-
-}
-
diff --git a/org/apache/commons/net/daytime/DaytimeTCPClient.java b/org/apache/commons/net/daytime/DaytimeTCPClient.java
deleted file mode 100644
index a77c8c1..0000000
--- a/org/apache/commons/net/daytime/DaytimeTCPClient.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.daytime;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-
-import org.apache.commons.net.SocketClient;
-
-/***
- * The DaytimeTCPClient class is a TCP implementation of a client for the
- * Daytime protocol described in RFC 867. To use the class, merely
- * establish a connection with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * and call {@link #getTime getTime() } to retrieve the daytime
- * string, then
- * call {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * to close the connection properly.
- *
- *
- * @author Daniel F. Savarese
- * @see DaytimeUDPClient
- ***/
-
-public final class DaytimeTCPClient extends SocketClient
-{
- /*** The default daytime port. It is set to 13 according to RFC 867. ***/
- public static final int DEFAULT_PORT = 13;
-
- // Received dates will likely be less than 64 characters.
- // This is a temporary buffer used while receiving data.
- private char[] __buffer = new char[64];
-
- /***
- * The default DaytimeTCPClient constructor. It merely sets the default
- * port to
- * @return The time string retrieved from the server.
- * @exception IOException If an error occurs while fetching the time string.
- ***/
- public String getTime() throws IOException
- {
- int read;
- StringBuffer result = new StringBuffer(__buffer.length);
- BufferedReader reader;
-
- reader = new BufferedReader(new InputStreamReader(_input_));
-
- while (true)
- {
- read = reader.read(__buffer, 0, __buffer.length);
- if (read <= 0)
- break;
- result.append(__buffer, 0, read);
- }
-
- return result.toString();
- }
-
-}
-
diff --git a/org/apache/commons/net/daytime/DaytimeUDPClient.java b/org/apache/commons/net/daytime/DaytimeUDPClient.java
deleted file mode 100644
index 64eef9d..0000000
--- a/org/apache/commons/net/daytime/DaytimeUDPClient.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.daytime;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-import org.apache.commons.net.DatagramSocketClient;
-
-/***
- * The DaytimeUDPClient class is a UDP implementation of a client for the
- * Daytime protocol described in RFC 867. To use the class, merely
- * open a local datagram socket with
- * {@link org.apache.commons.net.DatagramSocketClient#open open }
- * and call {@link #getTime getTime } to retrieve the daytime
- * string, then
- * call {@link org.apache.commons.net.DatagramSocketClient#close close }
- * to close the connection properly. Unlike
- * {@link org.apache.commons.net.daytime.DaytimeTCPClient},
- * successive calls to {@link #getTime getTime } are permitted
- * without re-establishing a connection. That is because UDP is a
- * connectionless protocol and the Daytime protocol is stateless.
- *
- *
- * @author Daniel F. Savarese
- * @see DaytimeTCPClient
- ***/
-
-public final class DaytimeUDPClient extends DatagramSocketClient
-{
- /*** The default daytime port. It is set to 13 according to RFC 867. ***/
- public static final int DEFAULT_PORT = 13;
-
- private byte[] __dummyData = new byte[1];
- // Received dates should be less than 256 bytes
- private byte[] __timeData = new byte[256];
-
- /***
- * Retrieves the time string from the specified server and port and
- * returns it.
- *
- * @param host The address of the server.
- * @param port The port of the service.
- * @return The time string.
- * @exception IOException If an error occurs while retrieving the time.
- ***/
- public String getTime(InetAddress host, int port) throws IOException
- {
- DatagramPacket sendPacket, receivePacket;
-
- sendPacket =
- new DatagramPacket(__dummyData, __dummyData.length, host, port);
- receivePacket = new DatagramPacket(__timeData, __timeData.length);
-
- _socket_.send(sendPacket);
- _socket_.receive(receivePacket);
-
- return new String(receivePacket.getData(), 0, receivePacket.getLength());
- }
-
- /*** Same as
- *
- * @author Daniel F. Savarese
- * @see DiscardUDPClient
- ***/
-
-public class DiscardTCPClient extends SocketClient
-{
- /*** The default discard port. It is set to 9 according to RFC 863. ***/
- public static final int DEFAULT_PORT = 9;
-
- /***
- * The default DiscardTCPClient constructor. It merely sets the default
- * port to
- * @return An OutputStream through which you can write data to the server.
- ***/
- public OutputStream getOutputStream()
- {
- return _output_;
- }
-}
diff --git a/org/apache/commons/net/discard/DiscardUDPClient.java b/org/apache/commons/net/discard/DiscardUDPClient.java
deleted file mode 100644
index a81b955..0000000
--- a/org/apache/commons/net/discard/DiscardUDPClient.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.discard;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-import org.apache.commons.net.DatagramSocketClient;
-
-/***
- * The DiscardUDPClient class is a UDP implementation of a client for the
- * Discard protocol described in RFC 863. To use the class,
- * just open a local UDP port
- * with {@link org.apache.commons.net.DatagramSocketClient#open open }
- * and call {@link #send send } to send datagrams to the server
- * After you're done sending discard data, call
- * {@link org.apache.commons.net.DatagramSocketClient#close close() }
- * to clean up properly.
- *
- *
- * @author Daniel F. Savarese
- * @see DiscardTCPClient
- ***/
-
-public class DiscardUDPClient extends DatagramSocketClient
-{
- /*** The default discard port. It is set to 9 according to RFC 863. ***/
- public static final int DEFAULT_PORT = 9;
-
- DatagramPacket _sendPacket;
-
- public DiscardUDPClient()
- {
- _sendPacket = new DatagramPacket(new byte[0], 0);
- }
-
-
- /***
- * Sends the specified data to the specified server at the specified port.
- *
- * @param data The discard data to send.
- * @param length The length of the data to send. Should be less than
- * or equal to the length of the data byte array.
- * @param host The address of the server.
- * @param port The service port.
- * @exception IOException If an error occurs during the datagram send
- * operation.
- ***/
- public void send(byte[] data, int length, InetAddress host, int port)
- throws IOException
- {
- _sendPacket.setData(data);
- _sendPacket.setLength(length);
- _sendPacket.setAddress(host);
- _sendPacket.setPort(port);
- _socket_.send(_sendPacket);
- }
-
-
- /***
- * Same as
- *
- *
- * @author Daniel F. Savarese
- * @see EchoUDPClient
- * @see DiscardTCPClient
- ***/
-
-public final class EchoTCPClient extends DiscardTCPClient
-{
- /*** The default echo port. It is set to 7 according to RFC 862. ***/
- public static final int DEFAULT_PORT = 7;
-
- /***
- * The default EchoTCPClient constructor. It merely sets the default
- * port to
- * @return An InputStream from which you can read echoed data from the
- * server.
- ***/
- public InputStream getInputStream()
- {
- return _input_;
- }
-
-}
diff --git a/org/apache/commons/net/echo/EchoUDPClient.java b/org/apache/commons/net/echo/EchoUDPClient.java
deleted file mode 100644
index 70a4898..0000000
--- a/org/apache/commons/net/echo/EchoUDPClient.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.echo;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-import org.apache.commons.net.discard.DiscardUDPClient;
-
-/***
- * The EchoUDPClient class is a UDP implementation of a client for the
- * Echo protocol described in RFC 862. To use the class,
- * just open a local UDP port
- * with {@link org.apache.commons.net.DatagramSocketClient#open open }
- * and call {@link #send send } to send datagrams to the server,
- * then call {@link #receive receive } to receive echoes.
- * After you're done echoing data, call
- * {@link org.apache.commons.net.DatagramSocketClient#close close() }
- * to clean up properly.
- *
- *
- * @author Daniel F. Savarese
- * @see EchoTCPClient
- * @see DiscardUDPClient
- ***/
-
-public final class EchoUDPClient extends DiscardUDPClient
-{
- /*** The default echo port. It is set to 7 according to RFC 862. ***/
- public static final int DEFAULT_PORT = 7;
-
- private DatagramPacket __receivePacket = new DatagramPacket(new byte[0], 0);
-
- /***
- * Sends the specified data to the specified server at the default echo
- * port.
- *
- * @param data The echo data to send.
- * @param length The length of the data to send. Should be less than
- * or equal to the length of the data byte array.
- * @param host The address of the server.
- * @exception IOException If an error occurs during the datagram send
- * operation.
- ***/
- @Override
- public void send(byte[] data, int length, InetAddress host)
- throws IOException
- {
- send(data, length, host, DEFAULT_PORT);
- }
-
-
- /*** Same as
- * @return Length of actual data received.
- * @exception IOException If an error occurs while receiving the data.
- ***/
- public int receive(byte[] data, int length) throws IOException
- {
- __receivePacket.setData(data);
- __receivePacket.setLength(length);
- _socket_.receive(__receivePacket);
- return __receivePacket.getLength();
- }
-
- /*** Same as
- *
- * @author Daniel F. Savarese
- ***/
-
-public class FingerClient extends SocketClient
-{
- /***
- * The default FINGER port. Set to 79 according to RFC 1288.
- ***/
- public static final int DEFAULT_PORT = 79;
-
- private static final String __LONG_FLAG = "/W ";
-
- private transient StringBuffer __query = new StringBuffer(64);
- private transient char[] __buffer = new char[1024];
-
- /***
- * The default FingerClient constructor. Initializes the
- * default port to
- * @param longOutput Set to true if long output is requested, false if not.
- * @param username The name of the user to finger.
- * @return The result of the finger query.
- * @exception IOException If an I/O error occurs while reading the socket.
- ***/
- public String query(boolean longOutput, String username) throws IOException
- {
- int read;
- StringBuffer result = new StringBuffer(__buffer.length);
- BufferedReader input;
-
- input =
- new BufferedReader(new InputStreamReader(getInputStream(longOutput,
- username)));
-
- while (true)
- {
- read = input.read(__buffer, 0, __buffer.length);
- if (read <= 0)
- break;
- result.append(__buffer, 0, read);
- }
-
- input.close();
-
- return result.toString();
- }
-
-
- /***
- * Fingers the connected host and returns the output
- * as a String. You must first connect to a finger server before
- * calling this method, and you should disconnect afterward.
- * This is equivalent to calling
- * @param longOutput Set to true if long output is requested, false if not.
- * @return The result of the finger query.
- * @exception IOException If an I/O error occurs while reading the socket.
- ***/
- public String query(boolean longOutput) throws IOException
- {
- return query(longOutput, "");
- }
-
-
- /***
- * Fingers a user and returns the input stream from the network connection
- * of the finger query. You must first connect to a finger server before
- * calling this method, and you should disconnect after finishing reading
- * the stream.
- *
- * @param longOutput Set to true if long output is requested, false if not.
- * @param username The name of the user to finger.
- * @return The InputStream of the network connection of the finger query.
- * Can be read to obtain finger results.
- * @exception IOException If an I/O error during the operation.
- ***/
- public InputStream getInputStream(boolean longOutput, String username)
- throws IOException
- {
- return getInputStream(longOutput, username, null);
- }
-
- /***
- * Fingers a user and returns the input stream from the network connection
- * of the finger query. You must first connect to a finger server before
- * calling this method, and you should disconnect after finishing reading
- * the stream.
- *
- * @param longOutput Set to true if long output is requested, false if not.
- * @param username The name of the user to finger.
- * @param encoding the character encoding that should be used for the query,
- * null for the platform's default encoding
- * @return The InputStream of the network connection of the finger query.
- * Can be read to obtain finger results.
- * @exception IOException If an I/O error during the operation.
- ***/
- public InputStream getInputStream(boolean longOutput, String username, String encoding)
- throws IOException
- {
- DataOutputStream output;
-
- __query.setLength(0);
- if (longOutput)
- __query.append(__LONG_FLAG);
- __query.append(username);
- __query.append(SocketClient.NETASCII_EOL);
-
- byte[] encodedQuery =
- (encoding == null ? __query.toString().getBytes() : __query.toString().getBytes(encoding));
-
- output = new DataOutputStream(new BufferedOutputStream(_output_, 1024));
- output.write(encodedQuery, 0, encodedQuery.length);
- output.flush();
-
- return _input_;
- }
-
-
- /***
- * Fingers the connected host and returns the input stream from
- * the network connection of the finger query. This is equivalent to
- * calling getInputStream(longOutput, ""). You must first connect to a
- * finger server before calling this method, and you should disconnect
- * after finishing reading the stream.
- *
- * @param longOutput Set to true if long output is requested, false if not.
- * @return The InputStream of the network connection of the finger query.
- * Can be read to obtain finger results.
- * @exception IOException If an I/O error during the operation.
- ***/
- public InputStream getInputStream(boolean longOutput) throws IOException
- {
- return getInputStream(longOutput, "");
- }
-
-}
diff --git a/org/apache/commons/net/ftp/Configurable.class b/org/apache/commons/net/ftp/Configurable.class
deleted file mode 100644
index abcae1f..0000000
Binary files a/org/apache/commons/net/ftp/Configurable.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/Configurable.java b/org/apache/commons/net/ftp/Configurable.java
deleted file mode 100644
index 5e8e749..0000000
--- a/org/apache/commons/net/ftp/Configurable.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp;
-
-
-/**
- * This interface adds the aspect of configurability by means of
- * a supplied FTPClientConfig object to other classes in the
- * system, especially listing parsers.
- */
-public interface Configurable {
-
- /**
- * @param config the object containing the configuration data
- * @throws IllegalArgumentException if the elements of the
- *
- * To derive the full benefits of the FTP class requires some knowledge
- * of the FTP protocol defined in RFC 959. However, there is no reason
- * why you should have to use the FTP class. The
- * {@link org.apache.commons.net.ftp.FTPClient} class,
- * derived from FTP,
- * implements all the functionality required of an FTP client. The
- * FTP class is made public to provide access to various FTP constants
- * and to make it easier for adventurous programmers (or those with
- * special needs) to interact with the FTP protocol and implement their
- * own clients. A set of methods with names corresponding to the FTP
- * command names are provided to facilitate this interaction.
- *
- * You should keep in mind that the FTP server may choose to prematurely
- * close a connection if the client has been idle for longer than a
- * given time period (usually 900 seconds). The FTP class will detect a
- * premature FTP server connection closing when it receives a
- * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
- * response to a command.
- * When that occurs, the FTP class method encountering that reply will throw
- * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
- * .
- * Rather than list it separately for each method, we mention here that
- * every method communicating with the server and throwing an IOException
- * can also throw a
- * {@link org.apache.commons.net.MalformedServerReplyException}
- * , which is a subclass
- * of IOException. A MalformedServerReplyException will be thrown when
- * the reply received from the server deviates enough from the protocol
- * specification that it cannot be interpreted in a useful manner despite
- * attempts to be as lenient as possible.
- *
- *
- * @author Daniel F. Savarese
- * @author Rory Winston
- * @author Joseph Hindsley
- * @see FTPClient
- * @see FTPConnectionClosedException
- * @see org.apache.commons.net.MalformedServerReplyException
- * @version $Id: FTP.java 658520 2008-05-21 01:14:11Z sebb $
- ***/
-
-public class FTP extends SocketClient
-{
- /*** The default FTP data port (20). ***/
- public static final int DEFAULT_DATA_PORT = 20;
- /*** The default FTP control port (21). ***/
- public static final int DEFAULT_PORT = 21;
-
- /***
- * A constant used to indicate the file(s) being transfered should
- * be treated as ASCII. This is the default file type. All constants
- * ending in
- * @param listener The ProtocolCommandListener to add.
- ***/
- public void addProtocolCommandListener(ProtocolCommandListener listener)
- {
- _commandSupport_.addProtocolCommandListener(listener);
- }
-
- /***
- * Removes a ProtocolCommandListener. Delegates this task to
- * {@link #_commandSupport_ _commandSupport_ }.
- *
- * @param listener The ProtocolCommandListener to remove.
- ***/
- public void removeProtocolCommandListener(ProtocolCommandListener listener)
- {
- _commandSupport_.removeProtocolCommandListener(listener);
- }
-
-
- /***
- * Closes the control connection to the FTP server and sets to null
- * some internal data so that the memory may be reclaimed by the
- * garbage collector. The reply text and code information from the
- * last command is voided so that the memory it used may be reclaimed.
- * Also sets {@link #_controlInput_} and {@link #_controlOutput_} to null.
- *
- * @exception IOException If an error occurs while disconnecting.
- ***/
- @Override
- public void disconnect() throws IOException
- {
- super.disconnect();
- _controlInput_ = null;
- _controlOutput_ = null;
- _newReplyString = false;
- _replyString = null;
- }
-
-
- /***
- * Sends an FTP command to the server, waits for a reply and returns the
- * numerical response code. After invocation, for more detailed
- * information, the actual reply text can be accessed by calling
- * {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
- *
- * @param command The text representation of the FTP command to send.
- * @param args The arguments to the FTP command. If this parameter is
- * set to null, then the command is sent with no argument.
- * @return The integer value of the FTP reply code returned by the server
- * in response to the command.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(String command, String args) throws IOException
- {
- String message;
-
- __commandBuffer.setLength(0);
- __commandBuffer.append(command);
-
- if (args != null)
- {
- __commandBuffer.append(' ');
- __commandBuffer.append(args);
- }
- __commandBuffer.append(SocketClient.NETASCII_EOL);
-
- try{
- _controlOutput_.write(message = __commandBuffer.toString());
- _controlOutput_.flush();
- }
- catch (SocketException e)
- {
- if (!isConnected() || !socketIsConnected(_socket_))
- {
- throw new FTPConnectionClosedException("Connection unexpectedly closed.");
- }
- else
- {
- throw e;
- }
- }
-
-
- if (_commandSupport_.getListenerCount() > 0)
- _commandSupport_.fireCommandSent(command, message);
-
- __getReply();
- return _replyCode;
- }
-
- /**
- * Checks if the socket is connected
- *
- * @param socket
- * @return true if connected
- */
- private boolean socketIsConnected(Socket socket)
- {
- if (socket == null)
- {
- return false;
- }
-
- return socket.isConnected();
-
- }
-
- /***
- * Sends an FTP command to the server, waits for a reply and returns the
- * numerical response code. After invocation, for more detailed
- * information, the actual reply text can be accessed by calling
- * {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
- *
- * @param command The FTPCommand constant corresponding to the FTP command
- * to send.
- * @param args The arguments to the FTP command. If this parameter is
- * set to null, then the command is sent with no argument.
- * @return The integer value of the FTP reply code returned by the server
- * in response to the command.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(int command, String args) throws IOException
- {
- return sendCommand(FTPCommand._commands[command], args);
- }
-
-
- /***
- * Sends an FTP command with no arguments to the server, waits for a
- * reply and returns the numerical response code. After invocation, for
- * more detailed information, the actual reply text can be accessed by
- * calling {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
- *
- * @param command The text representation of the FTP command to send.
- * @return The integer value of the FTP reply code returned by the server
- * in response to the command.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(String command) throws IOException
- {
- return sendCommand(command, null);
- }
-
-
- /***
- * Sends an FTP command with no arguments to the server, waits for a
- * reply and returns the numerical response code. After invocation, for
- * more detailed information, the actual reply text can be accessed by
- * calling {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
- *
- * @param command The FTPCommand constant corresponding to the FTP command
- * to send.
- * @return The integer value of the FTP reply code returned by the server
- * in response to the command.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(int command) throws IOException
- {
- return sendCommand(command, null);
- }
-
-
- /***
- * Returns the integer value of the reply code of the last FTP reply.
- * You will usually only use this method after you connect to the
- * FTP server to check that the connection was successful since
- *
- * @return The integer value of the reply code of the last FTP reply.
- ***/
- public int getReplyCode()
- {
- return _replyCode;
- }
-
- /***
- * Fetches a reply from the FTP server and returns the integer reply
- * code. After calling this method, the actual reply text can be accessed
- * from either calling {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }. Only use this
- * method if you are implementing your own FTP client or if you need to
- * fetch a secondary response from the FTP server.
- *
- * @return The integer value of the reply code of the fetched FTP reply.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while receiving the
- * server reply.
- ***/
- public int getReply() throws IOException
- {
- __getReply();
- return _replyCode;
- }
-
-
- /***
- * Returns the lines of text from the last FTP server response as an array
- * of strings, one entry per line. The end of line markers of each are
- * stripped from each line.
- *
- * @return The lines of text from the last FTP response as an array.
- ***/
- public String[] getReplyStrings()
- {
- String[] lines;
- lines = new String[_replyLines.size()];
- _replyLines.addAll(Arrays.asList(lines));
- return lines;
- }
-
- /***
- * Returns the entire text of the last FTP server response exactly
- * as it was received, including all end of line markers in NETASCII
- * format.
- *
- * @return The entire text from the last FTP response as a String.
- ***/
- public String getReplyString()
- {
- StringBuilder buffer;
-
- if (!_newReplyString) {
- return _replyString;
- }
-
- buffer = new StringBuilder(256);
-
- for (String line : _replyLines) {
- buffer.append(line);
- buffer.append(SocketClient.NETASCII_EOL);
- }
-
- _newReplyString = false;
-
- return (_replyString = buffer.toString());
- }
-
-
- /***
- * A convenience method to send the FTP USER command to the server,
- * receive the reply, and return the reply code.
- *
- * @param username The username to login under.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int user(String username) throws IOException
- {
- return sendCommand(FTPCommand.USER, username);
- }
-
- /**
- * A convenience method to send the FTP PASS command to the server,
- * receive the reply, and return the reply code.
- * @param password The plain text password of the username being logged into.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int pass(String password) throws IOException
- {
- return sendCommand(FTPCommand.PASS, password);
- }
-
- /***
- * A convenience method to send the FTP ACCT command to the server,
- * receive the reply, and return the reply code.
- *
- * @param account The account name to access.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int acct(String account) throws IOException
- {
- return sendCommand(FTPCommand.ACCT, account);
- }
-
-
- /***
- * A convenience method to send the FTP ABOR command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int abor() throws IOException
- {
- return sendCommand(FTPCommand.ABOR);
- }
-
- /***
- * A convenience method to send the FTP CWD command to the server,
- * receive the reply, and return the reply code.
- *
- * @param directory The new working directory.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int cwd(String directory) throws IOException
- {
- return sendCommand(FTPCommand.CWD, directory);
- }
-
- /***
- * A convenience method to send the FTP CDUP command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int cdup() throws IOException
- {
- return sendCommand(FTPCommand.CDUP);
- }
-
- /***
- * A convenience method to send the FTP QUIT command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int quit() throws IOException
- {
- return sendCommand(FTPCommand.QUIT);
- }
-
- /***
- * A convenience method to send the FTP REIN command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int rein() throws IOException
- {
- return sendCommand(FTPCommand.REIN);
- }
-
- /***
- * A convenience method to send the FTP SMNT command to the server,
- * receive the reply, and return the reply code.
- *
- * @param dir The directory name.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int smnt(String dir) throws IOException
- {
- return sendCommand(FTPCommand.SMNT, dir);
- }
-
- /***
- * A convenience method to send the FTP PORT command to the server,
- * receive the reply, and return the reply code.
- *
- * @param host The host owning the port.
- * @param port The new port.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int port(InetAddress host, int port) throws IOException
- {
- int num;
- StringBuffer info = new StringBuffer(24);
-
- info.append(host.getHostAddress().replace('.', ','));
- num = port >>> 8;
- info.append(',');
- info.append(num);
- info.append(',');
- num = port & 0xff;
- info.append(num);
-
- return sendCommand(FTPCommand.PORT, info.toString());
- }
-
- /***
- * A convenience method to send the FTP PASV command to the server,
- * receive the reply, and return the reply code. Remember, it's up
- * to you to interpret the reply string containing the host/port
- * information.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int pasv() throws IOException
- {
- return sendCommand(FTPCommand.PASV);
- }
-
- /**
- * A convenience method to send the FTP TYPE command for text files
- * to the server, receive the reply, and return the reply code.
- * @param fileType The type of the file (one of the
- * @param fileType The type of the file (one of the
- * @param structure The structure of the file (one of the
- *
- * @param mode The transfer mode to use (one of the
- *
- * @param pathname The pathname of the file to retrieve.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int retr(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.RETR, pathname);
- }
-
- /***
- * A convenience method to send the FTP STOR command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
- *
- * @param pathname The pathname to use for the file when stored at
- * the remote end of the transfer.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int stor(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.STOR, pathname);
- }
-
- /***
- * A convenience method to send the FTP STOU command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int stou() throws IOException
- {
- return sendCommand(FTPCommand.STOU);
- }
-
- /***
- * A convenience method to send the FTP STOU command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
- * @param pathname The base pathname to use for the file when stored at
- * the remote end of the transfer. Some FTP servers
- * require this.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int stou(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.STOU, pathname);
- }
-
- /***
- * A convenience method to send the FTP APPE command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
- *
- * @param pathname The pathname to use for the file when stored at
- * the remote end of the transfer.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int appe(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.APPE, pathname);
- }
-
- /***
- * A convenience method to send the FTP ALLO command to the server,
- * receive the reply, and return the reply code.
- *
- * @param bytes The number of bytes to allocate.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int allo(int bytes) throws IOException
- {
- return sendCommand(FTPCommand.ALLO, Integer.toString(bytes));
- }
-
- /***
- * A convenience method to send the FTP ALLO command to the server,
- * receive the reply, and return the reply code.
- *
- * @param bytes The number of bytes to allocate.
- * @param recordSize The size of a record.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int allo(int bytes, int recordSize) throws IOException
- {
- return sendCommand(FTPCommand.ALLO, Integer.toString(bytes) + " R " +
- Integer.toString(recordSize));
- }
-
- /***
- * A convenience method to send the FTP REST command to the server,
- * receive the reply, and return the reply code.
- *
- * @param marker The marker at which to restart a transfer.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int rest(String marker) throws IOException
- {
- return sendCommand(FTPCommand.REST, marker);
- }
-
-
- /**
- * @since 2.0
- **/
- public int mdtm(String file) throws IOException
- {
- return sendCommand(FTPCommand.MDTM, file);
- }
-
- /***
- * A convenience method to send the FTP RNFR command to the server,
- * receive the reply, and return the reply code.
- *
- * @param pathname The pathname to rename from.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int rnfr(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.RNFR, pathname);
- }
-
- /***
- * A convenience method to send the FTP RNTO command to the server,
- * receive the reply, and return the reply code.
- *
- * @param pathname The pathname to rename to
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int rnto(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.RNTO, pathname);
- }
-
- /***
- * A convenience method to send the FTP DELE command to the server,
- * receive the reply, and return the reply code.
- *
- * @param pathname The pathname to delete.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int dele(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.DELE, pathname);
- }
-
- /***
- * A convenience method to send the FTP RMD command to the server,
- * receive the reply, and return the reply code.
- *
- * @param pathname The pathname of the directory to remove.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int rmd(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.RMD, pathname);
- }
-
- /***
- * A convenience method to send the FTP MKD command to the server,
- * receive the reply, and return the reply code.
- *
- * @param pathname The pathname of the new directory to create.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int mkd(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.MKD, pathname);
- }
-
- /***
- * A convenience method to send the FTP PWD command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int pwd() throws IOException
- {
- return sendCommand(FTPCommand.PWD);
- }
-
- /***
- * A convenience method to send the FTP LIST command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int list() throws IOException
- {
- return sendCommand(FTPCommand.LIST);
- }
-
- /***
- * A convenience method to send the FTP LIST command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
- *
- * @param pathname The pathname to list.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int list(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.LIST, pathname);
- }
-
- /***
- * A convenience method to send the FTP NLST command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int nlst() throws IOException
- {
- return sendCommand(FTPCommand.NLST);
- }
-
- /***
- * A convenience method to send the FTP NLST command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
- *
- * @param pathname The pathname to list.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int nlst(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.NLST, pathname);
- }
-
- /***
- * A convenience method to send the FTP SITE command to the server,
- * receive the reply, and return the reply code.
- *
- * @param parameters The site parameters to send.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int site(String parameters) throws IOException
- {
- return sendCommand(FTPCommand.SITE, parameters);
- }
-
- /***
- * A convenience method to send the FTP SYST command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int syst() throws IOException
- {
- return sendCommand(FTPCommand.SYST);
- }
-
- /***
- * A convenience method to send the FTP STAT command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int stat() throws IOException
- {
- return sendCommand(FTPCommand.STAT);
- }
-
- /***
- * A convenience method to send the FTP STAT command to the server,
- * receive the reply, and return the reply code.
- *
- * @param pathname A pathname to list.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int stat(String pathname) throws IOException
- {
- return sendCommand(FTPCommand.STAT, pathname);
- }
-
- /***
- * A convenience method to send the FTP HELP command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int help() throws IOException
- {
- return sendCommand(FTPCommand.HELP);
- }
-
- /***
- * A convenience method to send the FTP HELP command to the server,
- * receive the reply, and return the reply code.
- *
- * @param command The command name on which to request help.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int help(String command) throws IOException
- {
- return sendCommand(FTPCommand.HELP, command);
- }
-
- /***
- * A convenience method to send the FTP NOOP command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int noop() throws IOException
- {
- return sendCommand(FTPCommand.NOOP);
- }
-
- /**
- * Return whether strict multiline parsing is enabled, as per RFX 959, section 4.2.
- * @return True if strict, false if lenient
- * @since 2.0
- */
- public boolean isStrictMultilineParsing() {
- return strictMultilineParsing;
- }
-
- /**
- * Set strict multiline parsing.
- * @param strictMultilineParsing
- * @since 2.0
- */
- public void setStrictMultilineParsing(boolean strictMultilineParsing) {
- this.strictMultilineParsing = strictMultilineParsing;
- }
-}
-
-/* Emacs configuration
- * Local variables: **
- * mode: java **
- * c-basic-offset: 4 **
- * indent-tabs-mode: nil **
- * End: **
- */
diff --git a/org/apache/commons/net/ftp/FTPClient.class b/org/apache/commons/net/ftp/FTPClient.class
deleted file mode 100644
index 60ac793..0000000
Binary files a/org/apache/commons/net/ftp/FTPClient.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/FTPClient.java b/org/apache/commons/net/ftp/FTPClient.java
deleted file mode 100644
index 9a2c459..0000000
--- a/org/apache/commons/net/ftp/FTPClient.java
+++ /dev/null
@@ -1,2447 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.util.ArrayList;
-
-import org.apache.commons.net.MalformedServerReplyException;
-import org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory;
-import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
-import org.apache.commons.net.ftp.parser.ParserInitializationException;
-import org.apache.commons.net.io.CopyStreamEvent;
-import org.apache.commons.net.io.CopyStreamException;
-import org.apache.commons.net.io.FromNetASCIIInputStream;
-import org.apache.commons.net.io.ToNetASCIIOutputStream;
-import org.apache.commons.net.io.Util;
-
-/***
- * FTPClient encapsulates all the functionality necessary to store and
- * retrieve files from an FTP server. This class takes care of all
- * low level details of interacting with an FTP server and provides
- * a convenient higher level interface. As with all classes derived
- * from {@link org.apache.commons.net.SocketClient},
- * you must first connect to the server with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * before doing anything, and finally
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * after you're completely finished interacting with the server.
- * Then you need to check the FTP reply code to see if the connection
- * was successful. For example:
- *
- * Immediately after connecting is the only real time you need to check the
- * reply code (because connect is of type void). The convention for all the
- * FTP command methods in FTPClient is such that they either return a
- * boolean value or some other value.
- * The boolean methods return true on a successful completion reply from
- * the FTP server and false on a reply resulting in an error condition or
- * failure. The methods returning a value other than boolean return a value
- * containing the higher level data produced by the FTP command, or null if a
- * reply resulted in an error condition or failure. If you want to access
- * the exact FTP reply code causing a success or failure, you must call
- * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode } after
- * a success or failure.
- *
- * The default settings for FTPClient are for it to use
- *
- *
- * Because the handling of sockets on different platforms can differ
- * significantly, the FTPClient automatically issues a new PORT command
- * prior to every transfer requiring that the server connect to the client's
- * data port. This ensures identical problem-free behavior on Windows, Unix,
- * and Macintosh platforms. Additionally, it relieves programmers from
- * having to issue the PORT command themselves and dealing with platform
- * dependent issues.
- *
- * Additionally, for security purposes, all data connections to the
- * client are verified to ensure that they originated from the intended
- * party (host and port). If a data connection is initiated by an unexpected
- * party, the command will close the socket and throw an IOException. You
- * may disable this behavior with
- * {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}.
- *
- * You should keep in mind that the FTP server may choose to prematurely
- * close a connection if the client has been idle for longer than a
- * given time period (usually 900 seconds). The FTPClient class will detect a
- * premature FTP server connection closing when it receives a
- * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
- * response to a command.
- * When that occurs, the FTP class method encountering that reply will throw
- * an {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
- * .
- *
- * Rather than list it separately for each method, we mention here that
- * every method communicating with the server and throwing an IOException
- * can also throw a
- * {@link org.apache.commons.net.MalformedServerReplyException}
- * , which is a subclass
- * of IOException. A MalformedServerReplyException will be thrown when
- * the reply received from the server deviates enough from the protocol
- * specification that it cannot be interpreted in a useful manner despite
- * attempts to be as lenient as possible.
- *
- * Listing API Examples
- * Both paged and unpaged examples of directory listings are available,
- * as follows:
- *
- * Unpaged (whole list) access, using a parser accessible by auto-detect:
- *
- * Paged access, using a parser not accessible by auto-detect. The class
- * defined in the first parameter of initateListParsing should be derived
- * from org.apache.commons.net.FTPFileEntryParser:
- *
- * Paged access, using a parser accessible by auto-detect:
- *
- * For examples of using FTPClient on servers whose directory listings
- *
- * @author Daniel F. Savarese
- * @author Rory Winston
- * @see FTP
- * @see FTPConnectionClosedException
- * @see FTPFileEntryParser
- * @see FTPFileEntryParserFactory
- * @see DefaultFTPFileEntryParserFactory
- * @see FTPClientConfig
- *
- * @see org.apache.commons.net.MalformedServerReplyException
- **/
-public class FTPClient extends FTP
-implements Configurable
-{
- /***
- * A constant indicating the FTP session is expecting all transfers
- * to occur between the client (local) and server and that the server
- * should connect to the client's data port to initiate a data transfer.
- * This is the default data connection mode when and FTPClient instance
- * is created.
- ***/
- public static final int ACTIVE_LOCAL_DATA_CONNECTION_MODE = 0;
- /***
- * A constant indicating the FTP session is expecting all transfers
- * to occur between two remote servers and that the server
- * the client is connected to should connect to the other server's
- * data port to initiate a data transfer.
- ***/
- public static final int ACTIVE_REMOTE_DATA_CONNECTION_MODE = 1;
- /***
- * A constant indicating the FTP session is expecting all transfers
- * to occur between the client (local) and server and that the server
- * is in passive mode, requiring the client to connect to the
- * server's data port to initiate a transfer.
- ***/
- public static final int PASSIVE_LOCAL_DATA_CONNECTION_MODE = 2;
- /***
- * A constant indicating the FTP session is expecting all transfers
- * to occur between two remote servers and that the server
- * the client is connected to is in passive mode, requiring the other
- * server to connect to the first server's data port to initiate a data
- * transfer.
- ***/
- public static final int PASSIVE_REMOTE_DATA_CONNECTION_MODE = 3;
-
- private int __dataConnectionMode, __dataTimeout;
- private int __passivePort;
- private String __passiveHost;
- private int __fileType, __fileFormat, __fileStructure, __fileTransferMode;
- private boolean __remoteVerificationEnabled;
- private long __restartOffset;
- private FTPFileEntryParserFactory __parserFactory;
- private int __bufferSize;
- private boolean __listHiddenFiles;
-
- // __systemName is a cached value that should not be referenced directly
- // except when assigned in getSystemName and __initDefaults.
- private String __systemName;
-
- // __entryParser is a cached value that should not be referenced directly
- // except when assigned in listFiles(String, String) and __initDefaults.
- private FTPFileEntryParser __entryParser;
-
- private FTPClientConfig __configuration;
-
- /** Pattern for PASV mode responses */
- private static String __parms = "\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}";
- private static java.util.regex.Pattern __parms_pat;
- static {
- __parms_pat = java.util.regex.Pattern.compile(__parms);
- }
-
- /***
- * Default FTPClient constructor. Creates a new FTPClient instance
- * with the data connection mode set to
- *
- * @param command The text representation of the FTP command to send.
- * @param arg The arguments to the FTP command. If this parameter is
- * set to null, then the command is sent with no argument.
- * @return A Socket corresponding to the established data connection.
- * Null is returned if an FTP protocol error is reported at
- * any point during the establishment and initialization of
- * the connection.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- */
- protected Socket _openDataConnection_(int command, String arg)
- throws IOException
- {
- Socket socket;
-
- if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE &&
- __dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE)
- return null;
-
- if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE)
- {
- ServerSocket server;
- server = _serverSocketFactory_.createServerSocket(0, 1, getLocalAddress());
-
- if (!FTPReply.isPositiveCompletion(port(getLocalAddress(),
- server.getLocalPort())))
- {
- server.close();
- return null;
- }
-
- if ((__restartOffset > 0) && !restart(__restartOffset))
- {
- server.close();
- return null;
- }
-
- if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
- {
- server.close();
- return null;
- }
-
- // For now, let's just use the data timeout value for waiting for
- // the data connection. It may be desirable to let this be a
- // separately configurable value. In any case, we really want
- // to allow preventing the accept from blocking indefinitely.
- if (__dataTimeout >= 0)
- server.setSoTimeout(__dataTimeout);
- try {
- socket = server.accept();
- } finally {
- server.close();
- }
- }
- else
- { // We must be in PASSIVE_LOCAL_DATA_CONNECTION_MODE
-
- if (pasv() != FTPReply.ENTERING_PASSIVE_MODE)
- return null;
-
- __parsePassiveModeReply(_replyLines.get(_replyLines.size() - 1));
-
- socket = _socketFactory_.createSocket(__passiveHost, __passivePort);
- if ((__restartOffset > 0) && !restart(__restartOffset))
- {
- socket.close();
- return null;
- }
-
- if (!FTPReply.isPositivePreliminary(sendCommand(command, arg)))
- {
- socket.close();
- return null;
- }
- }
-
- if (__remoteVerificationEnabled && !verifyRemote(socket))
- {
- InetAddress host1, host2;
-
- host1 = socket.getInetAddress();
- host2 = getRemoteAddress();
-
- socket.close();
-
- throw new IOException(
- "Host attempting data connection " + host1.getHostAddress() +
- " is not same as server " + host2.getHostAddress());
- }
-
- if (__dataTimeout >= 0)
- socket.setSoTimeout(__dataTimeout);
-
- return socket;
- }
-
-
- @Override
- protected void _connectAction_() throws IOException
- {
- super._connectAction_();
- __initDefaults();
- }
-
-
- /***
- * Sets the timeout in milliseconds to use when reading from the
- * data connection. This timeout will be set immediately after
- * opening the data connection.
- *
- * @param timeout The default timeout in milliseconds that is used when
- * opening a data connection socket.
- ***/
- public void setDataTimeout(int timeout)
- {
- __dataTimeout = timeout;
- }
-
- /**
- * set the factory used for parser creation to the supplied factory object.
- *
- * @param parserFactory
- * factory object used to create FTPFileEntryParsers
- *
- * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
- * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
- */
- public void setParserFactory(FTPFileEntryParserFactory parserFactory) {
- __parserFactory = parserFactory;
- }
-
-
- /***
- * Closes the connection to the FTP server and restores
- * connection parameters to the default values.
- *
- * @exception IOException If an error occurs while disconnecting.
- ***/
- @Override
- public void disconnect() throws IOException
- {
- super.disconnect();
- __initDefaults();
- }
-
-
- /***
- * Enable or disable verification that the remote host taking part
- * of a data connection is the same as the host to which the control
- * connection is attached. The default is for verification to be
- * enabled. You may set this value at any time, whether the
- * FTPClient is currently connected or not.
- *
- * @param enable True to enable verification, false to disable verification.
- ***/
- public void setRemoteVerificationEnabled(boolean enable)
- {
- __remoteVerificationEnabled = enable;
- }
-
- /***
- * Return whether or not verification of the remote host participating
- * in data connections is enabled. The default behavior is for
- * verification to be enabled.
- *
- * @return True if verification is enabled, false if not.
- ***/
- public boolean isRemoteVerificationEnabled()
- {
- return __remoteVerificationEnabled;
- }
-
- /***
- * Login to the FTP server using the provided username and password.
- *
- * @param username The username to login under.
- * @param password The password to use.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean login(String username, String password) throws IOException
- {
- user(username);
-
- if (FTPReply.isPositiveCompletion(_replyCode))
- return true;
-
- // If we get here, we either have an error code, or an intermmediate
- // reply requesting password.
- if (!FTPReply.isPositiveIntermediate(_replyCode))
- return false;
-
- return FTPReply.isPositiveCompletion(pass(password));
- }
-
-
- /***
- * Login to the FTP server using the provided username, password,
- * and account. If no account is required by the server, only
- * the username and password, the account information is not used.
- *
- * @param username The username to login under.
- * @param password The password to use.
- * @param account The account to use.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean login(String username, String password, String account)
- throws IOException
- {
- user(username);
-
- if (FTPReply.isPositiveCompletion(_replyCode))
- return true;
-
- // If we get here, we either have an error code, or an intermmediate
- // reply requesting password.
- if (!FTPReply.isPositiveIntermediate(_replyCode))
- return false;
-
- pass(password);
-
- if (FTPReply.isPositiveCompletion(_replyCode))
- return true;
-
- if (!FTPReply.isPositiveIntermediate(_replyCode))
- return false;
-
- return FTPReply.isPositiveCompletion(acct(account));
- }
-
- /***
- * Logout of the FTP server by sending the QUIT command.
- *
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean logout() throws IOException
- {
- return FTPReply.isPositiveCompletion(quit());
- }
-
-
- /***
- * Change the current working directory of the FTP session.
- *
- * @param pathname The new current working directory.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean changeWorkingDirectory(String pathname) throws IOException
- {
- return FTPReply.isPositiveCompletion(cwd(pathname));
- }
-
-
- /***
- * Change to the parent directory of the current working directory.
- *
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean changeToParentDirectory() throws IOException
- {
- return FTPReply.isPositiveCompletion(cdup());
- }
-
-
- /***
- * Issue the FTP SMNT command.
- *
- * @param pathname The pathname to mount.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean structureMount(String pathname) throws IOException
- {
- return FTPReply.isPositiveCompletion(smnt(pathname));
- }
-
- /***
- * Reinitialize the FTP session. Not all FTP servers support this
- * command, which issues the FTP REIN command.
- *
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- boolean reinitialize() throws IOException
- {
- rein();
-
- if (FTPReply.isPositiveCompletion(_replyCode) ||
- (FTPReply.isPositivePreliminary(_replyCode) &&
- FTPReply.isPositiveCompletion(getReply())))
- {
-
- __initDefaults();
-
- return true;
- }
-
- return false;
- }
-
-
- /***
- * Set the current data connection mode to
- *
- * @param host The passive mode server accepting connections for data
- * transfers.
- * @param port The passive mode server's data port.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean enterRemoteActiveMode(InetAddress host, int port)
- throws IOException
- {
- if (FTPReply.isPositiveCompletion(port(host, port)))
- {
- __dataConnectionMode = ACTIVE_REMOTE_DATA_CONNECTION_MODE;
- __passiveHost = null;
- __passivePort = -1;
- return true;
- }
- return false;
- }
-
- /***
- * Set the current data connection mode to
- *
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean enterRemotePassiveMode() throws IOException
- {
- if (pasv() != FTPReply.ENTERING_PASSIVE_MODE)
- return false;
-
- __dataConnectionMode = PASSIVE_REMOTE_DATA_CONNECTION_MODE;
- __parsePassiveModeReply(_replyLines.get(0));
-
- return true;
- }
-
- /***
- * Returns the hostname or IP address (in the form of a string) returned
- * by the server when entering passive mode. If not in passive mode,
- * returns null. This method only returns a valid value AFTER a
- * data connection has been opened after a call to
- * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
- * This is because FTPClient sends a PASV command to the server only
- * just before opening a data connection, and not when you call
- * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
- *
- * @return The passive host name if in passive mode, otherwise null.
- ***/
- public String getPassiveHost()
- {
- return __passiveHost;
- }
-
- /***
- * If in passive mode, returns the data port of the passive host.
- * This method only returns a valid value AFTER a
- * data connection has been opened after a call to
- * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
- * This is because FTPClient sends a PASV command to the server only
- * just before opening a data connection, and not when you call
- * {@link #enterLocalPassiveMode enterLocalPassiveMode()}.
- *
- * @return The data port of the passive server. If not in passive
- * mode, undefined.
- ***/
- public int getPassivePort()
- {
- return __passivePort;
- }
-
-
- /***
- * Returns the current data connection mode (one of the
- *
- * @return The current data connection mode (one of the
- *
- * @param fileType The
- * @param fileType The
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean setFileType(int fileType, int formatOrByteSize)
- throws IOException
- {
- if (FTPReply.isPositiveCompletion(type(fileType, formatOrByteSize)))
- {
- __fileType = fileType;
- __fileFormat = formatOrByteSize;
- return true;
- }
- return false;
- }
-
-
- /***
- * Sets the file structure. The default structure is
- *
- * @param structure The structure of the file (one of the FTP class
- *
- * @param mode The new transfer mode to use (one of the FTP class
- *
- * @param filename The name of the file to retrieve.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean remoteRetrieve(String filename) throws IOException
- {
- if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
- __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
- return FTPReply.isPositivePreliminary(retr(filename));
- return false;
- }
-
-
- /***
- * Initiate a server to server file transfer. This method tells the
- * server to which the client is connected to store a file on
- * the other server using the given filename. The other server must
- * have had a
- * @param filename The name to call the file that is to be stored.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean remoteStore(String filename) throws IOException
- {
- if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
- __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
- return FTPReply.isPositivePreliminary(stor(filename));
- return false;
- }
-
-
- /***
- * Initiate a server to server file transfer. This method tells the
- * server to which the client is connected to store a file on
- * the other server using a unique filename based on the given filename.
- * The other server must have had a
- * @param filename The name on which to base the filename of the file
- * that is to be stored.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean remoteStoreUnique(String filename) throws IOException
- {
- if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
- __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
- return FTPReply.isPositivePreliminary(stou(filename));
- return false;
- }
-
-
- /***
- * Initiate a server to server file transfer. This method tells the
- * server to which the client is connected to store a file on
- * the other server using a unique filename.
- * The other server must have had a
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean remoteStoreUnique() throws IOException
- {
- if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
- __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
- return FTPReply.isPositivePreliminary(stou());
- return false;
- }
-
- // For server to server transfers
- /***
- * Initiate a server to server file transfer. This method tells the
- * server to which the client is connected to append to a given file on
- * the other server. The other server must have had a
- *
- * @param filename The name of the file to be appended to, or if the
- * file does not exist, the name to call the file being stored.
- *
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean remoteAppend(String filename) throws IOException
- {
- if (__dataConnectionMode == ACTIVE_REMOTE_DATA_CONNECTION_MODE ||
- __dataConnectionMode == PASSIVE_REMOTE_DATA_CONNECTION_MODE)
- return FTPReply.isPositivePreliminary(stor(filename));
- return false;
- }
-
- /***
- * There are a few FTPClient methods that do not complete the
- * entire sequence of FTP commands to complete a transaction. These
- * commands require some action by the programmer after the reception
- * of a positive intermediate command. After the programmer's code
- * completes its actions, it must call this method to receive
- * the completion reply from the server and verify the success of the
- * entire transaction.
- *
- * For example,
- *
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean completePendingCommand() throws IOException
- {
- return FTPReply.isPositiveCompletion(getReply());
- }
-
-
- /***
- * Retrieves a named file from the server and writes it to the given
- * OutputStream. This method does NOT close the given OutputStream.
- * If the current file type is ASCII, line separators in the file are
- * converted to the local representation.
- *
- * @param remote The name of the remote file.
- * @param local The local OutputStream to which to write the file.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception CopyStreamException If an I/O error occurs while actually
- * transferring the file. The CopyStreamException allows you to
- * determine the number of bytes transferred and the IOException
- * causing the error. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean retrieveFile(String remote, OutputStream local)
- throws IOException
- {
- InputStream input;
- Socket socket;
-
- if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null)
- return false;
-
- input = new BufferedInputStream(socket.getInputStream(),
- getBufferSize());
- if (__fileType == ASCII_FILE_TYPE)
- input = new FromNetASCIIInputStream(input);
- // Treat everything else as binary for now
- try
- {
- Util.copyStream(input, local, getBufferSize(),
- CopyStreamEvent.UNKNOWN_STREAM_SIZE, null,
- false);
- }
- catch (IOException e)
- {
- try
- {
- socket.close();
- }
- catch (IOException f)
- {}
- throw e;
- }
- socket.close();
- return completePendingCommand();
- }
-
- /***
- * Returns an InputStream from which a named file from the server
- * can be read. If the current file type is ASCII, the returned
- * InputStream will convert line separators in the file to
- * the local representation. You must close the InputStream when you
- * finish reading from it. The InputStream itself will take care of
- * closing the parent data connection socket upon being closed. To
- * finalize the file transfer you must call
- * {@link #completePendingCommand completePendingCommand } and
- * check its return value to verify success.
- *
- * @param remote The name of the remote file.
- * @return An InputStream from which the remote file can be read. If
- * the data connection cannot be opened (e.g., the file does not
- * exist), null is returned (in which case you may check the reply
- * code to determine the exact reason for failure).
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public InputStream retrieveFileStream(String remote) throws IOException
- {
- InputStream input;
- Socket socket;
-
- if ((socket = _openDataConnection_(FTPCommand.RETR, remote)) == null)
- return null;
-
- input = socket.getInputStream();
- if (__fileType == ASCII_FILE_TYPE) {
- // We buffer ascii transfers because the buffering has to
- // be interposed between FromNetASCIIOutputSream and the underlying
- // socket input stream. We don't buffer binary transfers
- // because we don't want to impose a buffering policy on the
- // programmer if possible. Programmers can decide on their
- // own if they want to wrap the SocketInputStream we return
- // for file types other than ASCII.
- input = new BufferedInputStream(input,
- getBufferSize());
- input = new FromNetASCIIInputStream(input);
- }
- return new org.apache.commons.net.io.SocketInputStream(socket, input);
- }
-
-
- /***
- * Stores a file on the server using the given name and taking input
- * from the given InputStream. This method does NOT close the given
- * InputStream. If the current file type is ASCII, line separators in
- * the file are transparently converted to the NETASCII format (i.e.,
- * you should not attempt to create a special InputStream to do this).
- *
- * @param remote The name to give the remote file.
- * @param local The local InputStream from which to read the file.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception CopyStreamException If an I/O error occurs while actually
- * transferring the file. The CopyStreamException allows you to
- * determine the number of bytes transferred and the IOException
- * causing the error. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean storeFile(String remote, InputStream local)
- throws IOException
- {
- return __storeFile(FTPCommand.STOR, remote, local);
- }
-
-
- /***
- * Returns an OutputStream through which data can be written to store
- * a file on the server using the given name. If the current file type
- * is ASCII, the returned OutputStream will convert line separators in
- * the file to the NETASCII format (i.e., you should not attempt to
- * create a special OutputStream to do this). You must close the
- * OutputStream when you finish writing to it. The OutputStream itself
- * will take care of closing the parent data connection socket upon being
- * closed. To finalize the file transfer you must call
- * {@link #completePendingCommand completePendingCommand } and
- * check its return value to verify success.
- *
- * @param remote The name to give the remote file.
- * @return An OutputStream through which the remote file can be written. If
- * the data connection cannot be opened (e.g., the file does not
- * exist), null is returned (in which case you may check the reply
- * code to determine the exact reason for failure).
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public OutputStream storeFileStream(String remote) throws IOException
- {
- return __storeFileStream(FTPCommand.STOR, remote);
- }
-
- /***
- * Appends to a file on the server with the given name, taking input
- * from the given InputStream. This method does NOT close the given
- * InputStream. If the current file type is ASCII, line separators in
- * the file are transparently converted to the NETASCII format (i.e.,
- * you should not attempt to create a special InputStream to do this).
- *
- * @param remote The name of the remote file.
- * @param local The local InputStream from which to read the data to
- * be appended to the remote file.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception CopyStreamException If an I/O error occurs while actually
- * transferring the file. The CopyStreamException allows you to
- * determine the number of bytes transferred and the IOException
- * causing the error. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean appendFile(String remote, InputStream local)
- throws IOException
- {
- return __storeFile(FTPCommand.APPE, remote, local);
- }
-
- /***
- * Returns an OutputStream through which data can be written to append
- * to a file on the server with the given name. If the current file type
- * is ASCII, the returned OutputStream will convert line separators in
- * the file to the NETASCII format (i.e., you should not attempt to
- * create a special OutputStream to do this). You must close the
- * OutputStream when you finish writing to it. The OutputStream itself
- * will take care of closing the parent data connection socket upon being
- * closed. To finalize the file transfer you must call
- * {@link #completePendingCommand completePendingCommand } and
- * check its return value to verify success.
- *
- * @param remote The name of the remote file.
- * @return An OutputStream through which the remote file can be appended.
- * If the data connection cannot be opened (e.g., the file does not
- * exist), null is returned (in which case you may check the reply
- * code to determine the exact reason for failure).
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public OutputStream appendFileStream(String remote) throws IOException
- {
- return __storeFileStream(FTPCommand.APPE, remote);
- }
-
- /***
- * Stores a file on the server using a unique name derived from the
- * given name and taking input
- * from the given InputStream. This method does NOT close the given
- * InputStream. If the current file type is ASCII, line separators in
- * the file are transparently converted to the NETASCII format (i.e.,
- * you should not attempt to create a special InputStream to do this).
- *
- * @param remote The name on which to base the unique name given to
- * the remote file.
- * @param local The local InputStream from which to read the file.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception CopyStreamException If an I/O error occurs while actually
- * transferring the file. The CopyStreamException allows you to
- * determine the number of bytes transferred and the IOException
- * causing the error. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean storeUniqueFile(String remote, InputStream local)
- throws IOException
- {
- return __storeFile(FTPCommand.STOU, remote, local);
- }
-
-
- /***
- * Returns an OutputStream through which data can be written to store
- * a file on the server using a unique name derived from the given name.
- * If the current file type
- * is ASCII, the returned OutputStream will convert line separators in
- * the file to the NETASCII format (i.e., you should not attempt to
- * create a special OutputStream to do this). You must close the
- * OutputStream when you finish writing to it. The OutputStream itself
- * will take care of closing the parent data connection socket upon being
- * closed. To finalize the file transfer you must call
- * {@link #completePendingCommand completePendingCommand } and
- * check its return value to verify success.
- *
- * @param remote The name on which to base the unique name given to
- * the remote file.
- * @return An OutputStream through which the remote file can be written. If
- * the data connection cannot be opened (e.g., the file does not
- * exist), null is returned (in which case you may check the reply
- * code to determine the exact reason for failure).
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public OutputStream storeUniqueFileStream(String remote) throws IOException
- {
- return __storeFileStream(FTPCommand.STOU, remote);
- }
-
- /**
- * Stores a file on the server using a unique name assigned by the
- * server and taking input from the given InputStream. This method does
- * NOT close the given
- * InputStream. If the current file type is ASCII, line separators in
- * the file are transparently converted to the NETASCII format (i.e.,
- * you should not attempt to create a special InputStream to do this).
- *
- * @param local The local InputStream from which to read the file.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception CopyStreamException If an I/O error occurs while actually
- * transferring the file. The CopyStreamException allows you to
- * determine the number of bytes transferred and the IOException
- * causing the error. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- */
- public boolean storeUniqueFile(InputStream local) throws IOException
- {
- return __storeFile(FTPCommand.STOU, null, local);
- }
-
- /**
- * Returns an OutputStream through which data can be written to store
- * a file on the server using a unique name assigned by the server.
- * If the current file type
- * is ASCII, the returned OutputStream will convert line separators in
- * the file to the NETASCII format (i.e., you should not attempt to
- * create a special OutputStream to do this). You must close the
- * OutputStream when you finish writing to it. The OutputStream itself
- * will take care of closing the parent data connection socket upon being
- * closed. To finalize the file transfer you must call
- * {@link #completePendingCommand completePendingCommand } and
- * check its return value to verify success.
- *
- * @return An OutputStream through which the remote file can be written. If
- * the data connection cannot be opened (e.g., the file does not
- * exist), null is returned (in which case you may check the reply
- * code to determine the exact reason for failure).
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- */
- public OutputStream storeUniqueFileStream() throws IOException
- {
- return __storeFileStream(FTPCommand.STOU, null);
- }
-
- /***
- * Reserve a number of bytes on the server for the next file transfer.
- *
- * @param bytes The number of bytes which the server should allocate.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean allocate(int bytes) throws IOException
- {
- return FTPReply.isPositiveCompletion(allo(bytes));
- }
-
-
- /**
- * Reserve space on the server for the next file transfer.
- *
- * @param bytes The number of bytes which the server should allocate.
- * @param recordSize The size of a file record.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- */
- public boolean allocate(int bytes, int recordSize) throws IOException
- {
- return FTPReply.isPositiveCompletion(allo(bytes, recordSize));
- }
-
-
- /***
- * Restart a
- * @param offset The offset into the remote file at which to start the
- * next file transfer.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- private boolean restart(long offset) throws IOException
- {
- __restartOffset = 0;
- return FTPReply.isPositiveIntermediate(rest(Long.toString(offset)));
- }
-
- /***
- * Sets the restart offset. The restart command is sent to the server
- * only before sending the file transfer command. When this is done,
- * the restart marker is reset to zero.
- *
- * @param offset The offset into the remote file at which to start the
- * next file transfer. This must be a value greater than or
- * equal to zero.
- ***/
- public void setRestartOffset(long offset)
- {
- if (offset >= 0)
- __restartOffset = offset;
- }
-
- /***
- * Fetches the restart offset.
- *
- * @return offset The offset into the remote file at which to start the
- * next file transfer.
- ***/
- public long getRestartOffset()
- {
- return __restartOffset;
- }
-
-
-
- /***
- * Renames a remote file.
- *
- * @param from The name of the remote file to rename.
- * @param to The new name of the remote file.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean rename(String from, String to) throws IOException
- {
- if (!FTPReply.isPositiveIntermediate(rnfr(from)))
- return false;
-
- return FTPReply.isPositiveCompletion(rnto(to));
- }
-
-
- /***
- * Abort a transfer in progress.
- *
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean abort() throws IOException
- {
- return FTPReply.isPositiveCompletion(abor());
- }
-
- /***
- * Deletes a file on the FTP server.
- *
- * @param pathname The pathname of the file to be deleted.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean deleteFile(String pathname) throws IOException
- {
- return FTPReply.isPositiveCompletion(dele(pathname));
- }
-
-
- /***
- * Removes a directory on the FTP server (if empty).
- *
- * @param pathname The pathname of the directory to remove.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean removeDirectory(String pathname) throws IOException
- {
- return FTPReply.isPositiveCompletion(rmd(pathname));
- }
-
-
- /***
- * Creates a new subdirectory on the FTP server in the current directory
- * (if a relative pathname is given) or where specified (if an absolute
- * pathname is given).
- *
- * @param pathname The pathname of the directory to create.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean makeDirectory(String pathname) throws IOException
- {
- return FTPReply.isPositiveCompletion(mkd(pathname));
- }
-
-
- /***
- * Returns the pathname of the current working directory.
- *
- * @return The pathname of the current working directory. If it cannot
- * be obtained, returns null.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String printWorkingDirectory() throws IOException
- {
- if (pwd() != FTPReply.PATHNAME_CREATED)
- return null;
-
- return __parsePathname(_replyLines.get( _replyLines.size() - 1));
- }
-
-
- /**
- * Send a site specific command.
- * @param arguments The site specific command and arguments.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- */
- public boolean sendSiteCommand(String arguments) throws IOException
- {
- return FTPReply.isPositiveCompletion(site(arguments));
- }
-
-
- /***
- * Fetches the system type name from the server and returns the string.
- * This value is cached for the duration of the connection after the
- * first call to this method. In other words, only the first time
- * that you invoke this method will it issue a SYST command to the
- * FTP server. FTPClient will remember the value and return the
- * cached value until a call to disconnect.
- *
- * @return The system type name obtained from the server. null if the
- * information could not be obtained.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String getSystemName() throws IOException
- {
- //if (syst() == FTPReply.NAME_SYSTEM_TYPE)
- // Technically, we should expect a NAME_SYSTEM_TYPE response, but
- // in practice FTP servers deviate, so we soften the condition to
- // a positive completion.
- if (__systemName == null && FTPReply.isPositiveCompletion(syst()))
- __systemName = _replyLines.get(_replyLines.size() - 1).substring(4);
-
- return __systemName;
- }
-
-
- /***
- * Fetches the system help information from the server and returns the
- * full string.
- *
- * @return The system help string obtained from the server. null if the
- * information could not be obtained.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String listHelp() throws IOException
- {
- if (FTPReply.isPositiveCompletion(help()))
- return getReplyString();
- return null;
- }
-
-
- /**
- * Fetches the help information for a given command from the server and
- * returns the full string.
- * @param command The command on which to ask for help.
- * @return The command help string obtained from the server. null if the
- * information could not be obtained.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- */
- public String listHelp(String command) throws IOException
- {
- if (FTPReply.isPositiveCompletion(help(command)))
- return getReplyString();
- return null;
- }
-
-
- /***
- * Sends a NOOP command to the FTP server. This is useful for preventing
- * server timeouts.
- *
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean sendNoOp() throws IOException
- {
- return FTPReply.isPositiveCompletion(noop());
- }
-
-
- /***
- * Obtain a list of filenames in a directory (or just the name of a given
- * file, which is not particularly useful). This information is obtained
- * through the NLST command. If the given pathname is a directory and
- * contains no files, a zero length array is returned only
- * if the FTP server returned a positive completion code, otherwise
- * null is returned (the FTP server returned a 550 error No files found.).
- * If the directory is not empty, an array of filenames in the directory is
- * returned. If the pathname corresponds
- * to a file, only that file will be listed. The server may or may not
- * expand glob expressions.
- *
- * @param pathname The file or directory to list.
- * @return The list of filenames contained in the given path. null if
- * the list could not be obtained. If there are no filenames in
- * the directory, a zero-length array is returned.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String[] listNames(String pathname) throws IOException
- {
- String line;
- Socket socket;
- BufferedReader reader;
- ArrayList
- * @return The list of filenames contained in the current working
- * directory. null if the list could not be obtained.
- * If there are no filenames in the directory, a zero-length array
- * is returned.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String[] listNames() throws IOException
- {
- return listNames(null);
- }
-
-
-
- /**
- * Using the default system autodetect mechanism, obtain a
- * list of file information for the current working directory
- * or for just a single file.
- *
- * This information is obtained through the LIST command. The contents of
- * the returned array is determined by the
- * @param pathname The file or directory to list. Since the server may
- * or may not expand glob expressions, using them here
- * is not recommended and may well cause this method to
- * fail.
- *
- * @return The list of file information contained in the given path in
- * the format determined by the autodetection mechanism
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection
- * as a result of the client being idle or some other
- * reason causing the server to send FTP reply code 421.
- * This exception may be caught either as an IOException
- * or independently as itself.
- * @exception IOException
- * If an I/O error occurs while either sending a
- * command to the server or receiving a reply
- * from the server.
- * @exception ParserInitializationException
- * Thrown if the parserKey parameter cannot be
- * resolved by the selected parser factory.
- * In the DefaultFTPEntryParserFactory, this will
- * happen when parserKey is neither
- * the fully qualified class name of a class
- * implementing the interface
- * org.apache.commons.net.ftp.FTPFileEntryParser
- * nor a string containing one of the recognized keys
- * mapping to such a parser or if class loader
- * security issues prevent its being loaded.
- * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
- * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
- * @see org.apache.commons.net.ftp.FTPFileEntryParser
- */
- public FTPFile[] listFiles(String pathname)
- throws IOException
- {
- String key = null;
- FTPListParseEngine engine =
- initiateListParsing(key, pathname);
- return engine.getFiles();
-
- }
- /**
- * Using the default system autodetect mechanism, obtain a
- * list of file information for the current working directory.
- *
- * This information is obtained through the LIST command. The contents of
- * the returned array is determined by the
- * @return The list of file information contained in the current directory
- * in the format determined by the autodetection mechanism.
- *
- * NOTE: This array may contain null members if any of the
- * individual file listings failed to parse. The caller should
- * check each entry for null before referencing it.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection
- * as a result of the client being idle or some other
- * reason causing the server to send FTP reply code 421.
- * This exception may be caught either as an IOException
- * or independently as itself.
- * @exception IOException
- * If an I/O error occurs while either sending a
- * command to the server or receiving a reply
- * from the server.
- * @exception ParserInitializationException
- * Thrown if the parserKey parameter cannot be
- * resolved by the selected parser factory.
- * In the DefaultFTPEntryParserFactory, this will
- * happen when parserKey is neither
- * the fully qualified class name of a class
- * implementing the interface
- * org.apache.commons.net.ftp.FTPFileEntryParser
- * nor a string containing one of the recognized keys
- * mapping to such a parser or if class loader
- * security issues prevent its being loaded.
- * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
- * @see org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory
- * @see org.apache.commons.net.ftp.FTPFileEntryParser
- */
- public FTPFile[] listFiles()
- throws IOException
- {
- return listFiles((String) null);
- }
-
- /**
- * Using the default autodetect mechanism, initialize an FTPListParseEngine
- * object containing a raw file information for the current working
- * directory on the server
- * This information is obtained through the LIST command. This object
- * is then capable of being iterated to return a sequence of FTPFile
- * objects with information filled in by the
- *
- * This method differs from using the listFiles() methods in that
- * expensive FTPFile objects are not created until needed which may be
- * an advantage on large lists.
- *
- * @return A FTPListParseEngine object that holds the raw information and
- * is capable of providing parsed FTPFile objects, one for each file
- * containing information contained in the given path in the format
- * determined by the
- * The server may or may not expand glob expressions. You should avoid
- * using glob expressions because the return format for glob listings
- * differs from server to server and will likely cause this method to fail.
- *
- * This method differs from using the listFiles() methods in that
- * expensive FTPFile objects are not created until needed which may be
- * an advantage on large lists.
- *
- *
- * The server may or may not expand glob expressions. You should avoid
- * using glob expressions because the return format for glob listings
- * differs from server to server and will likely cause this method to fail.
- *
- * This method differs from using the listFiles() methods in that
- * expensive FTPFile objects are not created until needed which may be
- * an advantage on large lists.
- *
- * @param parserKey A string representing a designated code or fully-qualified
- * class name of an
- * @return The status information returned by the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String getStatus() throws IOException
- {
- if (FTPReply.isPositiveCompletion(stat()))
- return getReplyString();
- return null;
- }
-
-
- /***
- * Issue the FTP STAT command to the server for a given pathname. This
- * should produce a listing of the file or directory.
- *
- * @return The status information returned by the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String getStatus(String pathname) throws IOException
- {
- if (FTPReply.isPositiveCompletion(stat(pathname)))
- return getReplyString();
- return null;
- }
-
-
- /**
- * Issue the FTP MDTM command (not supported by all servers to retrieve the last
- * modification time of a file. The modification string should be in the
- * ISO 3077 form "YYYYMMDDhhmmss(.xxx)?". The timestamp represented should also be in
- * GMT, but not all FTP servers honour this.
- *
- * @param pathname The file path to query.
- * @return A string representing the last file modification time in
- * This class implements an alternate means of configuring the
- * {@link org.apache.commons.net.ftp.FTPClient FTPClient} object and
- * also subordinate objects which it uses. Any class implementing the
- * {@link org.apache.commons.net.ftp.Configurable Configurable }
- * interface can be configured by this object.
- *
- * In particular this class was designed primarily to support configuration
- * of FTP servers which express file timestamps in formats and languages
- * other than those for the US locale, which although it is the most common
- * is not universal. Unfortunately, nothing in the FTP spec allows this to
- * be determined in an automated way, so manual configuration such as this
- * is necessary.
- *
- * This functionality was designed to allow existing clients to work exactly
- * as before without requiring use of this component. This component should
- * only need to be explicitly invoked by the user of this package for problem
- * cases that previous implementations could not solve.
- *
- * Unpaged (whole list) access on a UNIX server that uses French month names
- * but uses the "standard"
- * Paged access on a UNIX server that uses Danish month names
- * and "European" date formatting in Denmark's time zone, when you
- * are in some other time zone.
- *
- * Unpaged (whole list) access on a VMS server that uses month names
- * in a language not {@link #getSupportedLanguageCodes() supported} by the system.
- * but uses the "standard"
- * Unpaged (whole list) access on a Windows-NT server in a different time zone.
- * (Note, since the NT Format uses numeric date formatting, language issues
- * are irrelevant here).
- *
- * getter for the {@link #setShortMonthNames(String) shortMonthNames}
- * property.
- *
- * getter for the {@link #setServerLanguageCode(String) serverLanguageCode} property.
- *
- * getter for the {@link #setLenientFutureDates(boolean) lenientFutureDates} property.
- *
- * setter for the defaultDateFormatStr property. This property
- * specifies the main date format that will be used by a parser configured
- * by this configuration to parse file timestamps. If this is not
- * specified, such a parser will use as a default value, the most commonly
- * used format which will be in as used in
- * This should be in the format described for
- *
- * setter for the recentDateFormatStr property. This property
- * specifies a secondary date format that will be used by a parser
- * configured by this configuration to parse file timestamps, typically
- * those less than a year old. If this is not specified, such a parser
- * will not attempt to parse using an alternate format.
- *
- * setter for the lenientFutureDates property. This boolean property
- * (default: false) only has meaning when a
- * {@link #setRecentDateFormatStr(String) recentDateFormatStr} property
- * has been set. In that case, if this property is set true, then the
- * parser, when it encounters a listing parseable with the recent date
- * format, will only consider a date to belong to the previous year if
- * it is more than one day in the future. This will allow all
- * out-of-synch situations (whether based on "slop" - i.e. servers simply
- * out of synch with one another or because of time zone differences -
- * but in the latter case it is highly recommended to use the
- * {@link #setServerTimeZoneId(String) serverTimeZoneId} property
- * instead) to resolve correctly.
- *
- * This is used primarily in unix-based systems.
- *
- * setter for the serverTimeZoneId property. This property
- * allows a time zone to be specified corresponding to that known to be
- * used by an FTP server in file listings. This might be particularly
- * useful to clients such as Ant that try to use these timestamps for
- * dependency checking.
- *
- * This should be one of the identifiers used by
- *
- * setter for the shortMonthNames property.
- * This property allows the user to specify a set of month names
- * used by the server that is different from those that may be
- * specified using the {@link #setServerLanguageCode(String) serverLanguageCode}
- * property.
- *
- * This should be a string containing twelve strings each composed of
- * three characters, delimited by pipe (|) characters. Currently,
- * only 8-bit ASCII characters are known to be supported. For example,
- * a set of month names used by a hypothetical Icelandic FTP server might
- * conceivably be specified as
- *
- * setter for the serverLanguageCode property. This property allows
- * user to specify a
- *
- * two-letter ISO-639 language code that will be used to
- * configure the set of month names used by the file timestamp parser.
- * If neither this nor the {@link #setShortMonthNames(String) shortMonthNames}
- * is specified, parsing will assume English month names, which may or
- * may not be significant, depending on whether the date format(s)
- * specified via {@link #setDefaultDateFormatStr(String) defaultDateFormatStr}
- * and/or {@link #setRecentDateFormatStr(String) recentDateFormatStr} are using
- * numeric or alphabetic month names.
- * If the code supplied is not supported here,
- * Please note that this attribute will NOT be used to determine a
- * locale-based date format for the language.
- * Experience has shown that many if not most FTP servers outside the
- * United States employ the standard
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class FTPCommand
-{
-
-
- public static final int USER = 0;
- public static final int PASS = 1;
- public static final int ACCT = 2;
- public static final int CWD = 3;
- public static final int CDUP = 4;
- public static final int SMNT = 5;
- public static final int REIN = 6;
- public static final int QUIT = 7;
- public static final int PORT = 8;
- public static final int PASV = 9;
- public static final int TYPE = 10;
- public static final int STRU = 11;
- public static final int MODE = 12;
- public static final int RETR = 13;
- public static final int STOR = 14;
- public static final int STOU = 15;
- public static final int APPE = 16;
- public static final int ALLO = 17;
- public static final int REST = 18;
- public static final int RNFR = 19;
- public static final int RNTO = 20;
- public static final int ABOR = 21;
- public static final int DELE = 22;
- public static final int RMD = 23;
- public static final int MKD = 24;
- public static final int PWD = 25;
- public static final int LIST = 26;
- public static final int NLST = 27;
- public static final int SITE = 28;
- public static final int SYST = 29;
- public static final int STAT = 30;
- public static final int HELP = 31;
- public static final int NOOP = 32;
- /** @since 2.0 */
- public static final int MDTM = 33;
-
- public static final int USERNAME = USER;
- public static final int PASSWORD = PASS;
- public static final int ACCOUNT = ACCT;
- public static final int CHANGE_WORKING_DIRECTORY = CWD;
- public static final int CHANGE_TO_PARENT_DIRECTORY = CDUP;
- public static final int STRUCTURE_MOUNT = SMNT;
- public static final int REINITIALIZE = REIN;
- public static final int LOGOUT = QUIT;
- public static final int DATA_PORT = PORT;
- public static final int PASSIVE = PASV;
- public static final int REPRESENTATION_TYPE = TYPE;
- public static final int FILE_STRUCTURE = STRU;
- public static final int TRANSFER_MODE = MODE;
- public static final int RETRIEVE = RETR;
- public static final int STORE = STOR;
- public static final int STORE_UNIQUE = STOU;
- public static final int APPEND = APPE;
- public static final int ALLOCATE = ALLO;
- public static final int RESTART = REST;
- public static final int RENAME_FROM = RNFR;
- public static final int RENAME_TO = RNTO;
- public static final int ABORT = ABOR;
- public static final int DELETE = DELE;
- public static final int REMOVE_DIRECTORY = RMD;
- public static final int MAKE_DIRECTORY = MKD;
- public static final int PRINT_WORKING_DIRECTORY = PWD;
- // public static final int LIST = LIST;
- public static final int NAME_LIST = NLST;
- public static final int SITE_PARAMETERS = SITE;
- public static final int SYSTEM = SYST;
- public static final int STATUS = STAT;
- //public static final int HELP = HELP;
- //public static final int NOOP = NOOP;
- /** @since 2.0 */
- public static final int MOD_TIME = MDTM;
-
- // Cannot be instantiated
- private FTPCommand()
- {}
-
- static final String[] _commands = {
- "USER", "PASS", "ACCT", "CWD", "CDUP", "SMNT", "REIN", "QUIT", "PORT",
- "PASV", "TYPE", "STRU", "MODE", "RETR", "STOR", "STOU", "APPE", "ALLO",
- "REST", "RNFR", "RNTO", "ABOR", "DELE", "RMD", "MKD", "PWD", "LIST",
- "NLST", "SITE", "SYST", "STAT", "HELP", "NOOP"
- };
-
- /**
- * Retrieve the FTP protocol command string corresponding to a specified
- * command code.
- *
- * @param command The command code.
- * @return The FTP protcol command string corresponding to a specified
- * command code.
- */
- public static final String getCommand(int command)
- {
- return _commands[command];
- }
-}
diff --git a/org/apache/commons/net/ftp/FTPConnectionClosedException.class b/org/apache/commons/net/ftp/FTPConnectionClosedException.class
deleted file mode 100644
index 38004cb..0000000
Binary files a/org/apache/commons/net/ftp/FTPConnectionClosedException.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/FTPConnectionClosedException.java b/org/apache/commons/net/ftp/FTPConnectionClosedException.java
deleted file mode 100644
index 3eccbf4..0000000
--- a/org/apache/commons/net/ftp/FTPConnectionClosedException.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp;
-import java.io.IOException;
-
-/***
- * FTPConnectionClosedException is used to indicate the premature or
- * unexpected closing of an FTP connection resulting from a
- * {@link org.apache.commons.net.ftp.FTPReply#SERVICE_NOT_AVAILABLE FTPReply.SERVICE_NOT_AVAILABLE }
- * response (FTP reply code 421) to a
- * failed FTP command. This exception is derived from IOException and
- * therefore may be caught either as an IOException or specifically as an
- * FTPConnectionClosedException.
- *
- *
- * @author Daniel F. Savarese
- * @see FTP
- * @see FTPClient
- ***/
-
-public class FTPConnectionClosedException extends IOException
-{
-
- /*** Constructs a FTPConnectionClosedException with no message ***/
- public FTPConnectionClosedException()
- {
- super();
- }
-
- /***
- * Constructs a FTPConnectionClosedException with a specified message.
- *
- * @param message The message explaining the reason for the exception.
- ***/
- public FTPConnectionClosedException(String message)
- {
- super(message);
- }
-
-}
diff --git a/org/apache/commons/net/ftp/FTPFile.class b/org/apache/commons/net/ftp/FTPFile.class
deleted file mode 100644
index 6cb7744..0000000
Binary files a/org/apache/commons/net/ftp/FTPFile.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/FTPFile.java b/org/apache/commons/net/ftp/FTPFile.java
deleted file mode 100644
index dd67904..0000000
--- a/org/apache/commons/net/ftp/FTPFile.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp;
-import java.io.Serializable;
-import java.util.Calendar;
-
-/***
- * The FTPFile class is used to represent information about files stored
- * on an FTP server. Because there is no standard representation for
- * file information on FTP servers, it may not always be possible to
- * extract all the information that can be represented by FTPFile, or
- * it may even be possible to extract more information. In cases where
- * more information can be extracted, you will want to subclass FTPFile
- * and implement your own {@link org.apache.commons.net.ftp.FTPFileListParser}
- * to extract the information.
- * However, most FTP servers return file information in a format that
- * can be completely parsed by
- * {@link org.apache.commons.net.ftp.DefaultFTPFileListParser}
- * and stored in FTPFile.
- *
- *
- * @author Daniel F. Savarese
- * @see FTPFileListParser
- * @see DefaultFTPFileListParser
- * @see FTPClient#listFiles
- ***/
-
-public class FTPFile implements Serializable
-{
- /** A constant indicating an FTPFile is a file. ***/
- public static final int FILE_TYPE = 0;
- /** A constant indicating an FTPFile is a directory. ***/
- public static final int DIRECTORY_TYPE = 1;
- /** A constant indicating an FTPFile is a symbolic link. ***/
- public static final int SYMBOLIC_LINK_TYPE = 2;
- /** A constant indicating an FTPFile is of unknown type. ***/
- public static final int UNKNOWN_TYPE = 3;
-
- /** A constant indicating user access permissions. ***/
- public static final int USER_ACCESS = 0;
- /** A constant indicating group access permissions. ***/
- public static final int GROUP_ACCESS = 1;
- /** A constant indicating world access permissions. ***/
- public static final int WORLD_ACCESS = 2;
-
- /** A constant indicating file/directory read permission. ***/
- public static final int READ_PERMISSION = 0;
- /** A constant indicating file/directory write permission. ***/
- public static final int WRITE_PERMISSION = 1;
- /**
- * A constant indicating file execute permission or directory listing
- * permission.
- ***/
- public static final int EXECUTE_PERMISSION = 2;
-
- int _type, _hardLinkCount;
- long _size;
- String _rawListing, _user, _group, _name, _link;
- Calendar _date;
- boolean[] _permissions[];
-
- /*** Creates an empty FTPFile. ***/
- public FTPFile()
- {
- _permissions = new boolean[3][3];
- _rawListing = null;
- _type = UNKNOWN_TYPE;
- _hardLinkCount = 0;
- _size = 0;
- _user = null;
- _group = null;
- _date = null;
- _name = null;
- }
-
-
- /***
- * Set the original FTP server raw listing from which the FTPFile was
- * created.
- *
- * @param rawListing The raw FTP server listing.
- ***/
- public void setRawListing(String rawListing)
- {
- _rawListing = rawListing;
- }
-
- /***
- * Get the original FTP server raw listing used to initialize the FTPFile.
- *
- * @return The original FTP server raw listing used to initialize the
- * FTPFile.
- ***/
- public String getRawListing()
- {
- return _rawListing;
- }
-
-
- /***
- * Determine if the file is a directory.
- *
- * @return True if the file is of type
- * @return True if the file is of type
- * @return True if the file is of type
- * @return True if the file is of type
- * @param type The integer code representing the type of the file.
- ***/
- public void setType(int type)
- {
- _type = type;
- }
-
-
- /***
- * Return the type of the file (one of the
- * @return The type of the file.
- ***/
- public int getType()
- {
- return _type;
- }
-
-
- /***
- * Set the name of the file.
- *
- * @param name The name of the file.
- ***/
- public void setName(String name)
- {
- _name = name;
- }
-
- /***
- * Return the name of the file.
- *
- * @return The name of the file.
- ***/
- public String getName()
- {
- return _name;
- }
-
-
- /**
- * Set the file size in bytes.
- * @param size The file size in bytes.
- */
- public void setSize(long size)
- {
- _size = size;
- }
-
-
- /***
- * Return the file size in bytes.
- *
- * @return The file size in bytes.
- ***/
- public long getSize()
- {
- return _size;
- }
-
-
- /***
- * Set the number of hard links to this file. This is not to be
- * confused with symbolic links.
- *
- * @param links The number of hard links to this file.
- ***/
- public void setHardLinkCount(int links)
- {
- _hardLinkCount = links;
- }
-
-
- /***
- * Return the number of hard links to this file. This is not to be
- * confused with symbolic links.
- *
- * @return The number of hard links to this file.
- ***/
- public int getHardLinkCount()
- {
- return _hardLinkCount;
- }
-
-
- /***
- * Set the name of the group owning the file. This may be
- * a string representation of the group number.
- *
- * @param group The name of the group owning the file.
- ***/
- public void setGroup(String group)
- {
- _group = group;
- }
-
-
- /***
- * Returns the name of the group owning the file. Sometimes this will be
- * a string representation of the group number.
- *
- * @return The name of the group owning the file.
- ***/
- public String getGroup()
- {
- return _group;
- }
-
-
- /***
- * Set the name of the user owning the file. This may be
- * a string representation of the user number;
- *
- * @param user The name of the user owning the file.
- ***/
- public void setUser(String user)
- {
- _user = user;
- }
-
- /***
- * Returns the name of the user owning the file. Sometimes this will be
- * a string representation of the user number.
- *
- * @return The name of the user owning the file.
- ***/
- public String getUser()
- {
- return _user;
- }
-
-
- /***
- * If the FTPFile is a symbolic link, use this method to set the name of the
- * file being pointed to by the symbolic link.
- *
- * @param link The file pointed to by the symbolic link.
- ***/
- public void setLink(String link)
- {
- _link = link;
- }
-
-
- /***
- * If the FTPFile is a symbolic link, this method returns the name of the
- * file being pointed to by the symbolic link. Otherwise it returns null.
- *
- * @return The file pointed to by the symbolic link (null if the FTPFile
- * is not a symbolic link).
- ***/
- public String getLink()
- {
- return _link;
- }
-
-
- /***
- * Set the file timestamp. This usually the last modification time.
- * The parameter is not cloned, so do not alter its value after calling
- * this method.
- *
- * @param date A Calendar instance representing the file timestamp.
- ***/
- public void setTimestamp(Calendar date)
- {
- _date = date;
- }
-
-
- /***
- * Returns the file timestamp. This usually the last modification time.
- *
- * @return A Calendar instance representing the file timestamp.
- ***/
- public Calendar getTimestamp()
- {
- return _date;
- }
-
-
- /***
- * Set if the given access group (one of the
- * @param access The access group (one of the
- * @param access The access group (one of the
- * @return A string representation of the FTPFile information.
- ***/
- @Override
- public String toString()
- {
- return _rawListing;
- }
-
-}
diff --git a/org/apache/commons/net/ftp/FTPFileEntryParser.class b/org/apache/commons/net/ftp/FTPFileEntryParser.class
deleted file mode 100644
index 2643bb2..0000000
Binary files a/org/apache/commons/net/ftp/FTPFileEntryParser.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/FTPFileEntryParser.java b/org/apache/commons/net/ftp/FTPFileEntryParser.java
deleted file mode 100644
index 8e6d09c..0000000
--- a/org/apache/commons/net/ftp/FTPFileEntryParser.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.util.List;
-
-/**
- * FTPFileEntryParser defines the interface for parsing a single FTP file
- * listing and converting that information into an
- * {@link org.apache.commons.net.ftp.FTPFile} instance.
- * Sometimes you will want to parse unusual listing formats, in which
- * case you would create your own implementation of FTPFileEntryParser and
- * if necessary, subclass FTPFile.
- *
- * Here are some examples showing how to use one of the classes that
- * implement this interface.
- *
- * The first example shows how to get an iterable list of files in which the
- * more expensive
- * @param listEntry A line of text from the file listing
- * @return An FTPFile instance corresponding to the supplied entry
- */
- FTPFile parseFTPEntry(String listEntry);
-
- /**
- * Reads the next entry using the supplied BufferedReader object up to
- * whatever delemits one entry from the next. Implementors must define
- * this for the particular ftp system being parsed. In many but not all
- * cases, this can be defined simply by calling BufferedReader.readLine().
- *
- * @param reader The BufferedReader object from which entries are to be
- * read.
- *
- * @return A string representing the next ftp entry or null if none found.
- * @exception IOException thrown on any IO Error reading from the reader.
- */
- String readNextEntry(BufferedReader reader) throws IOException;
-
-
- /**
- * This method is a hook for those implementors (such as
- * VMSVersioningFTPEntryParser, and possibly others) which need to
- * perform some action upon the FTPFileList after it has been created
- * from the server stream, but before any clients see the list.
- *
- * The default implementation can be a no-op.
- *
- * @param original Original list after it has been created from the server stream
- *
- * @return Original list as processed by this method.
- */
- List
- * This object defines a two-part parsing mechanism.
- *
- * The first part is comprised of reading the raw input into an internal
- * list of strings. Every item in this list corresponds to an actual
- * file. All extraneous matter emitted by the server will have been
- * removed by the end of this phase. This is accomplished in conjunction
- * with the FTPFileEntryParser associated with this engine, by calling
- * its methods
- * The second part is composed of the actual parsing, again in conjunction
- * with the particular parser used by this engine. This is controlled
- * by an iterator over the internal list of strings. This may be done
- * either in block mode, by calling the
- * Examples:
- *
- * Paged access:
- *
- * For unpaged access, simply use FTPClient.listFiles(). That method
- * uses this class transparently.
- * @version $Id: FTPListParseEngine.java 658518 2008-05-21 01:04:30Z sebb $
- */
-public class FTPListParseEngine {
- private List
- * NOTE: This array may contain null members if any of the
- * individual file listings failed to parse. The caller should
- * check each entry for null before referencing it.
- */
- public FTPFile[] getNext(int quantityRequested) {
- List
- * NOTE: This array may contain null members if any of the
- * individual file listings failed to parse. The caller should
- * check each entry for null before referencing it.
- */
- public FTPFile[] getPrevious(int quantityRequested) {
- List
- * NOTE: This array may contain null members if any of the
- * individual file listings failed to parse. The caller should
- * check each entry for null before referencing it.
- * @exception IOException
- */
- public FTPFile[] getFiles()
- throws IOException
- {
- List
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class FTPReply
-{
-
- public static final int CODE_110 = 110;
- public static final int CODE_120 = 120;
- public static final int CODE_125 = 125;
- public static final int CODE_150 = 150;
- public static final int CODE_200 = 200;
- public static final int CODE_202 = 202;
- public static final int CODE_211 = 211;
- public static final int CODE_212 = 212;
- public static final int CODE_213 = 213;
- public static final int CODE_214 = 214;
- public static final int CODE_215 = 215;
- public static final int CODE_220 = 220;
- public static final int CODE_221 = 221;
- public static final int CODE_225 = 225;
- public static final int CODE_226 = 226;
- public static final int CODE_227 = 227;
- public static final int CODE_230 = 230;
- public static final int CODE_250 = 250;
- public static final int CODE_257 = 257;
- public static final int CODE_331 = 331;
- public static final int CODE_332 = 332;
- public static final int CODE_350 = 350;
- public static final int CODE_421 = 421;
- public static final int CODE_425 = 425;
- public static final int CODE_426 = 426;
- public static final int CODE_450 = 450;
- public static final int CODE_451 = 451;
- public static final int CODE_452 = 452;
- public static final int CODE_500 = 500;
- public static final int CODE_501 = 501;
- public static final int CODE_502 = 502;
- public static final int CODE_503 = 503;
- public static final int CODE_504 = 504;
- public static final int CODE_521 = 521;
- public static final int CODE_530 = 530;
- public static final int CODE_532 = 532;
- public static final int CODE_550 = 550;
- public static final int CODE_551 = 551;
- public static final int CODE_552 = 552;
- public static final int CODE_553 = 553;
-
- public static final int RESTART_MARKER = CODE_110;
- public static final int SERVICE_NOT_READY = CODE_120;
- public static final int DATA_CONNECTION_ALREADY_OPEN = CODE_125;
- public static final int FILE_STATUS_OK = CODE_150;
- public static final int COMMAND_OK = CODE_200;
- public static final int COMMAND_IS_SUPERFLUOUS = CODE_202;
- public static final int SYSTEM_STATUS = CODE_211;
- public static final int DIRECTORY_STATUS = CODE_212;
- public static final int FILE_STATUS = CODE_213;
- public static final int HELP_MESSAGE = CODE_214;
- public static final int NAME_SYSTEM_TYPE = CODE_215;
- public static final int SERVICE_READY = CODE_220;
- public static final int SERVICE_CLOSING_CONTROL_CONNECTION = CODE_221;
- public static final int DATA_CONNECTION_OPEN = CODE_225;
- public static final int CLOSING_DATA_CONNECTION = CODE_226;
- public static final int ENTERING_PASSIVE_MODE = CODE_227;
- public static final int USER_LOGGED_IN = CODE_230;
- public static final int FILE_ACTION_OK = CODE_250;
- public static final int PATHNAME_CREATED = CODE_257;
- public static final int NEED_PASSWORD = CODE_331;
- public static final int NEED_ACCOUNT = CODE_332;
- public static final int FILE_ACTION_PENDING = CODE_350;
- public static final int SERVICE_NOT_AVAILABLE = CODE_421;
- public static final int CANNOT_OPEN_DATA_CONNECTION = CODE_425;
- public static final int TRANSFER_ABORTED = CODE_426;
- public static final int FILE_ACTION_NOT_TAKEN = CODE_450;
- public static final int ACTION_ABORTED = CODE_451;
- public static final int INSUFFICIENT_STORAGE = CODE_452;
- public static final int UNRECOGNIZED_COMMAND = CODE_500;
- public static final int SYNTAX_ERROR_IN_ARGUMENTS = CODE_501;
- public static final int COMMAND_NOT_IMPLEMENTED = CODE_502;
- public static final int BAD_COMMAND_SEQUENCE = CODE_503;
- public static final int COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER = CODE_504;
- public static final int NOT_LOGGED_IN = CODE_530;
- public static final int NEED_ACCOUNT_FOR_STORING_FILES = CODE_532;
- public static final int FILE_UNAVAILABLE = CODE_550;
- public static final int PAGE_TYPE_UNKNOWN = CODE_551;
- public static final int STORAGE_ALLOCATION_EXCEEDED = CODE_552;
- public static final int FILE_NAME_NOT_ALLOWED = CODE_553;
-
- // FTPS Reply Codes
- /** @since 2.0 */
- public static final int CODE_234 = 234;
- /** @since 2.0 */
- public static final int CODE_235 = 235;
- /** @since 2.0 */
- public static final int CODE_334 = 334;
- /** @since 2.0 */
- public static final int CODE_335 = 335;
- /** @since 2.0 */
- public static final int CODE_431 = 431;
- /** @since 2.0 */
- public static final int CODE_533 = 533;
- /** @since 2.0 */
- public static final int CODE_534 = 534;
- /** @since 2.0 */
- public static final int CODE_535 = 535;
- /** @since 2.0 */
- public static final int CODE_536 = 536;
-
- /** @since 2.0 */
- public static final int SECURITY_DATA_EXCHANGE_COMPLETE = CODE_234;
- /** @since 2.0 */
- public static final int SECURITY_DATA_EXCHANGE_SUCCESSFULLY = CODE_235;
- /** @since 2.0 */
- public static final int SECURITY_MECHANISM_IS_OK = CODE_334;
- /** @since 2.0 */
- public static final int SECURITY_DATA_IS_ACCEPTABLE = CODE_335;
- /** @since 2.0 */
- public static final int UNAVAILABLE_RESOURCE = CODE_431;
- /** @since 2.0 */
- public static final int DENIED_FOR_POLICY_REASONS = CODE_533;
- /** @since 2.0 */
- public static final int REQUEST_DENIED = CODE_534;
- /** @since 2.0 */
- public static final int FAILED_SECURITY_CHECK = CODE_535;
- /** @since 2.0 */
- public static final int REQUESTED_PROT_LEVEL_NOT_SUPPORTED = CODE_536;
-
-
- // Cannot be instantiated
- private FTPReply()
- {}
-
- /***
- * Determine if a reply code is a positive preliminary response. All
- * codes beginning with a 1 are positive preliminary responses.
- * Postitive preliminary responses are used to indicate tentative success.
- * No further commands can be issued to the FTP server after a positive
- * preliminary response until a follow up response is received from the
- * server.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a postive preliminary response, false
- * if not.
- ***/
- public static boolean isPositivePreliminary(int reply)
- {
- return (reply >= 100 && reply < 200);
- }
-
- /***
- * Determine if a reply code is a positive completion response. All
- * codes beginning with a 2 are positive completion responses.
- * The FTP server will send a positive completion response on the final
- * successful completion of a command.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a postive completion response, false
- * if not.
- ***/
- public static boolean isPositiveCompletion(int reply)
- {
- return (reply >= 200 && reply < 300);
- }
-
- /***
- * Determine if a reply code is a positive intermediate response. All
- * codes beginning with a 3 are positive intermediate responses.
- * The FTP server will send a positive intermediate response on the
- * successful completion of one part of a multi-part sequence of
- * commands. For example, after a successful USER command, a positive
- * intermediate response will be sent to indicate that the server is
- * ready for the PASS command.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a postive intermediate response, false
- * if not.
- ***/
- public static boolean isPositiveIntermediate(int reply)
- {
- return (reply >= 300 && reply < 400);
- }
-
- /***
- * Determine if a reply code is a negative transient response. All
- * codes beginning with a 4 are negative transient responses.
- * The FTP server will send a negative transient response on the
- * failure of a command that can be reattempted with success.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a negative transient response, false
- * if not.
- ***/
- public static boolean isNegativeTransient(int reply)
- {
- return (reply >= 400 && reply < 500);
- }
-
- /***
- * Determine if a reply code is a negative permanent response. All
- * codes beginning with a 5 are negative permanent responses.
- * The FTP server will send a negative permanent response on the
- * failure of a command that cannot be reattempted with success.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a negative permanent response, false
- * if not.
- ***/
- public static boolean isNegativePermanent(int reply)
- {
- return (reply >= 500 && reply < 600);
- }
-
-}
diff --git a/org/apache/commons/net/ftp/FTPSClient.java b/org/apache/commons/net/ftp/FTPSClient.java
deleted file mode 100644
index f809c41..0000000
--- a/org/apache/commons/net/ftp/FTPSClient.java
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.net.Socket;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLServerSocketFactory;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-
-/**
- * FTP over SSL processing. If desired, the JVM property -Djavax.net.debug=all can be used to
- * see wire-level SSL details.
- *
- * @version $Id: FTPSClient.java 658520 2008-05-21 01:14:11Z sebb $
- * @since 2.0
- */
-public class FTPSClient extends FTPClient {
-
- /** keystore algorithm name. */
- public static String KEYSTORE_ALGORITHM;
- /** truststore algorithm name. */
- public static String TRUSTSTORE_ALGORITHM;
- /** provider name. */
- public static String PROVIDER;
- /** truststore type. */
- public static String STORE_TYPE;
-
- /** The value that I can set in PROT command */
- private static final String[] PROT_COMMAND_VALUE = {"C","E","S","P"};
- /** Default PROT Command */
- private static final String DEFAULT_PROT = "C";
- /** Default protocol name */
- private static final String DEFAULT_PROTOCOL = "TLS";
-
- /** The security mode. (True - Implicit Mode / False - Explicit Mode) */
- private boolean isImplicit;
- /** The use SSL/TLS protocol. */
- private String protocol = DEFAULT_PROTOCOL;
- /** The AUTH Command value */
- private String auth = DEFAULT_PROTOCOL;
- /** The context object. */
- private SSLContext context;
- /** The socket object. */
- private Socket planeSocket;
- /** The established socket flag. */
- private boolean isCreation = true;
- /** The use client mode flag. */
- private boolean isClientMode = true;
- /** The need client auth flag. */
- private boolean isNeedClientAuth = false;
- /** The want client auth flag. */
- private boolean isWantClientAuth = false;
- /** The cipher suites */
- private String[] suites = null;
- /** The protocol versions */
- private String[] protocols = null;
-
- /** The FTPS {@link TrustManager} implementation. */
- private TrustManager trustManager = new FTPSTrustManager();
-
- /** The {@link KeyManager} */
- private KeyManager keyManager;
-
- /**
- * Constructor for FTPSClient.
- * @throws NoSuchAlgorithmException A requested cryptographic algorithm
- * is not available in the environment.
- */
- public FTPSClient() throws NoSuchAlgorithmException {
- this.protocol = DEFAULT_PROTOCOL;
- this.isImplicit = false;
- }
-
- /**
- * Constructor for FTPSClient.
- * @param isImplicit The secutiry mode(Implicit/Explicit).
- * @throws NoSuchAlgorithmException A requested cryptographic algorithm
- * is not available in the environment.
- */
- public FTPSClient(boolean isImplicit) throws NoSuchAlgorithmException {
- this.protocol = DEFAULT_PROTOCOL;
- this.isImplicit = isImplicit;
- }
-
- /**
- * Constructor for FTPSClient.
- * @param protocol the protocol
- * @throws NoSuchAlgorithmException A requested cryptographic algorithm
- * is not available in the environment.
- */
- public FTPSClient(String protocol) throws NoSuchAlgorithmException {
- this.protocol = protocol;
- this.isImplicit = false;
- }
-
- /**
- * Constructor for FTPSClient.
- * @param protocol the protocol
- * @param isImplicit The secutiry mode(Implicit/Explicit).
- * @throws NoSuchAlgorithmException A requested cryptographic algorithm
- * is not available in the environment.
- */
- public FTPSClient(String protocol, boolean isImplicit)
- throws NoSuchAlgorithmException {
- this.protocol = protocol;
- this.isImplicit = isImplicit;
- }
-
-
- /**
- * Set AUTH command use value.
- * This processing is done before connected processing.
- * @param auth AUTH command use value.
- */
- public void setAuthValue(String auth) {
- this.auth = auth;
- }
-
- /**
- * Return AUTH command use value.
- * @return AUTH command use value.
- */
- public String getAuthValue() {
- return this.auth;
- }
-
-
- /**
- * Because there are so many connect() methods,
- * the _connectAction_() method is provided as a means of performing
- * some action immediately after establishing a connection,
- * rather than reimplementing all of the connect() methods.
- * @throws IOException If it throw by _connectAction_.
- * @see org.apache.commons.net.SocketClient#_connectAction_()
- */
- @Override
- protected void _connectAction_() throws IOException {
- // Implicit mode.
- if (isImplicit) sslNegotiation();
- super._connectAction_();
- // Explicit mode.
- if (!isImplicit) {
- execAUTH();
- sslNegotiation();
- }
- }
-
- /**
- * AUTH command.
- * @throws SSLException If it server reply code not equal "234" and "334".
- * @throws IOException If an I/O error occurs while either sending
- * the command.
- */
- private void execAUTH() throws SSLException, IOException {
- int replyCode = sendCommand(
- FTPSCommand._commands[FTPSCommand.AUTH], auth);
- if (FTPReply.SECURITY_MECHANISM_IS_OK == replyCode) {
- // replyCode = 334
- // I carry out an ADAT command.
- } else if (FTPReply.SECURITY_DATA_EXCHANGE_COMPLETE != replyCode) {
- throw new SSLException(getReplyString());
- }
- }
-
- /**
- * Performs a lazy init of the SSL context
- * @throws IOException
- */
- private void initSslContext() throws IOException {
- if(context == null) {
- try {
- context = SSLContext.getInstance(protocol);
-
- context.init(new KeyManager[] { getKeyManager() } , new TrustManager[] { getTrustManager() } , null);
- } catch (KeyManagementException e) {
- IOException ioe = new IOException("Could not initialize SSL context");
- ioe.initCause(e);
- throw ioe;
- } catch (NoSuchAlgorithmException e) {
- IOException ioe = new IOException("Could not initialize SSL context");
- ioe.initCause(e);
- throw ioe;
- }
- }
- }
-
- /**
- * SSL/TLS negotiation. Acquires an SSL socket of a control
- * connection and carries out handshake processing.
- * @throws IOException A handicap breaks out by sever negotiation.
- */
- private void sslNegotiation() throws IOException {
- // Evacuation not ssl socket.
- planeSocket = _socket_;
-
- initSslContext();
-
- SSLSocketFactory ssf = context.getSocketFactory();
- String ip = _socket_.getInetAddress().getHostAddress();
- int port = _socket_.getPort();
- SSLSocket socket =
- (SSLSocket) ssf.createSocket(_socket_, ip, port, true);
- socket.setEnableSessionCreation(isCreation);
- socket.setUseClientMode(isClientMode);
- // server mode
- if (!isClientMode) {
- socket.setNeedClientAuth(isNeedClientAuth);
- socket.setWantClientAuth(isWantClientAuth);
- }
- if (protocols != null) socket.setEnabledProtocols(protocols);
- if (suites != null) socket.setEnabledCipherSuites(suites);
-
- socket.startHandshake();
-
- _socket_ = socket;
- _controlInput_ = new BufferedReader(new InputStreamReader(
- socket .getInputStream(), getControlEncoding()));
- _controlOutput_ = new BufferedWriter(new OutputStreamWriter(
- socket.getOutputStream(), getControlEncoding()));
- }
-
- /**
- * Get the {@link KeyManager} instance.
- * @return The {@link KeyManager} instance
- */
- private KeyManager getKeyManager() {
- return keyManager;
- }
-
- /**
- * Set a {@link KeyManager} to use
- *
- * @param keyManager The KeyManager implementation to set.
- */
- public void setKeyManager(KeyManager keyManager) {
- this.keyManager = keyManager;
- }
-
- /**
- * Controls whether new a SSL session may be established by this socket.
- * @param isCreation The established socket flag.
- */
- public void setEnabledSessionCreation(boolean isCreation) {
- this.isCreation = isCreation;
- }
-
- /**
- * Returns true if new SSL sessions may be established by this socket.
- * When a socket does not have a ssl socket, This return False.
- * @return true - Indicates that sessions may be created;
- * this is the default.
- * false - indicates that an existing session must be resumed.
- */
- public boolean getEnableSessionCreation() {
- if (_socket_ instanceof SSLSocket)
- return ((SSLSocket)_socket_).getEnableSessionCreation();
- return false;
- }
-
- /**
- * Configures the socket to require client authentication.
- * @param isNeedClientAuth The need client auth flag.
- */
- public void setNeedClientAuth(boolean isNeedClientAuth) {
- this.isNeedClientAuth = isNeedClientAuth;
- }
-
- /**
- * Returns true if the socket will require client authentication.
- * When a socket does not have a ssl socket, This return False.
- * @return true - If the server mode socket should request
- * that the client authenticate itself.
- */
- public boolean getNeedClientAuth() {
- if (_socket_ instanceof SSLSocket)
- return ((SSLSocket)_socket_).getNeedClientAuth();
- return false;
- }
-
- /**
- * Configures the socket to request client authentication,
- * but only if such a request is appropriate to the cipher
- * suite negotiated.
- * @param isWantClientAuth The want client auth flag.
- */
- public void setWantClientAuth(boolean isWantClientAuth) {
- this.isWantClientAuth = isWantClientAuth;
- }
-
- /**
- * Returns true if the socket will request client authentication.
- * When a socket does not have a ssl socket, This return False.
- * @return true - If the server mode socket should request
- * that the client authenticate itself.
- */
- public boolean getWantClientAuth() {
- if (_socket_ instanceof SSLSocket)
- return ((SSLSocket)_socket_).getWantClientAuth();
- return false;
- }
-
- /**
- * Configures the socket to use client (or server) mode in its first
- * handshake.
- * @param isClientMode The use client mode flag.
- */
- public void setUseClientMode(boolean isClientMode) {
- this.isClientMode = isClientMode;
- }
-
- /**
- * Returns true if the socket is set to use client mode
- * in its first handshake.
- * When a socket does not have a ssl socket, This return False.
- * @return true - If the socket should start its first handshake
- * in "client" mode.
- */
- public boolean getUseClientMode() {
- if (_socket_ instanceof SSLSocket)
- return ((SSLSocket)_socket_).getUseClientMode();
- return false;
- }
-
- /**
- * Controls which particular cipher suites are enabled for use on this
- * connection. I perform setting before a server negotiation.
- * @param cipherSuites The cipher suites.
- */
- public void setEnabledCipherSuites(String[] cipherSuites) {
- suites = new String[cipherSuites.length];
- System.arraycopy(cipherSuites, 0, suites, 0, cipherSuites.length);
- }
-
- /**
- * Returns the names of the cipher suites which could be enabled
- * for use on this connection.
- * When a socket does not have a ssl socket, This return null.
- * @return An array of cipher suite names.
- */
- public String[] getEnabledCipherSuites() {
- if (_socket_ instanceof SSLSocket)
- return ((SSLSocket)_socket_).getEnabledCipherSuites();
- return null;
- }
-
- /**
- * Controls which particular protocol versions are enabled for use on this
- * connection. I perform setting before a server negotiation.
- * @param protocolVersions The protocol versions.
- */
- public void setEnabledProtocols(String[] protocolVersions) {
- protocols = new String[protocolVersions.length];
- System.arraycopy(protocolVersions, 0, protocols, 0, protocolVersions.length);
- }
-
- /**
- * Returns the names of the protocol versions which are currently
- * enabled for use on this connection.
- * When a socket does not have a ssl socket, This return null.
- * @return An array of protocols.
- */
- public String[] getEnabledProtocols() {
- if (_socket_ instanceof SSLSocket)
- return ((SSLSocket)_socket_).getEnabledProtocols();
- return null;
- }
-
- /**
- * PBSZ command. pbsz value: 0 to (2^32)-1 decimal integer.
- * @param pbsz Protection Buffer Size.
- * @throws SSLException If it server reply code not equal "200".
- * @throws IOException If an I/O error occurs while either sending
- * the command.
- */
- public void execPBSZ(long pbsz) throws SSLException, IOException {
- if (pbsz < 0 || 4294967295L < pbsz)
- throw new IllegalArgumentException();
- if (FTPReply.COMMAND_OK != sendCommand(
- FTPSCommand._commands[FTPSCommand.PBSZ],String.valueOf(pbsz)))
- throw new SSLException(getReplyString());
- }
-
- /**
- * PROT command.
- * C - Clear
- * S - Safe(SSL protocol only)
- * E - Confidential(SSL protocol only)
- * P - Private
- * @param prot Data Channel Protection Level.
- * @throws SSLException If it server reply code not equal "200".
- * @throws IOException If an I/O error occurs while either sending
- * the command.
- */
- public void execPROT(String prot) throws SSLException, IOException {
- if (prot == null) prot = DEFAULT_PROT;
- if (!checkPROTValue(prot)) throw new IllegalArgumentException();
- if (FTPReply.COMMAND_OK != sendCommand(
- FTPSCommand._commands[FTPSCommand.PROT], prot))
- throw new SSLException(getReplyString());
- if (DEFAULT_PROT.equals(prot)) {
- setSocketFactory(null);
- setServerSocketFactory(null);
- } else {
- setSocketFactory(new FTPSSocketFactory(context));
-
- initSslContext();
-
- SSLServerSocketFactory ssf = context.getServerSocketFactory();
-
- setServerSocketFactory(ssf);
- }
- }
-
- /**
- * I check the value that I can set in PROT Command value.
- * @param prot Data Channel Protection Level.
- * @return True - A set point is right / False - A set point is not right
- */
- private boolean checkPROTValue(String prot) {
- for (int p = 0; p < PROT_COMMAND_VALUE.length; p++) {
- if (PROT_COMMAND_VALUE[p].equals(prot)) return true;
- }
- return false;
- }
-
- /**
- * I carry out an ftp command.
- * When a CCC command was carried out, I steep socket and SocketFactory
- * in a state of not ssl.
- * @parm command ftp command.
- * @return server reply.
- * @throws IOException If an I/O error occurs while either sending
- * the command.
- * @see org.apache.commons.net.ftp.FTP#sendCommand(java.lang.String)
- */
- @Override
- public int sendCommand(String command, String args) throws IOException {
- int repCode = super.sendCommand(command, args);
- if (FTPSCommand._commands[FTPSCommand.CCC].equals(command)) {
- if (FTPReply.COMMAND_OK == repCode) {
- // TODO Check this - is this necessary at all?
- _socket_ = planeSocket;
- setSocketFactory(null);
- } else {
- throw new SSLException(getReplyString());
- }
- }
- return repCode;
- }
-
- /**
- * Returns a socket of the data connection.
- * Wrapped as an {@link SSLSocket}, which carries out handshake processing.
- * @pram command The text representation of the FTP command to send.
- * @param arg The arguments to the FTP command.
- * If this parameter is set to null, then the command is sent with
- * no argument.
- * @return A Socket corresponding to the established data connection.
- * Null is returned if an FTP protocol error is reported at any point
- * during the establishment and initialization of the connection.
- * @throws IOException If there is any problem with the connection.
- * @see org.apache.commons.net.ftp.FTPClient#_openDataConnection_(java.lang.String, int)
- */
- @Override
- protected Socket _openDataConnection_(int command, String arg)
- throws IOException {
- Socket socket = super._openDataConnection_(command, arg);
- if (socket != null && socket instanceof SSLSocket) {
- SSLSocket sslSocket = (SSLSocket)socket;
- sslSocket.setUseClientMode(isClientMode);
- sslSocket.setEnableSessionCreation(isCreation);
- // server mode
- if (!isClientMode) {
- sslSocket.setNeedClientAuth(isNeedClientAuth);
- sslSocket.setWantClientAuth(isWantClientAuth);
- }
- if (suites != null)
- sslSocket.setEnabledCipherSuites(suites);
- if (protocols != null)
- sslSocket.setEnabledProtocols(protocols);
- sslSocket.startHandshake();
- }
- return socket;
- }
-
- /**
- * Get the currently configured {@link TrustManager}.
- *
- * @return A TrustManager instance.
- */
- public TrustManager getTrustManager() {
- return trustManager;
- }
-
- /**
- * Override the default {@link TrustManager} to use.
- *
- * @param trustManager The TrustManager implementation to set.
- */
- public void setTrustManager(TrustManager trustManager) {
- this.trustManager = trustManager;
- }
-
-
-
-}
diff --git a/org/apache/commons/net/ftp/FTPSCommand.java b/org/apache/commons/net/ftp/FTPSCommand.java
deleted file mode 100644
index 6fd2efa..0000000
--- a/org/apache/commons/net/ftp/FTPSCommand.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp;
-
-/**
- * I acquire a command added in FTPS.
- * @since 2.0
- */
-public final class FTPSCommand {
- public static final int AUTH = 0;
- public static final int ADAT = 1;
- public static final int PBSZ = 2;
- public static final int PROT = 3;
- public static final int CCC = 4;
-
- public static final int AUTHENTICATION_SECURITY_MECHANISM = AUTH;
- public static final int AUTHENTICATION_SECURITY_DATA = ADAT;
- public static final int PROTECTION_BUFFER_SIZE = PBSZ;
- public static final int DATA_CHANNEL_PROTECTION_LEVEL = PROT;
- public static final int CLEAR_COMMAND_CHANNEL = CCC;
-
- static final String[] _commands = {"AUTH","ADAT","PBSZ","PROT","CCC"};
-
- /**
- * Retrieve the FTPS command string corresponding to a specified
- * command code.
- *
- * @param command The command code.
- * @return The FTPS command string corresponding to a specified
- * command code.
- */
- public static final String getCommand(int command) {
- return _commands[command];
- }
-}
diff --git a/org/apache/commons/net/ftp/FTPSSocketFactory.java b/org/apache/commons/net/ftp/FTPSSocketFactory.java
deleted file mode 100644
index b7e1186..0000000
--- a/org/apache/commons/net/ftp/FTPSSocketFactory.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.apache.commons.net.ftp;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.UnknownHostException;
-
-import javax.net.SocketFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocket;
-
-
-/**
- *
- * Implementation of org.apache.commons.net.SocketFactory
- *
- * @since 2.0
- */
-public class FTPSSocketFactory extends SocketFactory {
-
- private SSLContext context;
-
- public FTPSSocketFactory(SSLContext context) {
- this.context = context;
- }
-
- @Override
- public Socket createSocket(String address, int port) throws UnknownHostException, IOException {
- return this.context.getSocketFactory().createSocket(address, port);
- }
-
- @Override
- public Socket createSocket(InetAddress address, int port) throws IOException {
- return this.context.getSocketFactory().createSocket(address, port);
- }
-
- @Override
- public Socket createSocket(String address, int port, InetAddress localAddress, int localPort) throws UnknownHostException, IOException {
- return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort);
- }
-
- @Override
- public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
- return this.context.getSocketFactory().createSocket(address, port, localAddress, localPort);
- }
-
- public ServerSocket createServerSocket(int port) throws IOException {
- return this.init(this.context.getServerSocketFactory().createServerSocket(port));
- }
-
- public ServerSocket createServerSocket(int port, int backlog) throws IOException {
- return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog));
- }
-
- public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException {
- return this.init(this.context.getServerSocketFactory().createServerSocket(port, backlog, ifAddress));
- }
-
- public ServerSocket init(ServerSocket socket) throws IOException {
- ((SSLServerSocket) socket).setUseClientMode(true);
- return socket;
- }
-}
diff --git a/org/apache/commons/net/ftp/FTPSTrustManager.java b/org/apache/commons/net/ftp/FTPSTrustManager.java
deleted file mode 100644
index d1a2dd7..0000000
--- a/org/apache/commons/net/ftp/FTPSTrustManager.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp;
-
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-/**
- * Custom {@link TrustManager} implementation.
- *
- * @version $Id: FTPSTrustManager.java 658520 2008-05-21 01:14:11Z sebb $
- * @since 2.0
- */
-public class FTPSTrustManager implements X509TrustManager
-{
- /**
- * No-op
- */
- public void checkClientTrusted(X509Certificate[] certificates, String authType)
- {
- return;
- }
-
- public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException
- {
- for (int i = 0; i < certificates.length; ++i)
- {
- certificates[i].checkValidity();
- }
- }
-
- public X509Certificate[] getAcceptedIssuers()
- {
- return null;
- }
-}
diff --git a/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.class b/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.class
deleted file mode 100644
index 0beda53..0000000
Binary files a/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java b/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java
deleted file mode 100644
index 4977b3f..0000000
--- a/org/apache/commons/net/ftp/parser/CompositeFileEntryParser.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp.parser;
-
-import org.apache.commons.net.ftp.FTPFile;
-import org.apache.commons.net.ftp.FTPFileEntryParser;
-import org.apache.commons.net.ftp.FTPFileEntryParserImpl;
-
-/**
- * This implementation allows to pack some FileEntryParsers together
- * and handle the case where to returned dirstyle isnt clearly defined.
- * The matching parser will be cached.
- * If the cached parser wont match due to the server changed the dirstyle,
- * a new matching parser will be searched.
- *
- * @author Mario Ivankovits
- * This abstract class implements the common timestamp parsing
- * algorithm for all the concrete parsers. Classes derived from
- * this one will parse file listings via a supplied regular expression
- * that pulls out the date portion as a separate string which is
- * passed to the underlying {@link FTPTimestampParser delegate} to
- * handle parsing of the file timestamp.
- *
- * This class also implements the {@link Configurable Configurable}
- * interface to allow the parser to be configured from the outside.
- *
- * @param timestampStr the timestamp string pulled from the
- * file listing by the regular expression parser, to be submitted
- * to the Implementation extracts a key from the supplied
- * {@link FTPClientConfig FTPClientConfig}
- * parameter and creates an object implementing the
- * interface FTPFileEntryParser and uses the supplied configuration
- * to configure it.
- *
- * Note that this method will generally not be called in scenarios
- * that call for autodetection of parser type but rather, for situations
- * where the user knows that the server uses a non-default configuration
- * and knows what that configuration is.
- *
- * Note: EnterpriseUnixFTPEntryParser can only be instantiated through the
- * DefaultFTPParserFactory by classname. It will not be chosen
- * by the autodetection scheme.
- *
- * @version $Id: EnterpriseUnixFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
- * @author Winston Ojeda
- * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
- * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
- */
-public class EnterpriseUnixFTPEntryParser extends RegexFTPFileEntryParserImpl
-{
-
- /**
- * months abbreviations looked for by this parser. Also used
- * to determine which month has been matched by the parser.
- */
- private static final String MONTHS =
- "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)";
-
- /**
- * this is the regular expression used by this parser.
- */
- private static final String REGEX =
- "(([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])"
- + "([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z])([\\-]|[A-Z]))"
- + "(\\S*)\\s*"
- + "(\\S+)\\s*"
- + "(\\S*)\\s*"
- + "(\\d*)\\s*"
- + "(\\d*)\\s*"
- + MONTHS
- + "\\s*"
- + "((?:[012]\\d*)|(?:3[01]))\\s*"
- + "((\\d\\d\\d\\d)|((?:[01]\\d)|(?:2[0123])):([012345]\\d))\\s"
- + "(\\S*)(\\s*.*)";
-
- /**
- * The sole constructor for a EnterpriseUnixFTPEntryParser object.
- *
- */
- public EnterpriseUnixFTPEntryParser()
- {
- super(REGEX);
- }
-
- /**
- * Parses a line of a unix FTP server file listing and converts it into a
- * usable format in the form of an
- * Implementation should be a method that extracts
- * a key from the supplied {@link FTPClientConfig FTPClientConfig}
- * parameter and creates an object implementing the
- * interface FTPFileEntryParser and uses the supplied configuration
- * to configure it.
- *
- * Note that this method will generally not be called in scenarios
- * that call for autodetection of parser type but rather, for situations
- * where the user knows that the server uses a non-default configuration
- * and knows what that configuration is.
- *
- * Set up the {@link FTPClientConfig#setDefaultDateFormatStr(java.lang.String) defaultDateFormat}
- * and optionally the {@link FTPClientConfig#setRecentDateFormatStr(String) recentDateFormat}
- * to values supplied in the config based on month names configured as follows:
- *
- * Finally if a {@link org.apache.commons.net.ftp.FTPClientConfig#setServerTimeZoneId(String) serverTimeZoneId}
- * has been supplied via the config, set that into all date formats that have
- * been configured.
- *
- * @param entry A line of text from the file listing
- * @return An FTPFile instance corresponding to the supplied entry
- */
- public FTPFile parseFTPEntry(String entry)
- {
- FTPFile f = new FTPFile();
- f.setRawListing(entry);
-
- if (matches(entry))
- {
- String datestr = group(1)+" "+group(2);
- String dirString = group(3);
- String size = group(4);
- String name = group(5);
- try
- {
- f.setTimestamp(super.parseTimestamp(datestr));
- }
- catch (ParseException e)
- {
- // intentionally do nothing
- }
-
- if (null == name || name.equals(".") || name.equals(".."))
- {
- return (null);
- }
- f.setName(name);
-
-
- if ("
- *
- * Netware file permissions are in the following format: RWCEAFMS, and are explained as follows:
- *
- * @param entry A line of text from the file listing
- * @return An FTPFile instance corresponding to the supplied entry
- */
- public FTPFile parseFTPEntry(String entry)
- {
-
- FTPFile f = new FTPFile();
- if (matches(entry))
- {
- String size = group(1);
- String attrib = group(2);
- String dirString = group(3);
- String datestr = group(4)+" "+group(5);
- String name = group(6);
- try
- {
- f.setTimestamp(super.parseTimestamp(datestr));
- }
- catch (ParseException e)
- {
- // intentionally do nothing
- }
-
-
- //is it a DIR or a file
- if (dirString.trim().equals("DIR") || attrib.trim().equals("DIR"))
- {
- f.setType(FTPFile.DIRECTORY_TYPE);
- }
- else
- {
- f.setType(FTPFile.FILE_TYPE);
- }
-
-
- //set the name
- f.setName(name.trim());
-
- //set the size
- f.setSize(Long.parseLong(size.trim()));
-
- return (f);
- }
- return null;
-
- }
-
- /**
- * Defines a default configuration to be used when this class is
- * instantiated without a {@link FTPClientConfig FTPClientConfig}
- * parameter being specified.
- * @return the default configuration for this parser.
- */
- @Override
- protected FTPClientConfig getDefaultConfiguration() {
- return new FTPClientConfig(
- FTPClientConfig.SYST_OS2,
- DEFAULT_DATE_FORMAT,
- null, null, null, null);
- }
-
-}
diff --git a/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.class b/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.class
deleted file mode 100644
index b77795b..0000000
Binary files a/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java b/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
deleted file mode 100644
index 66c370b..0000000
--- a/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp.parser;
-
-import java.text.ParseException;
-
-import org.apache.commons.net.ftp.FTPClientConfig;
-import org.apache.commons.net.ftp.FTPFile;
-
-/**
- * @version $Id: OS400FTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
- */
-
-public class OS400FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
-{
- private static final String DEFAULT_DATE_FORMAT
- = "yy/MM/dd HH:mm:ss"; //01/11/09 12:30:24
-
-
-
- private static final String REGEX =
- "(\\S+)\\s+" // user
- + "(\\d+)\\s+" // size
- + "(\\S+)\\s+(\\S+)\\s+" // date stuff
- + "(\\*\\S+)\\s+" // *STMF/*DIR
- + "(\\S+/?)\\s*"; // filename
-
-
- /**
- * The default constructor for a OS400FTPEntryParser object.
- *
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- *
- * For now end users may specify this format only via
- *
- * @param entry A line of text from the file listing
- * @return An FTPFile instance corresponding to the supplied entry
- */
- public FTPFile parseFTPEntry(String entry) {
- FTPFile file = new FTPFile();
- file.setRawListing(entry);
- int type;
- boolean isDevice = false;
-
- if (matches(entry))
- {
- String typeStr = group(1);
- String hardLinkCount = group(15);
- String usr = group(16);
- String grp = group(17);
- String filesize = group(18);
- String datestr = group(19) + " " + group(20);
- String name = group(21);
- String endtoken = group(22);
-
- try
- {
- file.setTimestamp(super.parseTimestamp(datestr));
- }
- catch (ParseException e)
- {
- // intentionally do nothing
- }
-
-
- // bcdlfmpSs-
- switch (typeStr.charAt(0))
- {
- case 'd':
- type = FTPFile.DIRECTORY_TYPE;
- break;
- case 'e':
- type = FTPFile.SYMBOLIC_LINK_TYPE;
- break;
- case 'l':
- type = FTPFile.SYMBOLIC_LINK_TYPE;
- break;
- case 'b':
- case 'c':
- isDevice = true;
- // break; - fall through
- case 'f':
- case '-':
- type = FTPFile.FILE_TYPE;
- break;
- default:
- type = FTPFile.UNKNOWN_TYPE;
- }
-
- file.setType(type);
-
- int g = 4;
- for (int access = 0; access < 3; access++, g += 4)
- {
- // Use != '-' to avoid having to check for suid and sticky bits
- file.setPermission(access, FTPFile.READ_PERMISSION,
- (!group(g).equals("-")));
- file.setPermission(access, FTPFile.WRITE_PERMISSION,
- (!group(g + 1).equals("-")));
-
- String execPerm = group(g + 2);
- if (!execPerm.equals("-") && !Character.isUpperCase(execPerm.charAt(0)))
- {
- file.setPermission(access, FTPFile.EXECUTE_PERMISSION, true);
- }
- else
- {
- file.setPermission(access, FTPFile.EXECUTE_PERMISSION, false);
- }
- }
-
- if (!isDevice)
- {
- try
- {
- file.setHardLinkCount(Integer.parseInt(hardLinkCount));
- }
- catch (NumberFormatException e)
- {
- // intentionally do nothing
- }
- }
-
- file.setUser(usr);
- file.setGroup(grp);
-
- try
- {
- file.setSize(Long.parseLong(filesize));
- }
- catch (NumberFormatException e)
- {
- // intentionally do nothing
- }
-
- if (null == endtoken)
- {
- file.setName(name);
- }
- else
- {
- // oddball cases like symbolic links, file names
- // with spaces in them.
- name += endtoken;
- if (type == FTPFile.SYMBOLIC_LINK_TYPE)
- {
-
- int end = name.indexOf(" -> ");
- // Give up if no link indicator is present
- if (end == -1)
- {
- file.setName(name);
- }
- else
- {
- file.setName(name.substring(0, end));
- file.setLink(name.substring(end + 4));
- }
-
- }
- else
- {
- file.setName(name);
- }
- }
- return file;
- }
- return null;
- }
-
- /**
- * Defines a default configuration to be used when this class is
- * instantiated without a {@link FTPClientConfig FTPClientConfig}
- * parameter being specified.
- * @return the default configuration for this parser.
- */
- @Override
- protected FTPClientConfig getDefaultConfiguration() {
- return new FTPClientConfig(
- FTPClientConfig.SYST_UNIX,
- DEFAULT_DATE_FORMAT,
- DEFAULT_RECENT_DATE_FORMAT,
- null, null, null);
- }
-
-}
diff --git a/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.class b/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.class
deleted file mode 100644
index ee8d5f3..0000000
Binary files a/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java b/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java
deleted file mode 100644
index 1e55ede..0000000
--- a/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp.parser;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.ParseException;
-import java.util.StringTokenizer;
-
-import org.apache.commons.net.ftp.FTPClientConfig;
-import org.apache.commons.net.ftp.FTPFile;
-import org.apache.commons.net.ftp.FTPListParseEngine;
-
-/**
- * Implementation FTPFileEntryParser and FTPFileListParser for VMS Systems.
- * This is a sample of VMS LIST output
- *
- * "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
- * "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
- * "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
- *
- * Note: VMSFTPEntryParser can only be instantiated through the
- * DefaultFTPParserFactory by classname. It will not be chosen
- * by the autodetection scheme.
- *
- *
- *
- * @author Winston Ojeda
- * @author Steve Cohen
- * @author Stephane ESTE-GRACIAS
- * @version $Id: VMSFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
- *
- * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
- * @see org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory
- */
-public class VMSFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
-{
-
- private static final String DEFAULT_DATE_FORMAT
- = "d-MMM-yyyy HH:mm:ss"; //9-NOV-2001 12:30:24
-
- /**
- * this is the regular expression used by this parser.
- */
- private static final String REGEX =
- "(.*;[0-9]+)\\s*" //1 file and version
- + "(\\d+)/\\d+\\s*" //2 size/allocated
- +"(\\S+)\\s+(\\S+)\\s+" //3+4 date and time
- + "\\[(([0-9$A-Za-z_]+)|([0-9$A-Za-z_]+),([0-9$a-zA-Z_]+))\\]?\\s*" //5(6,7,8) owner
- + "\\([a-zA-Z]*,([a-zA-Z]*),([a-zA-Z]*),([a-zA-Z]*)\\)"; //9,10,11 Permissions (O,G,W)
- // TODO - perhaps restrict permissions to [RWED]* ?
-
-
-
- /**
- * Constructor for a VMSFTPEntryParser object.
- *
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- *
- * @param listStream The InputStream from which the file list should be
- * read.
- * @return The list of file information contained in the given path. null
- * if the list could not be obtained or if there are no files in
- * the directory.
- * @exception IOException If an I/O error occurs reading the listStream.
- ***/
- public FTPFile[] parseFileList(InputStream listStream) throws IOException {
- FTPListParseEngine engine = new FTPListParseEngine(this);
- engine.readServerList(listStream);
- return engine.getFiles();
- }
-
-
-
- /**
- * Parses a line of a VMS FTP server file listing and converts it into a
- * usable format in the form of an
- * @param entry A line of text from the file listing
- * @return An FTPFile instance corresponding to the supplied entry
- */
- public FTPFile parseFTPEntry(String entry)
- {
- //one block in VMS equals 512 bytes
- long longBlock = 512;
-
- if (matches(entry))
- {
- FTPFile f = new FTPFile();
- f.setRawListing(entry);
- String name = group(1);
- String size = group(2);
- String datestr = group(3)+" "+group(4);
- String owner = group(5);
- String permissions[] = new String[3];
- permissions[0]= group(9);
- permissions[1]= group(10);
- permissions[2]= group(11);
- try
- {
- f.setTimestamp(super.parseTimestamp(datestr));
- }
- catch (ParseException e)
- {
- // intentionally do nothing
- }
-
-
- String grp;
- String user;
- StringTokenizer t = new StringTokenizer(owner, ",");
- switch (t.countTokens()) {
- case 1:
- grp = null;
- user = t.nextToken();
- break;
- case 2:
- grp = t.nextToken();
- user = t.nextToken();
- break;
- default:
- grp = null;
- user = null;
- }
-
- if (name.lastIndexOf(".DIR") != -1)
- {
- f.setType(FTPFile.DIRECTORY_TYPE);
- }
- else
- {
- f.setType(FTPFile.FILE_TYPE);
- }
- //set FTPFile name
- //Check also for versions to be returned or not
- if (isVersioning())
- {
- f.setName(name);
- }
- else
- {
- name = name.substring(0, name.lastIndexOf(";"));
- f.setName(name);
- }
- //size is retreived in blocks and needs to be put in bytes
- //for us humans and added to the FTPFile array
- long sizeInBytes = Long.parseLong(size) * longBlock;
- f.setSize(sizeInBytes);
-
- f.setGroup(grp);
- f.setUser(user);
- //set group and owner
-
- //Set file permission.
- //VMS has (SYSTEM,OWNER,GROUP,WORLD) users that can contain
- //R (read) W (write) E (execute) D (delete)
-
- //iterate for OWNER GROUP WORLD permissions
- for (int access = 0; access < 3; access++)
- {
- String permission = permissions[access];
-
- f.setPermission(access, FTPFile.READ_PERMISSION, permission.indexOf('R')>=0);
- f.setPermission(access, FTPFile.WRITE_PERMISSION, permission.indexOf('W')>=0);
- f.setPermission(access, FTPFile.EXECUTE_PERMISSION, permission.indexOf('E')>=0);
- }
-
- return f;
- }
- return null;
- }
-
-
- /**
- * Reads the next entry using the supplied BufferedReader object up to
- * whatever delemits one entry from the next. This parser cannot use
- * the default implementation of simply calling BufferedReader.readLine(),
- * because one entry may span multiple lines.
- *
- * @param reader The BufferedReader object from which entries are to be
- * read.
- *
- * @return A string representing the next ftp entry or null if none found.
- * @exception IOException thrown on any IO Error reading from the reader.
- */
- @Override
- public String readNextEntry(BufferedReader reader) throws IOException
- {
- String line = reader.readLine();
- StringBuffer entry = new StringBuffer();
- while (line != null)
- {
- if (line.startsWith("Directory") || line.startsWith("Total")) {
- line = reader.readLine();
- continue;
- }
-
- entry.append(line);
- if (line.trim().endsWith(")"))
- {
- break;
- }
- line = reader.readLine();
- }
- return (entry.length() == 0 ? null : entry.toString());
- }
-
- protected boolean isVersioning() {
- return false;
- }
-
- /**
- * Defines a default configuration to be used when this class is
- * instantiated without a {@link FTPClientConfig FTPClientConfig}
- * parameter being specified.
- * @return the default configuration for this parser.
- */
- @Override
- protected FTPClientConfig getDefaultConfiguration() {
- return new FTPClientConfig(
- FTPClientConfig.SYST_VMS,
- DEFAULT_DATE_FORMAT,
- null, null, null, null);
- }
-
-
-}
-
-/* Emacs configuration
- * Local variables: **
- * mode: java **
- * c-basic-offset: 4 **
- * indent-tabs-mode: nil **
- * End: **
- */
diff --git a/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser$NameVersion.class b/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser$NameVersion.class
deleted file mode 100644
index fd27f2a..0000000
Binary files a/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser$NameVersion.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.class b/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.class
deleted file mode 100644
index c0e20b6..0000000
Binary files a/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java b/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java
deleted file mode 100644
index cb25709..0000000
--- a/org/apache/commons/net/ftp/parser/VMSVersioningFTPEntryParser.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp.parser;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.regex.MatchResult;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import org.apache.commons.net.ftp.FTPClientConfig;
-
-/**
- * Special implementation VMSFTPEntryParser with versioning turned on.
- * This parser removes all duplicates and only leaves the version with the highest
- * version number for each filename.
- *
- * This is a sample of VMS LIST output
- *
- * "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
- * "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
- * "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
- *
- *
- * @author Winston Ojeda
- * @author Stephane ESTE-GRACIAS
- * @version $Id: VMSVersioningFTPEntryParser.java 636854 2008-03-13 19:55:01Z sebb $
- *
- * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
- */
-public class VMSVersioningFTPEntryParser extends VMSFTPEntryParser
-{
-
- private Matcher _preparse_matcher_;
- private Pattern _preparse_pattern_;
- private static final String PRE_PARSE_REGEX =
- "(.*);([0-9]+)\\s*.*";
-
- /**
- * Constructor for a VMSFTPEntryParser object. Sets the versioning member
- * to the supplied value.
- *
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- *
- *
- * @see CopyStreamEvent
- * @see CopyStreamListener
- * @see Util
- * @author Daniel F. Savarese
- * @version $Id: CopyStreamAdapter.java 489397 2006-12-21 16:28:51Z rwinston $
- */
-public class CopyStreamAdapter implements CopyStreamListener
-{
- private ListenerList internalListeners;
-
- /**
- * Creates a new copyStreamAdapter.
- */
- public CopyStreamAdapter()
- {
- internalListeners = new ListenerList();
- }
-
- /**
- * This method is invoked by a CopyStreamEvent source after copying
- * a block of bytes from a stream. The CopyStreamEvent will contain
- * the total number of bytes transferred so far and the number of bytes
- * transferred in the last write. The CopyStreamAdapater will relay
- * the event to all of its registered listeners, listing itself as the
- * source of the event.
- * @param event The CopyStreamEvent fired by the copying of a block of
- * bytes.
- */
- public void bytesTransferred(CopyStreamEvent event)
- {
- bytesTransferred(event.getTotalBytesTransferred(),
- event.getBytesTransferred(),
- event.getStreamSize());
- }
-
- /**
- * This method is not part of the JavaBeans model and is used by the
- * static methods in the org.apache.commons.io.Util class for efficiency.
- * It is invoked after a block of bytes to inform the listener of the
- * transfer. The CopyStreamAdapater will create a CopyStreamEvent
- * from the arguments and relay the event to all of its registered
- * listeners, listing itself as the source of the event.
- * @param totalBytesTransferred The total number of bytes transferred
- * so far by the copy operation.
- * @param bytesTransferred The number of bytes copied by the most recent
- * write.
- * @param streamSize The number of bytes in the stream being copied.
- * This may be equal to CopyStreamEvent.UNKNOWN_STREAM_SIZE if
- * the size is unknown.
- */
- public void bytesTransferred(long totalBytesTransferred,
- int bytesTransferred, long streamSize)
- {
- CopyStreamEvent event;
-
- event = new CopyStreamEvent(this,
- totalBytesTransferred,
- bytesTransferred,
- streamSize);
-
- for (EventListener listener : internalListeners)
- {
- ((CopyStreamListener) (listener)).bytesTransferred(event);
- }
- }
-
- /**
- * Registers a CopyStreamListener to receive CopyStreamEvents.
- * Although this method is not declared to be synchronized, it is
- * implemented in a thread safe manner.
- * @param listener The CopyStreamlistener to register.
- */
- public void addCopyStreamListener(CopyStreamListener listener)
- {
- internalListeners.addListener(listener);
- }
-
- /**
- * Unregisters a CopyStreamListener. Although this method is not
- * synchronized, it is implemented in a thread safe manner.
- * @param listener The CopyStreamlistener to unregister.
- */
- public void removeCopyStreamListener(CopyStreamListener listener)
- {
- internalListeners.removeListener(listener);
- }
-}
diff --git a/org/apache/commons/net/io/CopyStreamEvent.class b/org/apache/commons/net/io/CopyStreamEvent.class
deleted file mode 100644
index 66d719c..0000000
Binary files a/org/apache/commons/net/io/CopyStreamEvent.class and /dev/null differ
diff --git a/org/apache/commons/net/io/CopyStreamEvent.java b/org/apache/commons/net/io/CopyStreamEvent.java
deleted file mode 100644
index d7d0ec3..0000000
--- a/org/apache/commons/net/io/CopyStreamEvent.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.util.EventObject;
-
-/**
- * A CopyStreamEvent is triggered after every write performed by a
- * stream copying operation. The event stores the number of bytes
- * transferred by the write triggering the event as well as the total
- * number of bytes transferred so far by the copy operation.
- *
- *
- * @see CopyStreamListener
- * @see CopyStreamAdapter
- * @see Util
- * @author Daniel F. Savarese
- * @version $Id: CopyStreamEvent.java 489397 2006-12-21 16:28:51Z rwinston $
- */
-public class CopyStreamEvent extends EventObject
-{
- /**
- * Constant used to indicate the stream size is unknown.
- */
- public static final long UNKNOWN_STREAM_SIZE = -1;
-
- private int bytesTransferred;
- private long totalBytesTransferred;
- private long streamSize;
-
- /**
- * Creates a new CopyStreamEvent instance.
- * @param source The source of the event.
- * @param totalBytesTransferred The total number of bytes transferred so
- * far during a copy operation.
- * @param bytesTransferred The number of bytes transferred during the
- * write that triggered the CopyStreamEvent.
- * @param streamSize The number of bytes in the stream being copied.
- * This may be set to
- *
- * @see CopyStreamEvent
- * @see CopyStreamAdapter
- * @see Util
- * @author Daniel F. Savarese
- * @version $Id: CopyStreamListener.java 489397 2006-12-21 16:28:51Z rwinston $
- */
-public interface CopyStreamListener extends EventListener
-{
- /**
- * This method is invoked by a CopyStreamEvent source after copying
- * a block of bytes from a stream. The CopyStreamEvent will contain
- * the total number of bytes transferred so far and the number of bytes
- * transferred in the last write.
- * @param event The CopyStreamEvent fired by the copying of a block of
- * bytes.
- */
- public void bytesTransferred(CopyStreamEvent event);
-
-
- /**
- * This method is not part of the JavaBeans model and is used by the
- * static methods in the org.apache.commons.io.Util class for efficiency.
- * It is invoked after a block of bytes to inform the listener of the
- * transfer.
- * @param totalBytesTransferred The total number of bytes transferred
- * so far by the copy operation.
- * @param bytesTransferred The number of bytes copied by the most recent
- * write.
- * @param streamSize The number of bytes in the stream being copied.
- * This may be equal to CopyStreamEvent.UNKNOWN_STREAM_SIZE if
- * the size is unknown.
- */
- public void bytesTransferred(long totalBytesTransferred,
- int bytesTransferred,
- long streamSize);
-}
diff --git a/org/apache/commons/net/io/DotTerminatedMessageReader.java b/org/apache/commons/net/io/DotTerminatedMessageReader.java
deleted file mode 100644
index c0f344d..0000000
--- a/org/apache/commons/net/io/DotTerminatedMessageReader.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.io.IOException;
-import java.io.PushbackReader;
-import java.io.Reader;
-
-/**
- * DotTerminatedMessageReader is a class used to read messages from a
- * server that are terminated by a single dot followed by a
- * <CR><LF>
- * sequence and with double dots appearing at the begining of lines which
- * do not signal end of message yet start with a dot. Various Internet
- * protocols such as NNTP and POP3 produce messages of this type.
- *
- * This class handles stripping of the duplicate period at the beginning
- * of lines starting with a period, converts NETASCII newlines to the
- * local line separator format, truncates the end of message indicator,
- * and ensures you cannot read past the end of the message.
- * @author Daniel F. Savarese
- * @version $Id: DotTerminatedMessageReader.java 636825 2008-03-13 18:34:52Z sebb $
- */
-public final class DotTerminatedMessageReader extends Reader
-{
- private static final String LS;
- private static final char[] LS_CHARS;
-
- static
- {
- LS = System.getProperty("line.separator");
- LS_CHARS = LS.toCharArray();
- }
-
- private boolean atBeginning;
- private boolean eof;
- private int pos;
- private char[] internalBuffer;
- private PushbackReader internalReader;
-
- /**
- * Creates a DotTerminatedMessageReader that wraps an existing Reader
- * input source.
- * @param reader The Reader input source containing the message.
- */
- public DotTerminatedMessageReader(Reader reader)
- {
- super(reader);
- internalBuffer = new char[LS_CHARS.length + 3];
- pos = internalBuffer.length;
- // Assumes input is at start of message
- atBeginning = true;
- eof = false;
- internalReader = new PushbackReader(reader);
- }
-
- /**
- * Reads and returns the next character in the message. If the end of the
- * message has been reached, returns -1. Note that a call to this method
- * may result in multiple reads from the underlying input stream to decode
- * the message properly (removing doubled dots and so on). All of
- * this is transparent to the programmer and is only mentioned for
- * completeness.
- * @return The next character in the message. Returns -1 if the end of the
- * message has been reached.
- * @exception IOException If an error occurs while reading the underlying
- * stream.
- */
- @Override
- public int read() throws IOException
- {
- int ch;
-
- synchronized (lock)
- {
- if (pos < internalBuffer.length)
- {
- return internalBuffer[pos++];
- }
-
- if (eof)
- {
- return -1;
- }
-
- if ((ch = internalReader.read()) == -1)
- {
- eof = true;
- return -1;
- }
-
- if (atBeginning)
- {
- atBeginning = false;
- if (ch == '.')
- {
- ch = internalReader.read();
-
- if (ch != '.')
- {
- // read newline
- eof = true;
- internalReader.read();
- return -1;
- }
- else
- {
- return '.';
- }
- }
- }
-
- if (ch == '\r')
- {
- ch = internalReader.read();
-
- if (ch == '\n')
- {
- ch = internalReader.read();
-
- if (ch == '.')
- {
- ch = internalReader.read();
-
- if (ch != '.')
- {
- // read newline and indicate end of file
- internalReader.read();
- eof = true;
- }
- else
- {
- internalBuffer[--pos] = (char) ch;
- }
- }
- else
- {
- internalReader.unread(ch);
- }
-
- pos -= LS_CHARS.length;
- System.arraycopy(LS_CHARS, 0, internalBuffer, pos,
- LS_CHARS.length);
- ch = internalBuffer[pos++];
- }
- else
- {
- internalBuffer[--pos] = (char) ch;
- return '\r';
- }
- }
-
- return ch;
- }
- }
-
- /**
- * Reads the next characters from the message into an array and
- * returns the number of characters read. Returns -1 if the end of the
- * message has been reached.
- * @param buffer The character array in which to store the characters.
- * @return The number of characters read. Returns -1 if the
- * end of the message has been reached.
- * @exception IOException If an error occurs in reading the underlying
- * stream.
- */
- @Override
- public int read(char[] buffer) throws IOException
- {
- return read(buffer, 0, buffer.length);
- }
-
- /**
- * Reads the next characters from the message into an array and
- * returns the number of characters read. Returns -1 if the end of the
- * message has been reached. The characters are stored in the array
- * starting from the given offset and up to the length specified.
- * @param buffer The character array in which to store the characters.
- * @param offset The offset into the array at which to start storing
- * characters.
- * @param length The number of characters to read.
- * @return The number of characters read. Returns -1 if the
- * end of the message has been reached.
- * @exception IOException If an error occurs in reading the underlying
- * stream.
- */
- @Override
- public int read(char[] buffer, int offset, int length) throws IOException
- {
- int ch, off;
- synchronized (lock)
- {
- if (length < 1)
- {
- return 0;
- }
- if ((ch = read()) == -1)
- {
- return -1;
- }
- off = offset;
-
- do
- {
- buffer[offset++] = (char) ch;
- }
- while (--length > 0 && (ch = read()) != -1);
-
- return (offset - off);
- }
- }
-
- /**
- * Determines if the message is ready to be read.
- * @return True if the message is ready to be read, false if not.
- * @exception IOException If an error occurs while checking the underlying
- * stream.
- */
- @Override
- public boolean ready() throws IOException
- {
- synchronized (lock)
- {
- return (pos < internalBuffer.length || internalReader.ready());
- }
- }
-
- /**
- * Closes the message for reading. This doesn't actually close the
- * underlying stream. The underlying stream may still be used for
- * communicating with the server and therefore is not closed.
- *
- * If the end of the message has not yet been reached, this method
- * will read the remainder of the message until it reaches the end,
- * so that the underlying stream may continue to be used properly
- * for communicating with the server. If you do not fully read
- * a message, you MUST close it, otherwise your program will likely
- * hang or behave improperly.
- * @exception IOException If an error occurs while reading the
- * underlying stream.
- */
- @Override
- public void close() throws IOException
- {
- synchronized (lock)
- {
- if (internalReader == null)
- {
- return;
- }
-
- if (!eof)
- {
- while (read() != -1)
- {
- ;
- }
- }
- eof = true;
- atBeginning = false;
- pos = internalBuffer.length;
- internalReader = null;
- }
- }
-}
diff --git a/org/apache/commons/net/io/DotTerminatedMessageWriter.java b/org/apache/commons/net/io/DotTerminatedMessageWriter.java
deleted file mode 100644
index 853e42f..0000000
--- a/org/apache/commons/net/io/DotTerminatedMessageWriter.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.io.IOException;
-import java.io.Writer;
-
-/***
- * DotTerminatedMessageWriter is a class used to write messages to a
- * server that are terminated by a single dot followed by a
- * <CR><LF>
- * sequence and with double dots appearing at the begining of lines which
- * do not signal end of message yet start with a dot. Various Internet
- * protocols such as NNTP and POP3 produce messages of this type.
- *
- * This class handles the doubling of line-starting periods,
- * converts single linefeeds to NETASCII newlines, and on closing
- * will send the final message terminator dot and NETASCII newline
- * sequence.
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class DotTerminatedMessageWriter extends Writer
-{
- private static final int __NOTHING_SPECIAL_STATE = 0;
- private static final int __LAST_WAS_CR_STATE = 1;
- private static final int __LAST_WAS_NL_STATE = 2;
-
- private int __state;
- private Writer __output;
-
-
- /***
- * Creates a DotTerminatedMessageWriter that wraps an existing Writer
- * output destination.
- *
- * @param output The Writer output destination to write the message.
- ***/
- public DotTerminatedMessageWriter(Writer output)
- {
- super(output);
- __output = output;
- __state = __NOTHING_SPECIAL_STATE;
- }
-
-
- /***
- * Writes a character to the output. Note that a call to this method
- * may result in multiple writes to the underling Writer in order to
- * convert naked linefeeds to NETASCII line separators and to double
- * line-leading periods. This is transparent to the programmer and
- * is only mentioned for completeness.
- *
- * @param ch The character to write.
- * @exception IOException If an error occurs while writing to the
- * underlying output.
- ***/
- @Override
- public void write(int ch) throws IOException
- {
- synchronized (lock)
- {
- switch (ch)
- {
- case '\r':
- __state = __LAST_WAS_CR_STATE;
- __output.write('\r');
- return ;
- case '\n':
- if (__state != __LAST_WAS_CR_STATE)
- __output.write('\r');
- __output.write('\n');
- __state = __LAST_WAS_NL_STATE;
- return ;
- case '.':
- // Double the dot at the beginning of a line
- if (__state == __LAST_WAS_NL_STATE)
- __output.write('.');
- // Fall through
- default:
- __state = __NOTHING_SPECIAL_STATE;
- __output.write(ch);
- return ;
- }
- }
- }
-
-
- /***
- * Writes a number of characters from a character array to the output
- * starting from a given offset.
- *
- * @param buffer The character array to write.
- * @param offset The offset into the array at which to start copying data.
- * @param length The number of characters to write.
- * @exception IOException If an error occurs while writing to the underlying
- * output.
- ***/
- @Override
- public void write(char[] buffer, int offset, int length) throws IOException
- {
- synchronized (lock)
- {
- while (length-- > 0)
- write(buffer[offset++]);
- }
- }
-
-
- /***
- * Writes a character array to the output.
- *
- * @param buffer The character array to write.
- * @exception IOException If an error occurs while writing to the underlying
- * output.
- ***/
- @Override
- public void write(char[] buffer) throws IOException
- {
- write(buffer, 0, buffer.length);
- }
-
-
- /***
- * Writes a String to the output.
- *
- * @param string The String to write.
- * @exception IOException If an error occurs while writing to the underlying
- * output.
- ***/
- @Override
- public void write(String string) throws IOException
- {
- write(string.toCharArray());
- }
-
-
- /***
- * Writes part of a String to the output starting from a given offset.
- *
- * @param string The String to write.
- * @param offset The offset into the String at which to start copying data.
- * @param length The number of characters to write.
- * @exception IOException If an error occurs while writing to the underlying
- * output.
- ***/
- @Override
- public void write(String string, int offset, int length) throws IOException
- {
- write(string.toCharArray(), offset, length);
- }
-
-
- /***
- * Flushes the underlying output, writing all buffered output.
- *
- * @exception IOException If an error occurs while writing to the underlying
- * output.
- ***/
- @Override
- public void flush() throws IOException
- {
- synchronized (lock)
- {
- __output.flush();
- }
- }
-
-
- /***
- * Flushes the underlying output, writing all buffered output, but doesn't
- * actually close the underlying stream. The underlying stream may still
- * be used for communicating with the server and therefore is not closed.
- *
- * @exception IOException If an error occurs while writing to the underlying
- * output or closing the Writer.
- ***/
- @Override
- public void close() throws IOException
- {
- synchronized (lock)
- {
- if (__output == null)
- return ;
-
- if (__state == __LAST_WAS_CR_STATE)
- __output.write('\n');
- else if (__state != __LAST_WAS_NL_STATE)
- __output.write("\r\n");
-
- __output.write(".\r\n");
-
- __output.flush();
- __output = null;
- }
- }
-
-}
diff --git a/org/apache/commons/net/io/FromNetASCIIInputStream.class b/org/apache/commons/net/io/FromNetASCIIInputStream.class
deleted file mode 100644
index d3bf9c1..0000000
Binary files a/org/apache/commons/net/io/FromNetASCIIInputStream.class and /dev/null differ
diff --git a/org/apache/commons/net/io/FromNetASCIIInputStream.java b/org/apache/commons/net/io/FromNetASCIIInputStream.java
deleted file mode 100644
index 76588ab..0000000
--- a/org/apache/commons/net/io/FromNetASCIIInputStream.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PushbackInputStream;
-
-/***
- * This class wraps an input stream, replacing all occurrences
- * of <CR><LF> (carriage return followed by a linefeed),
- * which is the NETASCII standard for representing a newline, with the
- * local line separator representation. You would use this class to
- * implement ASCII file transfers requiring conversion from NETASCII.
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class FromNetASCIIInputStream extends PushbackInputStream
-{
- static final boolean _noConversionRequired;
- static final String _lineSeparator;
- static final byte[] _lineSeparatorBytes;
-
- static {
- _lineSeparator = System.getProperty("line.separator");
- _noConversionRequired = _lineSeparator.equals("\r\n");
- _lineSeparatorBytes = _lineSeparator.getBytes();
- }
-
- private int __length = 0;
-
- /***
- * Returns true if the NetASCII line separator differs from the system
- * line separator, false if they are the same. This method is useful
- * to determine whether or not you need to instantiate a
- * FromNetASCIIInputStream object.
- *
- * @return True if the NETASCII line separator differs from the local
- * system line separator, false if they are the same.
- ***/
- public static final boolean isConversionRequired()
- {
- return !_noConversionRequired;
- }
-
- /***
- * Creates a FromNetASCIIInputStream instance that wraps an existing
- * InputStream.
- ***/
- public FromNetASCIIInputStream(InputStream input)
- {
- super(input, _lineSeparatorBytes.length + 1);
- }
-
-
- private int __read() throws IOException
- {
- int ch;
-
- ch = super.read();
-
- if (ch == '\r')
- {
- ch = super.read();
- if (ch == '\n')
- {
- unread(_lineSeparatorBytes);
- ch = super.read();
- // This is a kluge for read(byte[], ...) to read the right amount
- --__length;
- }
- else
- {
- if (ch != -1)
- unread(ch);
- return '\r';
- }
- }
-
- return ch;
- }
-
-
- /***
- * Reads and returns the next byte in the stream. If the end of the
- * message has been reached, returns -1. Note that a call to this method
- * may result in multiple reads from the underlying input stream in order
- * to convert NETASCII line separators to the local line separator format.
- * This is transparent to the programmer and is only mentioned for
- * completeness.
- *
- * @return The next character in the stream. Returns -1 if the end of the
- * stream has been reached.
- * @exception IOException If an error occurs while reading the underlying
- * stream.
- ***/
- @Override
- public int read() throws IOException
- {
- if (_noConversionRequired)
- return super.read();
-
- return __read();
- }
-
-
- /***
- * Reads the next number of bytes from the stream into an array and
- * returns the number of bytes read. Returns -1 if the end of the
- * stream has been reached.
- *
- * @param buffer The byte array in which to store the data.
- * @return The number of bytes read. Returns -1 if the
- * end of the message has been reached.
- * @exception IOException If an error occurs in reading the underlying
- * stream.
- ***/
- @Override
- public int read(byte buffer[]) throws IOException
- {
- return read(buffer, 0, buffer.length);
- }
-
-
- /***
- * Reads the next number of bytes from the stream into an array and returns
- * the number of bytes read. Returns -1 if the end of the
- * message has been reached. The characters are stored in the array
- * starting from the given offset and up to the length specified.
- *
- * @param buffer The byte array in which to store the data.
- * @param offset The offset into the array at which to start storing data.
- * @param length The number of bytes to read.
- * @return The number of bytes read. Returns -1 if the
- * end of the stream has been reached.
- * @exception IOException If an error occurs while reading the underlying
- * stream.
- ***/
- @Override
- public int read(byte buffer[], int offset, int length) throws IOException
- {
- int ch, off;
-
- if (length < 1)
- return 0;
-
- ch = available();
-
- __length = (length > ch ? ch : length);
-
- // If nothing is available, block to read only one character
- if (__length < 1)
- __length = 1;
-
- if (_noConversionRequired)
- return super.read(buffer, offset, __length);
-
- if ((ch = __read()) == -1)
- return -1;
-
- off = offset;
-
- do
- {
- buffer[offset++] = (byte)ch;
- }
- while (--__length > 0 && (ch = __read()) != -1);
-
-
- return (offset - off);
- }
-
-
- // PushbackInputStream in JDK 1.1.3 returns the wrong thing
- /***
- * Returns the number of bytes that can be read without blocking EXCEPT
- * when newline conversions have to be made somewhere within the
- * available block of bytes. In other words, you really should not
- * rely on the value returned by this method if you are trying to avoid
- * blocking.
- ***/
- @Override
- public int available() throws IOException
- {
- return (buf.length - pos) + in.available();
- }
-
-}
diff --git a/org/apache/commons/net/io/FromNetASCIIOutputStream.java b/org/apache/commons/net/io/FromNetASCIIOutputStream.java
deleted file mode 100644
index c025a1b..0000000
--- a/org/apache/commons/net/io/FromNetASCIIOutputStream.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/***
- * This class wraps an output stream, replacing all occurrences
- * of <CR><LF> (carriage return followed by a linefeed),
- * which is the NETASCII standard for representing a newline, with the
- * local line separator representation. You would use this class to
- * implement ASCII file transfers requiring conversion from NETASCII.
- *
- * Because of the translation process, a call to
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class FromNetASCIIOutputStream extends FilterOutputStream
-{
- private boolean __lastWasCR;
-
- /***
- * Creates a FromNetASCIIOutputStream instance that wraps an existing
- * OutputStream.
- *
- * @param output The OutputStream to wrap.
- ***/
- public FromNetASCIIOutputStream(OutputStream output)
- {
- super(output);
- __lastWasCR = false;
- }
-
-
- private void __write(int ch) throws IOException
- {
- switch (ch)
- {
- case '\r':
- __lastWasCR = true;
- // Don't write anything. We need to see if next one is linefeed
- break;
- case '\n':
- if (__lastWasCR)
- {
- out.write(FromNetASCIIInputStream._lineSeparatorBytes);
- __lastWasCR = false;
- break;
- }
- __lastWasCR = false;
- out.write('\n');
- break;
- default:
- if (__lastWasCR)
- {
- out.write('\r');
- __lastWasCR = false;
- }
- out.write(ch);
- break;
- }
- }
-
-
- /***
- * Writes a byte to the stream. Note that a call to this method
- * might not actually write a byte to the underlying stream until a
- * subsequent character is written, from which it can be determined if
- * a NETASCII line separator was encountered.
- * This is transparent to the programmer and is only mentioned for
- * completeness.
- *
- * @param ch The byte to write.
- * @exception IOException If an error occurs while writing to the underlying
- * stream.
- ***/
- @Override
- public synchronized void write(int ch)
- throws IOException
- {
- if (FromNetASCIIInputStream._noConversionRequired)
- {
- out.write(ch);
- return ;
- }
-
- __write(ch);
- }
-
-
- /***
- * Writes a byte array to the stream.
- *
- * @param buffer The byte array to write.
- * @exception IOException If an error occurs while writing to the underlying
- * stream.
- ***/
- @Override
- public synchronized void write(byte buffer[])
- throws IOException
- {
- write(buffer, 0, buffer.length);
- }
-
-
- /***
- * Writes a number of bytes from a byte array to the stream starting from
- * a given offset.
- *
- * @param buffer The byte array to write.
- * @param offset The offset into the array at which to start copying data.
- * @param length The number of bytes to write.
- * @exception IOException If an error occurs while writing to the underlying
- * stream.
- ***/
- @Override
- public synchronized void write(byte buffer[], int offset, int length)
- throws IOException
- {
- if (FromNetASCIIInputStream._noConversionRequired)
- {
- // FilterOutputStream method is very slow.
- //super.write(buffer, offset, length);
- out.write(buffer, offset, length);
- return ;
- }
-
- while (length-- > 0)
- __write(buffer[offset++]);
- }
-
-
- /***
- * Closes the stream, writing all pending data.
- *
- * @exception IOException If an error occurs while closing the stream.
- ***/
- @Override
- public synchronized void close()
- throws IOException
- {
- if (FromNetASCIIInputStream._noConversionRequired)
- {
- super.close();
- return ;
- }
-
- if (__lastWasCR)
- out.write('\r');
- super.close();
- }
-}
diff --git a/org/apache/commons/net/io/SocketInputStream.class b/org/apache/commons/net/io/SocketInputStream.class
deleted file mode 100644
index 97657e8..0000000
Binary files a/org/apache/commons/net/io/SocketInputStream.class and /dev/null differ
diff --git a/org/apache/commons/net/io/SocketInputStream.java b/org/apache/commons/net/io/SocketInputStream.java
deleted file mode 100644
index 673f434..0000000
--- a/org/apache/commons/net/io/SocketInputStream.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.Socket;
-
-/***
- * This class wraps an input stream, storing a reference to its originating
- * socket. When the stream is closed, it will also close the socket
- * immediately afterward. This class is useful for situations where you
- * are dealing with a stream originating from a socket, but do not have
- * a reference to the socket, and want to make sure it closes when the
- * stream closes.
- *
- *
- * @author Daniel F. Savarese
- * @see SocketOutputStream
- ***/
-
-public class SocketInputStream extends FilterInputStream
-{
- private Socket __socket;
-
- /***
- * Creates a SocketInputStream instance wrapping an input stream and
- * storing a reference to a socket that should be closed on closing
- * the stream.
- *
- * @param socket The socket to close on closing the stream.
- * @param stream The input stream to wrap.
- ***/
- public SocketInputStream(Socket socket, InputStream stream)
- {
- super(stream);
- __socket = socket;
- }
-
- /***
- * Closes the stream and immediately afterward closes the referenced
- * socket.
- *
- * @exception IOException If there is an error in closing the stream
- * or socket.
- ***/
- @Override
- public void close() throws IOException
- {
- super.close();
- __socket.close();
- }
-}
diff --git a/org/apache/commons/net/io/SocketOutputStream.class b/org/apache/commons/net/io/SocketOutputStream.class
deleted file mode 100644
index 41a30e5..0000000
Binary files a/org/apache/commons/net/io/SocketOutputStream.class and /dev/null differ
diff --git a/org/apache/commons/net/io/SocketOutputStream.java b/org/apache/commons/net/io/SocketOutputStream.java
deleted file mode 100644
index abd7f5d..0000000
--- a/org/apache/commons/net/io/SocketOutputStream.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.Socket;
-
-/***
- * This class wraps an output stream, storing a reference to its originating
- * socket. When the stream is closed, it will also close the socket
- * immediately afterward. This class is useful for situations where you
- * are dealing with a stream originating from a socket, but do not have
- * a reference to the socket, and want to make sure it closes when the
- * stream closes.
- *
- *
- * @author Daniel F. Savarese
- * @see SocketInputStream
- ***/
-
-public class SocketOutputStream extends FilterOutputStream
-{
- private Socket __socket;
-
- /***
- * Creates a SocketOutputStream instance wrapping an output stream and
- * storing a reference to a socket that should be closed on closing
- * the stream.
- *
- * @param socket The socket to close on closing the stream.
- * @param stream The input stream to wrap.
- ***/
- public SocketOutputStream(Socket socket, OutputStream stream)
- {
- super(stream);
- __socket = socket;
- }
-
-
- /***
- * Writes a number of bytes from a byte array to the stream starting from
- * a given offset. This method bypasses the equivalent method in
- * FilterOutputStream because the FilterOutputStream implementation is
- * very inefficient.
- *
- * @param buffer The byte array to write.
- * @param offset The offset into the array at which to start copying data.
- * @param length The number of bytes to write.
- * @exception IOException If an error occurs while writing to the underlying
- * stream.
- ***/
- @Override
- public void write(byte buffer[], int offset, int length) throws IOException
- {
- out.write(buffer, offset, length);
- }
-
-
- /***
- * Closes the stream and immediately afterward closes the referenced
- * socket.
- *
- * @exception IOException If there is an error in closing the stream
- * or socket.
- ***/
- @Override
- public void close() throws IOException
- {
- super.close();
- __socket.close();
- }
-}
diff --git a/org/apache/commons/net/io/ToNetASCIIInputStream.java b/org/apache/commons/net/io/ToNetASCIIInputStream.java
deleted file mode 100644
index 55e4735..0000000
--- a/org/apache/commons/net/io/ToNetASCIIInputStream.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/***
- * This class wraps an input stream, replacing all singly occurring
- * <LF> (linefeed) characters with <CR><LF> (carriage return
- * followed by linefeed), which is the NETASCII standard for representing
- * a newline.
- * You would use this class to implement ASCII file transfers requiring
- * conversion to NETASCII.
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class ToNetASCIIInputStream extends FilterInputStream
-{
- private static final int __NOTHING_SPECIAL = 0;
- private static final int __LAST_WAS_CR = 1;
- private static final int __LAST_WAS_NL = 2;
- private int __status;
-
- /***
- * Creates a ToNetASCIIInputStream instance that wraps an existing
- * InputStream.
- *
- * @param input The InputStream to .
- ***/
- public ToNetASCIIInputStream(InputStream input)
- {
- super(input);
- __status = __NOTHING_SPECIAL;
- }
-
-
- /***
- * Reads and returns the next byte in the stream. If the end of the
- * message has been reached, returns -1.
- *
- * @return The next character in the stream. Returns -1 if the end of the
- * stream has been reached.
- * @exception IOException If an error occurs while reading the underlying
- * stream.
- ***/
- @Override
- public int read() throws IOException
- {
- int ch;
-
- if (__status == __LAST_WAS_NL)
- {
- __status = __NOTHING_SPECIAL;
- return '\n';
- }
-
- ch = in.read();
-
- switch (ch)
- {
- case '\r':
- __status = __LAST_WAS_CR;
- return '\r';
- case '\n':
- if (__status != __LAST_WAS_CR)
- {
- __status = __LAST_WAS_NL;
- return '\r';
- }
- // else fall through
- default:
- __status = __NOTHING_SPECIAL;
- return ch;
- }
- // statement not reached
- //return ch;
- }
-
-
- /***
- * Reads the next number of bytes from the stream into an array and
- * returns the number of bytes read. Returns -1 if the end of the
- * stream has been reached.
- *
- * @param buffer The byte array in which to store the data.
- * @return The number of bytes read. Returns -1 if the
- * end of the message has been reached.
- * @exception IOException If an error occurs in reading the underlying
- * stream.
- ***/
- @Override
- public int read(byte buffer[]) throws IOException
- {
- return read(buffer, 0, buffer.length);
- }
-
-
- /***
- * Reads the next number of bytes from the stream into an array and returns
- * the number of bytes read. Returns -1 if the end of the
- * message has been reached. The characters are stored in the array
- * starting from the given offset and up to the length specified.
- *
- * @param buffer The byte array in which to store the data.
- * @param offset The offset into the array at which to start storing data.
- * @param length The number of bytes to read.
- * @return The number of bytes read. Returns -1 if the
- * end of the stream has been reached.
- * @exception IOException If an error occurs while reading the underlying
- * stream.
- ***/
- @Override
- public int read(byte buffer[], int offset, int length) throws IOException
- {
- int ch, off;
-
- if (length < 1)
- return 0;
-
- ch = available();
-
- if (length > ch)
- length = ch;
-
- // If nothing is available, block to read only one character
- if (length < 1)
- length = 1;
-
- if ((ch = read()) == -1)
- return -1;
-
- off = offset;
-
- do
- {
- buffer[offset++] = (byte)ch;
- }
- while (--length > 0 && (ch = read()) != -1);
-
- return (offset - off);
- }
-
- /*** Returns false. Mark is not supported. ***/
- @Override
- public boolean markSupported()
- {
- return false;
- }
-
- @Override
- public int available() throws IOException
- {
- int result;
-
- result = in.available();
-
- if (__status == __LAST_WAS_NL)
- return (result + 1);
-
- return result;
- }
-}
diff --git a/org/apache/commons/net/io/ToNetASCIIOutputStream.class b/org/apache/commons/net/io/ToNetASCIIOutputStream.class
deleted file mode 100644
index 62185e4..0000000
Binary files a/org/apache/commons/net/io/ToNetASCIIOutputStream.class and /dev/null differ
diff --git a/org/apache/commons/net/io/ToNetASCIIOutputStream.java b/org/apache/commons/net/io/ToNetASCIIOutputStream.java
deleted file mode 100644
index aeacc98..0000000
--- a/org/apache/commons/net/io/ToNetASCIIOutputStream.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/***
- * This class wraps an output stream, replacing all singly occurring
- * <LF> (linefeed) characters with <CR><LF> (carriage return
- * followed by linefeed), which is the NETASCII standard for representing
- * a newline.
- * You would use this class to implement ASCII file transfers requiring
- * conversion to NETASCII.
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class ToNetASCIIOutputStream extends FilterOutputStream
-{
- private boolean __lastWasCR;
-
- /***
- * Creates a ToNetASCIIOutputStream instance that wraps an existing
- * OutputStream.
- *
- * @param output The OutputStream to wrap.
- ***/
- public ToNetASCIIOutputStream(OutputStream output)
- {
- super(output);
- __lastWasCR = false;
- }
-
-
- /***
- * Writes a byte to the stream. Note that a call to this method
- * may result in multiple writes to the underlying input stream in order
- * to convert naked newlines to NETASCII line separators.
- * This is transparent to the programmer and is only mentioned for
- * completeness.
- *
- * @param ch The byte to write.
- * @exception IOException If an error occurs while writing to the underlying
- * stream.
- ***/
- @Override
- public synchronized void write(int ch)
- throws IOException
- {
- switch (ch)
- {
- case '\r':
- __lastWasCR = true;
- out.write('\r');
- return ;
- case '\n':
- if (!__lastWasCR)
- out.write('\r');
- // Fall through
- default:
- __lastWasCR = false;
- out.write(ch);
- return ;
- }
- }
-
-
- /***
- * Writes a byte array to the stream.
- *
- * @param buffer The byte array to write.
- * @exception IOException If an error occurs while writing to the underlying
- * stream.
- ***/
- @Override
- public synchronized void write(byte buffer[])
- throws IOException
- {
- write(buffer, 0, buffer.length);
- }
-
-
- /***
- * Writes a number of bytes from a byte array to the stream starting from
- * a given offset.
- *
- * @param buffer The byte array to write.
- * @param offset The offset into the array at which to start copying data.
- * @param length The number of bytes to write.
- * @exception IOException If an error occurs while writing to the underlying
- * stream.
- ***/
- @Override
- public synchronized void write(byte buffer[], int offset, int length)
- throws IOException
- {
- while (length-- > 0)
- write(buffer[offset++]);
- }
-
-}
diff --git a/org/apache/commons/net/io/Util.class b/org/apache/commons/net/io/Util.class
deleted file mode 100644
index 7509801..0000000
Binary files a/org/apache/commons/net/io/Util.class and /dev/null differ
diff --git a/org/apache/commons/net/io/Util.java b/org/apache/commons/net/io/Util.java
deleted file mode 100644
index 4e85a93..0000000
--- a/org/apache/commons/net/io/Util.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-
-/***
- * The Util class cannot be instantiated and stores short static convenience
- * methods that are often quite useful.
- *
- *
- * @see CopyStreamException
- * @see CopyStreamListener
- * @see CopyStreamAdapter
- * @author Daniel F. Savarese
- ***/
-
-public final class Util
-{
- /***
- * The default buffer size used by {@link #copyStream copyStream }
- * and {@link #copyReader copyReader }. It's value is 1024.
- ***/
- public static final int DEFAULT_COPY_BUFFER_SIZE = 1024;
-
- // Cannot be instantiated
- private Util()
- { }
-
-
- /***
- * Copies the contents of an InputStream to an OutputStream using a
- * copy buffer of a given size and notifies the provided
- * CopyStreamListener of the progress of the copy operation by calling
- * its bytesTransferred(long, int) method after each write to the
- * destination. If you wish to notify more than one listener you should
- * use a CopyStreamAdapter as the listener and register the additional
- * listeners with the CopyStreamAdapter.
- *
- * The contents of the InputStream are
- * read until the end of the stream is reached, but neither the
- * source nor the destination are closed. You must do this yourself
- * outside of the method call. The number of bytes read/written is
- * returned.
- *
- * @param source The source InputStream.
- * @param dest The destination OutputStream.
- * @param bufferSize The number of bytes to buffer during the copy.
- * @param streamSize The number of bytes in the stream being copied.
- * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
- * @param listener The CopyStreamListener to notify of progress. If
- * this parameter is null, notification is not attempted.
- * @param flush Whether to flush the output stream after every
- * write. This is necessary for interactive sessions that rely on
- * buffered streams. If you don't flush, the data will stay in
- * the stream buffer.
- * @exception CopyStreamException If an error occurs while reading from the
- * source or writing to the destination. The CopyStreamException
- * will contain the number of bytes confirmed to have been
- * transferred before an
- * IOException occurred, and it will also contain the IOException
- * that caused the error. These values can be retrieved with
- * the CopyStreamException getTotalBytesTransferred() and
- * getIOException() methods.
- ***/
- public static final long copyStream(InputStream source, OutputStream dest,
- int bufferSize, long streamSize,
- CopyStreamListener listener,
- boolean flush)
- throws CopyStreamException
- {
- int bytes;
- long total;
- byte[] buffer;
-
- buffer = new byte[bufferSize];
- total = 0;
-
- try
- {
- while ((bytes = source.read(buffer)) != -1)
- {
- // Technically, some read(byte[]) methods may return 0 and we cannot
- // accept that as an indication of EOF.
-
- if (bytes == 0)
- {
- bytes = source.read();
- if (bytes < 0)
- break;
- dest.write(bytes);
- if(flush)
- dest.flush();
- ++total;
- if (listener != null)
- listener.bytesTransferred(total, 1, streamSize);
- continue;
- }
-
- dest.write(buffer, 0, bytes);
- if(flush)
- dest.flush();
- total += bytes;
- if (listener != null)
- listener.bytesTransferred(total, bytes, streamSize);
- }
- }
- catch (IOException e)
- {
- throw new CopyStreamException("IOException caught while copying.",
- total, e);
- }
-
- return total;
- }
-
-
- /***
- * Copies the contents of an InputStream to an OutputStream using a
- * copy buffer of a given size and notifies the provided
- * CopyStreamListener of the progress of the copy operation by calling
- * its bytesTransferred(long, int) method after each write to the
- * destination. If you wish to notify more than one listener you should
- * use a CopyStreamAdapter as the listener and register the additional
- * listeners with the CopyStreamAdapter.
- *
- * The contents of the InputStream are
- * read until the end of the stream is reached, but neither the
- * source nor the destination are closed. You must do this yourself
- * outside of the method call. The number of bytes read/written is
- * returned.
- *
- * @param source The source InputStream.
- * @param dest The destination OutputStream.
- * @param bufferSize The number of bytes to buffer during the copy.
- * @param streamSize The number of bytes in the stream being copied.
- * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
- * @param listener The CopyStreamListener to notify of progress. If
- * this parameter is null, notification is not attempted.
- * @exception CopyStreamException If an error occurs while reading from the
- * source or writing to the destination. The CopyStreamException
- * will contain the number of bytes confirmed to have been
- * transferred before an
- * IOException occurred, and it will also contain the IOException
- * that caused the error. These values can be retrieved with
- * the CopyStreamException getTotalBytesTransferred() and
- * getIOException() methods.
- ***/
- public static final long copyStream(InputStream source, OutputStream dest,
- int bufferSize, long streamSize,
- CopyStreamListener listener)
- throws CopyStreamException
- {
- return copyStream(source, dest, bufferSize, streamSize, listener,
- true);
- }
-
-
- /***
- * Copies the contents of an InputStream to an OutputStream using a
- * copy buffer of a given size. The contents of the InputStream are
- * read until the end of the stream is reached, but neither the
- * source nor the destination are closed. You must do this yourself
- * outside of the method call. The number of bytes read/written is
- * returned.
- *
- * @param source The source InputStream.
- * @param dest The destination OutputStream.
- * @return The number of bytes read/written in the copy operation.
- * @exception CopyStreamException If an error occurs while reading from the
- * source or writing to the destination. The CopyStreamException
- * will contain the number of bytes confirmed to have been
- * transferred before an
- * IOException occurred, and it will also contain the IOException
- * that caused the error. These values can be retrieved with
- * the CopyStreamException getTotalBytesTransferred() and
- * getIOException() methods.
- ***/
- public static final long copyStream(InputStream source, OutputStream dest,
- int bufferSize)
- throws CopyStreamException
- {
- return copyStream(source, dest, bufferSize,
- CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
- }
-
-
- /***
- * Same as
- * The contents of the Reader are
- * read until its end is reached, but neither the source nor the
- * destination are closed. You must do this yourself outside of the
- * method call. The number of characters read/written is returned.
- *
- * @param source The source Reader.
- * @param dest The destination writer.
- * @param bufferSize The number of characters to buffer during the copy.
- * @param streamSize The number of characters in the stream being copied.
- * Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
- * @param listener The CopyStreamListener to notify of progress. If
- * this parameter is null, notification is not attempted.
- * @return The number of characters read/written in the copy operation.
- * @exception CopyStreamException If an error occurs while reading from the
- * source or writing to the destination. The CopyStreamException
- * will contain the number of bytes confirmed to have been
- * transferred before an
- * IOException occurred, and it will also contain the IOException
- * that caused the error. These values can be retrieved with
- * the CopyStreamException getTotalBytesTransferred() and
- * getIOException() methods.
- ***/
- public static final long copyReader(Reader source, Writer dest,
- int bufferSize, long streamSize,
- CopyStreamListener listener)
- throws CopyStreamException
- {
- int chars;
- long total;
- char[] buffer;
-
- buffer = new char[bufferSize];
- total = 0;
-
- try
- {
- while ((chars = source.read(buffer)) != -1)
- {
- // Technically, some read(char[]) methods may return 0 and we cannot
- // accept that as an indication of EOF.
- if (chars == 0)
- {
- chars = source.read();
- if (chars < 0)
- break;
- dest.write(chars);
- dest.flush();
- ++total;
- if (listener != null)
- listener.bytesTransferred(total, chars, streamSize);
- continue;
- }
-
- dest.write(buffer, 0, chars);
- dest.flush();
- total += chars;
- if (listener != null)
- listener.bytesTransferred(total, chars, streamSize);
- }
- }
- catch (IOException e)
- {
- throw new CopyStreamException("IOException caught while copying.",
- total, e);
- }
-
- return total;
- }
-
-
- /***
- * Copies the contents of a Reader to a Writer using a
- * copy buffer of a given size. The contents of the Reader are
- * read until its end is reached, but neither the source nor the
- * destination are closed. You must do this yourself outside of the
- * method call. The number of characters read/written is returned.
- *
- * @param source The source Reader.
- * @param dest The destination writer.
- * @param bufferSize The number of characters to buffer during the copy.
- * @return The number of characters read/written in the copy operation.
- * @exception CopyStreamException If an error occurs while reading from the
- * source or writing to the destination. The CopyStreamException
- * will contain the number of bytes confirmed to have been
- * transferred before an
- * IOException occurred, and it will also contain the IOException
- * that caused the error. These values can be retrieved with
- * the CopyStreamException getTotalBytesTransferred() and
- * getIOException() methods.
- ***/
- public static final long copyReader(Reader source, Writer dest,
- int bufferSize)
- throws CopyStreamException
- {
- return copyReader(source, dest, bufferSize,
- CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
- }
-
-
- /***
- * Same as
- * You should keep in mind that the NNTP server may choose to prematurely
- * close a connection if the client has been idle for longer than a
- * given time period or if the server is being shutdown by the operator or
- * some other reason. The NNTP class will detect a
- * premature NNTP server connection closing when it receives a
- * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED }
- * response to a command.
- * When that occurs, the NNTP class method encountering that reply will throw
- * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
- * .
- *
- * Rather than list it separately for each method, we mention here that
- * every method communicating with the server and throwing an IOException
- * can also throw a
- * {@link org.apache.commons.net.MalformedServerReplyException}
- * , which is a subclass
- * of IOException. A MalformedServerReplyException will be thrown when
- * the reply received from the server deviates enough from the protocol
- * specification that it cannot be interpreted in a useful manner despite
- * attempts to be as lenient as possible.
- *
- *
- * @author Daniel F. Savarese
- * @author Rory Winston
- * @author Ted Wise
- * @see NNTPClient
- * @see NNTPConnectionClosedException
- * @see org.apache.commons.net.MalformedServerReplyException
- ***/
-
-public class NNTP extends SocketClient
-{
- /*** The default NNTP port. Its value is 119 according to RFC 977. ***/
- public static final int DEFAULT_PORT = 119;
-
- // We have to ensure that the protocol communication is in ASCII
- // but we use ISO-8859-1 just in case 8-bit characters cross
- // the wire.
- private static final String __DEFAULT_ENCODING = "ISO-8859-1";
-
- private StringBuffer __commandBuffer;
-
- boolean _isAllowedToPost;
- int _replyCode;
- String _replyString;
-
- /**
- * Wraps {@link SocketClient#_input_}
- * to communicate with server. Initialized by {@link #_connectAction_}.
- * All server reads should be done through this variable.
- */
- protected BufferedReader _reader_;
-
- /**
- * Wraps {@link SocketClient#_output_}
- * to communicate with server. Initialized by {@link #_connectAction_}.
- * All server reads should be done through this variable.
- */
- protected BufferedWriter _writer_;
-
- /***
- * A ProtocolCommandSupport object used to manage the registering of
- * ProtocolCommandListeners and te firing of ProtocolCommandEvents.
- ***/
- protected ProtocolCommandSupport _commandSupport_;
-
- /***
- * The default NNTP constructor. Sets the default port to
- *
- * @param listener The ProtocolCommandListener to add.
- ***/
- public void addProtocolCommandListener(ProtocolCommandListener listener)
- {
- _commandSupport_.addProtocolCommandListener(listener);
- }
-
- /***
- * Removes a ProtocolCommandListener. Delegates this task to
- * {@link #_commandSupport_ _commandSupport_ }.
- *
- * @param listener The ProtocolCommandListener to remove.
- ***/
- public void removeProtocolCommandListener(ProtocolCommandListener listener)
- {
- _commandSupport_.removeProtocolCommandListener(listener);
- }
-
- /***
- * Closes the connection to the NNTP server and sets to null
- * some internal data so that the memory may be reclaimed by the
- * garbage collector. The reply text and code information from the
- * last command is voided so that the memory it used may be reclaimed.
- *
- * @exception IOException If an error occurs while disconnecting.
- ***/
- @Override
- public void disconnect() throws IOException
- {
- super.disconnect();
- _reader_ = null;
- _writer_ = null;
- _replyString = null;
- _isAllowedToPost = false;
- }
-
-
- /***
- * Indicates whether or not the client is allowed to post articles to
- * the server it is currently connected to.
- *
- * @return True if the client can post articles to the server, false
- * otherwise.
- ***/
- public boolean isAllowedToPost()
- {
- return _isAllowedToPost;
- }
-
-
- /***
- * Sends an NNTP command to the server, waits for a reply and returns the
- * numerical response code. After invocation, for more detailed
- * information, the actual reply text can be accessed by calling
- * {@link #getReplyString getReplyString }.
- *
- * @param command The text representation of the NNTP command to send.
- * @param args The arguments to the NNTP command. If this parameter is
- * set to null, then the command is sent with no argument.
- * @return The integer value of the NNTP reply code returned by the server
- * in response to the command.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(String command, String args) throws IOException
- {
- String message;
-
- __commandBuffer.setLength(0);
- __commandBuffer.append(command);
-
- if (args != null)
- {
- __commandBuffer.append(' ');
- __commandBuffer.append(args);
- }
- __commandBuffer.append(SocketClient.NETASCII_EOL);
-
- _writer_.write(message = __commandBuffer.toString());
- _writer_.flush();
-
- if (_commandSupport_.getListenerCount() > 0)
- _commandSupport_.fireCommandSent(command, message);
-
- __getReply();
- return _replyCode;
- }
-
-
- /***
- * Sends an NNTP command to the server, waits for a reply and returns the
- * numerical response code. After invocation, for more detailed
- * information, the actual reply text can be accessed by calling
- * {@link #getReplyString getReplyString }.
- *
- * @param command The NNTPCommand constant corresponding to the NNTP command
- * to send.
- * @param args The arguments to the NNTP command. If this parameter is
- * set to null, then the command is sent with no argument.
- * @return The integer value of the NNTP reply code returned by the server
- * in response to the command.
- * in response to the command.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(int command, String args) throws IOException
- {
- return sendCommand(NNTPCommand._commands[command], args);
- }
-
-
- /***
- * Sends an NNTP command with no arguments to the server, waits for a
- * reply and returns the numerical response code. After invocation, for
- * more detailed information, the actual reply text can be accessed by
- * calling {@link #getReplyString getReplyString }.
- *
- * @param command The text representation of the NNTP command to send.
- * @return The integer value of the NNTP reply code returned by the server
- * in response to the command.
- * in response to the command.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(String command) throws IOException
- {
- return sendCommand(command, null);
- }
-
-
- /***
- * Sends an NNTP command with no arguments to the server, waits for a
- * reply and returns the numerical response code. After invocation, for
- * more detailed information, the actual reply text can be accessed by
- * calling {@link #getReplyString getReplyString }.
- *
- * @param command The NNTPCommand constant corresponding to the NNTP command
- * to send.
- * @return The integer value of the NNTP reply code returned by the server
- * in response to the command.
- * in response to the command.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(int command) throws IOException
- {
- return sendCommand(command, null);
- }
-
-
- /***
- * Returns the integer value of the reply code of the last NNTP reply.
- * You will usually only use this method after you connect to the
- * NNTP server to check that the connection was successful since
- *
- * @return The integer value of the reply code of the last NNTP reply.
- ***/
- public int getReplyCode()
- {
- return _replyCode;
- }
-
- /***
- * Fetches a reply from the NNTP server and returns the integer reply
- * code. After calling this method, the actual reply text can be accessed
- * from {@link #getReplyString getReplyString }. Only use this
- * method if you are implementing your own NNTP client or if you need to
- * fetch a secondary response from the NNTP server.
- *
- * @return The integer value of the reply code of the fetched NNTP reply.
- * in response to the command.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while
- * receiving the server reply.
- ***/
- public int getReply() throws IOException
- {
- __getReply();
- return _replyCode;
- }
-
-
- /***
- * Returns the entire text of the last NNTP server response exactly
- * as it was received, not including the end of line marker.
- *
- * @return The entire text from the last NNTP response as a String.
- ***/
- public String getReplyString()
- {
- return _replyString;
- }
-
-
- /***
- * A convenience method to send the NNTP ARTICLE command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @param messageId The message identifier of the requested article,
- * including the encapsulating < and > characters.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int article(String messageId) throws IOException
- {
- return sendCommand(NNTPCommand.ARTICLE, messageId);
- }
-
- /***
- * A convenience method to send the NNTP ARTICLE command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @param articleNumber The number of the article to request from the
- * currently selected newsgroup.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int article(int articleNumber) throws IOException
- {
- return sendCommand(NNTPCommand.ARTICLE, Integer.toString(articleNumber));
- }
-
- /***
- * A convenience method to send the NNTP ARTICLE command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int article() throws IOException
- {
- return sendCommand(NNTPCommand.ARTICLE);
- }
-
-
-
- /***
- * A convenience method to send the NNTP BODY command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @param messageId The message identifier of the requested article,
- * including the encapsulating < and > characters.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int body(String messageId) throws IOException
- {
- return sendCommand(NNTPCommand.BODY, messageId);
- }
-
- /***
- * A convenience method to send the NNTP BODY command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @param articleNumber The number of the article to request from the
- * currently selected newsgroup.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int body(int articleNumber) throws IOException
- {
- return sendCommand(NNTPCommand.BODY, Integer.toString(articleNumber));
- }
-
- /***
- * A convenience method to send the NNTP BODY command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int body() throws IOException
- {
- return sendCommand(NNTPCommand.BODY);
- }
-
-
-
- /***
- * A convenience method to send the NNTP HEAD command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @param messageId The message identifier of the requested article,
- * including the encapsulating < and > characters.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int head(String messageId) throws IOException
- {
- return sendCommand(NNTPCommand.HEAD, messageId);
- }
-
- /***
- * A convenience method to send the NNTP HEAD command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @param articleNumber The number of the article to request from the
- * currently selected newsgroup.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int head(int articleNumber) throws IOException
- {
- return sendCommand(NNTPCommand.HEAD, Integer.toString(articleNumber));
- }
-
- /***
- * A convenience method to send the NNTP HEAD command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int head() throws IOException
- {
- return sendCommand(NNTPCommand.HEAD);
- }
-
-
-
- /***
- * A convenience method to send the NNTP STAT command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @param messageId The message identifier of the requested article,
- * including the encapsulating < and > characters.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int stat(String messageId) throws IOException
- {
- return sendCommand(NNTPCommand.STAT, messageId);
- }
-
- /***
- * A convenience method to send the NNTP STAT command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @param articleNumber The number of the article to request from the
- * currently selected newsgroup.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int stat(int articleNumber) throws IOException
- {
- return sendCommand(NNTPCommand.STAT, Integer.toString(articleNumber));
- }
-
- /***
- * A convenience method to send the NNTP STAT command to the server,
- * receive the initial reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int stat() throws IOException
- {
- return sendCommand(NNTPCommand.STAT);
- }
-
-
- /***
- * A convenience method to send the NNTP GROUP command to the server,
- * receive the reply, and return the reply code.
- *
- * @param newsgroup The name of the newsgroup to select.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int group(String newsgroup) throws IOException
- {
- return sendCommand(NNTPCommand.GROUP, newsgroup);
- }
-
-
- /***
- * A convenience method to send the NNTP HELP command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int help() throws IOException
- {
- return sendCommand(NNTPCommand.HELP);
- }
-
-
- /***
- * A convenience method to send the NNTP IHAVE command to the server,
- * receive the reply, and return the reply code.
- *
- * @param messageId The article identifier,
- * including the encapsulating < and > characters.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int ihave(String messageId) throws IOException
- {
- return sendCommand(NNTPCommand.IHAVE, messageId);
- }
-
-
- /***
- * A convenience method to send the NNTP LAST command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int last() throws IOException
- {
- return sendCommand(NNTPCommand.LAST);
- }
-
-
-
- /***
- * A convenience method to send the NNTP LIST command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int list() throws IOException
- {
- return sendCommand(NNTPCommand.LIST);
- }
-
-
-
- /***
- * A convenience method to send the NNTP NEXT command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int next() throws IOException
- {
- return sendCommand(NNTPCommand.NEXT);
- }
-
-
- /***
- * A convenience method to send the NNTP NEWGROUPS command to the server,
- * receive the reply, and return the reply code.
- *
- * @param date The date after which to check for new groups.
- * Date format is YYMMDD
- * @param time The time after which to check for new groups.
- * Time format is HHMMSS using a 24-hour clock.
- * @param GMT True if the time is in GMT, false if local server time.
- * @param distributions Comma-separated distribution list to check for
- * new groups. Set to null if no distributions.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int newgroups(String date, String time, boolean GMT,
- String distributions) throws IOException
- {
- StringBuffer buffer = new StringBuffer();
-
- buffer.append(date);
- buffer.append(' ');
- buffer.append(time);
-
- if (GMT)
- {
- buffer.append(' ');
- buffer.append("GMT");
- }
-
- if (distributions != null)
- {
- buffer.append(" <");
- buffer.append(distributions);
- buffer.append('>');
- }
-
- return sendCommand(NNTPCommand.NEWGROUPS, buffer.toString());
- }
-
-
- /***
- * A convenience method to send the NNTP NEWGROUPS command to the server,
- * receive the reply, and return the reply code.
- *
- * @param newsgroups A comma-separated list of newsgroups to check for new
- * news.
- * @param date The date after which to check for new news.
- * Date format is YYMMDD
- * @param time The time after which to check for new news.
- * Time format is HHMMSS using a 24-hour clock.
- * @param GMT True if the time is in GMT, false if local server time.
- * @param distributions Comma-separated distribution list to check for
- * new news. Set to null if no distributions.
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int newnews(String newsgroups, String date, String time, boolean GMT,
- String distributions) throws IOException
- {
- StringBuffer buffer = new StringBuffer();
-
- buffer.append(newsgroups);
- buffer.append(' ');
- buffer.append(date);
- buffer.append(' ');
- buffer.append(time);
-
- if (GMT)
- {
- buffer.append(' ');
- buffer.append("GMT");
- }
-
- if (distributions != null)
- {
- buffer.append(" <");
- buffer.append(distributions);
- buffer.append('>');
- }
-
- return sendCommand(NNTPCommand.NEWNEWS, buffer.toString());
- }
-
-
-
- /***
- * A convenience method to send the NNTP POST command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int post() throws IOException
- {
- return sendCommand(NNTPCommand.POST);
- }
-
-
-
- /***
- * A convenience method to send the NNTP QUIT command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int quit() throws IOException
- {
- return sendCommand(NNTPCommand.QUIT);
- }
-
- /***
- * A convenience method to send the AUTHINFO USER command to the server,
- * receive the reply, and return the reply code. (See RFC 2980)
- *
- * @param username A valid username.
- * @return The reply code received from the server. The server should
- * return a 381 or 281 for this command.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int authinfoUser(String username) throws IOException {
- String userParameter = "USER " + username;
- return sendCommand(NNTPCommand.AUTHINFO, userParameter);
- }
-
- /***
- * A convenience method to send the AUTHINFO PASS command to the server,
- * receive the reply, and return the reply code. If this step is
- * required, it should immediately follow the AUTHINFO USER command
- * (See RFC 2980)
- *
- * @param password a valid password.
- * @return The reply code received from the server. The server should
- * return a 281 or 502 for this command.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int authinfoPass(String password) throws IOException {
- String passParameter = "PASS " + password;
- return sendCommand(NNTPCommand.AUTHINFO, passParameter);
- }
-
- /***
- * A convenience method to send the NNTP XOVER command to the server,
- * receive the reply, and return the reply code.
- *
- * @param selectedArticles a String representation of the range of
- * article headers required. This may be an article number, or a
- * range of article numbers in the form "XXXX-YYYY", where XXXX
- * and YYYY are valid article numbers in the current group. It
- * also may be of the form "XXX-", meaning "return XXX and all
- * following articles" In this revision, the last format is not
- * possible (yet).
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int xover(String selectedArticles) throws IOException {
- return sendCommand(NNTPCommand.XOVER, selectedArticles);
- }
-
- /***
- * A convenience method to send the NNTP XHDR command to the server,
- * receive the reply, and return the reply code.
- *
- * @param header a String naming a header line (e.g., "subject"). See
- * RFC-1036 for a list of valid header lines.
- * @param selectedArticles a String representation of the range of
- * article headers required. This may be an article number, or a
- * range of article numbers in the form "XXXX-YYYY", where XXXX
- * and YYYY are valid article numbers in the current group. It
- * also may be of the form "XXX-", meaning "return XXX and all
- * following articles" In this revision, the last format is not
- * possible (yet).
- * @return The reply code received from the server.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int xhdr(String header, String selectedArticles) throws IOException {
- StringBuffer command = new StringBuffer(header);
- command.append(" ");
- command.append(selectedArticles);
- return sendCommand(NNTPCommand.XHDR, command.toString());
- }
-
- /**
- * A convenience wrapper for the extended LIST command that takes
- * an argument, allowing us to selectively list multiple groups.
- *
- * @param wildmat A wildmat (pseudo-regex) pattern. See RFC 2980 for
- * details.
- * @return the reply code received from the server.
- * @throws IOException
- */
- public int listActive(String wildmat) throws IOException {
- StringBuffer command = new StringBuffer("ACTIVE ");
- command.append(wildmat);
- return sendCommand(NNTPCommand.LIST, command.toString());
- }
-}
-
-/* Emacs configuration
- * Local variables: **
- * mode: java **
- * c-basic-offset: 4 **
- * indent-tabs-mode: nil **
- * End: **
- */
diff --git a/org/apache/commons/net/nntp/NNTPClient.java b/org/apache/commons/net/nntp/NNTPClient.java
deleted file mode 100644
index e10ce90..0000000
--- a/org/apache/commons/net/nntp/NNTPClient.java
+++ /dev/null
@@ -1,1285 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.nntp;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.StringTokenizer;
-import java.util.Vector;
-
-import org.apache.commons.net.MalformedServerReplyException;
-import org.apache.commons.net.io.DotTerminatedMessageReader;
-import org.apache.commons.net.io.DotTerminatedMessageWriter;
-import org.apache.commons.net.io.Util;
-
-/***
- * NNTPClient encapsulates all the functionality necessary to post and
- * retrieve articles from an NNTP server. As with all classes derived
- * from {@link org.apache.commons.net.SocketClient},
- * you must first connect to the server with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * before doing anything, and finally
- * {@link org.apache.commons.net.nntp.NNTP#disconnect disconnect() }
- * after you're completely finished interacting with the server.
- * Remember that the
- * {@link org.apache.commons.net.nntp.NNTP#isAllowedToPost isAllowedToPost()}
- * method is defined in
- * {@link org.apache.commons.net.nntp.NNTP}.
- *
- * You should keep in mind that the NNTP server may choose to prematurely
- * close a connection if the client has been idle for longer than a
- * given time period or if the server is being shutdown by the operator or
- * some other reason. The NNTP class will detect a
- * premature NNTP server connection closing when it receives a
- * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED }
- * response to a command.
- * When that occurs, the NNTP class method encountering that reply will throw
- * an {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
- * .
- *
- * Rather than list it separately for each method, we mention here that
- * every method communicating with the server and throwing an IOException
- * can also throw a
- * {@link org.apache.commons.net.MalformedServerReplyException}
- * , which is a subclass
- * of IOException. A MalformedServerReplyException will be thrown when
- * the reply received from the server deviates enough from the protocol
- * specification that it cannot be interpreted in a useful manner despite
- * attempts to be as lenient as possible.
- *
- *
- * @author Daniel F. Savarese
- * @author Rory Winston
- * @author Ted Wise
- * @see NNTP
- * @see NNTPConnectionClosedException
- * @see org.apache.commons.net.MalformedServerReplyException
- ***/
-
-public class NNTPClient extends NNTP
-{
-
- private void __parseArticlePointer(String reply, ArticlePointer pointer)
- throws MalformedServerReplyException
- {
- StringTokenizer tokenizer;
-
- // Do loop is a kluge to simulate goto
- do
- {
- tokenizer = new StringTokenizer(reply);
-
- if (tokenizer.countTokens() < 3)
- break;
-
- // Skip numeric response value
- tokenizer.nextToken();
- // Get article number
- try
- {
- pointer.articleNumber = Integer.parseInt(tokenizer.nextToken());
- }
- catch (NumberFormatException e)
- {
- break;
- }
-
- // Get article id
- pointer.articleId = tokenizer.nextToken();
- return ;
- }
- while (false);
-
- throw new MalformedServerReplyException(
- "Could not parse article pointer.\nServer reply: " + reply);
- }
-
-
- private void __parseGroupReply(String reply, NewsgroupInfo info)
- throws MalformedServerReplyException
- {
- String count, first, last;
- StringTokenizer tokenizer;
-
- // Do loop is a kluge to simulate goto
- do
- {
- tokenizer = new StringTokenizer(reply);
-
- if (tokenizer.countTokens() < 5)
- break;
-
- // Skip numeric response value
- tokenizer.nextToken();
- // Get estimated article count
- count = tokenizer.nextToken();
- // Get first article number
- first = tokenizer.nextToken();
- // Get last article number
- last = tokenizer.nextToken();
- // Get newsgroup name
- info._setNewsgroup(tokenizer.nextToken());
-
- try
- {
- info._setArticleCount(Integer.parseInt(count));
- info._setFirstArticle(Integer.parseInt(first));
- info._setLastArticle(Integer.parseInt(last));
- }
- catch (NumberFormatException e)
- {
- break;
- }
-
- info._setPostingPermission(NewsgroupInfo.UNKNOWN_POSTING_PERMISSION);
- return ;
- }
- while (false);
-
- throw new MalformedServerReplyException(
- "Could not parse newsgroup info.\nServer reply: " + reply);
- }
-
-
- private NewsgroupInfo __parseNewsgroupListEntry(String entry)
- {
- NewsgroupInfo result;
- StringTokenizer tokenizer;
- int lastNum, firstNum;
- String last, first, permission;
-
- result = new NewsgroupInfo();
- tokenizer = new StringTokenizer(entry);
-
- if (tokenizer.countTokens() < 4)
- return null;
-
- result._setNewsgroup(tokenizer.nextToken());
- last = tokenizer.nextToken();
- first = tokenizer.nextToken();
- permission = tokenizer.nextToken();
-
- try
- {
- lastNum = Integer.parseInt(last);
- firstNum = Integer.parseInt(first);
- result._setFirstArticle(firstNum);
- result._setLastArticle(lastNum);
-
- if((firstNum == 0) && (lastNum == 0))
- result._setArticleCount(0);
- else
- result._setArticleCount(lastNum - firstNum + 1);
- }
- catch (NumberFormatException e)
- {
- return null;
- }
-
- switch (permission.charAt(0))
- {
- case 'y':
- case 'Y':
- result._setPostingPermission(
- NewsgroupInfo.PERMITTED_POSTING_PERMISSION);
- break;
- case 'n':
- case 'N':
- result._setPostingPermission(
- NewsgroupInfo.PROHIBITED_POSTING_PERMISSION);
- break;
- case 'm':
- case 'M':
- result._setPostingPermission(
- NewsgroupInfo.MODERATED_POSTING_PERMISSION);
- break;
- default:
- result._setPostingPermission(
- NewsgroupInfo.UNKNOWN_POSTING_PERMISSION);
- break;
- }
-
- return result;
- }
-
- private NewsgroupInfo[] __readNewsgroupListing() throws IOException
- {
- int size;
- String line;
- Vector
- * A DotTerminatedMessageReader is returned from which the article can
- * be read. If the article does not exist, null is returned.
- *
- * You must not issue any commands to the NNTP server (i.e., call any
- * other methods) until you finish reading the message from the returned
- * Reader instance.
- * The NNTP protocol uses the same stream for issuing commands as it does
- * for returning results. Therefore the returned Reader actually reads
- * directly from the NNTP connection. After the end of message has been
- * reached, new commands can be executed and their replies read. If
- * you do not follow these requirements, your program will not work
- * properly.
- *
- * @param articleId The unique article identifier of the article to
- * retrieve. If this parameter is null, the currently selected
- * article is retrieved.
- * @param pointer A parameter through which to return the article's
- * number and unique id. The articleId field cannot always be trusted
- * because of server deviations from RFC 977 reply formats. You may
- * set this parameter to null if you do not desire to retrieve the
- * returned article information.
- * @return A DotTerminatedMessageReader instance from which the article
- * be read. null if the article does not exist.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public Reader retrieveArticle(String articleId, ArticlePointer pointer)
- throws IOException
- {
- return __retrieve(NNTPCommand.ARTICLE, articleId, pointer);
-
- }
-
- /*** Same as
- * A DotTerminatedMessageReader is returned from which the article can
- * be read. If the article does not exist, null is returned.
- *
- * You must not issue any commands to the NNTP server (i.e., call any
- * other methods) until you finish reading the message from the returned
- * Reader instance.
- * The NNTP protocol uses the same stream for issuing commands as it does
- * for returning results. Therefore the returned Reader actually reads
- * directly from the NNTP connection. After the end of message has been
- * reached, new commands can be executed and their replies read. If
- * you do not follow these requirements, your program will not work
- * properly.
- *
- * @param articleNumber The number of the the article to
- * retrieve.
- * @param pointer A parameter through which to return the article's
- * number and unique id. The articleId field cannot always be trusted
- * because of server deviations from RFC 977 reply formats. You may
- * set this parameter to null if you do not desire to retrieve the
- * returned article information.
- * @return A DotTerminatedMessageReader instance from which the article
- * be read. null if the article does not exist.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public Reader retrieveArticle(int articleNumber, ArticlePointer pointer)
- throws IOException
- {
- return __retrieve(NNTPCommand.ARTICLE, articleNumber, pointer);
- }
-
- /*** Same as
- * A DotTerminatedMessageReader is returned from which the article can
- * be read. If the article does not exist, null is returned.
- *
- * You must not issue any commands to the NNTP server (i.e., call any
- * other methods) until you finish reading the message from the returned
- * Reader instance.
- * The NNTP protocol uses the same stream for issuing commands as it does
- * for returning results. Therefore the returned Reader actually reads
- * directly from the NNTP connection. After the end of message has been
- * reached, new commands can be executed and their replies read. If
- * you do not follow these requirements, your program will not work
- * properly.
- *
- * @param articleId The unique article identifier of the article whose
- * header is being retrieved. If this parameter is null, the
- * header of the currently selected article is retrieved.
- * @param pointer A parameter through which to return the article's
- * number and unique id. The articleId field cannot always be trusted
- * because of server deviations from RFC 977 reply formats. You may
- * set this parameter to null if you do not desire to retrieve the
- * returned article information.
- * @return A DotTerminatedMessageReader instance from which the article
- * header can be read. null if the article does not exist.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public Reader retrieveArticleHeader(String articleId, ArticlePointer pointer)
- throws IOException
- {
- return __retrieve(NNTPCommand.HEAD, articleId, pointer);
-
- }
-
- /*** Same as
- * A DotTerminatedMessageReader is returned from which the article can
- * be read. If the article does not exist, null is returned.
- *
- * You must not issue any commands to the NNTP server (i.e., call any
- * other methods) until you finish reading the message from the returned
- * Reader instance.
- * The NNTP protocol uses the same stream for issuing commands as it does
- * for returning results. Therefore the returned Reader actually reads
- * directly from the NNTP connection. After the end of message has been
- * reached, new commands can be executed and their replies read. If
- * you do not follow these requirements, your program will not work
- * properly.
- *
- * @param articleNumber The number of the the article whose header is
- * being retrieved.
- * @param pointer A parameter through which to return the article's
- * number and unique id. The articleId field cannot always be trusted
- * because of server deviations from RFC 977 reply formats. You may
- * set this parameter to null if you do not desire to retrieve the
- * returned article information.
- * @return A DotTerminatedMessageReader instance from which the article
- * header can be read. null if the article does not exist.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public Reader retrieveArticleHeader(int articleNumber,
- ArticlePointer pointer)
- throws IOException
- {
- return __retrieve(NNTPCommand.HEAD, articleNumber, pointer);
- }
-
-
- /*** Same as
- * A DotTerminatedMessageReader is returned from which the article can
- * be read. If the article does not exist, null is returned.
- *
- * You must not issue any commands to the NNTP server (i.e., call any
- * other methods) until you finish reading the message from the returned
- * Reader instance.
- * The NNTP protocol uses the same stream for issuing commands as it does
- * for returning results. Therefore the returned Reader actually reads
- * directly from the NNTP connection. After the end of message has been
- * reached, new commands can be executed and their replies read. If
- * you do not follow these requirements, your program will not work
- * properly.
- *
- * @param articleId The unique article identifier of the article whose
- * body is being retrieved. If this parameter is null, the
- * body of the currently selected article is retrieved.
- * @param pointer A parameter through which to return the article's
- * number and unique id. The articleId field cannot always be trusted
- * because of server deviations from RFC 977 reply formats. You may
- * set this parameter to null if you do not desire to retrieve the
- * returned article information.
- * @return A DotTerminatedMessageReader instance from which the article
- * body can be read. null if the article does not exist.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public Reader retrieveArticleBody(String articleId, ArticlePointer pointer)
- throws IOException
- {
- return __retrieve(NNTPCommand.BODY, articleId, pointer);
-
- }
-
- /*** Same as
- * A DotTerminatedMessageReader is returned from which the article can
- * be read. If the article does not exist, null is returned.
- *
- * You must not issue any commands to the NNTP server (i.e., call any
- * other methods) until you finish reading the message from the returned
- * Reader instance.
- * The NNTP protocol uses the same stream for issuing commands as it does
- * for returning results. Therefore the returned Reader actually reads
- * directly from the NNTP connection. After the end of message has been
- * reached, new commands can be executed and their replies read. If
- * you do not follow these requirements, your program will not work
- * properly.
- *
- * @param articleNumber The number of the the article whose body is
- * being retrieved.
- * @param pointer A parameter through which to return the article's
- * number and unique id. The articleId field cannot always be trusted
- * because of server deviations from RFC 977 reply formats. You may
- * set this parameter to null if you do not desire to retrieve the
- * returned article information.
- * @return A DotTerminatedMessageReader instance from which the article
- * body can be read. null if the article does not exist.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public Reader retrieveArticleBody(int articleNumber,
- ArticlePointer pointer)
- throws IOException
- {
- return __retrieve(NNTPCommand.BODY, articleNumber, pointer);
- }
-
-
- /*** Same as
- * @param newsgroup The newsgroup to select.
- * @param info A parameter through which the newsgroup information of
- * the selected newsgroup contained in the server reply is returned.
- * Set this to null if you do not desire this information.
- * @return True if the newsgroup exists and was selected, false otherwise.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean selectNewsgroup(String newsgroup, NewsgroupInfo info)
- throws IOException
- {
- if (!NNTPReply.isPositiveCompletion(group(newsgroup)))
- return false;
-
- if (info != null)
- __parseGroupReply(getReplyString(), info);
-
- return true;
- }
-
- /*** Same as
- * @return The sever help information.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String listHelp() throws IOException
- {
- StringWriter help;
- Reader reader;
-
- if (!NNTPReply.isInformational(help()))
- return null;
-
- help = new StringWriter();
- reader = new DotTerminatedMessageReader(_reader_);
- Util.copyReader(reader, help);
- reader.close();
- help.close();
- return help.toString();
- }
-
-
- /***
- * Select an article by its unique identifier (including enclosing
- * < and >) and return its article number and id through the
- * pointer parameter. This is achieved through the STAT command.
- * According to RFC 977, this will NOT set the current article pointer
- * on the server. To do that, you must reference the article by its
- * number.
- *
- * @param articleId The unique article identifier of the article that
- * is being selectedd. If this parameter is null, the
- * body of the current article is selected
- * @param pointer A parameter through which to return the article's
- * number and unique id. The articleId field cannot always be trusted
- * because of server deviations from RFC 977 reply formats. You may
- * set this parameter to null if you do not desire to retrieve the
- * returned article information.
- * @return True if successful, false if not.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean selectArticle(String articleId, ArticlePointer pointer)
- throws IOException
- {
- if (articleId != null)
- {
- if (!NNTPReply.isPositiveCompletion(stat(articleId)))
- return false;
- }
- else
- {
- if (!NNTPReply.isPositiveCompletion(stat()))
- return false;
- }
-
- if (pointer != null)
- __parseArticlePointer(getReplyString(), pointer);
-
- return true;
- }
-
- /**** Same as
- * @param articleNumber The number of the article to select from the
- * currently selected newsgroup.
- * @param pointer A parameter through which to return the article's
- * number and unique id. Although the articleId field cannot always
- * be trusted because of server deviations from RFC 977 reply formats,
- * we haven't found a server that misformats this information in response
- * to this particular command. You may set this parameter to null if
- * you do not desire to retrieve the returned article information.
- * @return True if successful, false if not.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean selectArticle(int articleNumber, ArticlePointer pointer)
- throws IOException
- {
- if (!NNTPReply.isPositiveCompletion(stat(articleNumber)))
- return false;
-
- if (pointer != null)
- __parseArticlePointer(getReplyString(), pointer);
-
- return true;
- }
-
-
- /*** Same as
- * @param pointer A parameter through which to return the article's
- * number and unique id. The articleId field cannot always be trusted
- * because of server deviations from RFC 977 reply formats. You may
- * set this parameter to null if you do not desire to retrieve the
- * returned article information.
- * @return True if successful, false if not (e.g., there is no previous
- * article).
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean selectPreviousArticle(ArticlePointer pointer)
- throws IOException
- {
- if (!NNTPReply.isPositiveCompletion(last()))
- return false;
-
- if (pointer != null)
- __parseArticlePointer(getReplyString(), pointer);
-
- return true;
- }
-
- /*** Same as
- * @param pointer A parameter through which to return the article's
- * number and unique id. The articleId field cannot always be trusted
- * because of server deviations from RFC 977 reply formats. You may
- * set this parameter to null if you do not desire to retrieve the
- * returned article information.
- * @return True if successful, false if not (e.g., there is no following
- * article).
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean selectNextArticle(ArticlePointer pointer) throws IOException
- {
- if (!NNTPReply.isPositiveCompletion(next()))
- return false;
-
- if (pointer != null)
- __parseArticlePointer(getReplyString(), pointer);
-
- return true;
- }
-
-
- /*** Same as
- * @return An array of NewsgroupInfo instances containing the information
- * for each newsgroup served by the NNTP server. If no newsgroups
- * are served, a zero length array will be returned. If the command
- * fails, null will be returned.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public NewsgroupInfo[] listNewsgroups() throws IOException
- {
- if (!NNTPReply.isPositiveCompletion(list()))
- return null;
-
- return __readNewsgroupListing();
- }
-
- /**
- * An overloaded listNewsgroups() command that allows us to
- * specify with a pattern what groups we want to list. Wraps the
- * LIST ACTIVE command.
- *
- * @param wildmat a pseudo-regex pattern (cf. RFC 2980)
- * @return An array of NewsgroupInfo instances containing the information
- * for each newsgroup served by the NNTP server corresponding to the
- * supplied pattern. If no such newsgroups are served, a zero length
- * array will be returned. If the command fails, null will be returned.
- * @throws IOException
- */
- public NewsgroupInfo[] listNewsgroups(String wildmat) throws IOException
- {
- if(!NNTPReply.isPositiveCompletion(listActive(wildmat)))
- return null;
- return __readNewsgroupListing();
- }
-
-
- /***
- * List all new newsgroups added to the NNTP server since a particular
- * date subject to the conditions of the specified query. If no new
- * newsgroups were added, a zero length array will be returned. If the
- * command fails, null will be returned.
- *
- * @param query The query restricting how to search for new newsgroups.
- * @return An array of NewsgroupInfo instances containing the information
- * for each new newsgroup added to the NNTP server. If no newsgroups
- * were added, a zero length array will be returned. If the command
- * fails, null will be returned.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public NewsgroupInfo[] listNewNewsgroups(NewGroupsOrNewsQuery query)
- throws IOException
- {
- if (!NNTPReply.isPositiveCompletion(newgroups(
- query.getDate(), query.getTime(),
- query.isGMT(), query.getDistributions())))
- return null;
-
- return __readNewsgroupListing();
- }
-
-
- /***
- * List all new articles added to the NNTP server since a particular
- * date subject to the conditions of the specified query. If no new
- * new news is found, a zero length array will be returned. If the
- * command fails, null will be returned. You must add at least one
- * newsgroup to the query, else the command will fail. Each String
- * in the returned array is a unique message identifier including the
- * enclosing < and >.
- *
- * @param query The query restricting how to search for new news. You
- * must add at least one newsgroup to the query.
- * @return An array of String instances containing the unique message
- * identifiers for each new article added to the NNTP server. If no
- * new news is found, a zero length array will be returned. If the
- * command fails, null will be returned.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String[] listNewNews(NewGroupsOrNewsQuery query)
- throws IOException
- {
- int size;
- String line;
- Vector
- * For example
- *
- * @return True if successfully completed, false if not.
- * @exception NNTPConnectionClosedException
- * If the NNTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send NNTP reply code 400. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean completePendingCommand() throws IOException
- {
- return NNTPReply.isPositiveCompletion(getReply());
- }
-
- /***
- * Post an article to the NNTP server. This method returns a
- * DotTerminatedMessageWriter instance to which the article can be
- * written. Null is returned if the posting attempt fails. You
- * should check {@link NNTP#isAllowedToPost isAllowedToPost() }
- * before trying to post. However, a posting
- * attempt can fail due to malformed headers.
- *
- * You must not issue any commands to the NNTP server (i.e., call any
- * (other methods) until you finish writing to the returned Writer
- * instance and close it. The NNTP protocol uses the same stream for
- * issuing commands as it does for returning results. Therefore the
- * returned Writer actually writes directly to the NNTP connection.
- * After you close the writer, you can execute new commands. If you
- * do not follow these requirements your program will not work properly.
- *
- * Different NNTP servers will require different header formats, but
- * you can use the provided
- * {@link org.apache.commons.net.nntp.SimpleNNTPHeader}
- * class to construct the bare minimum acceptable header for most
- * news readers. To construct more complicated headers you should
- * refer to RFC 822. When the Java Mail API is finalized, you will be
- * able to use it to compose fully compliant Internet text messages.
- * The DotTerminatedMessageWriter takes care of doubling line-leading
- * dots and ending the message with a single dot upon closing, so all
- * you have to worry about is writing the header and the message.
- *
- * Upon closing the returned Writer, you need to call
- * {@link #completePendingCommand completePendingCommand() }
- * to finalize the posting and verify its success or failure from
- * the server reply.
- *
- * @return A DotTerminatedMessageWriter to which the article (including
- * header) can be written. Returns null if the command fails.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
-
- public Writer postArticle() throws IOException
- {
- if (!NNTPReply.isPositiveIntermediate(post()))
- return null;
-
- return new DotTerminatedMessageWriter(_writer_);
- }
-
-
- public Writer forwardArticle(String articleId) throws IOException
- {
- if (!NNTPReply.isPositiveIntermediate(ihave(articleId)))
- return null;
-
- return new DotTerminatedMessageWriter(_writer_);
- }
-
-
- /***
- * Logs out of the news server gracefully by sending the QUIT command.
- * However, you must still disconnect from the server before you can open
- * a new connection.
- *
- * @return True if successfully completed, false if not.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean logout() throws IOException
- {
- return NNTPReply.isPositiveCompletion(quit());
- }
-
-
- /**
- * Log into a news server by sending the AUTHINFO USER/AUTHINFO
- * PASS command sequence. This is usually sent in response to a
- * 480 reply code from the NNTP server.
- *
- * @param username a valid username
- * @param password the corresponding password
- * @return True for successful login, false for a failure
- * @throws IOException
- */
- public boolean authenticate(String username, String password)
- throws IOException
- {
- int replyCode = authinfoUser(username);
-
- if (replyCode == NNTPReply.MORE_AUTH_INFO_REQUIRED)
- {
- replyCode = authinfoPass(password);
-
- if (replyCode == NNTPReply.AUTHENTICATION_ACCEPTED)
- {
- _isAllowedToPost = true;
- return true;
- }
- }
- return false;
- }
-
- /***
- * Private implementation of XOVER functionality.
- *
- * See {@link NNTP#xover}
- * for legal agument formats. Alternatively, read RFC 2980 :-)
- *
- * @param articleRange
- * @return Returns a DotTerminatedMessageReader if successful, null
- * otherwise
- * @exception IOException
- */
- private Reader __retrieveArticleInfo(String articleRange)
- throws IOException
- {
- if (!NNTPReply.isPositiveCompletion(xover(articleRange)))
- return null;
-
- return new DotTerminatedMessageReader(_reader_);
- }
-
- /**
- * Return article headers for a specified post.
- *
- * @param articleNumber the article to retrieve headers for
- * @return a DotTerminatedReader if successful, null otherwise
- * @throws IOException
- */
- public Reader retrieveArticleInfo(int articleNumber) throws IOException
- {
- return __retrieveArticleInfo(Integer.toString(articleNumber));
- }
-
- /**
- * Return article headers for all articles between lowArticleNumber
- * and highArticleNumber, inclusively.
- *
- * @param lowArticleNumber
- * @param highArticleNumber
- * @return a DotTerminatedReader if successful, null otherwise
- * @throws IOException
- */
- public Reader retrieveArticleInfo(int lowArticleNumber,
- int highArticleNumber)
- throws IOException
- {
- return
- __retrieveArticleInfo(lowArticleNumber + "-" +
- highArticleNumber);
- }
-
- /***
- * Private implementation of XHDR functionality.
- *
- * See {@link NNTP#xhdr}
- * for legal agument formats. Alternatively, read RFC 1036.
- *
- * @param header
- * @param articleRange
- * @return Returns a DotTerminatedMessageReader if successful, null
- * otherwise
- * @exception IOException
- */
- private Reader __retrieveHeader(String header, String articleRange)
- throws IOException
- {
- if (!NNTPReply.isPositiveCompletion(xhdr(header, articleRange)))
- return null;
-
- return new DotTerminatedMessageReader(_reader_);
- }
-
- /**
- * Return an article header for a specified post.
- *
- * @param header the header to retrieve
- * @param articleNumber the article to retrieve the header for
- * @return a DotTerminatedReader if successful, null otherwise
- * @throws IOException
- */
- public Reader retrieveHeader(String header, int articleNumber)
- throws IOException
- {
- return __retrieveHeader(header, Integer.toString(articleNumber));
- }
-
- /**
- * Return an article header for all articles between lowArticleNumber
- * and highArticleNumber, inclusively.
- *
- * @param header
- * @param lowArticleNumber
- * @param highArticleNumber
- * @return a DotTerminatedReader if successful, null otherwise
- * @throws IOException
- */
- public Reader retrieveHeader(String header, int lowArticleNumber,
- int highArticleNumber)
- throws IOException
- {
- return
- __retrieveHeader(header,lowArticleNumber + "-" + highArticleNumber);
- }
-}
-
-
-/* Emacs configuration
- * Local variables: **
- * mode: java **
- * c-basic-offset: 4 **
- * indent-tabs-mode: nil **
- * End: **
- */
diff --git a/org/apache/commons/net/nntp/NNTPCommand.java b/org/apache/commons/net/nntp/NNTPCommand.java
deleted file mode 100644
index 09f4015..0000000
--- a/org/apache/commons/net/nntp/NNTPCommand.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.nntp;
-
-/***
- * NNTPCommand stores a set of constants for NNTP command codes. To interpret
- * the meaning of the codes, familiarity with RFC 977 is assumed.
- *
- * @author Daniel F. Savarese
- * @author Rory Winston
- * @author Ted Wise
- ***/
-
-public final class NNTPCommand
-{
-
- public static final int ARTICLE = 0;
- public static final int BODY = 1;
- public static final int GROUP = 2;
- public static final int HEAD = 3;
- public static final int HELP = 4;
- public static final int IHAVE = 5;
- public static final int LAST = 6;
- public static final int LIST = 7;
- public static final int NEWGROUPS = 8;
- public static final int NEWNEWS = 9;
- public static final int NEXT = 10;
- public static final int POST = 11;
- public static final int QUIT = 12;
- public static final int SLAVE = 13;
- public static final int STAT = 14;
- public static final int AUTHINFO = 15;
- public static final int XOVER = 16;
- public static final int XHDR = 17;
-
- // Cannot be instantiated
- private NNTPCommand()
- {}
-
- static final String[] _commands = {
- "ARTICLE", "BODY", "GROUP", "HEAD", "HELP", "IHAVE", "LAST", "LIST",
- "NEWGROUPS", "NEWNEWS", "NEXT", "POST", "QUIT", "SLAVE", "STAT",
- "AUTHINFO", "XOVER", "XHDR"
- };
-
-
- /***
- * Retrieve the NNTP protocol command string corresponding to a specified
- * command code.
- *
- * @param command The command code.
- * @return The NNTP protcol command string corresponding to a specified
- * command code.
- ***/
- public static final String getCommand(int command)
- {
- return _commands[command];
- }
-
-}
-
-/* Emacs configuration
- * Local variables: **
- * mode: java **
- * c-basic-offset: 4 **
- * indent-tabs-mode: nil **
- * End: **
- */
diff --git a/org/apache/commons/net/nntp/NNTPConnectionClosedException.java b/org/apache/commons/net/nntp/NNTPConnectionClosedException.java
deleted file mode 100644
index 948ed12..0000000
--- a/org/apache/commons/net/nntp/NNTPConnectionClosedException.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.nntp;
-
-import java.io.IOException;
-
-/***
- * NNTPConnectionClosedException is used to indicate the premature or
- * unexpected closing of an NNTP connection resulting from a
- * {@link org.apache.commons.net.nntp.NNTPReply#SERVICE_DISCONTINUED NNTPReply.SERVICE_DISCONTINUED }
- * response (NNTP reply code 400) to a
- * failed NNTP command. This exception is derived from IOException and
- * therefore may be caught either as an IOException or specifically as an
- * NNTPConnectionClosedException.
- *
- *
- * @author Daniel F. Savarese
- * @see NNTP
- * @see NNTPClient
- ***/
-
-public final class NNTPConnectionClosedException extends IOException
-{
-
- /*** Constructs a NNTPConnectionClosedException with no message ***/
- public NNTPConnectionClosedException()
- {
- super();
- }
-
- /***
- * Constructs a NNTPConnectionClosedException with a specified message.
- *
- * @param message The message explaining the reason for the exception.
- ***/
- public NNTPConnectionClosedException(String message)
- {
- super(message);
- }
-
-}
diff --git a/org/apache/commons/net/nntp/NNTPReply.java b/org/apache/commons/net/nntp/NNTPReply.java
deleted file mode 100644
index f7d0fbd..0000000
--- a/org/apache/commons/net/nntp/NNTPReply.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.nntp;
-
-/***
- * NNTPReply stores a set of constants for NNTP reply codes. To interpret
- * the meaning of the codes, familiarity with RFC 977 is assumed.
- * The mnemonic constant names are transcriptions from the code descriptions
- * of RFC 977. For those who think in terms of the actual reply code values,
- * a set of CODE_NUM constants are provided where NUM is the numerical value
- * of the code.
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class NNTPReply
-{
-
- public static final int CODE_100 = 100;
- public static final int CODE_199 = 199;
- public static final int CODE_200 = 200;
- public static final int CODE_201 = 201;
- public static final int CODE_202 = 202;
- public static final int CODE_205 = 205;
- public static final int CODE_211 = 211;
- public static final int CODE_215 = 215;
- public static final int CODE_220 = 220;
- public static final int CODE_221 = 221;
- public static final int CODE_222 = 222;
- public static final int CODE_223 = 223;
- public static final int CODE_230 = 230;
- public static final int CODE_231 = 231;
- public static final int CODE_235 = 235;
- public static final int CODE_240 = 240;
- public static final int CODE_281 = 281;
- public static final int CODE_335 = 335;
- public static final int CODE_340 = 340;
- public static final int CODE_381 = 381;
- public static final int CODE_400 = 400;
- public static final int CODE_408 = 408;
- public static final int CODE_411 = 411;
- public static final int CODE_412 = 412;
- public static final int CODE_420 = 420;
- public static final int CODE_421 = 421;
- public static final int CODE_422 = 422;
- public static final int CODE_423 = 423;
- public static final int CODE_430 = 430;
- public static final int CODE_435 = 435;
- public static final int CODE_436 = 436;
- public static final int CODE_437 = 437;
- public static final int CODE_440 = 440;
- public static final int CODE_441 = 441;
- public static final int CODE_482 = 482;
- public static final int CODE_500 = 500;
- public static final int CODE_501 = 501;
- public static final int CODE_502 = 502;
- public static final int CODE_503 = 503;
-
- public static final int HELP_TEXT_FOLLOWS = CODE_100;
- public static final int DEBUG_OUTPUT = CODE_199;
- public static final int SERVER_READY_POSTING_ALLOWED = CODE_200;
- public static final int SERVER_READY_POSTING_NOT_ALLOWED = CODE_201;
- public static final int SLAVE_STATUS_NOTED = CODE_202;
- public static final int CLOSING_CONNECTION = CODE_205;
- public static final int GROUP_SELECTED = CODE_211;
- public static final int ARTICLE_RETRIEVED_HEAD_AND_BODY_FOLLOW = CODE_220;
- public static final int ARTICLE_RETRIEVED_HEAD_FOLLOWS = CODE_221;
- public static final int ARTICLE_RETRIEVED_BODY_FOLLOWS = CODE_222;
- public static final int
- ARTICLE_RETRIEVED_REQUEST_TEXT_SEPARATELY = CODE_223;
- public static final int ARTICLE_LIST_BY_MESSAGE_ID_FOLLOWS = CODE_230;
- public static final int NEW_NEWSGROUP_LIST_FOLLOWS = CODE_231;
- public static final int ARTICLE_TRANSFERRED_OK = CODE_235;
- public static final int ARTICLE_POSTED_OK = CODE_240;
- public static final int AUTHENTICATION_ACCEPTED = CODE_281;
- public static final int SEND_ARTICLE_TO_TRANSFER = CODE_335;
- public static final int SEND_ARTICLE_TO_POST = CODE_340;
- public static final int MORE_AUTH_INFO_REQUIRED = CODE_381;
- public static final int SERVICE_DISCONTINUED = CODE_400;
- public static final int NO_SUCH_NEWSGROUP = CODE_411;
- public static final int AUTHENTICATION_REQUIRED = CODE_408;
- public static final int NO_NEWSGROUP_SELECTED = CODE_412;
- public static final int NO_CURRENT_ARTICLE_SELECTED = CODE_420;
- public static final int NO_NEXT_ARTICLE = CODE_421;
- public static final int NO_PREVIOUS_ARTICLE = CODE_422;
- public static final int NO_SUCH_ARTICLE_NUMBER = CODE_423;
- public static final int NO_SUCH_ARTICLE_FOUND = CODE_430;
- public static final int ARTICLE_NOT_WANTED = CODE_435;
- public static final int TRANSFER_FAILED = CODE_436;
- public static final int ARTICLE_REJECTED = CODE_437;
- public static final int POSTING_NOT_ALLOWED = CODE_440;
- public static final int POSTING_FAILED = CODE_441;
- public static final int AUTHENTICATION_REJECTED = CODE_482;
- public static final int COMMAND_NOT_RECOGNIZED = CODE_500;
- public static final int COMMAND_SYNTAX_ERROR = CODE_501;
- public static final int PERMISSION_DENIED = CODE_502;
- public static final int PROGRAM_FAULT = CODE_503;
-
- // Cannot be instantiated
-
- private NNTPReply()
- {}
-
- /***
- * Determine if a reply code is an informational response. All
- * codes beginning with a 1 are positive informational responses.
- * Informational responses are used to provide human readable
- * information such as help text.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is an informational response, false
- * if not.
- ***/
- public static boolean isInformational(int reply)
- {
- return (reply >= 100 && reply < 200);
- }
-
- /***
- * Determine if a reply code is a positive completion response. All
- * codes beginning with a 2 are positive completion responses.
- * The NNTP server will send a positive completion response on the final
- * successful completion of a command.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a postive completion response, false
- * if not.
- ***/
- public static boolean isPositiveCompletion(int reply)
- {
- return (reply >= 200 && reply < 300);
- }
-
- /***
- * Determine if a reply code is a positive intermediate response. All
- * codes beginning with a 3 are positive intermediate responses.
- * The NNTP server will send a positive intermediate response on the
- * successful completion of one part of a multi-part command or
- * sequence of commands. For example, after a successful POST command,
- * a positive intermediate response will be sent to indicate that the
- * server is ready to receive the article to be posted.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a postive intermediate response, false
- * if not.
- ***/
- public static boolean isPositiveIntermediate(int reply)
- {
- return (reply >= 300 && reply < 400);
- }
-
- /***
- * Determine if a reply code is a negative transient response. All
- * codes beginning with a 4 are negative transient responses.
- * The NNTP server will send a negative transient response on the
- * failure of a correctly formatted command that could not be performed
- * for some reason. For example, retrieving an article that does not
- * exist will result in a negative transient response.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a negative transient response, false
- * if not.
- ***/
- public static boolean isNegativeTransient(int reply)
- {
- return (reply >= 400 && reply < 500);
- }
-
- /***
- * Determine if a reply code is a negative permanent response. All
- * codes beginning with a 5 are negative permanent responses.
- * The NNTP server will send a negative permanent response when
- * it does not implement a command, a command is incorrectly formatted,
- * or a serious program error occurs.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a negative permanent response, false
- * if not.
- ***/
- public static boolean isNegativePermanent(int reply)
- {
- return (reply >= 500 && reply < 600);
- }
-
-}
-
-/* Emacs configuration
- * Local variables: **
- * mode: java **
- * c-basic-offset: 4 **
- * indent-tabs-mode: nil **
- * End: **
- */
diff --git a/org/apache/commons/net/nntp/NewGroupsOrNewsQuery.java b/org/apache/commons/net/nntp/NewGroupsOrNewsQuery.java
deleted file mode 100644
index a0d9aeb..0000000
--- a/org/apache/commons/net/nntp/NewGroupsOrNewsQuery.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.nntp;
-
-import java.util.Calendar;
-
-/***
- * The NewGroupsOrNewsQuery class. This is used to issue NNTP NEWGROUPS and
- * NEWNEWS queries, implemented by
- * {@link org.apache.commons.net.nntp.NNTPClient#listNewNewsgroups listNewNewsGroups }
- * and
- * {@link org.apache.commons.net.nntp.NNTPClient#listNewNews listNewNews }
- * respectively. It prevents you from having to format
- * date, time, distribution, and newgroup arguments.
- *
- * You might use the class as follows:
- *
- *
- * @author Daniel F. Savarese
- * @see NNTPClient
- ***/
-
-public final class NewGroupsOrNewsQuery
-{
- private String __date, __time;
- private StringBuffer __distributions;
- private StringBuffer __newsgroups;
- private boolean __isGMT;
-
-
- /***
- * Creates a new query using the given time as a reference point.
- *
- * @param date The date since which new groups or news have arrived.
- * @param gmt True if the date should be considered as GMT, false if not.
- ***/
- public NewGroupsOrNewsQuery(Calendar date, boolean gmt)
- {
- int num;
- String str;
- StringBuffer buffer;
-
- __distributions = null;
- __newsgroups = null;
- __isGMT = gmt;
-
- buffer = new StringBuffer();
-
- // Get year
- num = date.get(Calendar.YEAR);
- str = Integer.toString(num);
- num = str.length();
-
- if (num >= 2)
- buffer.append(str.substring(num - 2));
- else
- buffer.append("00");
-
- // Get month
- num = date.get(Calendar.MONTH) + 1;
- str = Integer.toString(num);
- num = str.length();
-
- if (num == 1)
- {
- buffer.append('0');
- buffer.append(str);
- }
- else if (num == 2)
- buffer.append(str);
- else
- buffer.append("01");
-
- // Get day
- num = date.get(Calendar.DAY_OF_MONTH);
- str = Integer.toString(num);
- num = str.length();
-
- if (num == 1)
- {
- buffer.append('0');
- buffer.append(str);
- }
- else if (num == 2)
- buffer.append(str);
- else
- buffer.append("01");
-
- __date = buffer.toString();
-
- buffer.setLength(0);
-
- // Get hour
- num = date.get(Calendar.HOUR_OF_DAY);
- str = Integer.toString(num);
- num = str.length();
-
- if (num == 1)
- {
- buffer.append('0');
- buffer.append(str);
- }
- else if (num == 2)
- buffer.append(str);
- else
- buffer.append("00");
-
- // Get minutes
- num = date.get(Calendar.MINUTE);
- str = Integer.toString(num);
- num = str.length();
-
- if (num == 1)
- {
- buffer.append('0');
- buffer.append(str);
- }
- else if (num == 2)
- buffer.append(str);
- else
- buffer.append("00");
-
-
- // Get seconds
- num = date.get(Calendar.SECOND);
- str = Integer.toString(num);
- num = str.length();
-
- if (num == 1)
- {
- buffer.append('0');
- buffer.append(str);
- }
- else if (num == 2)
- buffer.append(str);
- else
- buffer.append("00");
-
- __time = buffer.toString();
- }
-
-
- /***
- * Add a newsgroup to the list of newsgroups being queried. Newsgroups
- * added this way are only meaningful to the NEWNEWS command. Newsgroup
- * names may include the
- * @param newsgroup The newsgroup to add to the list of groups to be
- * checked for new news.
- ***/
- public void addNewsgroup(String newsgroup)
- {
- if (__newsgroups != null)
- __newsgroups.append(',');
- else
- __newsgroups = new StringBuffer();
- __newsgroups.append(newsgroup);
- }
-
-
- /***
- * Add a newsgroup to the list of newsgroups being queried, but indicate
- * that group should not be checked for new news. Newsgroups
- * added this way are only meaningful to the NEWNEWS command.
- * Newsgroup names may include the
- * The following would create a query that searched for new news in
- * all comp.lang.java newsgroups except for comp.lang.java.advocacy.
- *
- * @param newsgroup The newsgroup to add to the list of groups to be
- * checked for new news, but which should be omitted from
- * the search for new news..
- ***/
- public void omitNewsgroup(String newsgroup)
- {
- addNewsgroup("!" + newsgroup);
- }
-
-
- /***
- * Add a distribution group to the query. The distribution part of a
- * newsgroup is the segment of the name preceding the first dot (e.g.,
- * comp, alt, rec). Only those newsgroups matching one of the
- * distributions or, in the case of NEWNEWS, an article in a newsgroup
- * matching one of the distributions, will be reported as a query result.
- * Adding distributions is purely optional.
- *
- * @param distribution A distribution to add to the query.
- ***/
- public void addDistribution(String distribution)
- {
- if (__distributions != null)
- __distributions.append(',');
- else
- __distributions = new StringBuffer();
- __distributions.append(distribution);
- }
-
- /***
- * Return the NNTP query formatted date (year, month, day in the form
- * YYMMDD.
- *
- * @return The NNTP query formatted date.
- ***/
- public String getDate()
- {
- return __date;
- }
-
- /***
- * Return the NNTP query formatted time (hour, minutes, seconds in the form
- * HHMMSS.
- *
- * @return The NNTP query formatted time.
- ***/
- public String getTime()
- {
- return __time;
- }
-
- /***
- * Return whether or not the query date should be treated as GMT.
- *
- * @return True if the query date is to be treated as GMT, false if not.
- ***/
- public boolean isGMT()
- {
- return __isGMT;
- }
-
- /***
- * Return the comma separated list of distributions. This may be null
- * if there are no distributions.
- *
- * @return The list of distributions, which may be null if no distributions
- * have been specified.
- ***/
- public String getDistributions()
- {
- return (__distributions == null ? null : __distributions.toString());
- }
-
- /***
- * Return the comma separated list of newsgroups. This may be null
- * if there are no newsgroups
- *
- * @return The list of newsgroups, which may be null if no newsgroups
- * have been specified.
- ***/
- public String getNewsgroups()
- {
- return (__newsgroups == null ? null : __newsgroups.toString());
- }
-}
diff --git a/org/apache/commons/net/nntp/NewsgroupInfo.java b/org/apache/commons/net/nntp/NewsgroupInfo.java
deleted file mode 100644
index aa48d16..0000000
--- a/org/apache/commons/net/nntp/NewsgroupInfo.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.nntp;
-
-/***
- * NewsgroupInfo stores information pertaining to a newsgroup returned by
- * the NNTP GROUP, LIST, and NEWGROUPS commands, implemented by
- * {@link org.apache.commons.net.nntp.NNTPClient#selectNewsgroup selectNewsgroup }
- * ,
- * {@link org.apache.commons.net.nntp.NNTPClient#listNewsgroups listNewsgroups }
- * , and
- * {@link org.apache.commons.net.nntp.NNTPClient#listNewNewsgroups listNewNewsgroups }
- * respectively.
- *
- *
- * @author Daniel F. Savarese
- * @see NNTPClient
- ***/
-
-public final class NewsgroupInfo
-{
- /***
- * A constant indicating that the posting permission of a newsgroup is
- * unknown. For example, the NNTP GROUP command does not return posting
- * information, so NewsgroupInfo instances obtained from that command
- * willhave an UNKNOWN_POSTING_PERMISSION.
- ***/
- public static final int UNKNOWN_POSTING_PERMISSION = 0;
-
- /*** A constant indicating that a newsgroup is moderated. ***/
- public static final int MODERATED_POSTING_PERMISSION = 1;
-
- /*** A constant indicating that a newsgroup is public and unmoderated. ***/
- public static final int PERMITTED_POSTING_PERMISSION = 2;
-
- /***
- * A constant indicating that a newsgroup is closed for general posting.
- ***/
- public static final int PROHIBITED_POSTING_PERMISSION = 3;
-
- private String __newsgroup;
- private int __estimatedArticleCount;
- private int __firstArticle, __lastArticle;
- private int __postingPermission;
-
- void _setNewsgroup(String newsgroup)
- {
- __newsgroup = newsgroup;
- }
-
- void _setArticleCount(int count)
- {
- __estimatedArticleCount = count;
- }
-
- void _setFirstArticle(int first)
- {
- __firstArticle = first;
- }
-
- void _setLastArticle(int last)
- {
- __lastArticle = last;
- }
-
- void _setPostingPermission(int permission)
- {
- __postingPermission = permission;
- }
-
- /***
- * Get the newsgroup name.
- *
- * @return The name of the newsgroup.
- ***/
- public String getNewsgroup()
- {
- return __newsgroup;
- }
-
- /***
- * Get the estimated number of articles in the newsgroup. The
- * accuracy of this value will depend on the server implementation.
- *
- * @return The estimated number of articles in the newsgroup.
- ***/
- public int getArticleCount()
- {
- return __estimatedArticleCount;
- }
-
- /***
- * Get the number of the first article in the newsgroup.
- *
- * @return The number of the first article in the newsgroup.
- ***/
- public int getFirstArticle()
- {
- return __firstArticle;
- }
-
- /***
- * Get the number of the last article in the newsgroup.
- *
- * @return The number of the last article in the newsgroup.
- ***/
- public int getLastArticle()
- {
- return __lastArticle;
- }
-
- /***
- * Get the posting permission of the newsgroup. This will be one of
- * the
- * @return The posting permission status of the newsgroup.
- ***/
- public int getPostingPermission()
- {
- return __postingPermission;
- }
-
- /*
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- buffer.append(__newsgroup);
- buffer.append(' ');
- buffer.append(__lastArticle);
- buffer.append(' ');
- buffer.append(__firstArticle);
- buffer.append(' ');
- switch(__postingPermission) {
- case 1: buffer.append('m'); break;
- case 2: buffer.append('y'); break;
- case 3: buffer.append('n'); break;
- }
- return buffer.toString();
-}
- */
-}
diff --git a/org/apache/commons/net/nntp/SimpleNNTPHeader.java b/org/apache/commons/net/nntp/SimpleNNTPHeader.java
deleted file mode 100644
index d18a8cf..0000000
--- a/org/apache/commons/net/nntp/SimpleNNTPHeader.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.nntp;
-
-/***
- * This class is used to construct the bare minimum
- * acceptable header for most news readers. To construct more
- * complicated headers you should refer to RFC 822. When the
- * Java Mail API is finalized, you will be
- * able to use it to compose fully compliant Internet text messages.
- *
- * The main purpose of the class is to faciliatate the article posting
- * process, by relieving the programmer from having to explicitly format
- * an article header. For example:
- *
- *
- * @author Daniel F. Savarese
- * @see NNTPClient
- ***/
-
-public class SimpleNNTPHeader
-{
- private String __subject, __from;
- private StringBuilder __newsgroups;
- private StringBuilder __headerFields;
- private int __newsgroupCount;
-
- /***
- * Creates a new SimpleNNTPHeader instance initialized with the given
- * from and subject header field values.
- *
- * @param from The value of the
- * @param newsgroup The newsgroup to add to the article's newsgroup
- * distribution list.
- ***/
- public void addNewsgroup(String newsgroup)
- {
- if (__newsgroupCount++ > 0)
- __newsgroups.append(',');
- __newsgroups.append(newsgroup);
- }
-
- /***
- * Adds an arbitrary header field with the given value to the article
- * header. These headers will be written after the From, Newsgroups,
- * and Subject fields when the SimpleNNTPHeader is convertered to a string.
- * An example use would be:
- *
- * @param headerField The header field to add, not including the colon.
- * @param value The value of the added header field.
- ***/
- public void addHeaderField(String headerField, String value)
- {
- __headerFields.append(headerField);
- __headerFields.append(": ");
- __headerFields.append(value);
- __headerFields.append('\n');
- }
-
-
- /***
- * Returns the address used in the
- * @return The from address.
- ***/
- public String getFromAddress()
- {
- return __from;
- }
-
- /***
- * Returns the subject used in the
- * @return The subject.
- ***/
- public String getSubject()
- {
- return __subject;
- }
-
- /***
- * Returns the contents of the
- * @return The comma-separated list of newsgroups to which the article
- * is being posted.
- ***/
- public String getNewsgroups()
- {
- return __newsgroups.toString();
- }
-
- /***
- * Converts the SimpleNNTPHeader to a properly formatted header in
- * the form of a String, including the blank line used to separate
- * the header from the article body.
- *
- * @return The article header in the form of a String.
- ***/
- @Override
- public String toString()
- {
- StringBuffer header = new StringBuffer();
-
- header.append("From: ");
- header.append(__from);
- header.append("\nNewsgroups: ");
- header.append(__newsgroups.toString());
- header.append("\nSubject: ");
- header.append(__subject);
- header.append('\n');
- if (__headerFields.length() > 0)
- header.append(__headerFields.toString());
- header.append('\n');
-
- return header.toString();
- }
-}
diff --git a/org/apache/commons/net/nntp/Threadable.java b/org/apache/commons/net/nntp/Threadable.java
deleted file mode 100644
index 518a9a4..0000000
--- a/org/apache/commons/net/nntp/Threadable.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.nntp;
-
-/**
- * A placeholder interface for threadable message objects
- * Author: Rory Winston
- * @param host The address of the server.
- * @param port The port of the service.
- * @return The time value retrieved from the server.
- * @exception IOException If an error occurs while retrieving the time.
- ***/
- public TimeInfo getTime(InetAddress host, int port) throws IOException
- {
- // if not connected then open to next available UDP port
- if (!isOpen())
- {
- open();
- }
-
- NtpV3Packet message = new NtpV3Impl();
- message.setMode(NtpV3Packet.MODE_CLIENT);
- message.setVersion(_version);
- DatagramPacket sendPacket = message.getDatagramPacket();
- sendPacket.setAddress(host);
- sendPacket.setPort(port);
-
- NtpV3Packet recMessage = new NtpV3Impl();
- DatagramPacket receivePacket = recMessage.getDatagramPacket();
-
- /*
- * Must minimize the time between getting the current time,
- * timestamping the packet, and sending it out which
- * introduces an error in the delay time.
- * No extraneous logging and initializations here !!!
- */
- TimeStamp now = TimeStamp.getCurrentTime();
-
- // Note that if you do not set the transmit time field then originating time
- // in server response is all 0's which is "Thu Feb 07 01:28:16 EST 2036".
- message.setTransmitTime(now);
-
- _socket_.send(sendPacket);
- _socket_.receive(receivePacket);
-
- long returnTime = System.currentTimeMillis();
- // create TimeInfo message container but don't pre-compute the details yet
- TimeInfo info = new TimeInfo(recMessage, returnTime, false);
-
- return info;
- }
-
- /***
- * Retrieves the time information from the specified server on the
- * default NTP port and returns it. The time is the number of miliiseconds
- * since 00:00 (midnight) 1 January 1900 UTC, as specified by RFC 1305.
- * This method reads the raw NTP packet and constructs a TimeInfo
- * object that allows access to all the fields of the NTP message header.
- *
- * @param host The address of the server.
- * @return The time value retrieved from the server.
- * @exception IOException If an error occurs while retrieving the time.
- ***/
- public TimeInfo getTime(InetAddress host) throws IOException
- {
- return getTime(host, NtpV3Packet.NTP_PORT);
- }
-
- /***
- * Returns the NTP protocol version number that client sets on request packet
- * that is sent to remote host (e.g. 3=NTP v3, 4=NTP v4, etc.)
- *
- * @return the NTP protocol version number that client sets on request packet.
- * @see #setVersion(int)
- ***/
- public int getVersion()
- {
- return _version;
- }
-
- /***
- * Sets the NTP protocol version number that client sets on request packet
- * communicate with remote host.
- *
- * @param version the NTP protocol version number
- ***/
- public void setVersion(int version)
- {
- _version = version;
- }
-
-}
diff --git a/org/apache/commons/net/ntp/NtpUtils.java b/org/apache/commons/net/ntp/NtpUtils.java
deleted file mode 100644
index ca1fb41..0000000
--- a/org/apache/commons/net/ntp/NtpUtils.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.apache.commons.net.ntp;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-/***
- * Common NtpUtils Helper class.
- *
- * @author Jason Mathews, MITRE Corp
- *
- * @version $Revision: 489397 $ $Date: 2006-12-21 16:28:51 +0000 (Thu, 21 Dec 2006) $
- */
-public final class NtpUtils {
-
- /***
- * Returns 32-bit integer address to IPv4 address string "%d.%d.%d.%d" format.
- *
- * @param address the 32-bit address
- * @return the raw IP address in a string format.
- */
- public static String getHostAddress(int address)
- {
- return ((address >>> 24) & 0xFF) + "." +
- ((address >>> 16) & 0xFF) + "." +
- ((address >>> 8) & 0xFF) + "." +
- ((address >>> 0) & 0xFF);
- }
-
- /***
- * Returns NTP packet reference identifier as IP address.
- *
- * @param packet NTP packet
- * @return the packet reference id (as IP address) in "%d.%d.%d.%d" format.
- */
- public static String getRefAddress(NtpV3Packet packet)
- {
- int address = (packet == null) ? 0 : packet.getReferenceId();
- return getHostAddress(address);
- }
-
- /***
- * Get refId as reference clock string (e.g. GPS, WWV, LCL). If string is
- * invalid (non-ASCII character) then returns empty string "".
- * For details refer to the Comprehensive
- * List of Clock Drivers.
- *
- * @param message
- * @return reference clock string if primary NTP server
- */
- public static String getReferenceClock(NtpV3Packet message) {
- if (message == null)
- return "";
- int refId = message.getReferenceId();
- if (refId == 0)
- return "";
- StringBuffer buf = new StringBuffer(4);
- // start at highest-order byte (0x4c434c00 -> LCL)
- for (int shiftBits = 24; shiftBits >= 0; shiftBits -= 8)
- {
- char c = (char) ((refId >>> shiftBits) & 0xff);
- if (c == 0) break; // 0-terminated ASCII string
- if (!Character.isLetterOrDigit(c))
- return "";
- buf.append(c);
- }
- return buf.toString();
- }
-
- /***
- * Return human-readable name of message mode type (RFC 1305).
- *
- * @param mode
- * @return mode name
- */
- public static String getModeName(int mode)
- {
- switch (mode) {
- case NtpV3Packet.MODE_RESERVED:
- return "Reserved";
- case NtpV3Packet.MODE_SYMMETRIC_ACTIVE:
- return "Symmetric Active";
- case NtpV3Packet.MODE_SYMMETRIC_PASSIVE:
- return "Symmetric Passive";
- case NtpV3Packet.MODE_CLIENT:
- return "Client";
- case NtpV3Packet.MODE_SERVER:
- return "Server";
- case NtpV3Packet.MODE_BROADCAST:
- return "Broadcast";
- case NtpV3Packet.MODE_CONTROL_MESSAGE:
- return "Control";
- case NtpV3Packet.MODE_PRIVATE:
- return "Private";
- default:
- return "Unknown";
- }
- }
-
-}
diff --git a/org/apache/commons/net/ntp/NtpV3Impl.java b/org/apache/commons/net/ntp/NtpV3Impl.java
deleted file mode 100644
index 4a8569a..0000000
--- a/org/apache/commons/net/ntp/NtpV3Impl.java
+++ /dev/null
@@ -1,583 +0,0 @@
-package org.apache.commons.net.ntp;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.net.DatagramPacket;
-
-/***
- * Implementation of NtpV3Packet with methods converting Java objects to/from
- * the Network Time Protocol (NTP) data message header format described in RFC-1305.
- *
- * @author Naz Irizarry, MITRE Corp
- * @author Jason Mathews, MITRE Corp
- *
- * @version $Revision: 658518 $ $Date: 2008-05-21 02:04:30 +0100 (Wed, 21 May 2008) $
- */
-public class NtpV3Impl implements NtpV3Packet
-{
-
- private static final int MODE_INDEX = 0;
- private static final int MODE_SHIFT = 0;
-
- private static final int VERSION_INDEX = 0;
- private static final int VERSION_SHIFT = 3;
-
- private static final int LI_INDEX = 0;
- private static final int LI_SHIFT = 6;
-
- private static final int STRATUM_INDEX = 1;
- private static final int POLL_INDEX = 2;
- private static final int PRECISION_INDEX = 3;
-
- private static final int ROOT_DELAY_INDEX = 4;
- private static final int ROOT_DISPERSION_INDEX = 8;
- private static final int REFERENCE_ID_INDEX = 12;
-
- private static final int REFERENCE_TIMESTAMP_INDEX = 16;
- private static final int ORIGINATE_TIMESTAMP_INDEX = 24;
- private static final int RECEIVE_TIMESTAMP_INDEX = 32;
- private static final int TRANSMIT_TIMESTAMP_INDEX = 40;
-
- private static final int KEY_IDENTIFIER_INDEX = 48;
- private static final int MESSAGE_DIGEST = 54; /* len 16 bytes */
-
- private byte[] buf = new byte[48];
-
- private volatile DatagramPacket dp;
-
- /** Creates a new instance of NtpV3Impl */
- public NtpV3Impl()
- {
- }
-
- /***
- * Returns mode as defined in RFC-1305 which is a 3-bit integer
- * whose value is indicated by the MODE_xxx parameters.
- *
- * @return mode as defined in RFC-1305.
- */
- public int getMode()
- {
- return (ui(buf[MODE_INDEX]) >> MODE_SHIFT) & 0x7;
- }
-
- /***
- * Return human-readable name of message mode type as described in
- * RFC 1305.
- * @return mode name as string.
- */
- public String getModeName()
- {
- return NtpUtils.getModeName(getMode());
- }
-
- /***
- * Set mode as defined in RFC-1305.
- * @param mode
- */
- public void setMode(int mode)
- {
- buf[MODE_INDEX] = (byte) (buf[MODE_INDEX] & 0xF8 | mode & 0x7);
- }
-
- /***
- * Returns leap indicator as defined in RFC-1305 which is a two-bit code:
- * 0=no warning
- * 1=last minute has 61 seconds
- * 2=last minute has 59 seconds
- * 3=alarm condition (clock not synchronized)
- *
- * @return leap indicator as defined in RFC-1305.
- */
- public int getLeapIndicator()
- {
- return (ui(buf[LI_INDEX]) >> LI_SHIFT) & 0x3;
- }
-
- /***
- * Set leap indicator as defined in RFC-1305.
- * @param li leap indicator.
- */
- public void setLeapIndicator(int li)
- {
- buf[LI_INDEX] = (byte) (buf[LI_INDEX] & 0x3F | ((li & 0x3) << LI_SHIFT));
- }
-
- /***
- * Returns poll interval as defined in RFC-1305, which is an eight-bit
- * signed integer indicating the maximum interval between successive
- * messages, in seconds to the nearest power of two (e.g. value of six
- * indicates an interval of 64 seconds. The values that can appear in
- * this field range from NTP_MINPOLL to NTP_MAXPOLL inclusive.
- *
- * @return poll interval as defined in RFC-1305.
- */
- public int getPoll()
- {
- return buf[POLL_INDEX];
- }
-
- /***
- * Set poll interval as defined in RFC-1305.
- *
- * @param poll poll interval.
- */
- public void setPoll(int poll)
- {
- buf[POLL_INDEX] = (byte) (poll & 0xFF);
- }
-
- /***
- * Returns precision as defined in RFC-1305 encoded as an 8-bit signed
- * integer (seconds to nearest power of two).
- * Values normally range from -6 to -20.
- *
- * @return precision as defined in RFC-1305.
- */
- public int getPrecision()
- {
- return buf[PRECISION_INDEX];
- }
-
- /***
- * Set precision as defined in RFC-1305.
- * @param precision
- */
- public void setPrecision(int precision)
- {
- buf[PRECISION_INDEX] = (byte) (precision & 0xFF);
- }
-
- /***
- * Returns NTP version number as defined in RFC-1305.
- *
- * @return NTP version number.
- */
- public int getVersion()
- {
- return (ui(buf[VERSION_INDEX]) >> VERSION_SHIFT) & 0x7;
- }
-
- /***
- * Set NTP version as defined in RFC-1305.
- *
- * @param version NTP version.
- */
- public void setVersion(int version)
- {
- buf[VERSION_INDEX] = (byte) (buf[VERSION_INDEX] & 0xC7 | ((version & 0x7) << VERSION_SHIFT));
- }
-
- /***
- * Returns Stratum as defined in RFC-1305, which indicates the stratum level
- * of the local clock, with values defined as follows: 0=unspecified,
- * 1=primary ref clock, and all others a secondary reference (via NTP).
- *
- * @return Stratum level as defined in RFC-1305.
- */
- public int getStratum()
- {
- return ui(buf[STRATUM_INDEX]);
- }
-
- /***
- * Set stratum level as defined in RFC-1305.
- *
- * @param stratum stratum level.
- */
- public void setStratum(int stratum)
- {
- buf[STRATUM_INDEX] = (byte) (stratum & 0xFF);
- }
-
- /***
- * Return root delay as defined in RFC-1305, which is the total roundtrip delay
- * to the primary reference source, in seconds. Values can take positive and
- * negative values, depending on clock precision and skew.
- *
- * @return root delay as defined in RFC-1305.
- */
- public int getRootDelay()
- {
- return getInt(ROOT_DELAY_INDEX);
- }
-
- /***
- * Return root delay as defined in RFC-1305 in milliseconds, which is
- * the total roundtrip delay to the primary reference source, in
- * seconds. Values can take positive and negative values, depending
- * on clock precision and skew.
- *
- * @return root delay in milliseconds
- */
- public double getRootDelayInMillisDouble()
- {
- double l = getRootDelay();
- return l / 65.536;
- }
-
- /***
- * Returns root dispersion as defined in RFC-1305.
- * @return root dispersion.
- */
- public int getRootDispersion()
- {
- return getInt(ROOT_DISPERSION_INDEX);
- }
-
- /***
- * Returns root dispersion (as defined in RFC-1305) in milliseconds.
- *
- * @return root dispersion in milliseconds
- */
- public long getRootDispersionInMillis()
- {
- long l = getRootDispersion();
- return (l * 1000) / 65536L;
- }
-
- /***
- * Returns root dispersion (as defined in RFC-1305) in milliseconds
- * as double precision value.
- *
- * @return root dispersion in milliseconds
- */
- public double getRootDispersionInMillisDouble()
- {
- double l = getRootDispersion();
- return l / 65.536;
- }
-
- /***
- * Set reference clock identifier field with 32-bit unsigned integer value.
- * See RFC-1305 for description.
- *
- * @param refId reference clock identifier.
- */
- public void setReferenceId(int refId)
- {
- for (int i = 3; i >= 0; i--) {
- buf[REFERENCE_ID_INDEX + i] = (byte) (refId & 0xff);
- refId >>>= 8; // shift right one-byte
- }
- }
-
- /***
- * Returns the reference id as defined in RFC-1305, which is
- * a 32-bit integer whose value is dependent on several criteria.
- *
- * @return the reference id as defined in RFC-1305.
- */
- public int getReferenceId()
- {
- return getInt(REFERENCE_ID_INDEX);
- }
-
- /***
- * Returns the reference id string. String cannot be null but
- * value is dependent on the version of the NTP spec supported
- * and stratum level. Value can be an empty string, clock type string,
- * IP address, or a hex string.
- *
- * @return the reference id string.
- */
- public String getReferenceIdString()
- {
- int version = getVersion();
- int stratum = getStratum();
- if (version == VERSION_3 || version == VERSION_4) {
- if (stratum == 0 || stratum == 1) {
- return idAsString(); // 4-character ASCII string (e.g. GPS, USNO)
- }
- // in NTPv4 servers this is latest transmit timestamp of ref source
- if (version == VERSION_4)
- return idAsHex();
- }
-
- // Stratum 2 and higher this is a four-octet IPv4 address
- // of the primary reference host.
- if (stratum >= 2) {
- return idAsIPAddress();
- }
- return idAsHex();
- }
-
- /***
- * Returns Reference id as dotted IP address.
- * @return refId as IP address string.
- */
- private String idAsIPAddress()
- {
- return ui(buf[REFERENCE_ID_INDEX]) + "." +
- ui(buf[REFERENCE_ID_INDEX + 1]) + "." +
- ui(buf[REFERENCE_ID_INDEX + 2]) + "." +
- ui(buf[REFERENCE_ID_INDEX + 3]);
- }
-
- private String idAsString()
- {
- StringBuilder id = new StringBuilder();
- for (int i = 0; i <= 3; i++) {
- char c = (char) buf[REFERENCE_ID_INDEX + i];
- if (c == 0) break; // 0-terminated string
- id.append(c);
- }
- return id.toString();
- }
-
- private String idAsHex()
- {
- return Integer.toHexString(getReferenceId());
- }
-
- /***
- * Returns the transmit timestamp as defined in RFC-1305.
- *
- * @return the transmit timestamp as defined in RFC-1305.
- * Never returns a null object.
- */
- public TimeStamp getTransmitTimeStamp()
- {
- return getTimestamp(TRANSMIT_TIMESTAMP_INDEX);
- }
-
- /***
- * Set transmit time with NTP timestamp.
- * If
- * Methods exist to convert NTP timestamps to and from the equivalent Java date
- * representation, which is the number of milliseconds since the standard base
- * time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
- *
- * Rather than list it separately for each method, we mention here that
- * every method communicating with the server and throwing an IOException
- * can also throw a
- * {@link org.apache.commons.net.MalformedServerReplyException}
- * , which is a subclass
- * of IOException. A MalformedServerReplyException will be thrown when
- * the reply received from the server deviates enough from the protocol
- * specification that it cannot be interpreted in a useful manner despite
- * attempts to be as lenient as possible.
- *
- *
- * @author Daniel F. Savarese
- * @see POP3Client
- * @see org.apache.commons.net.MalformedServerReplyException
- ***/
-
-public class POP3 extends SocketClient
-{
- /*** The default POP3 port. Set to 110 according to RFC 1288. ***/
- public static final int DEFAULT_PORT = 110;
- /***
- * A constant representing the state where the client is not yet connected
- * to a POP3 server.
- ***/
- public static final int DISCONNECTED_STATE = -1;
- /*** A constant representing the POP3 authorization state. ***/
- public static final int AUTHORIZATION_STATE = 0;
- /*** A constant representing the POP3 transaction state. ***/
- public static final int TRANSACTION_STATE = 1;
- /*** A constant representing the POP3 update state. ***/
- public static final int UPDATE_STATE = 2;
-
- static final String _OK = "+OK";
- static final String _ERROR = "-ERR";
-
- // We have to ensure that the protocol communication is in ASCII
- // but we use ISO-8859-1 just in case 8-bit characters cross
- // the wire.
- private static final String __DEFAULT_ENCODING = "ISO-8859-1";
-
- private int __popState;
- private BufferedWriter __writer;
- private StringBuffer __commandBuffer;
-
- BufferedReader _reader;
- int _replyCode;
- String _lastReplyLine;
- Vector
- * @param listener The ProtocolCommandListener to add.
- ***/
- public void addProtocolCommandListener(ProtocolCommandListener listener)
- {
- _commandSupport_.addProtocolCommandListener(listener);
- }
-
- /***
- * Removes a ProtocolCommandListener. Delegates this task to
- * {@link #_commandSupport_ _commandSupport_ }.
- *
- * @param listener The ProtocolCommandListener to remove.
- ***/
- public void removeProtocolCommandistener(ProtocolCommandListener listener)
- {
- _commandSupport_.removeProtocolCommandListener(listener);
- }
-
-
- /***
- * Sets POP3 client state. This must be one of the
- *
- * @param state The new state.
- ***/
- public void setState(int state)
- {
- __popState = state;
- }
-
-
- /***
- * Returns the current POP3 client state.
- *
- * @return The current POP3 client state.
- ***/
- public int getState()
- {
- return __popState;
- }
-
-
- /***
- * Retrieves the additional lines of a multi-line server reply.
- ***/
- public void getAdditionalReply() throws IOException
- {
- String line;
-
- line = _reader.readLine();
- while (line != null)
- {
- _replyLines.addElement(line);
- if (line.equals("."))
- break;
- line = _reader.readLine();
- }
- }
-
-
- /***
- * Disconnects the client from the server, and sets the state to
- *
- * @exception IOException If there is an error in disconnecting.
- ***/
- @Override
- public void disconnect() throws IOException
- {
- super.disconnect();
- _reader = null;
- __writer = null;
- _lastReplyLine = null;
- _replyLines.setSize(0);
- setState(DISCONNECTED_STATE);
- }
-
-
- /***
- * Sends a command an arguments to the server and returns the reply code.
- *
- * @param command The POP3 command to send.
- * @param args The command arguments.
- * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
- ***/
- public int sendCommand(String command, String args) throws IOException
- {
- String message;
-
- __commandBuffer.setLength(0);
- __commandBuffer.append(command);
-
- if (args != null)
- {
- __commandBuffer.append(' ');
- __commandBuffer.append(args);
- }
- __commandBuffer.append(SocketClient.NETASCII_EOL);
-
- __writer.write(message = __commandBuffer.toString());
- __writer.flush();
-
- if (_commandSupport_.getListenerCount() > 0)
- _commandSupport_.fireCommandSent(command, message);
-
- __getReply();
- return _replyCode;
- }
-
- /***
- * Sends a command with no arguments to the server and returns the
- * reply code.
- *
- * @param command The POP3 command to send.
- * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
- ***/
- public int sendCommand(String command) throws IOException
- {
- return sendCommand(command, null);
- }
-
- /***
- * Sends a command an arguments to the server and returns the reply code.
- *
- * @param command The POP3 command to send
- * (one of the POP3Command constants).
- * @param args The command arguments.
- * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
- ***/
- public int sendCommand(int command, String args) throws IOException
- {
- return sendCommand(POP3Command._commands[command], args);
- }
-
- /***
- * Sends a command with no arguments to the server and returns the
- * reply code.
- *
- * @param command The POP3 command to send
- * (one of the POP3Command constants).
- * @return The server reply code (either POP3Reply.OK or POP3Reply.ERROR).
- ***/
- public int sendCommand(int command) throws IOException
- {
- return sendCommand(POP3Command._commands[command], null);
- }
-
-
- /***
- * Returns an array of lines received as a reply to the last command
- * sent to the server. The lines have end of lines truncated. If
- * the reply is a single line, but its format ndicates it should be
- * a multiline reply, then you must call
- * {@link #getAdditionalReply getAdditionalReply() } to
- * fetch the rest of the reply, and then call
- * @return The last server response.
- ***/
- public String[] getReplyStrings()
- {
- String[] lines;
- lines = new String[_replyLines.size()];
- _replyLines.copyInto(lines);
- return lines;
- }
-
- /***
- * Returns the reply to the last command sent to the server.
- * The value is a single string containing all the reply lines including
- * newlines. If the reply is a single line, but its format ndicates it
- * should be a multiline reply, then you must call
- * {@link #getAdditionalReply getAdditionalReply() } to
- * fetch the rest of the reply, and then call
- * @return The last server response.
- ***/
- public String getReplyString()
- {
- Enumeration
- * Rather than list it separately for each method, we mention here that
- * every method communicating with the server and throwing an IOException
- * can also throw a
- * {@link org.apache.commons.net.MalformedServerReplyException}
- * , which is a subclass
- * of IOException. A MalformedServerReplyException will be thrown when
- * the reply received from the server deviates enough from the protocol
- * specification that it cannot be interpreted in a useful manner despite
- * attempts to be as lenient as possible.
- *
- *
- * @author Daniel F. Savarese
- * @see POP3MessageInfo
- * @see org.apache.commons.net.io.DotTerminatedMessageReader
- * @see org.apache.commons.net.MalformedServerReplyException
- ***/
-
-public class POP3Client extends POP3
-{
-
- private static POP3MessageInfo __parseStatus(String line)
- {
- int num, size;
- StringTokenizer tokenizer;
-
- tokenizer = new StringTokenizer(line);
-
- if (!tokenizer.hasMoreElements())
- return null;
-
- num = size = 0;
-
- try
- {
- num = Integer.parseInt(tokenizer.nextToken());
-
- if (!tokenizer.hasMoreElements())
- return null;
-
- size = Integer.parseInt(tokenizer.nextToken());
- }
- catch (NumberFormatException e)
- {
- return null;
- }
-
- return new POP3MessageInfo(num, size);
- }
-
- private static POP3MessageInfo __parseUID(String line)
- {
- int num;
- StringTokenizer tokenizer;
-
- tokenizer = new StringTokenizer(line);
-
- if (!tokenizer.hasMoreElements())
- return null;
-
- num = 0;
-
- try
- {
- num = Integer.parseInt(tokenizer.nextToken());
-
- if (!tokenizer.hasMoreElements())
- return null;
-
- line = tokenizer.nextToken();
- }
- catch (NumberFormatException e)
- {
- return null;
- }
-
- return new POP3MessageInfo(num, line);
- }
-
- /***
- * Login to the POP3 server with the given username and password. You
- * must first connect to the server with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * before attempting to login. A login attempt is only valid if
- * the client is in the
- * {@link org.apache.commons.net.pop3.POP3#AUTHORIZATION_STATE AUTHORIZATION_STATE }
- * . After logging in, the client enters the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * .
- *
- * @param username The account name being logged in to.
- * @param password The plain text password of the account.
- * @return True if the login attempt was successful, false if not.
- * @exception IOException If a network I/O error occurs in the process of
- * logging in.
- ***/
- public boolean login(String username, String password) throws IOException
- {
- if (getState() != AUTHORIZATION_STATE)
- return false;
-
- if (sendCommand(POP3Command.USER, username) != POP3Reply.OK)
- return false;
-
- if (sendCommand(POP3Command.PASS, password) != POP3Reply.OK)
- return false;
-
- setState(TRANSACTION_STATE);
-
- return true;
- }
-
-
- /***
- * Login to the POP3 server with the given username and authentication
- * information. Use this method when connecting to a server requiring
- * authentication using the APOP command. Because the timestamp
- * produced in the greeting banner varies from server to server, it is
- * not possible to consistently extract the information. Therefore,
- * after connecting to the server, you must call
- * {@link org.apache.commons.net.pop3.POP3#getReplyString getReplyString }
- * and parse out the timestamp information yourself.
- *
- * You must first connect to the server with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * before attempting to login. A login attempt is only valid if
- * the client is in the
- * {@link org.apache.commons.net.pop3.POP3#AUTHORIZATION_STATE AUTHORIZATION_STATE }
- * . After logging in, the client enters the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * . After connecting, you must parse out the
- * server specific information to use as a timestamp, and pass that
- * information to this method. The secret is a shared secret known
- * to you and the server. See RFC 1939 for more details regarding
- * the APOP command.
- *
- * @param username The account name being logged in to.
- * @param timestamp The timestamp string to combine with the secret.
- * @param secret The shared secret which produces the MD5 digest when
- * combined with the timestamp.
- * @return True if the login attempt was successful, false if not.
- * @exception IOException If a network I/O error occurs in the process of
- * logging in.
- * @exception NoSuchAlgorithmException If the MD5 encryption algorithm
- * cannot be instantiated by the Java runtime system.
- ***/
- public boolean login(String username, String timestamp, String secret)
- throws IOException, NoSuchAlgorithmException
- {
- int i;
- byte[] digest;
- StringBuffer buffer, digestBuffer;
- MessageDigest md5;
-
- if (getState() != AUTHORIZATION_STATE)
- return false;
-
- md5 = MessageDigest.getInstance("MD5");
- timestamp += secret;
- digest = md5.digest(timestamp.getBytes());
- digestBuffer = new StringBuffer(128);
-
- for (i = 0; i < digest.length; i++)
- digestBuffer.append(Integer.toHexString(digest[i] & 0xff));
-
- buffer = new StringBuffer(256);
- buffer.append(username);
- buffer.append(' ');
- buffer.append(digestBuffer.toString());
-
- if (sendCommand(POP3Command.APOP, buffer.toString()) != POP3Reply.OK)
- return false;
-
- setState(TRANSACTION_STATE);
-
- return true;
- }
-
-
- /***
- * Logout of the POP3 server. To fully disconnect from the server
- * you must call
- * {@link org.apache.commons.net.pop3.POP3#disconnect disconnect }.
- * A logout attempt is valid in any state. If
- * the client is in the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * , it enters the
- * {@link org.apache.commons.net.pop3.POP3#UPDATE_STATE UPDATE_STATE }
- * on a successful logout.
- *
- * @return True if the logout attempt was successful, false if not.
- * @exception IOException If a network I/O error occurs in the process
- * of logging out.
- ***/
- public boolean logout() throws IOException
- {
- if (getState() == TRANSACTION_STATE)
- setState(UPDATE_STATE);
- sendCommand(POP3Command.QUIT);
- return (_replyCode == POP3Reply.OK);
- }
-
-
- /***
- * Send a NOOP command to the POP3 server. This is useful for keeping
- * a connection alive since most POP3 servers will timeout after 10
- * minutes of inactivity. A noop attempt will only succeed if
- * the client is in the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * .
- *
- * @return True if the noop attempt was successful, false if not.
- * @exception IOException If a network I/O error occurs in the process of
- * sending the NOOP command.
- ***/
- public boolean noop() throws IOException
- {
- if (getState() == TRANSACTION_STATE)
- return (sendCommand(POP3Command.NOOP) == POP3Reply.OK);
- return false;
- }
-
-
- /***
- * Delete a message from the POP3 server. The message is only marked
- * for deletion by the server. If you decide to unmark the message, you
- * must issuse a {@link #reset reset } command. Messages marked
- * for deletion are only deleted by the server on
- * {@link #logout logout }.
- * A delete attempt can only succeed if the client is in the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * .
- *
- * @param messageId The message number to delete.
- * @return True if the deletion attempt was successful, false if not.
- * @exception IOException If a network I/O error occurs in the process of
- * sending the delete command.
- ***/
- public boolean deleteMessage(int messageId) throws IOException
- {
- if (getState() == TRANSACTION_STATE)
- return (sendCommand(POP3Command.DELE, Integer.toString(messageId))
- == POP3Reply.OK);
- return false;
- }
-
-
- /***
- * Reset the POP3 session. This is useful for undoing any message
- * deletions that may have been performed. A reset attempt can only
- * succeed if the client is in the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * .
- *
- * @return True if the reset attempt was successful, false if not.
- * @exception IOException If a network I/O error occurs in the process of
- * sending the reset command.
- ***/
- public boolean reset() throws IOException
- {
- if (getState() == TRANSACTION_STATE)
- return (sendCommand(POP3Command.RSET) == POP3Reply.OK);
- return false;
- }
-
- /***
- * Get the mailbox status. A status attempt can only
- * succeed if the client is in the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * . Returns a POP3MessageInfo instance
- * containing the number of messages in the mailbox and the total
- * size of the messages in bytes. Returns null if the status the
- * attempt fails.
- *
- * @return A POP3MessageInfo instance containing the number of
- * messages in the mailbox and the total size of the messages
- * in bytes. Returns null if the status the attempt fails.
- * @exception IOException If a network I/O error occurs in the process of
- * sending the status command.
- ***/
- public POP3MessageInfo status() throws IOException
- {
- if (getState() != TRANSACTION_STATE)
- return null;
- if (sendCommand(POP3Command.STAT) != POP3Reply.OK)
- return null;
- return __parseStatus(_lastReplyLine.substring(3));
- }
-
-
- /***
- * List an individual message. A list attempt can only
- * succeed if the client is in the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * . Returns a POP3MessageInfo instance
- * containing the number of the listed message and the
- * size of the message in bytes. Returns null if the list
- * attempt fails (e.g., if the specified message number does
- * not exist).
- *
- * @param messageId The number of the message list.
- * @return A POP3MessageInfo instance containing the number of the
- * listed message and the size of the message in bytes. Returns
- * null if the list attempt fails.
- * @exception IOException If a network I/O error occurs in the process of
- * sending the list command.
- ***/
- public POP3MessageInfo listMessage(int messageId) throws IOException
- {
- if (getState() != TRANSACTION_STATE)
- return null;
- if (sendCommand(POP3Command.LIST, Integer.toString(messageId))
- != POP3Reply.OK)
- return null;
- return __parseStatus(_lastReplyLine.substring(3));
- }
-
-
- /***
- * List all messages. A list attempt can only
- * succeed if the client is in the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * . Returns an array of POP3MessageInfo instances,
- * each containing the number of a message and its size in bytes.
- * If there are no messages, this method returns a zero length array.
- * If the list attempt fails, it returns null.
- *
- * @return An array of POP3MessageInfo instances representing all messages
- * in the order they appear in the mailbox,
- * each containing the number of a message and its size in bytes.
- * If there are no messages, this method returns a zero length array.
- * If the list attempt fails, it returns null.
- * @exception IOException If a network I/O error occurs in the process of
- * sending the list command.
- ***/
- public POP3MessageInfo[] listMessages() throws IOException
- {
- POP3MessageInfo[] messages;
- Enumeration
- * @param messageId The number of the message list.
- * @return A POP3MessageInfo instance containing the number of the
- * listed message and the unique identifier for that message.
- * Returns null if the list attempt fails.
- * @exception IOException If a network I/O error occurs in the process of
- * sending the list unique identifier command.
- ***/
- public POP3MessageInfo listUniqueIdentifier(int messageId)
- throws IOException
- {
- if (getState() != TRANSACTION_STATE)
- return null;
- if (sendCommand(POP3Command.UIDL, Integer.toString(messageId))
- != POP3Reply.OK)
- return null;
- return __parseUID(_lastReplyLine.substring(3));
- }
-
-
- /***
- * List the unique identifiers for all messages. A list attempt can only
- * succeed if the client is in the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * . Returns an array of POP3MessageInfo instances,
- * each containing the number of a message and its unique identifier.
- * If there are no messages, this method returns a zero length array.
- * If the list attempt fails, it returns null.
- *
- * @return An array of POP3MessageInfo instances representing all messages
- * in the order they appear in the mailbox,
- * each containing the number of a message and its unique identifier
- * If there are no messages, this method returns a zero length array.
- * If the list attempt fails, it returns null.
- * @exception IOException If a network I/O error occurs in the process of
- * sending the list unique identifier command.
- ***/
- public POP3MessageInfo[] listUniqueIdentifiers() throws IOException
- {
- POP3MessageInfo[] messages;
- Enumeration
- * You must not issue any commands to the POP3 server (i.e., call any
- * other methods) until you finish reading the message from the
- * returned Reader instance.
- * The POP3 protocol uses the same stream for issuing commands as it does
- * for returning results. Therefore the returned Reader actually reads
- * directly from the POP3 connection. After the end of message has been
- * reached, new commands can be executed and their replies read. If
- * you do not follow these requirements, your program will not work
- * properly.
- *
- * @param messageId The number of the message to fetch.
- * @return A DotTerminatedMessageReader instance
- * from which the entire message can be read.
- * Returns null if the retrieval attempt fails (e.g., if the specified
- * message number does not exist).
- * @exception IOException If a network I/O error occurs in the process of
- * sending the retrieve message command.
- ***/
- public Reader retrieveMessage(int messageId) throws IOException
- {
- if (getState() != TRANSACTION_STATE)
- return null;
- if (sendCommand(POP3Command.RETR, Integer.toString(messageId))
- != POP3Reply.OK)
- return null;
-
- return new DotTerminatedMessageReader(_reader);
- }
-
-
- /***
- * Retrieve only the specified top number of lines of a message from the
- * POP3 server. A retrieve top lines attempt
- * can only succeed if the client is in the
- * {@link org.apache.commons.net.pop3.POP3#TRANSACTION_STATE TRANSACTION_STATE }
- * . Returns a DotTerminatedMessageReader instance
- * from which the specified top number of lines of the message can be
- * read.
- * Returns null if the retrieval attempt fails (e.g., if the specified
- * message number does not exist).
- *
- * You must not issue any commands to the POP3 server (i.e., call any
- * other methods) until you finish reading the message from the returned
- * Reader instance.
- * The POP3 protocol uses the same stream for issuing commands as it does
- * for returning results. Therefore the returned Reader actually reads
- * directly from the POP3 connection. After the end of message has been
- * reached, new commands can be executed and their replies read. If
- * you do not follow these requirements, your program will not work
- * properly.
- *
- * @param messageId The number of the message to fetch.
- * @param numLines The top number of lines to fetch. This must be >= 0.
- * @return A DotTerminatedMessageReader instance
- * from which the specified top number of lines of the message can be
- * read.
- * Returns null if the retrieval attempt fails (e.g., if the specified
- * message number does not exist).
- * @exception IOException If a network I/O error occurs in the process of
- * sending the top command.
- ***/
- public Reader retrieveMessageTop(int messageId, int numLines)
- throws IOException
- {
- if (numLines < 0 || getState() != TRANSACTION_STATE)
- return null;
- if (sendCommand(POP3Command.TOP, Integer.toString(messageId) + " " +
- Integer.toString(numLines)) != POP3Reply.OK)
- return null;
-
- return new DotTerminatedMessageReader(_reader);
- }
-
-
-}
-
diff --git a/org/apache/commons/net/pop3/POP3Command.java b/org/apache/commons/net/pop3/POP3Command.java
deleted file mode 100644
index 0f583bc..0000000
--- a/org/apache/commons/net/pop3/POP3Command.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.pop3;
-
-/***
- * POP3Command stores POP3 command code constants.
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class POP3Command
-{
- /*** Send user name. ***/
- public static final int USER = 0;
- /*** Send password. ***/
- public static final int PASS = 1;
- /*** Quit session. ***/
- public static final int QUIT = 2;
- /*** Get status. ***/
- public static final int STAT = 3;
- /*** List message(s). ***/
- public static final int LIST = 4;
- /*** Retrieve message(s). ***/
- public static final int RETR = 5;
- /*** Delete message(s). ***/
- public static final int DELE = 6;
- /*** No operation. Used as a session keepalive. ***/
- public static final int NOOP = 7;
- /*** Reset session. ***/
- public static final int RSET = 8;
- /*** Authorization. ***/
- public static final int APOP = 9;
- /*** Retrieve top number lines from message. ***/
- public static final int TOP = 10;
- /*** List unique message identifier(s). ***/
- public static final int UIDL = 11;
-
- static final String[] _commands = {
- "USER", "PASS", "QUIT", "STAT", "LIST", "RETR", "DELE", "NOOP", "RSET",
- "APOP", "TOP", "UIDL"
- };
-
- // Cannot be instantiated.
- private POP3Command()
- {}
-
- /***
- * Get the POP3 protocol string command corresponding to a command code.
- *
- * @return The POP3 protocol string command corresponding to a command code.
- ***/
- public static final String getCommand(int command)
- {
- return _commands[command];
- }
-}
diff --git a/org/apache/commons/net/pop3/POP3MessageInfo.java b/org/apache/commons/net/pop3/POP3MessageInfo.java
deleted file mode 100644
index 070fd69..0000000
--- a/org/apache/commons/net/pop3/POP3MessageInfo.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.pop3;
-
-/***
- * POP3MessageInfo is used to return information about messages stored on
- * a POP3 server. Its fields are used to mean slightly different things
- * depending on the information being returned.
- *
- * In response to a status command,
- * In response to a message listings,
- * In response to unique identifier listings,
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class POP3MessageInfo
-{
- public int number;
- public int size;
- public String identifier;
-
- /***
- * Creates a POP3MessageInfo instance with
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class POP3Reply
-{
- /*** The reply code indicating success of an operation. ***/
- public static final int OK = 0;
-
- /*** The reply code indicating failure of an operation. ***/
- public static final int ERROR = 1;
-
- // Cannot be instantiated.
- private POP3Reply()
- {}
-}
diff --git a/org/apache/commons/net/smtp/RelayPath.java b/org/apache/commons/net/smtp/RelayPath.java
deleted file mode 100644
index 62d1098..0000000
--- a/org/apache/commons/net/smtp/RelayPath.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.smtp;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
-/***
- * A class used to represent forward and reverse relay paths. The
- * SMTP MAIL command requires a reverse relay path while the SMTP RCPT
- * command requires a forward relay path. See RFC 821 for more details.
- * In general, you will not have to deal with relay paths.
- *
- *
- * @author Daniel F. Savarese
- * @see SMTPClient
- ***/
-
-public final class RelayPath
-{
- Vector
- * @param emailAddress The destination email address.
- ***/
- public RelayPath(String emailAddress)
- {
- _path = new Vector
- * @param hostname The host to add to the relay path.
- ***/
- public void addRelay(String hostname)
- {
- _path.addElement(hostname);
- }
-
- /***
- * Return the properly formatted string representation of the relay path.
- *
- * @return The properly formatted string representation of the relay path.
- ***/
- @Override
- public String toString()
- {
- StringBuffer buffer = new StringBuffer();
- Enumeration
- * You should keep in mind that the SMTP server may choose to prematurely
- * close a connection for various reasons. The SMTP class will detect a
- * premature SMTP server connection closing when it receives a
- * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE }
- * response to a command.
- * When that occurs, the SMTP class method encountering that reply will throw
- * an {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
- * .
- *
- * Rather than list it separately for each method, we mention here that
- * every method communicating with the server and throwing an IOException
- * can also throw a
- * {@link org.apache.commons.net.MalformedServerReplyException}
- * , which is a subclass
- * of IOException. A MalformedServerReplyException will be thrown when
- * the reply received from the server deviates enough from the protocol
- * specification that it cannot be interpreted in a useful manner despite
- * attempts to be as lenient as possible.
- *
- *
- * @author Daniel F. Savarese
- * @see SMTPClient
- * @see SMTPConnectionClosedException
- * @see org.apache.commons.net.MalformedServerReplyException
- ***/
-
-public class SMTP extends SocketClient
-{
- /*** The default SMTP port (25). ***/
- public static final int DEFAULT_PORT = 25;
-
- // We have to ensure that the protocol communication is in ASCII
- // but we use ISO-8859-1 just in case 8-bit characters cross
- // the wire.
- private static final String __DEFAULT_ENCODING = "ISO-8859-1";
-
- /** The encoding to use (user-settable) */
- private String encoding = __DEFAULT_ENCODING;
-
- private StringBuffer __commandBuffer;
-
- BufferedReader _reader;
- BufferedWriter _writer;
- int _replyCode;
- ArrayList
- * @param listener The ProtocolCommandListener to add.
- ***/
- public void addProtocolCommandListener(ProtocolCommandListener listener)
- {
- _commandSupport_.addProtocolCommandListener(listener);
- }
-
- /***
- * Removes a ProtocolCommandListener. Delegates this task to
- * {@link #_commandSupport_ _commandSupport_ }.
- *
- * @param listener The ProtocolCommandListener to remove.
- ***/
- public void removeProtocolCommandistener(ProtocolCommandListener listener)
- {
- _commandSupport_.removeProtocolCommandListener(listener);
- }
-
-
- /***
- * Closes the connection to the SMTP server and sets to null
- * some internal data so that the memory may be reclaimed by the
- * garbage collector. The reply text and code information from the
- * last command is voided so that the memory it used may be reclaimed.
- *
- * @exception IOException If an error occurs while disconnecting.
- ***/
- @Override
- public void disconnect() throws IOException
- {
- super.disconnect();
- _reader = null;
- _writer = null;
- _replyString = null;
- _replyLines.clear();
- _newReplyString = false;
- }
-
-
- /***
- * Sends an SMTP command to the server, waits for a reply and returns the
- * numerical response code. After invocation, for more detailed
- * information, the actual reply text can be accessed by calling
- * {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
- *
- * @param command The text representation of the SMTP command to send.
- * @param args The arguments to the SMTP command. If this parameter is
- * set to null, then the command is sent with no argument.
- * @return The integer value of the SMTP reply code returned by the server
- * in response to the command.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(String command, String args) throws IOException
- {
- return __sendCommand(command, args, true);
- }
-
-
- /***
- * Sends an SMTP command to the server, waits for a reply and returns the
- * numerical response code. After invocation, for more detailed
- * information, the actual reply text can be accessed by calling
- * {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
- *
- * @param command The SMTPCommand constant corresponding to the SMTP command
- * to send.
- * @param args The arguments to the SMTP command. If this parameter is
- * set to null, then the command is sent with no argument.
- * @return The integer value of the SMTP reply code returned by the server
- * in response to the command.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(int command, String args) throws IOException
- {
- return sendCommand(SMTPCommand._commands[command], args);
- }
-
-
- /***
- * Sends an SMTP command with no arguments to the server, waits for a
- * reply and returns the numerical response code. After invocation, for
- * more detailed information, the actual reply text can be accessed by
- * calling {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
- *
- * @param command The text representation of the SMTP command to send.
- * @return The integer value of the SMTP reply code returned by the server
- * in response to the command.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(String command) throws IOException
- {
- return sendCommand(command, null);
- }
-
-
- /***
- * Sends an SMTP command with no arguments to the server, waits for a
- * reply and returns the numerical response code. After invocation, for
- * more detailed information, the actual reply text can be accessed by
- * calling {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }.
- *
- * @param command The SMTPCommand constant corresponding to the SMTP command
- * to send.
- * @return The integer value of the SMTP reply code returned by the server
- * in response to the command.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int sendCommand(int command) throws IOException
- {
- return sendCommand(command, null);
- }
-
-
- /***
- * Returns the integer value of the reply code of the last SMTP reply.
- * You will usually only use this method after you connect to the
- * SMTP server to check that the connection was successful since
- *
- * @return The integer value of the reply code of the last SMTP reply.
- ***/
- public int getReplyCode()
- {
- return _replyCode;
- }
-
- /***
- * Fetches a reply from the SMTP server and returns the integer reply
- * code. After calling this method, the actual reply text can be accessed
- * from either calling {@link #getReplyString getReplyString } or
- * {@link #getReplyStrings getReplyStrings }. Only use this
- * method if you are implementing your own SMTP client or if you need to
- * fetch a secondary response from the SMTP server.
- *
- * @return The integer value of the reply code of the fetched SMTP reply.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while receiving the
- * server reply.
- ***/
- public int getReply() throws IOException
- {
- __getReply();
- return _replyCode;
- }
-
-
- /***
- * Returns the lines of text from the last SMTP server response as an array
- * of strings, one entry per line. The end of line markers of each are
- * stripped from each line.
- *
- * @return The lines of text from the last SMTP response as an array.
- ***/
- public String[] getReplyStrings()
- {
- String[] lines;
- lines = new String[_replyLines.size()];
- _replyLines.addAll(Arrays.asList(lines));
- return lines;
- }
-
- /***
- * Returns the entire text of the last SMTP server response exactly
- * as it was received, including all end of line markers in NETASCII
- * format.
- *
- * @return The entire text from the last SMTP response as a String.
- ***/
- public String getReplyString()
- {
- StringBuilder buffer;
-
- if (!_newReplyString)
- return _replyString;
-
- buffer = new StringBuilder();
-
- for (String line : _replyLines)
- {
- buffer.append(line);
- buffer.append(SocketClient.NETASCII_EOL);
- }
-
- _newReplyString = false;
-
- return (_replyString = buffer.toString());
- }
-
-
- /***
- * A convenience method to send the SMTP HELO command to the server,
- * receive the reply, and return the reply code.
- *
- * @param hostname The hostname of the sender.
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int helo(String hostname) throws IOException
- {
- return sendCommand(SMTPCommand.HELO, hostname);
- }
-
-
- /***
- * A convenience method to send the SMTP MAIL command to the server,
- * receive the reply, and return the reply code.
- *
- * @param reversePath The reverese path.
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int mail(String reversePath) throws IOException
- {
- return __sendCommand(SMTPCommand.MAIL, reversePath, false);
- }
-
-
- /***
- * A convenience method to send the SMTP RCPT command to the server,
- * receive the reply, and return the reply code.
- *
- * @param forwardPath The forward path.
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int rcpt(String forwardPath) throws IOException
- {
- return __sendCommand(SMTPCommand.RCPT, forwardPath, false);
- }
-
-
- /***
- * A convenience method to send the SMTP DATA command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int data() throws IOException
- {
- return sendCommand(SMTPCommand.DATA);
- }
-
-
- /***
- * A convenience method to send the SMTP SEND command to the server,
- * receive the reply, and return the reply code.
- *
- * @param reversePath The reverese path.
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int send(String reversePath) throws IOException
- {
- return sendCommand(SMTPCommand.SEND, reversePath);
- }
-
-
- /***
- * A convenience method to send the SMTP SOML command to the server,
- * receive the reply, and return the reply code.
- *
- * @param reversePath The reverese path.
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int soml(String reversePath) throws IOException
- {
- return sendCommand(SMTPCommand.SOML, reversePath);
- }
-
-
- /***
- * A convenience method to send the SMTP SAML command to the server,
- * receive the reply, and return the reply code.
- *
- * @param reversePath The reverese path.
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int saml(String reversePath) throws IOException
- {
- return sendCommand(SMTPCommand.SAML, reversePath);
- }
-
-
- /***
- * A convenience method to send the SMTP RSET command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int rset() throws IOException
- {
- return sendCommand(SMTPCommand.RSET);
- }
-
-
- /***
- * A convenience method to send the SMTP VRFY command to the server,
- * receive the reply, and return the reply code.
- *
- * @param user The user address to verify.
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int vrfy(String user) throws IOException
- {
- return sendCommand(SMTPCommand.VRFY, user);
- }
-
-
- /***
- * A convenience method to send the SMTP VRFY command to the server,
- * receive the reply, and return the reply code.
- *
- * @param name The name to expand.
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int expn(String name) throws IOException
- {
- return sendCommand(SMTPCommand.EXPN, name);
- }
-
- /***
- * A convenience method to send the SMTP HELP command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int help() throws IOException
- {
- return sendCommand(SMTPCommand.HELP);
- }
-
- /***
- * A convenience method to send the SMTP HELP command to the server,
- * receive the reply, and return the reply code.
- *
- * @param command The command name on which to request help.
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int help(String command) throws IOException
- {
- return sendCommand(SMTPCommand.HELP, command);
- }
-
- /***
- * A convenience method to send the SMTP NOOP command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int noop() throws IOException
- {
- return sendCommand(SMTPCommand.NOOP);
- }
-
-
- /***
- * A convenience method to send the SMTP TURN command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int turn() throws IOException
- {
- return sendCommand(SMTPCommand.TURN);
- }
-
-
- /***
- * A convenience method to send the SMTP QUIT command to the server,
- * receive the reply, and return the reply code.
- *
- * @return The reply code received from the server.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int quit() throws IOException
- {
- return sendCommand(SMTPCommand.QUIT);
- }
-
-}
-
-/* Emacs configuration
- * Local variables: **
- * mode: java **
- * c-basic-offset: 4 **
- * indent-tabs-mode: nil **
- * End: **
- */
diff --git a/org/apache/commons/net/smtp/SMTPClient.java b/org/apache/commons/net/smtp/SMTPClient.java
deleted file mode 100644
index 8b9ed45..0000000
--- a/org/apache/commons/net/smtp/SMTPClient.java
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.smtp;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.net.InetAddress;
-
-import org.apache.commons.net.io.DotTerminatedMessageWriter;
-
-/***
- * SMTPClient encapsulates all the functionality necessary to send files
- * through an SMTP server. This class takes care of all
- * low level details of interacting with an SMTP server and provides
- * a convenient higher level interface. As with all classes derived
- * from {@link org.apache.commons.net.SocketClient},
- * you must first connect to the server with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * before doing anything, and finally
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * after you're completely finished interacting with the server.
- * Then you need to check the SMTP reply code to see if the connection
- * was successful. For example:
- *
- * Immediately after connecting is the only real time you need to check the
- * reply code (because connect is of type void). The convention for all the
- * SMTP command methods in SMTPClient is such that they either return a
- * boolean value or some other value.
- * The boolean methods return true on a successful completion reply from
- * the SMTP server and false on a reply resulting in an error condition or
- * failure. The methods returning a value other than boolean return a value
- * containing the higher level data produced by the SMTP command, or null if a
- * reply resulted in an error condition or failure. If you want to access
- * the exact SMTP reply code causing a success or failure, you must call
- * {@link org.apache.commons.net.smtp.SMTP#getReplyCode getReplyCode } after
- * a success or failure.
- *
- * You should keep in mind that the SMTP server may choose to prematurely
- * close a connection for various reasons. The SMTPClient class will detect a
- * premature SMTP server connection closing when it receives a
- * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE }
- * response to a command.
- * When that occurs, the method encountering that reply will throw
- * an {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
- * .
- *
- * Rather than list it separately for each method, we mention here that
- * every method communicating with the server and throwing an IOException
- * can also throw a
- * {@link org.apache.commons.net.MalformedServerReplyException}
- * , which is a subclass
- * of IOException. A MalformedServerReplyException will be thrown when
- * the reply received from the server deviates enough from the protocol
- * specification that it cannot be interpreted in a useful manner despite
- * attempts to be as lenient as possible.
- *
- *
- * @author Daniel F. Savarese
- * @see SMTP
- * @see SimpleSMTPHeader
- * @see RelayPath
- * @see SMTPConnectionClosedException
- * @see org.apache.commons.net.MalformedServerReplyException
- ***/
-
-public class SMTPClient extends SMTP
-{
-
- /**
- * Default SMTPClient constructor. Creates a new SMTPClient instance.
- */
- public SMTPClient() { }
-
- /**
- * Overloaded constructor that takes an encoding specification
- * @param encoding The encoding to use
- * @since 2.0
- */
- public SMTPClient(String encoding) {
- super(encoding);
- }
-
-
- /***
- * At least one SMTPClient method ({@link #sendMessageData sendMessageData })
- * does not complete the entire sequence of SMTP commands to complete a
- * transaction. These types of commands require some action by the
- * programmer after the reception of a positive intermediate command.
- * After the programmer's code completes its actions, it must call this
- * method to receive the completion reply from the server and verify the
- * success of the entire transaction.
- *
- * For example,
- *
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean completePendingCommand() throws IOException
- {
- return SMTPReply.isPositiveCompletion(getReply());
- }
-
-
- /***
- * Login to the SMTP server by sending the HELO command with the
- * given hostname as an argument. Before performing any mail commands,
- * you must first login.
- *
- * @param hostname The hostname with which to greet the SMTP server.
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean login(String hostname) throws IOException
- {
- return SMTPReply.isPositiveCompletion(helo(hostname));
- }
-
-
- /***
- * Login to the SMTP server by sending the HELO command with the
- * client hostname as an argument. Before performing any mail commands,
- * you must first login.
- *
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean login() throws IOException
- {
- String name;
- InetAddress host;
-
- host = getLocalAddress();
- name = host.getHostName();
-
- if (name == null)
- return false;
-
- return SMTPReply.isPositiveCompletion(helo(name));
- }
-
-
- /***
- * Set the sender of a message using the SMTP MAIL command, specifying
- * a reverse relay path. The sender must be set first before any
- * recipients may be specified, otherwise the mail server will reject
- * your commands.
- *
- * @param path The reverse relay path pointing back to the sender.
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean setSender(RelayPath path) throws IOException
- {
- return SMTPReply.isPositiveCompletion(mail(path.toString()));
- }
-
-
- /***
- * Set the sender of a message using the SMTP MAIL command, specifying
- * the sender's email address. The sender must be set first before any
- * recipients may be specified, otherwise the mail server will reject
- * your commands.
- *
- * @param address The sender's email address.
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean setSender(String address) throws IOException
- {
- return SMTPReply.isPositiveCompletion(mail("<" + address + ">"));
- }
-
-
- /***
- * Add a recipient for a message using the SMTP RCPT command, specifying
- * a forward relay path. The sender must be set first before any
- * recipients may be specified, otherwise the mail server will reject
- * your commands.
- *
- * @param path The forward relay path pointing to the recipient.
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean addRecipient(RelayPath path) throws IOException
- {
- return SMTPReply.isPositiveCompletion(rcpt(path.toString()));
- }
-
-
- /***
- * Add a recipient for a message using the SMTP RCPT command, the
- * recipient's email address. The sender must be set first before any
- * recipients may be specified, otherwise the mail server will reject
- * your commands.
- *
- * @param address The recipient's email address.
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean addRecipient(String address) throws IOException
- {
- return SMTPReply.isPositiveCompletion(rcpt("<" + address + ">"));
- }
-
-
-
- /***
- * Send the SMTP DATA command in preparation to send an email message.
- * This method returns a DotTerminatedMessageWriter instance to which
- * the message can be written. Null is returned if the DATA command
- * fails.
- *
- * You must not issue any commands to the SMTP server (i.e., call any
- * (other methods) until you finish writing to the returned Writer
- * instance and close it. The SMTP protocol uses the same stream for
- * issuing commands as it does for returning results. Therefore the
- * returned Writer actually writes directly to the SMTP connection.
- * After you close the writer, you can execute new commands. If you
- * do not follow these requirements your program will not work properly.
- *
- * You can use the provided
- * {@link org.apache.commons.net.smtp.SimpleSMTPHeader}
- * class to construct a bare minimum header.
- * To construct more complicated headers you should
- * refer to RFC 822. When the Java Mail API is finalized, you will be
- * able to use it to compose fully compliant Internet text messages.
- * The DotTerminatedMessageWriter takes care of doubling line-leading
- * dots and ending the message with a single dot upon closing, so all
- * you have to worry about is writing the header and the message.
- *
- * Upon closing the returned Writer, you need to call
- * {@link #completePendingCommand completePendingCommand() }
- * to finalize the transaction and verify its success or failure from
- * the server reply.
- *
- * @return A DotTerminatedMessageWriter to which the message (including
- * header) can be written. Returns null if the command fails.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public Writer sendMessageData() throws IOException
- {
- if (!SMTPReply.isPositiveIntermediate(data()))
- return null;
-
- return new DotTerminatedMessageWriter(_writer);
- }
-
-
- /***
- * A convenience method for sending short messages. This method fetches
- * the Writer returned by {@link #sendMessageData sendMessageData() }
- * and writes the specified String to it. After writing the message,
- * this method calls {@link #completePendingCommand completePendingCommand() }
- * to finalize the transaction and returns
- * its success or failure.
- *
- * @param message The short email message to send.
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean sendShortMessageData(String message) throws IOException
- {
- Writer writer;
-
- writer = sendMessageData();
-
- if (writer == null)
- return false;
-
- writer.write(message);
- writer.close();
-
- return completePendingCommand();
- }
-
-
- /***
- * A convenience method for a sending short email without having to
- * explicitly set the sender and recipient(s). This method
- * sets the sender and recipient using
- * {@link #setSender setSender } and
- * {@link #addRecipient addRecipient }, and then sends the
- * message using {@link #sendShortMessageData sendShortMessageData }.
- *
- * @param sender The email address of the sender.
- * @param recipient The email address of the recipient.
- * @param message The short email message to send.
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean sendSimpleMessage(String sender, String recipient,
- String message)
- throws IOException
- {
- if (!setSender(sender))
- return false;
-
- if (!addRecipient(recipient))
- return false;
-
- return sendShortMessageData(message);
- }
-
-
-
- /***
- * A convenience method for a sending short email without having to
- * explicitly set the sender and recipient(s). This method
- * sets the sender and recipients using
- * {@link #setSender setSender } and
- * {@link #addRecipient addRecipient }, and then sends the
- * message using {@link #sendShortMessageData sendShortMessageData }.
- *
- * @param sender The email address of the sender.
- * @param recipients An array of recipient email addresses.
- * @param message The short email message to send.
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean sendSimpleMessage(String sender, String[] recipients,
- String message)
- throws IOException
- {
- boolean oneSuccess = false;
- int count;
-
- if (!setSender(sender))
- return false;
-
- for (count = 0; count < recipients.length; count++)
- {
- if (addRecipient(recipients[count]))
- oneSuccess = true;
- }
-
- if (!oneSuccess)
- return false;
-
- return sendShortMessageData(message);
- }
-
-
- /***
- * Logout of the SMTP server by sending the QUIT command.
- *
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean logout() throws IOException
- {
- return SMTPReply.isPositiveCompletion(quit());
- }
-
-
-
- /***
- * Aborts the current mail transaction, resetting all server stored
- * sender, recipient, and mail data, cleaing all buffers and tables.
- *
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean reset() throws IOException
- {
- return SMTPReply.isPositiveCompletion(rset());
- }
-
-
- /***
- * Verify that a username or email address is valid, i.e., that mail
- * can be delivered to that mailbox on the server.
- *
- * @param username The username or email address to validate.
- * @return True if the username is valid, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean verify(String username) throws IOException
- {
- int result;
-
- result = vrfy(username);
-
- return (result == SMTPReply.ACTION_OK ||
- result == SMTPReply.USER_NOT_LOCAL_WILL_FORWARD);
- }
-
-
- /***
- * Fetches the system help information from the server and returns the
- * full string.
- *
- * @return The system help string obtained from the server. null if the
- * information could not be obtained.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String listHelp() throws IOException
- {
- if (SMTPReply.isPositiveCompletion(help()))
- return getReplyString();
- return null;
- }
-
-
- /***
- * Fetches the help information for a given command from the server and
- * returns the full string.
- *
- * @param command The command on which to ask for help.
- * @return The command help string obtained from the server. null if the
- * information could not be obtained.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public String listHelp(String command) throws IOException
- {
- if (SMTPReply.isPositiveCompletion(help(command)))
- return getReplyString();
- return null;
- }
-
-
- /***
- * Sends a NOOP command to the SMTP server. This is useful for preventing
- * server timeouts.
- *
- * @return True if successfully completed, false if not.
- * @exception SMTPConnectionClosedException
- * If the SMTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send SMTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean sendNoOp() throws IOException
- {
- return SMTPReply.isPositiveCompletion(noop());
- }
-
-}
diff --git a/org/apache/commons/net/smtp/SMTPCommand.java b/org/apache/commons/net/smtp/SMTPCommand.java
deleted file mode 100644
index 04dbf99..0000000
--- a/org/apache/commons/net/smtp/SMTPCommand.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.smtp;
-
-/***
- * SMTPCommand stores a set of constants for SMTP command codes. To interpret
- * the meaning of the codes, familiarity with RFC 821 is assumed.
- * The mnemonic constant names are transcriptions from the code descriptions
- * of RFC 821. For those who think in terms of the actual SMTP commands,
- * a set of constants such as {@link #HELO HELO } are provided
- * where the constant name is the same as the SMTP command.
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class SMTPCommand
-{
-
-
- public static final int HELO = 0;
- public static final int MAIL = 1;
- public static final int RCPT = 2;
- public static final int DATA = 3;
- public static final int SEND = 4;
- public static final int SOML = 5;
- public static final int SAML = 6;
- public static final int RSET = 7;
- public static final int VRFY = 8;
- public static final int EXPN = 9;
- public static final int HELP = 10;
- public static final int NOOP = 11;
- public static final int TURN = 12;
- public static final int QUIT = 13;
-
- public static final int HELLO = HELO;
- public static final int LOGIN = HELO;
- public static final int MAIL_FROM = MAIL;
- public static final int RECIPIENT = RCPT;
- public static final int SEND_MESSAGE_DATA = DATA;
- public static final int SEND_FROM = SEND;
- public static final int SEND_OR_MAIL_FROM = SOML;
- public static final int SEND_AND_MAIL_FROM = SAML;
- public static final int RESET = RSET;
- public static final int VERIFY = VRFY;
- public static final int EXPAND = EXPN;
- // public static final int HELP = HELP;
- // public static final int NOOP = NOOP;
- // public static final int TURN = TURN;
- // public static final int QUIT = QUIT;
- public static final int LOGOUT = QUIT;
-
- // Cannot be instantiated
- private SMTPCommand()
- {}
-
- static final String[] _commands = {
- "HELO", "MAIL FROM:", "RCPT TO:", "DATA", "SEND FROM:", "SOML FROM:",
- "SAML FROM:", "RSET", "VRFY", "EXPN", "HELP", "NOOP", "TURN", "QUIT"
- };
-
-
- /***
- * Retrieve the SMTP protocol command string corresponding to a specified
- * command code.
- *
- * @param command The command code.
- * @return The SMTP protcol command string corresponding to a specified
- * command code.
- ***/
- public static final String getCommand(int command)
- {
- return _commands[command];
- }
-
-}
diff --git a/org/apache/commons/net/smtp/SMTPConnectionClosedException.java b/org/apache/commons/net/smtp/SMTPConnectionClosedException.java
deleted file mode 100644
index f9a5762..0000000
--- a/org/apache/commons/net/smtp/SMTPConnectionClosedException.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.smtp;
-
-import java.io.IOException;
-
-/***
- * SMTPConnectionClosedException is used to indicate the premature or
- * unexpected closing of an SMTP connection resulting from a
- * {@link org.apache.commons.net.smtp.SMTPReply#SERVICE_NOT_AVAILABLE SMTPReply.SERVICE_NOT_AVAILABLE }
- * response (SMTP reply code 421) to a
- * failed SMTP command. This exception is derived from IOException and
- * therefore may be caught either as an IOException or specifically as an
- * SMTPConnectionClosedException.
- *
- *
- * @author Daniel F. Savarese
- * @see SMTP
- * @see SMTPClient
- ***/
-
-public final class SMTPConnectionClosedException extends IOException
-{
-
- /*** Constructs a SMTPConnectionClosedException with no message ***/
- public SMTPConnectionClosedException()
- {
- super();
- }
-
- /***
- * Constructs a SMTPConnectionClosedException with a specified message.
- *
- * @param message The message explaining the reason for the exception.
- ***/
- public SMTPConnectionClosedException(String message)
- {
- super(message);
- }
-
-}
diff --git a/org/apache/commons/net/smtp/SMTPReply.java b/org/apache/commons/net/smtp/SMTPReply.java
deleted file mode 100644
index 45fd7c8..0000000
--- a/org/apache/commons/net/smtp/SMTPReply.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.smtp;
-
-/***
- * SMTPReply stores a set of constants for SMTP reply codes. To interpret
- * the meaning of the codes, familiarity with RFC 821 is assumed.
- * The mnemonic constant names are transcriptions from the code descriptions
- * of RFC 821. For those who think in terms of the actual reply code values,
- * a set of CODE_NUM constants are provided where NUM is the numerical value
- * of the code.
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class SMTPReply
-{
-
- public static final int CODE_211 = 211;
- public static final int CODE_214 = 214;
- public static final int CODE_215 = 215;
- public static final int CODE_220 = 220;
- public static final int CODE_221 = 221;
- public static final int CODE_250 = 250;
- public static final int CODE_251 = 251;
- public static final int CODE_354 = 354;
- public static final int CODE_421 = 421;
- public static final int CODE_450 = 450;
- public static final int CODE_451 = 451;
- public static final int CODE_452 = 452;
- public static final int CODE_500 = 500;
- public static final int CODE_501 = 501;
- public static final int CODE_502 = 502;
- public static final int CODE_503 = 503;
- public static final int CODE_504 = 504;
- public static final int CODE_550 = 550;
- public static final int CODE_551 = 551;
- public static final int CODE_552 = 552;
- public static final int CODE_553 = 553;
- public static final int CODE_554 = 554;
-
- public static final int SYSTEM_STATUS = CODE_211;
- public static final int HELP_MESSAGE = CODE_214;
- public static final int SERVICE_READY = CODE_220;
- public static final int SERVICE_CLOSING_TRANSMISSION_CHANNEL = CODE_221;
- public static final int ACTION_OK = CODE_250;
- public static final int USER_NOT_LOCAL_WILL_FORWARD = CODE_251;
- public static final int START_MAIL_INPUT = CODE_354;
- public static final int SERVICE_NOT_AVAILABLE = CODE_421;
- public static final int ACTION_NOT_TAKEN = CODE_450;
- public static final int ACTION_ABORTED = CODE_451;
- public static final int INSUFFICIENT_STORAGE = CODE_452;
- public static final int UNRECOGNIZED_COMMAND = CODE_500;
- public static final int SYNTAX_ERROR_IN_ARGUMENTS = CODE_501;
- public static final int COMMAND_NOT_IMPLEMENTED = CODE_502;
- public static final int BAD_COMMAND_SEQUENCE = CODE_503;
- public static final int COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER = CODE_504;
- public static final int MAILBOX_UNAVAILABLE = CODE_550;
- public static final int USER_NOT_LOCAL = CODE_551;
- public static final int STORAGE_ALLOCATION_EXCEEDED = CODE_552;
- public static final int MAILBOX_NAME_NOT_ALLOWED = CODE_553;
- public static final int TRANSACTION_FAILED = CODE_554;
-
- // Cannot be instantiated
- private SMTPReply()
- {}
-
- /***
- * Determine if a reply code is a positive preliminary response. All
- * codes beginning with a 1 are positive preliminary responses.
- * Postitive preliminary responses are used to indicate tentative success.
- * No further commands can be issued to the SMTP server after a positive
- * preliminary response until a follow up response is received from the
- * server.
- *
- * Note: No SMTP commands defined in RFC 822 provide this
- * type of reply.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a postive preliminary response, false
- * if not.
- ***/
- public static boolean isPositivePreliminary(int reply)
- {
- return (reply >= 100 && reply < 200);
- }
-
- /***
- * Determine if a reply code is a positive completion response. All
- * codes beginning with a 2 are positive completion responses.
- * The SMTP server will send a positive completion response on the final
- * successful completion of a command.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a postive completion response, false
- * if not.
- ***/
- public static boolean isPositiveCompletion(int reply)
- {
- return (reply >= 200 && reply < 300);
- }
-
- /***
- * Determine if a reply code is a positive intermediate response. All
- * codes beginning with a 3 are positive intermediate responses.
- * The SMTP server will send a positive intermediate response on the
- * successful completion of one part of a multi-part sequence of
- * commands. For example, after a successful DATA command, a positive
- * intermediate response will be sent to indicate that the server is
- * ready to receive the message data.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a postive intermediate response, false
- * if not.
- ***/
- public static boolean isPositiveIntermediate(int reply)
- {
- return (reply >= 300 && reply < 400);
- }
-
- /***
- * Determine if a reply code is a negative transient response. All
- * codes beginning with a 4 are negative transient responses.
- * The SMTP server will send a negative transient response on the
- * failure of a command that can be reattempted with success.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a negative transient response, false
- * if not.
- ***/
- public static boolean isNegativeTransient(int reply)
- {
- return (reply >= 400 && reply < 500);
- }
-
- /***
- * Determine if a reply code is a negative permanent response. All
- * codes beginning with a 5 are negative permanent responses.
- * The SMTP server will send a negative permanent response on the
- * failure of a command that cannot be reattempted with success.
- *
- * @param reply The reply code to test.
- * @return True if a reply code is a negative permanent response, false
- * if not.
- ***/
- public static boolean isNegativePermanent(int reply)
- {
- return (reply >= 500 && reply < 600);
- }
-
-}
diff --git a/org/apache/commons/net/smtp/SimpleSMTPHeader.java b/org/apache/commons/net/smtp/SimpleSMTPHeader.java
deleted file mode 100644
index ed0ea4d..0000000
--- a/org/apache/commons/net/smtp/SimpleSMTPHeader.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.smtp;
-
-/***
- * This class is used to construct a bare minimum
- * acceptable header for an email message. To construct more
- * complicated headers you should refer to RFC 822. When the
- * Java Mail API is finalized, you will be
- * able to use it to compose fully compliant Internet text messages.
- *
- * The main purpose of the class is to faciliatate the mail sending
- * process, by relieving the programmer from having to explicitly format
- * a simple message header. For example:
- *
- *
- * @author Daniel F. Savarese
- * @see SMTPClient
- ***/
-
-public class SimpleSMTPHeader
-{
- private String __subject, __from, __to;
- private StringBuffer __headerFields, __cc;
-
- /***
- * Creates a new SimpleSMTPHeader instance initialized with the given
- * from, to, and subject header field values.
- *
- * @param from The value of the
- * @param headerField The header field to add, not including the colon.
- * @param value The value of the added header field.
- ***/
- public void addHeaderField(String headerField, String value)
- {
- __headerFields.append(headerField);
- __headerFields.append(": ");
- __headerFields.append(value);
- __headerFields.append('\n');
- }
-
-
- /***
- * Add an email address to the CC (carbon copy or courtesy copy) list.
- *
- * @param address The email address to add to the CC list.
- ***/
- public void addCC(String address)
- {
- if (__cc == null)
- __cc = new StringBuffer();
- else
- __cc.append(", ");
-
- __cc.append(address);
- }
-
-
- /***
- * Converts the SimpleSMTPHeader to a properly formatted header in
- * the form of a String, including the blank line used to separate
- * the header from the article body. The header fields CC and Subject
- * are only included when they are non-null.
- *
- * @return The message header in the form of a String.
- ***/
- @Override
- public String toString()
- {
- StringBuffer header = new StringBuffer();
-
- if (__headerFields.length() > 0)
- header.append(__headerFields.toString());
-
- header.append("From: ");
- header.append(__from);
- header.append("\nTo: ");
- header.append(__to);
-
- if (__cc != null)
- {
- header.append("\nCc: ");
- header.append(__cc.toString());
- }
-
- if (__subject != null)
- {
- header.append("\nSubject: ");
- header.append(__subject);
- }
-
- header.append('\n');
- header.append('\n');
-
- return header.toString();
- }
-}
-
-
-
diff --git a/org/apache/commons/net/telnet/EchoOptionHandler.java b/org/apache/commons/net/telnet/EchoOptionHandler.java
deleted file mode 100644
index 8c43f85..0000000
--- a/org/apache/commons/net/telnet/EchoOptionHandler.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-/***
- * Implements the telnet echo option RFC 857.
- *
- * @author Bruno D'Avanzo
- ***/
-public class EchoOptionHandler extends TelnetOptionHandler
-{
- /***
- * Constructor for the EchoOptionHandler. Allows defining desired
- * initial setting for local/remote activation of this option and
- * behaviour in case a local/remote activation request for this
- * option is received.
- *
- * @param initlocal - if set to true, a WILL is sent upon connection.
- * @param initremote - if set to true, a DO is sent upon connection.
- * @param acceptlocal - if set to true, any DO request is accepted.
- * @param acceptremote - if set to true, any WILL request is accepted.
- ***/
- public EchoOptionHandler(boolean initlocal, boolean initremote,
- boolean acceptlocal, boolean acceptremote)
- {
- super(TelnetOption.ECHO, initlocal, initremote,
- acceptlocal, acceptremote);
- }
-
- /***
- * Constructor for the EchoOptionHandler. Initial and accept
- * behaviour flags are set to false
- ***/
- public EchoOptionHandler()
- {
- super(TelnetOption.ECHO, false, false, false, false);
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
- * @param suboptionLength - the length of data in suboption_data
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] answerSubnegotiation(int suboptionData[],
- int suboptionLength)
- {
- return null;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] startSubnegotiationLocal()
- {
- return null;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] startSubnegotiationRemote()
- {
- return null;
- }
-}
diff --git a/org/apache/commons/net/telnet/InvalidTelnetOptionException.java b/org/apache/commons/net/telnet/InvalidTelnetOptionException.java
deleted file mode 100644
index 740d185..0000000
--- a/org/apache/commons/net/telnet/InvalidTelnetOptionException.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-/***
- * The InvalidTelnetOptionException is the exception that is
- * thrown whenever a TelnetOptionHandler with an invlaid
- * option code is registered in TelnetClient with addOptionHandler.
- *
- * @author Bruno D'Avanzo
- ***/
-public class InvalidTelnetOptionException extends Exception
-{
-
- /***
- * Option code
- ***/
- private int optionCode = -1;
-
- /***
- * Error message
- ***/
- private String msg;
-
- /***
- * Constructor for the exception.
- *
- * @param message - Error message.
- * @param optcode - Option code.
- ***/
- public InvalidTelnetOptionException(String message, int optcode)
- {
- optionCode = optcode;
- msg = message;
- }
-
- /***
- * Gets the error message of ths exception.
- *
- * @return the error message.
- ***/
- @Override
- public String getMessage()
- {
- return (msg + ": " + optionCode);
- }
-}
diff --git a/org/apache/commons/net/telnet/SimpleOptionHandler.java b/org/apache/commons/net/telnet/SimpleOptionHandler.java
deleted file mode 100644
index 3395508..0000000
--- a/org/apache/commons/net/telnet/SimpleOptionHandler.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-/***
- * Simple option handler that can be used for options
- * that don't require subnegotiation.
- *
- * @author Bruno D'Avanzo
- ***/
-public class SimpleOptionHandler extends TelnetOptionHandler
-{
- /***
- * Constructor for the SimpleOptionHandler. Allows defining desired
- * initial setting for local/remote activation of this option and
- * behaviour in case a local/remote activation request for this
- * option is received.
- *
- * @param optcode - option code.
- * @param initlocal - if set to true, a WILL is sent upon connection.
- * @param initremote - if set to true, a DO is sent upon connection.
- * @param acceptlocal - if set to true, any DO request is accepted.
- * @param acceptremote - if set to true, any WILL request is accepted.
- ***/
- public SimpleOptionHandler(int optcode,
- boolean initlocal,
- boolean initremote,
- boolean acceptlocal,
- boolean acceptremote)
- {
- super(optcode, initlocal, initremote,
- acceptlocal, acceptremote);
- }
-
- /***
- * Constructor for the SimpleOptionHandler. Initial and accept
- * behaviour flags are set to false
- *
- * @param optcode - option code.
- ***/
- public SimpleOptionHandler(int optcode)
- {
- super(optcode, false, false, false, false);
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
- * @param suboptionLength - the length of data in suboption_data
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
- {
- return null;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] startSubnegotiationLocal()
- {
- return null;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] startSubnegotiationRemote()
- {
- return null;
- }
-}
diff --git a/org/apache/commons/net/telnet/SuppressGAOptionHandler.java b/org/apache/commons/net/telnet/SuppressGAOptionHandler.java
deleted file mode 100644
index aa18452..0000000
--- a/org/apache/commons/net/telnet/SuppressGAOptionHandler.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-/***
- * Implements the telnet suppress go ahead option RFC 858.
- *
- * @author Bruno D'Avanzo
- ***/
-public class SuppressGAOptionHandler extends TelnetOptionHandler
-{
- /***
- * Constructor for the SuppressGAOptionHandler. Allows defining desired
- * initial setting for local/remote activation of this option and
- * behaviour in case a local/remote activation request for this
- * option is received.
- *
- * @param initlocal - if set to true, a WILL is sent upon connection.
- * @param initremote - if set to true, a DO is sent upon connection.
- * @param acceptlocal - if set to true, any DO request is accepted.
- * @param acceptremote - if set to true, any WILL request is accepted.
- ***/
- public SuppressGAOptionHandler(boolean initlocal, boolean initremote,
- boolean acceptlocal, boolean acceptremote)
- {
- super(TelnetOption.SUPPRESS_GO_AHEAD, initlocal, initremote,
- acceptlocal, acceptremote);
- }
-
- /***
- * Constructor for the SuppressGAOptionHandler. Initial and accept
- * behaviour flags are set to false
- ***/
- public SuppressGAOptionHandler()
- {
- super(TelnetOption.SUPPRESS_GO_AHEAD, false, false, false, false);
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
- * @param suboptionLength - the length of data in suboption_data
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
- {
- return null;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] startSubnegotiationLocal()
- {
- return null;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] startSubnegotiationRemote()
- {
- return null;
- }
-}
diff --git a/org/apache/commons/net/telnet/Telnet.java b/org/apache/commons/net/telnet/Telnet.java
deleted file mode 100644
index c05b563..0000000
--- a/org/apache/commons/net/telnet/Telnet.java
+++ /dev/null
@@ -1,1317 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-import org.apache.commons.net.SocketClient;
-
-/**
- * @author Daniel F. Savarese
- * @author Bruno D'Avanzo
- */
-
-class Telnet extends SocketClient
-{
- static final boolean debug = /*true;*/ false;
-
- static final boolean debugoptions = /*true;*/ false;
-
- static final byte[] _COMMAND_DO = {
- (byte)TelnetCommand.IAC, (byte)TelnetCommand.DO
- };
-
- static final byte[] _COMMAND_DONT = {
- (byte)TelnetCommand.IAC, (byte)TelnetCommand.DONT
- };
-
- static final byte[] _COMMAND_WILL = {
- (byte)TelnetCommand.IAC, (byte)TelnetCommand.WILL
- };
-
- static final byte[] _COMMAND_WONT = {
- (byte)TelnetCommand.IAC, (byte)TelnetCommand.WONT
- };
-
- static final byte[] _COMMAND_SB = {
- (byte)TelnetCommand.IAC, (byte)TelnetCommand.SB
- };
-
- static final byte[] _COMMAND_SE = {
- (byte)TelnetCommand.IAC, (byte)TelnetCommand.SE
- };
-
- static final int _WILL_MASK = 0x01, _DO_MASK = 0x02,
- _REQUESTED_WILL_MASK = 0x04, _REQUESTED_DO_MASK = 0x08;
-
- /* public */
- static final int DEFAULT_PORT = 23;
-
- int[] _doResponse, _willResponse, _options;
-
- /* TERMINAL-TYPE option (start)*/
- /***
- * Terminal type option
- ***/
- protected static final int TERMINAL_TYPE = 24;
-
- /***
- * Send (for subnegotiation)
- ***/
- protected static final int TERMINAL_TYPE_SEND = 1;
-
- /***
- * Is (for subnegotiation)
- ***/
- protected static final int TERMINAL_TYPE_IS = 0;
-
- /***
- * Is sequence (for subnegotiation)
- ***/
- static final byte[] _COMMAND_IS = {
- (byte) TERMINAL_TYPE, (byte) TERMINAL_TYPE_IS
- };
-
- /***
- * Terminal type
- ***/
- private String terminalType = null;
- /* TERMINAL-TYPE option (end)*/
-
- /* open TelnetOptionHandler functionality (start)*/
- /***
- * Array of option handlers
- ***/
- private TelnetOptionHandler optionHandlers[];
-
- /* open TelnetOptionHandler functionality (end)*/
-
- /* Code Section added for supporting AYT (start)*/
- /***
- * AYT sequence
- ***/
- static final byte[] _COMMAND_AYT = {
- (byte) TelnetCommand.IAC, (byte) TelnetCommand.AYT
- };
-
- /***
- * monitor to wait for AYT
- ***/
- private Object aytMonitor = new Object();
-
- /***
- * flag for AYT
- ***/
- private boolean aytFlag = true;
- /* Code Section added for supporting AYT (end)*/
-
- /***
- * The stream on which to spy
- ***/
- private OutputStream spyStream = null;
-
- /***
- * The notification handler
- ***/
- private TelnetNotificationHandler __notifhand = null;
- /***
- * Empty Constructor
- ***/
- Telnet()
- {
- setDefaultPort(DEFAULT_PORT);
- _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
- _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
- _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
- optionHandlers =
- new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
- }
-
- /* TERMINAL-TYPE option (start)*/
- /***
- * This constructor lets you specify the terminal type.
- *
- * @param termtype - terminal type to be negotiated (ej. VT100)
- ***/
- Telnet(String termtype)
- {
- setDefaultPort(DEFAULT_PORT);
- _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
- _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
- _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
- terminalType = termtype;
- optionHandlers =
- new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
- }
- /* TERMINAL-TYPE option (end)*/
-
- /***
- * Looks for the state of the option.
- *
- * @return returns true if a will has been acknowledged
- *
- * @param option - option code to be looked up.
- ***/
- boolean _stateIsWill(int option)
- {
- return ((_options[option] & _WILL_MASK) != 0);
- }
-
- /***
- * Looks for the state of the option.
- *
- * @return returns true if a wont has been acknowledged
- *
- * @param option - option code to be looked up.
- ***/
- boolean _stateIsWont(int option)
- {
- return !_stateIsWill(option);
- }
-
- /***
- * Looks for the state of the option.
- *
- * @return returns true if a do has been acknowledged
- *
- * @param option - option code to be looked up.
- ***/
- boolean _stateIsDo(int option)
- {
- return ((_options[option] & _DO_MASK) != 0);
- }
-
- /***
- * Looks for the state of the option.
- *
- * @return returns true if a dont has been acknowledged
- *
- * @param option - option code to be looked up.
- ***/
- boolean _stateIsDont(int option)
- {
- return !_stateIsDo(option);
- }
-
- /***
- * Looks for the state of the option.
- *
- * @return returns true if a will has been reuqested
- *
- * @param option - option code to be looked up.
- ***/
- boolean _requestedWill(int option)
- {
- return ((_options[option] & _REQUESTED_WILL_MASK) != 0);
- }
-
- /***
- * Looks for the state of the option.
- *
- * @return returns true if a wont has been reuqested
- *
- * @param option - option code to be looked up.
- ***/
- boolean _requestedWont(int option)
- {
- return !_requestedWill(option);
- }
-
- /***
- * Looks for the state of the option.
- *
- * @return returns true if a do has been reuqested
- *
- * @param option - option code to be looked up.
- ***/
- boolean _requestedDo(int option)
- {
- return ((_options[option] & _REQUESTED_DO_MASK) != 0);
- }
-
- /***
- * Looks for the state of the option.
- *
- * @return returns true if a dont has been reuqested
- *
- * @param option - option code to be looked up.
- ***/
- boolean _requestedDont(int option)
- {
- return !_requestedDo(option);
- }
-
- /***
- * Sets the state of the option.
- *
- * @param option - option code to be set.
- ***/
- void _setWill(int option)
- {
- _options[option] |= _WILL_MASK;
-
- /* open TelnetOptionHandler functionality (start)*/
- if (_requestedWill(option))
- {
- if (optionHandlers[option] != null)
- {
- optionHandlers[option].setWill(true);
-
- int subneg[] =
- optionHandlers[option].startSubnegotiationLocal();
-
- if (subneg != null)
- {
- try
- {
- _sendSubnegotiation(subneg);
- }
- catch (IOException e)
- {
- System.err.println(
- "Exception in option subnegotiation"
- + e.getMessage());
- }
- }
- }
- }
- /* open TelnetOptionHandler functionality (end)*/
- }
-
- /***
- * Sets the state of the option.
- *
- * @param option - option code to be set.
- ***/
- void _setDo(int option)
- {
- _options[option] |= _DO_MASK;
-
- /* open TelnetOptionHandler functionality (start)*/
- if (_requestedDo(option))
- {
- if (optionHandlers[option] != null)
- {
- optionHandlers[option].setDo(true);
-
- int subneg[] =
- optionHandlers[option].startSubnegotiationRemote();
-
- if (subneg != null)
- {
- try
- {
- _sendSubnegotiation(subneg);
- }
- catch (IOException e)
- {
- System.err.println("Exception in option subnegotiation"
- + e.getMessage());
- }
- }
- }
- }
- /* open TelnetOptionHandler functionality (end)*/
- }
-
- /***
- * Sets the state of the option.
- *
- * @param option - option code to be set.
- ***/
- void _setWantWill(int option)
- {
- _options[option] |= _REQUESTED_WILL_MASK;
- }
-
- /***
- * Sets the state of the option.
- *
- * @param option - option code to be set.
- ***/
- void _setWantDo(int option)
- {
- _options[option] |= _REQUESTED_DO_MASK;
- }
-
- /***
- * Sets the state of the option.
- *
- * @param option - option code to be set.
- ***/
- void _setWont(int option)
- {
- _options[option] &= ~_WILL_MASK;
-
- /* open TelnetOptionHandler functionality (start)*/
- if (optionHandlers[option] != null)
- {
- optionHandlers[option].setWill(false);
- }
- /* open TelnetOptionHandler functionality (end)*/
- }
-
- /***
- * Sets the state of the option.
- *
- * @param option - option code to be set.
- ***/
- void _setDont(int option)
- {
- _options[option] &= ~_DO_MASK;
-
- /* open TelnetOptionHandler functionality (start)*/
- if (optionHandlers[option] != null)
- {
- optionHandlers[option].setDo(false);
- }
- /* open TelnetOptionHandler functionality (end)*/
- }
-
- /***
- * Sets the state of the option.
- *
- * @param option - option code to be set.
- ***/
- void _setWantWont(int option)
- {
- _options[option] &= ~_REQUESTED_WILL_MASK;
- }
-
- /***
- * Sets the state of the option.
- *
- * @param option - option code to be set.
- ***/
- void _setWantDont(int option)
- {
- _options[option] &= ~_REQUESTED_DO_MASK;
- }
-
- /**
- * Processes a DO request.
- *
- * @param option - option code to be set.
- * @throws IOException - Exception in I/O.
- **/
- void _processDo(int option) throws IOException
- {
- if (debugoptions)
- {
- System.err.println("RECEIVED DO: "
- + TelnetOption.getOption(option));
- }
-
- if (__notifhand != null)
- {
- __notifhand.receivedNegotiation(
- TelnetNotificationHandler.RECEIVED_DO,
- option);
- }
-
- boolean acceptNewState = false;
-
-
- /* open TelnetOptionHandler functionality (start)*/
- if (optionHandlers[option] != null)
- {
- acceptNewState = optionHandlers[option].getAcceptLocal();
- }
- else
- {
- /* open TelnetOptionHandler functionality (end)*/
- /* TERMINAL-TYPE option (start)*/
- if (option == TERMINAL_TYPE)
- {
- if ((terminalType != null) && (terminalType.length() > 0))
- {
- acceptNewState = true;
- }
- }
- /* TERMINAL-TYPE option (end)*/
- /* open TelnetOptionHandler functionality (start)*/
- }
- /* open TelnetOptionHandler functionality (end)*/
-
- if (_willResponse[option] > 0)
- {
- --_willResponse[option];
- if (_willResponse[option] > 0 && _stateIsWill(option))
- {
- --_willResponse[option];
- }
- }
-
- if (_willResponse[option] == 0)
- {
- if (_requestedWont(option))
- {
-
- switch (option)
- {
-
- default:
- break;
-
- }
-
-
- if (acceptNewState)
- {
- _setWantWill(option);
- _sendWill(option);
- }
- else
- {
- ++_willResponse[option];
- _sendWont(option);
- }
- }
- else
- {
- // Other end has acknowledged option.
-
- switch (option)
- {
-
- default:
- break;
-
- }
-
- }
- }
-
- _setWill(option);
- }
-
- /**
- * Processes a DONT request.
- *
- * @param option - option code to be set.
- * @throws IOException - Exception in I/O.
- **/
- void _processDont(int option) throws IOException
- {
- if (debugoptions)
- {
- System.err.println("RECEIVED DONT: "
- + TelnetOption.getOption(option));
- }
- if (__notifhand != null)
- {
- __notifhand.receivedNegotiation(
- TelnetNotificationHandler.RECEIVED_DONT,
- option);
- }
- if (_willResponse[option] > 0)
- {
- --_willResponse[option];
- if (_willResponse[option] > 0 && _stateIsWont(option))
- {
- --_willResponse[option];
- }
- }
-
- if (_willResponse[option] == 0 && _requestedWill(option))
- {
-
- switch (option)
- {
-
- default:
- break;
-
- }
-
- /* FIX for a BUG in the negotiation (start)*/
- if ((_stateIsWill(option)) || (_requestedWill(option)))
- {
- _sendWont(option);
- }
-
- _setWantWont(option);
- /* FIX for a BUG in the negotiation (end)*/
- }
-
- _setWont(option);
- }
-
-
- /**
- * Processes a WILL request.
- *
- * @param option - option code to be set.
- * @throws IOException - Exception in I/O.
- **/
- void _processWill(int option) throws IOException
- {
- if (debugoptions)
- {
- System.err.println("RECEIVED WILL: "
- + TelnetOption.getOption(option));
- }
-
- if (__notifhand != null)
- {
- __notifhand.receivedNegotiation(
- TelnetNotificationHandler.RECEIVED_WILL,
- option);
- }
-
- boolean acceptNewState = false;
-
- /* open TelnetOptionHandler functionality (start)*/
- if (optionHandlers[option] != null)
- {
- acceptNewState = optionHandlers[option].getAcceptRemote();
- }
- /* open TelnetOptionHandler functionality (end)*/
-
- if (_doResponse[option] > 0)
- {
- --_doResponse[option];
- if (_doResponse[option] > 0 && _stateIsDo(option))
- {
- --_doResponse[option];
- }
- }
-
- if (_doResponse[option] == 0 && _requestedDont(option))
- {
-
- switch (option)
- {
-
- default:
- break;
-
- }
-
-
- if (acceptNewState)
- {
- _setWantDo(option);
- _sendDo(option);
- }
- else
- {
- ++_doResponse[option];
- _sendDont(option);
- }
- }
-
- _setDo(option);
- }
-
- /**
- * Processes a WONT request.
- *
- * @param option - option code to be set.
- * @throws IOException - Exception in I/O.
- **/
- void _processWont(int option) throws IOException
- {
- if (debugoptions)
- {
- System.err.println("RECEIVED WONT: "
- + TelnetOption.getOption(option));
- }
-
- if (__notifhand != null)
- {
- __notifhand.receivedNegotiation(
- TelnetNotificationHandler.RECEIVED_WONT,
- option);
- }
-
- if (_doResponse[option] > 0)
- {
- --_doResponse[option];
- if (_doResponse[option] > 0 && _stateIsDont(option))
- {
- --_doResponse[option];
- }
- }
-
- if (_doResponse[option] == 0 && _requestedDo(option))
- {
-
- switch (option)
- {
-
- default:
- break;
-
- }
-
- /* FIX for a BUG in the negotiation (start)*/
- if ((_stateIsDo(option)) || (_requestedDo(option)))
- {
- _sendDont(option);
- }
-
- _setWantDont(option);
- /* FIX for a BUG in the negotiation (end)*/
- }
-
- _setDont(option);
- }
-
- /* TERMINAL-TYPE option (start)*/
- /**
- * Processes a suboption negotiation.
- *
- * @param suboption - subnegotiation data received
- * @param suboptionLength - length of data received
- * @throws IOException - Exception in I/O.
- **/
- void _processSuboption(int suboption[], int suboptionLength)
- throws IOException
- {
- if (debug)
- {
- System.err.println("PROCESS SUBOPTION.");
- }
-
- /* open TelnetOptionHandler functionality (start)*/
- if (suboptionLength > 0)
- {
- if (optionHandlers[suboption[0]] != null)
- {
- int responseSuboption[] =
- optionHandlers[suboption[0]].answerSubnegotiation(suboption,
- suboptionLength);
- _sendSubnegotiation(responseSuboption);
- }
- else
- {
- if (suboptionLength > 1)
- {
- if (debug)
- {
- for (int ii = 0; ii < suboptionLength; ii++)
- {
- System.err.println("SUB[" + ii + "]: "
- + suboption[ii]);
- }
- }
- if ((suboption[0] == TERMINAL_TYPE)
- && (suboption[1] == TERMINAL_TYPE_SEND))
- {
- _sendTerminalType();
- }
- }
- }
- }
- /* open TelnetOptionHandler functionality (end)*/
- }
-
- /***
- * Sends terminal type information.
- *
- * @throws IOException - Exception in I/O.
- ***/
- final synchronized void _sendTerminalType()
- throws IOException
- {
- if (debug)
- {
- System.err.println("SEND TERMINAL-TYPE: " + terminalType);
- }
- if (terminalType != null)
- {
- _output_.write(_COMMAND_SB);
- _output_.write(_COMMAND_IS);
- _output_.write(terminalType.getBytes());
- _output_.write(_COMMAND_SE);
- _output_.flush();
- }
- }
-
- /* TERMINAL-TYPE option (end)*/
-
- /* open TelnetOptionHandler functionality (start)*/
- /**
- * Manages subnegotiation for Terminal Type.
- *
- * @param subn - subnegotiation data to be sent
- * @throws IOException - Exception in I/O.
- **/
- final synchronized void _sendSubnegotiation(int subn[])
- throws IOException
- {
- if (debug)
- {
- System.err.println("SEND SUBNEGOTIATION: ");
- if (subn != null)
- {
- for (int ii = 0; ii < subn.length; ii++)
- {
- System.err.println("subn[" + ii + "]=" + subn[ii]);
- }
- }
- }
- if (subn != null)
- {
- byte byteresp[] = new byte[subn.length];
- for (int ii = 0; ii < subn.length; ii++)
- {
- byteresp[ii] = (byte) subn[ii];
- }
-
- _output_.write(_COMMAND_SB);
- _output_.write(byteresp);
- _output_.write(_COMMAND_SE);
-
- /* Code Section added for sending the negotiation ASAP (start)*/
- _output_.flush();
- /* Code Section added for sending the negotiation ASAP (end)*/
- }
- }
- /* open TelnetOptionHandler functionality (end)*/
-
- /* Code Section added for supporting AYT (start)*/
- /***
- * Processes the response of an AYT
- ***/
- final synchronized void _processAYTResponse()
- {
- if (!aytFlag)
- {
- synchronized (aytMonitor)
- {
- aytFlag = true;
- try
- {
- aytMonitor.notifyAll();
- }
- catch (IllegalMonitorStateException e)
- {
- System.err.println("Exception notifying:" + e.getMessage());
- }
- }
- }
- }
- /* Code Section added for supporting AYT (end)*/
-
- /***
- * Called upon connection.
- *
- * @throws IOException - Exception in I/O.
- ***/
- @Override
- protected void _connectAction_() throws IOException
- {
- /* (start). BUGFIX: clean the option info for each connection*/
- for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++)
- {
- _doResponse[ii] = 0;
- _willResponse[ii] = 0;
- _options[ii] = 0;
- if (optionHandlers[ii] != null)
- {
- optionHandlers[ii].setDo(false);
- optionHandlers[ii].setWill(false);
- }
- }
- /* (end). BUGFIX: clean the option info for each connection*/
-
- super._connectAction_();
- _input_ = new BufferedInputStream(_input_);
- _output_ = new BufferedOutputStream(_output_);
-
- /* open TelnetOptionHandler functionality (start)*/
- for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++)
- {
- if (optionHandlers[ii] != null)
- {
- if (optionHandlers[ii].getInitLocal())
- {
- try
- {
- _requestWill(optionHandlers[ii].getOptionCode());
- }
- catch (IOException e)
- {
- System.err.println(
- "Exception while initializing option: "
- + e.getMessage());
- }
- }
-
- if (optionHandlers[ii].getInitRemote())
- {
- try
- {
- _requestDo(optionHandlers[ii].getOptionCode());
- }
- catch (IOException e)
- {
- System.err.println(
- "Exception while initializing option: "
- + e.getMessage());
- }
- }
- }
- }
- /* open TelnetOptionHandler functionality (end)*/
- }
-
- /**
- * Sends a DO.
- *
- * @param option - Option code.
- * @throws IOException - Exception in I/O.
- **/
- final synchronized void _sendDo(int option)
- throws IOException
- {
- if (debug || debugoptions)
- {
- System.err.println("DO: " + TelnetOption.getOption(option));
- }
- _output_.write(_COMMAND_DO);
- _output_.write(option);
-
- /* Code Section added for sending the negotiation ASAP (start)*/
- _output_.flush();
- /* Code Section added for sending the negotiation ASAP (end)*/
- }
-
- /**
- * Requests a DO.
- *
- * @param option - Option code.
- * @throws IOException - Exception in I/O.
- **/
- final synchronized void _requestDo(int option)
- throws IOException
- {
- if ((_doResponse[option] == 0 && _stateIsDo(option))
- || _requestedDo(option))
- {
- return ;
- }
- _setWantDo(option);
- ++_doResponse[option];
- _sendDo(option);
- }
-
- /**
- * Sends a DONT.
- *
- * @param option - Option code.
- * @throws IOException - Exception in I/O.
- **/
- final synchronized void _sendDont(int option)
- throws IOException
- {
- if (debug || debugoptions)
- {
- System.err.println("DONT: " + TelnetOption.getOption(option));
- }
- _output_.write(_COMMAND_DONT);
- _output_.write(option);
-
- /* Code Section added for sending the negotiation ASAP (start)*/
- _output_.flush();
- /* Code Section added for sending the negotiation ASAP (end)*/
- }
-
- /**
- * Requests a DONT.
- *
- * @param option - Option code.
- * @throws IOException - Exception in I/O.
- **/
- final synchronized void _requestDont(int option)
- throws IOException
- {
- if ((_doResponse[option] == 0 && _stateIsDont(option))
- || _requestedDont(option))
- {
- return ;
- }
- _setWantDont(option);
- ++_doResponse[option];
- _sendDont(option);
- }
-
-
- /**
- * Sends a WILL.
- *
- * @param option - Option code.
- * @throws IOException - Exception in I/O.
- **/
- final synchronized void _sendWill(int option)
- throws IOException
- {
- if (debug || debugoptions)
- {
- System.err.println("WILL: " + TelnetOption.getOption(option));
- }
- _output_.write(_COMMAND_WILL);
- _output_.write(option);
-
- /* Code Section added for sending the negotiation ASAP (start)*/
- _output_.flush();
- /* Code Section added for sending the negotiation ASAP (end)*/
- }
-
- /**
- * Requests a WILL.
- *
- * @param option - Option code.
- * @throws IOException - Exception in I/O.
- **/
- final synchronized void _requestWill(int option)
- throws IOException
- {
- if ((_willResponse[option] == 0 && _stateIsWill(option))
- || _requestedWill(option))
- {
- return ;
- }
- _setWantWill(option);
- ++_doResponse[option];
- _sendWill(option);
- }
-
- /**
- * Sends a WONT.
- *
- * @param option - Option code.
- * @throws IOException - Exception in I/O.
- **/
- final synchronized void _sendWont(int option)
- throws IOException
- {
- if (debug || debugoptions)
- {
- System.err.println("WONT: " + TelnetOption.getOption(option));
- }
- _output_.write(_COMMAND_WONT);
- _output_.write(option);
-
- /* Code Section added for sending the negotiation ASAP (start)*/
- _output_.flush();
- /* Code Section added for sending the negotiation ASAP (end)*/
- }
-
- /**
- * Requests a WONT.
- *
- * @param option - Option code.
- * @throws IOException - Exception in I/O.
- **/
- final synchronized void _requestWont(int option)
- throws IOException
- {
- if ((_willResponse[option] == 0 && _stateIsWont(option))
- || _requestedWont(option))
- {
- return ;
- }
- _setWantWont(option);
- ++_doResponse[option];
- _sendWont(option);
- }
-
- /**
- * Sends a byte.
- *
- * @param b - byte to send
- * @throws IOException - Exception in I/O.
- **/
- final synchronized void _sendByte(int b)
- throws IOException
- {
- _output_.write(b);
-
- /* Code Section added for supporting spystreams (start)*/
- _spyWrite(b);
- /* Code Section added for supporting spystreams (end)*/
-
- }
-
- /* Code Section added for supporting AYT (start)*/
- /**
- * Sends an Are You There sequence and waits for the result.
- *
- * @param timeout - Time to wait for a response (millis.)
- * @throws IOException - Exception in I/O.
- * @throws IllegalArgumentException - Illegal argument
- * @throws InterruptedException - Interrupted during wait.
- * @return true if AYT received a response, false otherwise
- **/
- final boolean _sendAYT(long timeout)
- throws IOException, IllegalArgumentException, InterruptedException
- {
- boolean retValue = false;
- synchronized (aytMonitor)
- {
- synchronized (this)
- {
- aytFlag = false;
- _output_.write(_COMMAND_AYT);
- _output_.flush();
- }
-
- try
- {
- aytMonitor.wait(timeout);
- if (aytFlag == false)
- {
- retValue = false;
- aytFlag = true;
- }
- else
- {
- retValue = true;
- }
- }
- catch (IllegalMonitorStateException e)
- {
- System.err.println("Exception processing AYT:"
- + e.getMessage());
- }
- }
-
- return (retValue);
- }
- /* Code Section added for supporting AYT (end)*/
-
- /* open TelnetOptionHandler functionality (start)*/
-
- /**
- * Registers a new TelnetOptionHandler for this telnet to use.
- *
- * @param opthand - option handler to be registered.
- * @throws InvalidTelnetOptionException - The option code is invalid.
- **/
- void addOptionHandler(TelnetOptionHandler opthand)
- throws InvalidTelnetOptionException
- {
- int optcode = opthand.getOptionCode();
- if (TelnetOption.isValidOption(optcode))
- {
- if (optionHandlers[optcode] == null)
- {
- optionHandlers[optcode] = opthand;
- if (isConnected())
- {
- if (opthand.getInitLocal())
- {
- try
- {
- _requestWill(optcode);
- }
- catch (IOException e)
- {
- System.err.println(
- "Exception while initializing option: "
- + e.getMessage());
- }
- }
-
- if (opthand.getInitRemote())
- {
- try
- {
- _requestDo(optcode);
- }
- catch (IOException e)
- {
- System.err.println(
- "Exception while initializing option: "
- + e.getMessage());
- }
- }
- }
- }
- else
- {
- throw (new InvalidTelnetOptionException(
- "Already registered option", optcode));
- }
- }
- else
- {
- throw (new InvalidTelnetOptionException(
- "Invalid Option Code", optcode));
- }
- }
-
- /**
- * Unregisters a TelnetOptionHandler.
- *
- * @param optcode - Code of the option to be unregistered.
- * @throws InvalidTelnetOptionException - The option code is invalid.
- **/
- void deleteOptionHandler(int optcode)
- throws InvalidTelnetOptionException
- {
- if (TelnetOption.isValidOption(optcode))
- {
- if (optionHandlers[optcode] == null)
- {
- throw (new InvalidTelnetOptionException(
- "Unregistered option", optcode));
- }
- else
- {
- TelnetOptionHandler opthand = optionHandlers[optcode];
- optionHandlers[optcode] = null;
-
- if (opthand.getWill())
- {
- try
- {
- _requestWont(optcode);
- }
- catch (IOException e)
- {
- System.err.println(
- "Exception while turning off option: "
- + e.getMessage());
- }
- }
-
- if (opthand.getDo())
- {
- try
- {
- _requestDont(optcode);
- }
- catch (IOException e)
- {
- System.err.println(
- "Exception while turning off option: "
- + e.getMessage());
- }
- }
- }
- }
- else
- {
- throw (new InvalidTelnetOptionException(
- "Invalid Option Code", optcode));
- }
- }
- /* open TelnetOptionHandler functionality (end)*/
-
- /* Code Section added for supporting spystreams (start)*/
- /***
- * Registers an OutputStream for spying what's going on in
- * the Telnet session.
- *
- * @param spystream - OutputStream on which session activity
- * will be echoed.
- ***/
- void _registerSpyStream(OutputStream spystream)
- {
- spyStream = spystream;
- }
-
- /***
- * Stops spying this Telnet.
- *
- ***/
- void _stopSpyStream()
- {
- spyStream = null;
- }
-
- /***
- * Sends a read char on the spy stream.
- *
- * @param ch - character read from the session
- ***/
- void _spyRead(int ch)
- {
- if (spyStream != null)
- {
- try
- {
- if (ch != '\r')
- {
- spyStream.write(ch);
- if (ch == '\n')
- {
- spyStream.write('\r');
- }
- spyStream.flush();
- }
- }
- catch (IOException e)
- {
- spyStream = null;
- }
- }
- }
-
- /***
- * Sends a written char on the spy stream.
- *
- * @param ch - character written to the session
- ***/
- void _spyWrite(int ch)
- {
- if (!(_stateIsDo(TelnetOption.ECHO)
- && _requestedDo(TelnetOption.ECHO)))
- {
- if (spyStream != null)
- {
- try
- {
- spyStream.write(ch);
- spyStream.flush();
- }
- catch (IOException e)
- {
- spyStream = null;
- }
- }
- }
- }
- /* Code Section added for supporting spystreams (end)*/
-
- /***
- * Registers a notification handler to which will be sent
- * notifications of received telnet option negotiation commands.
- *
- * @param notifhand - TelnetNotificationHandler to be registered
- ***/
- public void registerNotifHandler(TelnetNotificationHandler notifhand)
- {
- __notifhand = notifhand;
- }
-
- /***
- * Unregisters the current notification handler.
- *
- ***/
- public void unregisterNotifHandler()
- {
- __notifhand = null;
- }
-}
diff --git a/org/apache/commons/net/telnet/TelnetClient.java b/org/apache/commons/net/telnet/TelnetClient.java
deleted file mode 100644
index 3237779..0000000
--- a/org/apache/commons/net/telnet/TelnetClient.java
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import org.apache.commons.net.io.FromNetASCIIInputStream;
-import org.apache.commons.net.io.ToNetASCIIOutputStream;
-
-/***
- * The TelnetClient class implements the simple network virtual
- * terminal (NVT) for the Telnet protocol according to RFC 854. It
- * does not implement any of the extra Telnet options because it
- * is meant to be used within a Java program providing automated
- * access to Telnet accessible resources.
- *
- * The class can be used by first connecting to a server using the
- * SocketClient
- * {@link org.apache.commons.net.SocketClient#connect connect}
- * method. Then an InputStream and OutputStream for sending and
- * receiving data over the Telnet connection can be obtained by
- * using the {@link #getInputStream getInputStream() } and
- * {@link #getOutputStream getOutputStream() } methods.
- * When you finish using the streams, you must call
- * {@link #disconnect disconnect } rather than simply
- * closing the streams.
- *
- *
- * @author Daniel F. Savarese
- * @author Bruno D'Avanzo
- ***/
-
-public class TelnetClient extends Telnet
-{
- private InputStream __input;
- private OutputStream __output;
- protected boolean readerThread = true;
-
- /***
- * Default TelnetClient constructor.
- ***/
- public TelnetClient()
- {
- /* TERMINAL-TYPE option (start)*/
- super ("VT100");
- /* TERMINAL-TYPE option (end)*/
- __input = null;
- __output = null;
- }
-
- /* TERMINAL-TYPE option (start)*/
- public TelnetClient(String termtype)
- {
- super (termtype);
- __input = null;
- __output = null;
- }
- /* TERMINAL-TYPE option (end)*/
-
- void _flushOutputStream() throws IOException
- {
- _output_.flush();
- }
- void _closeOutputStream() throws IOException
- {
- _output_.close();
- }
-
- /***
- * Handles special connection requirements.
- *
- * @exception IOException If an error occurs during connection setup.
- ***/
- @Override
- protected void _connectAction_() throws IOException
- {
- super._connectAction_();
- InputStream input;
- TelnetInputStream tmp;
-
- if (FromNetASCIIInputStream.isConversionRequired())
- input = new FromNetASCIIInputStream(_input_);
- else
- input = _input_;
-
-
- tmp = new TelnetInputStream(input, this, readerThread);
- if(readerThread)
- {
- tmp._start();
- }
- // __input CANNOT refer to the TelnetInputStream. We run into
- // blocking problems when some classes use TelnetInputStream, so
- // we wrap it with a BufferedInputStream which we know is safe.
- // This blocking behavior requires further investigation, but right
- // now it looks like classes like InputStreamReader are not implemented
- // in a safe manner.
- __input = new BufferedInputStream(tmp);
- __output = new ToNetASCIIOutputStream(new TelnetOutputStream(this));
- }
-
- /***
- * Disconnects the telnet session, closing the input and output streams
- * as well as the socket. If you have references to the
- * input and output streams of the telnet connection, you should not
- * close them yourself, but rather call disconnect to properly close
- * the connection.
- ***/
- @Override
- public void disconnect() throws IOException
- {
- if (__input != null)
- __input.close();
- if (__output != null)
- __output.close();
- super.disconnect();
- }
-
- /***
- * Returns the telnet connection output stream. You should not close the
- * stream when you finish with it. Rather, you should call
- * {@link #disconnect disconnect }.
- *
- * @return The telnet connection output stream.
- ***/
- public OutputStream getOutputStream()
- {
- return __output;
- }
-
- /***
- * Returns the telnet connection input stream. You should not close the
- * stream when you finish with it. Rather, you should call
- * {@link #disconnect disconnect }.
- *
- * @return The telnet connection input stream.
- ***/
- public InputStream getInputStream()
- {
- return __input;
- }
-
- /***
- * Returns the state of the option on the local side.
- *
- * @param option - Option to be checked.
- *
- * @return The state of the option on the local side.
- ***/
- public boolean getLocalOptionState(int option)
- {
- /* BUG (option active when not already acknowledged) (start)*/
- return (_stateIsWill(option) && _requestedWill(option));
- /* BUG (option active when not already acknowledged) (end)*/
- }
-
- /***
- * Returns the state of the option on the remote side.
- *
- * @param option - Option to be checked.
- *
- * @return The state of the option on the remote side.
- ***/
- public boolean getRemoteOptionState(int option)
- {
- /* BUG (option active when not already acknowledged) (start)*/
- return (_stateIsDo(option) && _requestedDo(option));
- /* BUG (option active when not already acknowledged) (end)*/
- }
- /* open TelnetOptionHandler functionality (end)*/
-
- /* Code Section added for supporting AYT (start)*/
-
- /***
- * Sends an Are You There sequence and waits for the result.
- *
- * @throws InterruptedException
- * @throws IllegalArgumentException
- * @throws IOException
- *
- * @param timeout - Time to wait for a response (millis.)
- *
- * @return true if AYT received a response, false otherwise
- ***/
- public boolean sendAYT(long timeout)
- throws IOException, IllegalArgumentException, InterruptedException
- {
- return (_sendAYT(timeout));
- }
- /* Code Section added for supporting AYT (start)*/
-
- /* open TelnetOptionHandler functionality (start)*/
-
- /***
- * Registers a new TelnetOptionHandler for this telnet client to use.
- *
- * @param opthand - option handler to be registered.
- *
- * @throws InvalidTelnetOptionException
- ***/
- @Override
- public void addOptionHandler(TelnetOptionHandler opthand)
- throws InvalidTelnetOptionException
- {
- super.addOptionHandler(opthand);
- }
- /* open TelnetOptionHandler functionality (end)*/
-
- /***
- * Unregisters a TelnetOptionHandler.
- *
- * @param optcode - Code of the option to be unregistered.
- *
- * @throws InvalidTelnetOptionException
- ***/
- @Override
- public void deleteOptionHandler(int optcode)
- throws InvalidTelnetOptionException
- {
- super.deleteOptionHandler(optcode);
- }
-
- /* Code Section added for supporting spystreams (start)*/
- /***
- * Registers an OutputStream for spying what's going on in
- * the TelnetClient session.
- *
- * @param spystream - OutputStream on which session activity
- * will be echoed.
- ***/
- public void registerSpyStream(OutputStream spystream)
- {
- super._registerSpyStream(spystream);
- }
-
- /***
- * Stops spying this TelnetClient.
- *
- ***/
- public void stopSpyStream()
- {
- super._stopSpyStream();
- }
- /* Code Section added for supporting spystreams (end)*/
-
- /***
- * Registers a notification handler to which will be sent
- * notifications of received telnet option negotiation commands.
- *
- * @param notifhand - TelnetNotificationHandler to be registered
- ***/
- @Override
- public void registerNotifHandler(TelnetNotificationHandler notifhand)
- {
- super.registerNotifHandler(notifhand);
- }
-
- /***
- * Unregisters the current notification handler.
- *
- ***/
- @Override
- public void unregisterNotifHandler()
- {
- super.unregisterNotifHandler();
- }
-
- /***
- * Sets the status of the reader thread.
- * The reader thread status will apply to all subsequent connections
- *
- * @param flag - true switches the reader thread on, false switches it off
- ***/
- public void setReaderThread(boolean flag)
- {
- readerThread = flag;
- }
-
- /***
- * Gets the status of the reader thread.
- *
- * @return true if the reader thread is on, false otherwise
- ***/
- public boolean getReaderThread()
- {
- return (readerThread);
- }
-}
diff --git a/org/apache/commons/net/telnet/TelnetCommand.java b/org/apache/commons/net/telnet/TelnetCommand.java
deleted file mode 100644
index 725057b..0000000
--- a/org/apache/commons/net/telnet/TelnetCommand.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-/**
- * The TelnetCommand class cannot be instantiated and only serves as a
- * storehouse for telnet command constants.
- * @author Daniel F. Savarese
- * @see org.apache.commons.net.telnet.Telnet
- * @see org.apache.commons.net.telnet.TelnetClient
- */
-
-public final class TelnetCommand
-{
- /*** The maximum value a command code can have. This value is 255. ***/
- public static final int MAX_COMMAND_VALUE = 255;
-
- /*** Interpret As Command code. Value is 255 according to RFC 854. ***/
- public static final int IAC = 255;
-
- /*** Don't use option code. Value is 254 according to RFC 854. ***/
- public static final int DONT = 254;
-
- /*** Request to use option code. Value is 253 according to RFC 854. ***/
- public static final int DO = 253;
-
- /*** Refuse to use option code. Value is 252 according to RFC 854. ***/
- public static final int WONT = 252;
-
- /*** Agree to use option code. Value is 251 according to RFC 854. ***/
- public static final int WILL = 251;
-
- /*** Start subnegotiation code. Value is 250 according to RFC 854. ***/
- public static final int SB = 250;
-
- /*** Go Ahead code. Value is 249 according to RFC 854. ***/
- public static final int GA = 249;
-
- /*** Erase Line code. Value is 248 according to RFC 854. ***/
- public static final int EL = 248;
-
- /*** Erase Character code. Value is 247 according to RFC 854. ***/
- public static final int EC = 247;
-
- /*** Are You There code. Value is 246 according to RFC 854. ***/
- public static final int AYT = 246;
-
- /*** Abort Output code. Value is 245 according to RFC 854. ***/
- public static final int AO = 245;
-
- /*** Interrupt Process code. Value is 244 according to RFC 854. ***/
- public static final int IP = 244;
-
- /*** Break code. Value is 243 according to RFC 854. ***/
- public static final int BREAK = 243;
-
- /*** Data mark code. Value is 242 according to RFC 854. ***/
- public static final int DM = 242;
-
- /*** No Operation code. Value is 241 according to RFC 854. ***/
- public static final int NOP = 241;
-
- /*** End subnegotiation code. Value is 240 according to RFC 854. ***/
- public static final int SE = 240;
-
- /*** End of record code. Value is 239. ***/
- public static final int EOR = 239;
-
- /*** Abort code. Value is 238. ***/
- public static final int ABORT = 238;
-
- /*** Suspend process code. Value is 237. ***/
- public static final int SUSP = 237;
-
- /*** End of file code. Value is 236. ***/
- public static final int EOF = 236;
-
- /*** Synchronize code. Value is 242. ***/
- public static final int SYNCH = 242;
-
- /*** String representations of commands. ***/
- private static final String __commandString[] = {
- "IAC", "DONT", "DO", "WONT", "WILL", "SB", "GA", "EL", "EC", "AYT",
- "AO", "IP", "BRK", "DMARK", "NOP", "SE", "EOR", "ABORT", "SUSP", "EOF"
- };
-
- private static final int __FIRST_COMMAND = IAC;
- private static final int __LAST_COMMAND = EOF;
-
- /***
- * Returns the string representation of the telnet protocol command
- * corresponding to the given command code.
- *
- * @param code The command code of the telnet protocol command.
- * @return The string representation of the telnet protocol command.
- ***/
- public static final String getCommand(int code)
- {
- return __commandString[__FIRST_COMMAND - code];
- }
-
- /***
- * Determines if a given command code is valid. Returns true if valid,
- * false if not.
- *
- * @param code The command code to test.
- * @return True if the command code is valid, false if not.
- **/
- public static final boolean isValidCommand(int code)
- {
- return (code <= __FIRST_COMMAND && code >= __LAST_COMMAND);
- }
-
- // Cannot be instantiated
- private TelnetCommand()
- { }
-}
diff --git a/org/apache/commons/net/telnet/TelnetInputStream.java b/org/apache/commons/net/telnet/TelnetInputStream.java
deleted file mode 100644
index 8a83b68..0000000
--- a/org/apache/commons/net/telnet/TelnetInputStream.java
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-
-/***
- *
- *
- *
- *
- *
- * @author Daniel F. Savarese
- * @author Bruno D'Avanzo
- ***/
-
-
-final class TelnetInputStream extends BufferedInputStream implements Runnable
-{
- static final int _STATE_DATA = 0, _STATE_IAC = 1, _STATE_WILL = 2,
- _STATE_WONT = 3, _STATE_DO = 4, _STATE_DONT = 5,
- _STATE_SB = 6, _STATE_SE = 7, _STATE_CR = 8, _STATE_IAC_SB = 9;
-
- private boolean __hasReachedEOF, __isClosed;
- private boolean __readIsWaiting;
- private int __receiveState, __queueHead, __queueTail, __bytesAvailable;
- private int[] __queue;
- private TelnetClient __client;
- private Thread __thread;
- private IOException __ioException;
-
- /* TERMINAL-TYPE option (start)*/
- private int __suboption[] = new int[256];
- private int __suboption_count = 0;
- /* TERMINAL-TYPE option (end)*/
-
- private boolean __threaded;
-
- TelnetInputStream(InputStream input, TelnetClient client,
- boolean readerThread)
- {
- super(input);
- __client = client;
- __receiveState = _STATE_DATA;
- __isClosed = true;
- __hasReachedEOF = false;
- // Make it 2049, because when full, one slot will go unused, and we
- // want a 2048 byte buffer just to have a round number (base 2 that is)
- __queue = new int[2049];
- __queueHead = 0;
- __queueTail = 0;
- __bytesAvailable = 0;
- __ioException = null;
- __readIsWaiting = false;
- __threaded = false;
- if(readerThread)
- __thread = new Thread(this);
- else
- __thread = null;
- }
-
- TelnetInputStream(InputStream input, TelnetClient client) {
- this(input, client, true);
- }
-
- void _start()
- {
- if(__thread == null)
- return;
-
- int priority;
- __isClosed = false;
- // TODO remove this
- // Need to set a higher priority in case JVM does not use pre-emptive
- // threads. This should prevent scheduler induced deadlock (rather than
- // deadlock caused by a bug in this code).
- priority = Thread.currentThread().getPriority() + 1;
- if (priority > Thread.MAX_PRIORITY)
- priority = Thread.MAX_PRIORITY;
- __thread.setPriority(priority);
- __thread.setDaemon(true);
- __thread.start();
- __threaded = true;
- }
-
-
- // synchronized(__client) critical sections are to protect against
- // TelnetOutputStream writing through the telnet client at same time
- // as a processDo/Will/etc. command invoked from TelnetInputStream
- // tries to write.
- private int __read(boolean mayBlock) throws IOException
- {
- int ch;
-
-_loop:
- while (true)
- {
-
- // If there is no more data AND we were told not to block, just return -2. (More efficient than exception.)
- if(!mayBlock && super.available() == 0)
- return -2;
-
- // Otherwise, exit only when we reach end of stream.
- if ((ch = super.read()) < 0)
- return -1;
-
- ch = (ch & 0xff);
-
- /* Code Section added for supporting AYT (start)*/
- synchronized (__client)
- {
- __client._processAYTResponse();
- }
- /* Code Section added for supporting AYT (end)*/
-
- /* Code Section added for supporting spystreams (start)*/
- __client._spyRead(ch);
- /* Code Section added for supporting spystreams (end)*/
-
-_mainSwitch:
- switch (__receiveState)
- {
-
- case _STATE_CR:
- if (ch == '\0')
- {
- // Strip null
- continue;
- }
- // How do we handle newline after cr?
- // else if (ch == '\n' && _requestedDont(TelnetOption.ECHO) &&
-
- // Handle as normal data by falling through to _STATE_DATA case
-
- case _STATE_DATA:
- if (ch == TelnetCommand.IAC)
- {
- __receiveState = _STATE_IAC;
- continue;
- }
-
-
- if (ch == '\r')
- {
- synchronized (__client)
- {
- if (__client._requestedDont(TelnetOption.BINARY))
- __receiveState = _STATE_CR;
- else
- __receiveState = _STATE_DATA;
- }
- }
- else
- __receiveState = _STATE_DATA;
- break;
-
- case _STATE_IAC:
- switch (ch)
- {
- case TelnetCommand.WILL:
- __receiveState = _STATE_WILL;
- continue;
- case TelnetCommand.WONT:
- __receiveState = _STATE_WONT;
- continue;
- case TelnetCommand.DO:
- __receiveState = _STATE_DO;
- continue;
- case TelnetCommand.DONT:
- __receiveState = _STATE_DONT;
- continue;
- /* TERMINAL-TYPE option (start)*/
- case TelnetCommand.SB:
- __suboption_count = 0;
- __receiveState = _STATE_SB;
- continue;
- /* TERMINAL-TYPE option (end)*/
- case TelnetCommand.IAC:
- __receiveState = _STATE_DATA;
- break;
- default:
- break;
- }
- __receiveState = _STATE_DATA;
- continue;
- case _STATE_WILL:
- synchronized (__client)
- {
- __client._processWill(ch);
- __client._flushOutputStream();
- }
- __receiveState = _STATE_DATA;
- continue;
- case _STATE_WONT:
- synchronized (__client)
- {
- __client._processWont(ch);
- __client._flushOutputStream();
- }
- __receiveState = _STATE_DATA;
- continue;
- case _STATE_DO:
- synchronized (__client)
- {
- __client._processDo(ch);
- __client._flushOutputStream();
- }
- __receiveState = _STATE_DATA;
- continue;
- case _STATE_DONT:
- synchronized (__client)
- {
- __client._processDont(ch);
- __client._flushOutputStream();
- }
- __receiveState = _STATE_DATA;
- continue;
- /* TERMINAL-TYPE option (start)*/
- case _STATE_SB:
- switch (ch)
- {
- case TelnetCommand.IAC:
- __receiveState = _STATE_IAC_SB;
- continue;
- default:
- // store suboption char
- __suboption[__suboption_count++] = ch;
- break;
- }
- __receiveState = _STATE_SB;
- continue;
- case _STATE_IAC_SB:
- switch (ch)
- {
- case TelnetCommand.SE:
- synchronized (__client)
- {
- __client._processSuboption(__suboption, __suboption_count);
- __client._flushOutputStream();
- }
- __receiveState = _STATE_DATA;
- continue;
- default:
- __receiveState = _STATE_SB;
- break;
- }
- __receiveState = _STATE_DATA;
- continue;
- /* TERMINAL-TYPE option (end)*/
- }
-
- break;
- }
-
- return ch;
- }
-
- // synchronized(__client) critical sections are to protect against
- // TelnetOutputStream writing through the telnet client at same time
- // as a processDo/Will/etc. command invoked from TelnetInputStream
- // tries to write.
- private void __processChar(int ch) throws InterruptedException
- {
- // Critical section because we're altering __bytesAvailable,
- // __queueTail, and the contents of _queue.
- synchronized (__queue)
- {
- while (__bytesAvailable >= __queue.length - 1)
- {
- // The queue is full. We need to wait before adding any more data to it. Hopefully the stream owner
- // will consume some data soon!
- if(__threaded)
- {
- __queue.notify();
- try
- {
- __queue.wait();
- }
- catch (InterruptedException e)
- {
- throw e;
- }
- }
- else
- {
- // We've been asked to add another character to the queue, but it is already full and there's
- // no other thread to drain it. This should not have happened!
- throw new IllegalStateException("Queue is full! Cannot process another character.");
- }
- }
-
- // Need to do this in case we're not full, but block on a read
- if (__readIsWaiting && __threaded)
- {
- __queue.notify();
- }
-
- __queue[__queueTail] = ch;
- ++__bytesAvailable;
-
- if (++__queueTail >= __queue.length)
- __queueTail = 0;
- }
- }
-
- @Override
- public int read() throws IOException
- {
- // Critical section because we're altering __bytesAvailable,
- // __queueHead, and the contents of _queue in addition to
- // testing value of __hasReachedEOF.
- synchronized (__queue)
- {
-
- while (true)
- {
- if (__ioException != null)
- {
- IOException e;
- e = __ioException;
- __ioException = null;
- throw e;
- }
-
- if (__bytesAvailable == 0)
- {
- // Return -1 if at end of file
- if (__hasReachedEOF)
- return -1;
-
- // Otherwise, we have to wait for queue to get something
- if(__threaded)
- {
- __queue.notify();
- try
- {
- __readIsWaiting = true;
- __queue.wait();
- __readIsWaiting = false;
- }
- catch (InterruptedException e)
- {
- throw new InterruptedIOException("Fatal thread interruption during read.");
- }
- }
- else
- {
- //__alreadyread = false;
- __readIsWaiting = true;
- int ch;
- boolean mayBlock = true; // block on the first read only
-
- do
- {
- try
- {
- if ((ch = __read(mayBlock)) < 0)
- if(ch != -2)
- return (ch);
- }
- catch (InterruptedIOException e)
- {
- synchronized (__queue)
- {
- __ioException = e;
- __queue.notifyAll();
- try
- {
- __queue.wait(100);
- }
- catch (InterruptedException interrupted)
- {
- }
- }
- return (-1);
- }
-
-
- try
- {
- if(ch != -2)
- {
- __processChar(ch);
- }
- }
- catch (InterruptedException e)
- {
- if (__isClosed)
- return (-1);
- }
-
- // Reads should not block on subsequent iterations. Potentially, this could happen if the
- // remaining buffered socket data consists entirely of Telnet command sequence and no "user" data.
- mayBlock = false;
-
- }
- // Continue reading as long as there is data available and the queue is not full.
- while (super.available() > 0 && __bytesAvailable < __queue.length - 1);
-
- __readIsWaiting = false;
- }
- continue;
- }
- else
- {
- int ch;
-
- ch = __queue[__queueHead];
-
- if (++__queueHead >= __queue.length)
- __queueHead = 0;
-
- --__bytesAvailable;
-
- // Need to explicitly notify() so available() works properly
- if(__bytesAvailable == 0 && __threaded) {
- __queue.notify();
- }
-
- return ch;
- }
- }
- }
- }
-
-
- /***
- * Reads the next number of bytes from the stream into an array and
- * returns the number of bytes read. Returns -1 if the end of the
- * stream has been reached.
- *
- * @param buffer The byte array in which to store the data.
- * @return The number of bytes read. Returns -1 if the
- * end of the message has been reached.
- * @exception IOException If an error occurs in reading the underlying
- * stream.
- ***/
- @Override
- public int read(byte buffer[]) throws IOException
- {
- return read(buffer, 0, buffer.length);
- }
-
-
- /***
- * Reads the next number of bytes from the stream into an array and returns
- * the number of bytes read. Returns -1 if the end of the
- * message has been reached. The characters are stored in the array
- * starting from the given offset and up to the length specified.
- *
- * @param buffer The byte array in which to store the data.
- * @param offset The offset into the array at which to start storing data.
- * @param length The number of bytes to read.
- * @return The number of bytes read. Returns -1 if the
- * end of the stream has been reached.
- * @exception IOException If an error occurs while reading the underlying
- * stream.
- ***/
- @Override
- public int read(byte buffer[], int offset, int length) throws IOException
- {
- int ch, off;
-
- if (length < 1)
- return 0;
-
- // Critical section because run() may change __bytesAvailable
- synchronized (__queue)
- {
- if (length > __bytesAvailable)
- length = __bytesAvailable;
- }
-
- if ((ch = read()) == -1)
- return -1;
-
- off = offset;
-
- do
- {
- buffer[offset++] = (byte)ch;
- }
- while (--length > 0 && (ch = read()) != -1);
-
- //__client._spyRead(buffer, off, offset - off);
- return (offset - off);
- }
-
-
- /*** Returns false. Mark is not supported. ***/
- @Override
- public boolean markSupported()
- {
- return false;
- }
-
- @Override
- public int available() throws IOException
- {
- // Critical section because run() may change __bytesAvailable
- synchronized (__queue)
- {
- return __bytesAvailable;
- }
- }
-
-
- // Cannot be synchronized. Will cause deadlock if run() is blocked
- // in read because BufferedInputStream read() is synchronized.
- @Override
- public void close() throws IOException
- {
- // Completely disregard the fact thread may still be running.
- // We can't afford to block on this close by waiting for
- // thread to terminate because few if any JVM's will actually
- // interrupt a system read() from the interrupt() method.
- super.close();
-
- synchronized (__queue)
- {
- __hasReachedEOF = true;
- __isClosed = true;
-
- if (__thread != null && __thread.isAlive())
- {
- __thread.interrupt();
- }
-
- __queue.notifyAll();
- }
-
- __threaded = false;
- }
-
- public void run()
- {
- int ch;
-
- try
- {
-_outerLoop:
- while (!__isClosed)
- {
- try
- {
- if ((ch = __read(true)) < 0)
- break;
- }
- catch (InterruptedIOException e)
- {
- synchronized (__queue)
- {
- __ioException = e;
- __queue.notifyAll();
- try
- {
- __queue.wait(100);
- }
- catch (InterruptedException interrupted)
- {
- if (__isClosed)
- break _outerLoop;
- }
- continue;
- }
- } catch(RuntimeException re) {
- // We treat any runtime exceptions as though the
- // stream has been closed. We close the
- // underlying stream just to be sure.
- super.close();
- // Breaking the loop has the effect of setting
- // the state to closed at the end of the method.
- break _outerLoop;
- }
-
- try
- {
- __processChar(ch);
- }
- catch (InterruptedException e)
- {
- if (__isClosed)
- break _outerLoop;
- }
- }
- }
- catch (IOException ioe)
- {
- synchronized (__queue)
- {
- __ioException = ioe;
- }
- }
-
- synchronized (__queue)
- {
- __isClosed = true; // Possibly redundant
- __hasReachedEOF = true;
- __queue.notify();
- }
-
- __threaded = false;
- }
-}
-
-/* Emacs configuration
- * Local variables: **
- * mode: java **
- * c-basic-offset: 4 **
- * indent-tabs-mode: nil **
- * End: **
- */
diff --git a/org/apache/commons/net/telnet/TelnetNotificationHandler.java b/org/apache/commons/net/telnet/TelnetNotificationHandler.java
deleted file mode 100644
index d509021..0000000
--- a/org/apache/commons/net/telnet/TelnetNotificationHandler.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-/***
- * The TelnetNotificationHandler interface can be used to handle
- * notification of options negotiation commands received on a telnet
- * session.
- *
- * The user can implement this interface and register a
- * TelnetNotificationHandler by using the registerNotificationHandler()
- * of TelnetClient to be notified of option negotiation commands.
- *
- *
- * @author Bruno D'Avanzo
- ***/
-
-public interface TelnetNotificationHandler
-{
- /***
- * The remote party sent a DO command.
- ***/
- public static final int RECEIVED_DO = 1;
-
- /***
- * The remote party sent a DONT command.
- ***/
- public static final int RECEIVED_DONT = 2;
-
- /***
- * The remote party sent a WILL command.
- ***/
- public static final int RECEIVED_WILL = 3;
-
- /***
- * The remote party sent a WONT command.
- ***/
- public static final int RECEIVED_WONT = 4;
-
- /***
- * Callback method called when TelnetClient receives an option
- * negotiation command.
- *
- * @param negotiation_code - type of negotiation command received
- * (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT)
- *
- * @param option_code - code of the option negotiated
- *
- ***/
- public void receivedNegotiation(int negotiation_code, int option_code);
-}
diff --git a/org/apache/commons/net/telnet/TelnetOption.java b/org/apache/commons/net/telnet/TelnetOption.java
deleted file mode 100644
index 77799b6..0000000
--- a/org/apache/commons/net/telnet/TelnetOption.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-/***
- * The TelnetOption class cannot be instantiated and only serves as a
- * storehouse for telnet option constants.
- *
- * Details regarding Telnet option specification can be found in RFC 855.
- *
- *
- * @author Daniel F. Savarese
- * @see org.apache.commons.net.telnet.Telnet
- * @see org.apache.commons.net.telnet.TelnetClient
- ***/
-
-public class TelnetOption
-{
- /*** The maximum value an option code can have. This value is 255. ***/
- public static final int MAX_OPTION_VALUE = 255;
-
- public static final int BINARY = 0;
-
- public static final int ECHO = 1;
-
- public static final int PREPARE_TO_RECONNECT = 2;
-
- public static final int SUPPRESS_GO_AHEAD = 3;
-
- public static final int APPROXIMATE_MESSAGE_SIZE = 4;
-
- public static final int STATUS = 5;
-
- public static final int TIMING_MARK = 6;
-
- public static final int REMOTE_CONTROLLED_TRANSMISSION = 7;
-
- public static final int NEGOTIATE_OUTPUT_LINE_WIDTH = 8;
-
- public static final int NEGOTIATE_OUTPUT_PAGE_SIZE = 9;
-
- public static final int NEGOTIATE_CARRIAGE_RETURN = 10;
-
- public static final int NEGOTIATE_HORIZONTAL_TAB_STOP = 11;
-
- public static final int NEGOTIATE_HORIZONTAL_TAB = 12;
-
- public static final int NEGOTIATE_FORMFEED = 13;
-
- public static final int NEGOTIATE_VERTICAL_TAB_STOP = 14;
-
- public static final int NEGOTIATE_VERTICAL_TAB = 15;
-
- public static final int NEGOTIATE_LINEFEED = 16;
-
- public static final int EXTENDED_ASCII = 17;
-
- public static final int FORCE_LOGOUT = 18;
-
- public static final int BYTE_MACRO = 19;
-
- public static final int DATA_ENTRY_TERMINAL = 20;
-
- public static final int SUPDUP = 21;
-
- public static final int SUPDUP_OUTPUT = 22;
-
- public static final int SEND_LOCATION = 23;
-
- public static final int TERMINAL_TYPE = 24;
-
- public static final int END_OF_RECORD = 25;
-
- public static final int TACACS_USER_IDENTIFICATION = 26;
-
- public static final int OUTPUT_MARKING = 27;
-
- public static final int TERMINAL_LOCATION_NUMBER = 28;
-
- public static final int REGIME_3270 = 29;
-
- public static final int X3_PAD = 30;
-
- public static final int WINDOW_SIZE = 31;
-
- public static final int TERMINAL_SPEED = 32;
-
- public static final int REMOTE_FLOW_CONTROL = 33;
-
- public static final int LINEMODE = 34;
-
- public static final int X_DISPLAY_LOCATION = 35;
-
- public static final int OLD_ENVIRONMENT_VARIABLES = 36;
-
- public static final int AUTHENTICATION = 37;
-
- public static final int ENCRYPTION = 38;
-
- public static final int NEW_ENVIRONMENT_VARIABLES = 39;
-
- public static final int EXTENDED_OPTIONS_LIST = 255;
-
- private static final int __FIRST_OPTION = BINARY;
- private static final int __LAST_OPTION = EXTENDED_OPTIONS_LIST;
-
- private static final String __optionString[] = {
- "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS",
- "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD",
- "NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT",
- "BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
- "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID",
- "OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED",
- "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
- "ENCRYPT", "NEW-ENVIRON", "TN3270E", "XAUTH", "CHARSET", "RSP",
- "Com Port Control", "Suppress Local Echo", "Start TLS",
- "KERMIT", "SEND-URL", "FORWARD_X", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "TELOPT PRAGMA LOGON", "TELOPT SSPI LOGON",
- "TELOPT PRAGMA HEARTBEAT", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "", "", "",
- "Extended-Options-List"
- };
-
-
- /***
- * Returns the string representation of the telnet protocol option
- * corresponding to the given option code.
- *
- * @param code The option code of the telnet protocol option
- * @return The string representation of the telnet protocol option.
- ***/
- public static final String getOption(int code)
- {
- if(__optionString[code].length() == 0)
- {
- return "UNASSIGNED";
- }
- else
- {
- return __optionString[code];
- }
- }
-
-
- /***
- * Determines if a given option code is valid. Returns true if valid,
- * false if not.
- *
- * @param code The option code to test.
- * @return True if the option code is valid, false if not.
- **/
- public static final boolean isValidOption(int code)
- {
- return (code <= __LAST_OPTION);
- }
-
- // Cannot be instantiated
- private TelnetOption()
- { }
-}
diff --git a/org/apache/commons/net/telnet/TelnetOptionHandler.java b/org/apache/commons/net/telnet/TelnetOptionHandler.java
deleted file mode 100644
index 52486ba..0000000
--- a/org/apache/commons/net/telnet/TelnetOptionHandler.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-/***
- * The TelnetOptionHandler class is the base class to be used
- * for implementing handlers for telnet options.
- *
- * TelnetOptionHandler implements basic option handling
- * functionality and defines abstract methods that must be
- * implemented to define subnegotiation behaviour.
- *
- * @author Bruno D'Avanzo
- ***/
-public abstract class TelnetOptionHandler
-{
- /***
- * Option code
- ***/
- private int optionCode = -1;
-
- /***
- * true if the option should be activated on the local side
- ***/
- private boolean initialLocal = false;
-
- /***
- * true if the option should be activated on the remote side
- ***/
- private boolean initialRemote = false;
-
- /***
- * true if the option should be accepted on the local side
- ***/
- private boolean acceptLocal = false;
-
- /***
- * true if the option should be accepted on the remote side
- ***/
- private boolean acceptRemote = false;
-
- /***
- * true if the option is active on the local side
- ***/
- private boolean doFlag = false;
-
- /***
- * true if the option is active on the remote side
- ***/
- private boolean willFlag = false;
-
- /***
- * Constructor for the TelnetOptionHandler. Allows defining desired
- * initial setting for local/remote activation of this option and
- * behaviour in case a local/remote activation request for this
- * option is received.
- *
- * @param optcode - Option code.
- * @param initlocal - if set to true, a WILL is sent upon connection.
- * @param initremote - if set to true, a DO is sent upon connection.
- * @param acceptlocal - if set to true, any DO request is accepted.
- * @param acceptremote - if set to true, any WILL request is accepted.
- ***/
- public TelnetOptionHandler(int optcode,
- boolean initlocal,
- boolean initremote,
- boolean acceptlocal,
- boolean acceptremote)
- {
- optionCode = optcode;
- initialLocal = initlocal;
- initialRemote = initremote;
- acceptLocal = acceptlocal;
- acceptRemote = acceptremote;
- }
-
-
- /***
- * Returns the option code for this option.
- *
- * @return Option code.
- ***/
- public int getOptionCode()
- {
- return (optionCode);
- }
-
- /***
- * Returns a boolean indicating whether to accept a DO
- * request coming from the other end.
- *
- * @return true if a DO request shall be accepted.
- ***/
- public boolean getAcceptLocal()
- {
- return (acceptLocal);
- }
-
- /***
- * Returns a boolean indicating whether to accept a WILL
- * request coming from the other end.
- *
- * @return true if a WILL request shall be accepted.
- ***/
- public boolean getAcceptRemote()
- {
- return (acceptRemote);
- }
-
- /***
- * Set behaviour of the option for DO requests coming from
- * the other end.
- *
- * @param accept - if true, subsequent DO requests will be accepted.
- ***/
- public void setAcceptLocal(boolean accept)
- {
- acceptLocal = accept;
- }
-
- /***
- * Set behaviour of the option for WILL requests coming from
- * the other end.
- *
- * @param accept - if true, subsequent WILL requests will be accepted.
- ***/
- public void setAcceptRemote(boolean accept)
- {
- acceptRemote = accept;
- }
-
- /***
- * Returns a boolean indicating whether to send a WILL request
- * to the other end upon connection.
- *
- * @return true if a WILL request shall be sent upon connection.
- ***/
- public boolean getInitLocal()
- {
- return (initialLocal);
- }
-
- /***
- * Returns a boolean indicating whether to send a DO request
- * to the other end upon connection.
- *
- * @return true if a DO request shall be sent upon connection.
- ***/
- public boolean getInitRemote()
- {
- return (initialRemote);
- }
-
- /***
- * Tells this option whether to send a WILL request upon connection.
- *
- * @param init - if true, a WILL request will be sent upon subsequent
- * connections.
- ***/
- public void setInitLocal(boolean init)
- {
- initialLocal = init;
- }
-
- /***
- * Tells this option whether to send a DO request upon connection.
- *
- * @param init - if true, a DO request will be sent upon subsequent
- * connections.
- ***/
- public void setInitRemote(boolean init)
- {
- initialRemote = init;
- }
-
- /***
- * Method called upon reception of a subnegotiation for this option
- * coming from the other end.
- * Must be implemented by the actual TelnetOptionHandler to specify
- * which response must be sent for the subnegotiation request.
- *
- * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
- * @param suboptionLength - the length of data in suboption_data
- *
- * @return response to be sent to the subnegotiation sequence. TelnetClient
- * will add IAC SB & IAC SE. null means no response
- ***/
- public abstract int[] answerSubnegotiation(int suboptionData[],
- int suboptionLength);
-
- /***
- * This method is invoked whenever this option is acknowledged active on
- * the local end (TelnetClient sent a WILL, remote side sent a DO).
- * The method is used to specify a subnegotiation sequence that will be
- * sent by TelnetClient when the option is activated.
- *
- * @return subnegotiation sequence to be sent by TelnetClient. TelnetClient
- * will add IAC SB & IAC SE. null means no subnegotiation.
- ***/
- public abstract int[] startSubnegotiationLocal();
-
- /***
- * This method is invoked whenever this option is acknowledged active on
- * the remote end (TelnetClient sent a DO, remote side sent a WILL).
- * The method is used to specify a subnegotiation sequence that will be
- * sent by TelnetClient when the option is activated.
- *
- * @return subnegotiation sequence to be sent by TelnetClient. TelnetClient
- * will add IAC SB & IAC SE. null means no subnegotiation.
- ***/
- public abstract int[] startSubnegotiationRemote();
-
- /***
- * Returns a boolean indicating whether a WILL request sent to the other
- * side has been acknowledged.
- *
- * @return true if a WILL sent to the other side has been acknowledged.
- ***/
- boolean getWill()
- {
- return willFlag;
- }
-
- /***
- * Tells this option whether a WILL request sent to the other
- * side has been acknowledged (invoked by TelnetClient).
- *
- * @param state - if true, a WILL request has been acknowledged.
- ***/
- void setWill(boolean state)
- {
- willFlag = state;
- }
-
- /***
- * Returns a boolean indicating whether a DO request sent to the other
- * side has been acknowledged.
- *
- * @return true if a DO sent to the other side has been acknowledged.
- ***/
- boolean getDo()
- {
- return doFlag;
- }
-
-
- /***
- * Tells this option whether a DO request sent to the other
- * side has been acknowledged (invoked by TelnetClient).
- *
- * @param state - if true, a DO request has been acknowledged.
- ***/
- void setDo(boolean state)
- {
- doFlag = state;
- }
-}
diff --git a/org/apache/commons/net/telnet/TelnetOutputStream.java b/org/apache/commons/net/telnet/TelnetOutputStream.java
deleted file mode 100644
index fd796d1..0000000
--- a/org/apache/commons/net/telnet/TelnetOutputStream.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/***
- *
- *
- *
- *
- *
- * @author Daniel F. Savarese
- ***/
-
-
-final class TelnetOutputStream extends OutputStream
-{
- private TelnetClient __client;
- private boolean __convertCRtoCRLF = true;
- private boolean __lastWasCR = false;
-
- TelnetOutputStream(TelnetClient client)
- {
- __client = client;
- }
-
-
- /***
- * Writes a byte to the stream.
- *
- * @param ch The byte to write.
- * @exception IOException If an error occurs while writing to the underlying
- * stream.
- ***/
- @Override
- public void write(int ch) throws IOException
- {
-
- synchronized (__client)
- {
- ch &= 0xff;
-
- if (__client._requestedWont(TelnetOption.BINARY))
- {
- if (__lastWasCR)
- {
- if (__convertCRtoCRLF)
- {
- __client._sendByte('\n');
- if (ch == '\n')
- {
- __lastWasCR = false;
- return ;
- }
- }
- else if (ch != '\n')
- __client._sendByte('\0');
- }
-
- __lastWasCR = false;
-
- switch (ch)
- {
- case '\r':
- __client._sendByte('\r');
- __lastWasCR = true;
- break;
- case TelnetCommand.IAC:
- __client._sendByte(TelnetCommand.IAC);
- __client._sendByte(TelnetCommand.IAC);
- break;
- default:
- __client._sendByte(ch);
- break;
- }
- }
- else if (ch == TelnetCommand.IAC)
- {
- __client._sendByte(ch);
- __client._sendByte(TelnetCommand.IAC);
- }
- else
- __client._sendByte(ch);
- }
- }
-
-
- /***
- * Writes a byte array to the stream.
- *
- * @param buffer The byte array to write.
- * @exception IOException If an error occurs while writing to the underlying
- * stream.
- ***/
- @Override
- public void write(byte buffer[]) throws IOException
- {
- write(buffer, 0, buffer.length);
- }
-
-
- /***
- * Writes a number of bytes from a byte array to the stream starting from
- * a given offset.
- *
- * @param buffer The byte array to write.
- * @param offset The offset into the array at which to start copying data.
- * @param length The number of bytes to write.
- * @exception IOException If an error occurs while writing to the underlying
- * stream.
- ***/
- @Override
- public void write(byte buffer[], int offset, int length) throws IOException
- {
- synchronized (__client)
- {
- while (length-- > 0)
- write(buffer[offset++]);
- }
- }
-
- /*** Flushes the stream. ***/
- @Override
- public void flush() throws IOException
- {
- __client._flushOutputStream();
- }
-
- /*** Closes the stream. ***/
- @Override
- public void close() throws IOException
- {
- __client._closeOutputStream();
- }
-}
diff --git a/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java b/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java
deleted file mode 100644
index 0cbe0c0..0000000
--- a/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-/***
- * Implements the telnet terminal type option RFC 1091.
- *
- * @author Bruno D'Avanzo
- ***/
-public class TerminalTypeOptionHandler extends TelnetOptionHandler
-{
- /***
- * Terminal type
- ***/
- private String termType = null;
-
- /***
- * Terminal type option
- ***/
- protected static final int TERMINAL_TYPE = 24;
-
- /***
- * Send (for subnegotiation)
- ***/
- protected static final int TERMINAL_TYPE_SEND = 1;
-
- /***
- * Is (for subnegotiation)
- ***/
- protected static final int TERMINAL_TYPE_IS = 0;
-
- /***
- * Constructor for the TerminalTypeOptionHandler. Allows defining desired
- * initial setting for local/remote activation of this option and
- * behaviour in case a local/remote activation request for this
- * option is received.
- *
- * @param termtype - terminal type that will be negotiated.
- * @param initlocal - if set to true, a WILL is sent upon connection.
- * @param initremote - if set to true, a DO is sent upon connection.
- * @param acceptlocal - if set to true, any DO request is accepted.
- * @param acceptremote - if set to true, any WILL request is accepted.
- ***/
- public TerminalTypeOptionHandler(String termtype,
- boolean initlocal,
- boolean initremote,
- boolean acceptlocal,
- boolean acceptremote)
- {
- super(TelnetOption.TERMINAL_TYPE, initlocal, initremote,
- acceptlocal, acceptremote);
- termType = termtype;
- }
-
- /***
- * Constructor for the TerminalTypeOptionHandler. Initial and accept
- * behaviour flags are set to false
- *
- * @param termtype - terminal type that will be negotiated.
- ***/
- public TerminalTypeOptionHandler(String termtype)
- {
- super(TelnetOption.TERMINAL_TYPE, false, false, false, false);
- termType = termtype;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
- * @param suboptionLength - the length of data in suboption_data
- *
- * @return terminal type information
- ***/
- @Override
- public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
- {
- if ((suboptionData != null) && (suboptionLength > 1)
- && (termType != null))
- {
- if ((suboptionData[0] == TERMINAL_TYPE)
- && (suboptionData[1] == TERMINAL_TYPE_SEND))
- {
- int response[] = new int[termType.length() + 2];
-
- response[0] = TERMINAL_TYPE;
- response[1] = TERMINAL_TYPE_IS;
-
- for (int ii = 0; ii < termType.length(); ii++)
- {
- response[ii + 2] = termType.charAt(ii);
- }
-
- return response;
- }
- }
- return null;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] startSubnegotiationLocal()
- {
- return null;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] startSubnegotiationRemote()
- {
- return null;
- }
-}
diff --git a/org/apache/commons/net/telnet/WindowSizeOptionHandler.java b/org/apache/commons/net/telnet/WindowSizeOptionHandler.java
deleted file mode 100644
index 34bb46f..0000000
--- a/org/apache/commons/net/telnet/WindowSizeOptionHandler.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.telnet;
-
-/***
- * Implements the telnet window size option RFC 1073.
- *
- * @author Yuval Kashtan
- * @version $Id: WindowSizeOptionHandler.java 658520 2008-05-21 01:14:11Z sebb $
- * @since 2.0
- ***/
-public class WindowSizeOptionHandler extends TelnetOptionHandler
-{
- /***
- * Horizontal Size
- ***/
- private int m_nWidth = 80;
-
- /***
- * Vertical Size
- ***/
- private int m_nHeight = 24;
-
- /***
- * Window size option
- ***/
- protected static final int WINDOW_SIZE = 31;
-
- /***
- * Constructor for the WindowSizeOptionHandler. Allows defining desired
- * initial setting for local/remote activation of this option and
- * behaviour in case a local/remote activation request for this
- * option is received.
- *
- * @param nWidth - Window width.
- * @param nHeight - Window Height
- * @param initlocal - if set to true, a WILL is sent upon connection.
- * @param initremote - if set to true, a DO is sent upon connection.
- * @param acceptlocal - if set to true, any DO request is accepted.
- * @param acceptremote - if set to true, any WILL request is accepted.
- ***/
- public WindowSizeOptionHandler(
- int nWidth,
- int nHeight,
- boolean initlocal,
- boolean initremote,
- boolean acceptlocal,
- boolean acceptremote
- ) {
- super (
- TelnetOption.WINDOW_SIZE,
- initlocal,
- initremote,
- acceptlocal,
- acceptremote
- );
-
- m_nWidth = nWidth;
- m_nHeight = nHeight;
- }
-
- /***
- * Constructor for the WindowSizeOptionHandler. Initial and accept
- * behaviour flags are set to false
- *
- * @param nWidth - Window width.
- * @param nHeight - Window Height
- ***/
- public WindowSizeOptionHandler(
- int nWidth,
- int nHeight
- ) {
- super (
- TelnetOption.WINDOW_SIZE,
- false,
- false,
- false,
- false
- );
-
- m_nWidth = nWidth;
- m_nHeight = nHeight;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
- * @param suboptionLength - the length of data in suboption_data
- *
- * @return terminal type information
- ***/
- @Override
- public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
- {
- return null;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- * This will send the client Height and Width to the server.
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] startSubnegotiationLocal()
- {
- int nCompoundWindowSize = m_nWidth * 0x10000 + m_nHeight;
- int nResponseSize = 5;
- int nIndex;
- int nShift;
- int nTurnedOnBits;
-
- if ((m_nWidth % 0x100) == 0xFF) {
- nResponseSize += 1;
- }
-
- if ((m_nWidth / 0x100) == 0xFF) {
- nResponseSize += 1;
- }
-
- if ((m_nHeight % 0x100) == 0xFF) {
- nResponseSize += 1;
- }
-
- if ((m_nHeight / 0x100) == 0xFF) {
- nResponseSize += 1;
- }
-
- //
- // allocate response array
- //
- int response[] = new int[nResponseSize];
-
- //
- // Build response array.
- // ---------------------
- // 1. put option name.
- // 2. loop through Window size and fill the values,
- // 3. duplicate 'ff' if needed.
- //
-
- response[0] = WINDOW_SIZE; // 1 //
-
- for ( // 2 //
- nIndex=1, nShift = 24;
- nIndex < nResponseSize;
- nIndex++, nShift -=8
- ) {
- nTurnedOnBits = 0xFF;
- nTurnedOnBits <<= nShift;
- response[nIndex] = (nCompoundWindowSize & nTurnedOnBits) >>> nShift;
-
- if (response[nIndex] == 0xff) { // 3 //
- nIndex++;
- response[nIndex] = 0xff;
- }
- }
-
- return response;
- }
-
- /***
- * Implements the abstract method of TelnetOptionHandler.
- *
- * @return always null (no response to subnegotiation)
- ***/
- @Override
- public int[] startSubnegotiationRemote()
- {
- return null;
- }
-}
diff --git a/org/apache/commons/net/tftp/TFTP.java b/org/apache/commons/net/tftp/TFTP.java
deleted file mode 100644
index 662da11..0000000
--- a/org/apache/commons/net/tftp/TFTP.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.tftp;
-
-import java.io.IOException;
-import java.io.InterruptedIOException;
-import java.net.DatagramPacket;
-import java.net.SocketException;
-
-import org.apache.commons.net.DatagramSocketClient;
-
-/***
- * The TFTP class exposes a set of methods to allow you to deal with the TFTP
- * protocol directly, in case you want to write your own TFTP client or
- * server. However, almost every user should only be concerend with
- * the {@link org.apache.commons.net.DatagramSocketClient#open open() },
- * and {@link org.apache.commons.net.DatagramSocketClient#close close() },
- * methods. Additionally,the a
- * {@link org.apache.commons.net.DatagramSocketClient#setDefaultTimeout setDefaultTimeout() }
- * method may be of importance for performance tuning.
- *
- * Details regarding the TFTP protocol and the format of TFTP packets can
- * be found in RFC 783. But the point of these classes is to keep you
- * from having to worry about the internals.
- *
- *
- * @author Daniel F. Savarese
- * @see org.apache.commons.net.DatagramSocketClient
- * @see TFTPPacket
- * @see TFTPPacketException
- * @see TFTPClient
- ***/
-
-public class TFTP extends DatagramSocketClient
-{
- /***
- * The ascii transfer mode. Its value is 0 and equivalent to NETASCII_MODE
- ***/
- public static final int ASCII_MODE = 0;
-
- /***
- * The netascii transfer mode. Its value is 0.
- ***/
- public static final int NETASCII_MODE = 0;
-
- /***
- * The binary transfer mode. Its value is 1 and equivalent to OCTET_MODE.
- ***/
- public static final int BINARY_MODE = 1;
-
- /***
- * The image transfer mode. Its value is 1 and equivalent to OCTET_MODE.
- ***/
- public static final int IMAGE_MODE = 1;
-
- /***
- * The octet transfer mode. Its value is 1.
- ***/
- public static final int OCTET_MODE = 1;
-
- /***
- * The default number of milliseconds to wait to receive a datagram
- * before timing out. The default is 5000 milliseconds (5 seconds).
- ***/
- public static final int DEFAULT_TIMEOUT = 5000;
-
- /***
- * The default TFTP port according to RFC 783 is 69.
- ***/
- public static final int DEFAULT_PORT = 69;
-
- /***
- * The size to use for TFTP packet buffers. Its 4 plus the
- * TFTPPacket.SEGMENT_SIZE, i.e. 516.
- ***/
- static final int PACKET_SIZE = TFTPPacket.SEGMENT_SIZE + 4;
-
- /*** A buffer used to accelerate receives in bufferedReceive() ***/
- private byte[] __receiveBuffer;
-
- /*** A datagram used to minimize memory allocation in bufferedReceive() ***/
- private DatagramPacket __receiveDatagram;
-
- /*** A datagram used to minimize memory allocation in bufferedSend() ***/
- private DatagramPacket __sendDatagram;
-
- /***
- * A buffer used to accelerate sends in bufferedSend().
- * It is left package visible so that TFTPClient may be slightly more
- * efficient during file sends. It saves the creation of an
- * additional buffer and prevents a buffer copy in _newDataPcket().
- ***/
- byte[] _sendBuffer;
-
-
- /***
- * Returns the TFTP string representation of a TFTP transfer mode.
- * Will throw an ArrayIndexOutOfBoundsException if an invalid transfer
- * mode is specified.
- *
- * @param mode The TFTP transfer mode. One of the MODE constants.
- * @return The TFTP string representation of the TFTP transfer mode.
- ***/
- public static final String getModeName(int mode)
- {
- return TFTPRequestPacket._modeStrings[mode];
- }
-
- /***
- * Creates a TFTP instance with a default timeout of DEFAULT_TIMEOUT,
- * a null socket, and buffered operations disabled.
- ***/
- public TFTP()
- {
- setDefaultTimeout(DEFAULT_TIMEOUT);
- __receiveBuffer = null;
- __receiveDatagram = null;
- }
-
- /***
- * This method synchronizes a connection by discarding all packets that
- * may be in the local socket buffer. This method need only be called
- * when you implement your own TFTP client or server.
- *
- * @exception IOException if an I/O error occurs.
- ***/
- public final void discardPackets() throws IOException
- {
- int to;
- DatagramPacket datagram;
-
- datagram = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE);
-
- to = getSoTimeout();
- setSoTimeout(1);
-
- try
- {
- while (true)
- _socket_.receive(datagram);
- }
- catch (SocketException e)
- {
- // Do nothing. We timed out so we hope we're caught up.
- }
- catch (InterruptedIOException e)
- {
- // Do nothing. We timed out so we hope we're caught up.
- }
-
- setSoTimeout(to);
- }
-
-
- /***
- * This is a special method to perform a more efficient packet receive.
- * It should only be used after calling
- * {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps()
- * initializes a set of buffers used internally that prevent the new
- * allocation of a DatagramPacket and byte array for each send and receive.
- * To use these buffers you must call the bufferedReceive() and
- * bufferedSend() methods instead of send() and receive(). You must
- * also be certain that you don't manipulate the resulting packet in
- * such a way that it interferes with future buffered operations.
- * For example, a TFTPDataPacket received with bufferedReceive() will
- * have a reference to the internal byte buffer. You must finish using
- * this data before calling bufferedReceive() again, or else the data
- * will be overwritten by the the call.
- *
- * @return The TFTPPacket received.
- * @exception InterruptedIOException If a socket timeout occurs. The
- * Java documentation claims an InterruptedIOException is thrown
- * on a DatagramSocket timeout, but in practice we find a
- * SocketException is thrown. You should catch both to be safe.
- * @exception SocketException If a socket timeout occurs. The
- * Java documentation claims an InterruptedIOException is thrown
- * on a DatagramSocket timeout, but in practice we find a
- * SocketException is thrown. You should catch both to be safe.
- * @exception IOException If some other I/O error occurs.
- * @exception TFTPPacketException If an invalid TFTP packet is received.
- ***/
- public final TFTPPacket bufferedReceive() throws IOException,
- InterruptedIOException, SocketException, TFTPPacketException
- {
- __receiveDatagram.setData(__receiveBuffer);
- __receiveDatagram.setLength(__receiveBuffer.length);
- _socket_.receive(__receiveDatagram);
-
- return TFTPPacket.newTFTPPacket(__receiveDatagram);
- }
-
- /***
- * This is a special method to perform a more efficient packet send.
- * It should only be used after calling
- * {@link #beginBufferedOps beginBufferedOps() }. beginBufferedOps()
- * initializes a set of buffers used internally that prevent the new
- * allocation of a DatagramPacket and byte array for each send and receive.
- * To use these buffers you must call the bufferedReceive() and
- * bufferedSend() methods instead of send() and receive(). You must
- * also be certain that you don't manipulate the resulting packet in
- * such a way that it interferes with future buffered operations.
- * For example, a TFTPDataPacket received with bufferedReceive() will
- * have a reference to the internal byte buffer. You must finish using
- * this data before calling bufferedReceive() again, or else the data
- * will be overwritten by the the call.
- *
- * @param packet The TFTP packet to send.
- * @exception IOException If some I/O error occurs.
- ***/
- public final void bufferedSend(TFTPPacket packet) throws IOException
- {
- _socket_.send(packet._newDatagram(__sendDatagram, _sendBuffer));
- }
-
-
- /***
- * Initializes the internal buffers. Buffers are used by
- * {@link #bufferedSend bufferedSend() } and
- * {@link #bufferedReceive bufferedReceive() }. This
- * method must be called before calling either one of those two
- * methods. When you finish using buffered operations, you must
- * call {@link #endBufferedOps endBufferedOps() }.
- ***/
- public final void beginBufferedOps()
- {
- __receiveBuffer = new byte[PACKET_SIZE];
- __receiveDatagram =
- new DatagramPacket(__receiveBuffer, __receiveBuffer.length);
- _sendBuffer = new byte[PACKET_SIZE];
- __sendDatagram =
- new DatagramPacket(_sendBuffer, _sendBuffer.length);
- }
-
- /***
- * Releases the resources used to perform buffered sends and receives.
- ***/
- public final void endBufferedOps()
- {
- __receiveBuffer = null;
- __receiveDatagram = null;
- _sendBuffer = null;
- __sendDatagram = null;
- }
-
-
- /***
- * Sends a TFTP packet to its destination.
- *
- * @param packet The TFTP packet to send.
- * @exception IOException If some I/O error occurs.
- ***/
- public final void send(TFTPPacket packet) throws IOException
- {
- _socket_.send(packet.newDatagram());
- }
-
-
- /***
- * Receives a TFTPPacket.
- *
- * @return The TFTPPacket received.
- * @exception InterruptedIOException If a socket timeout occurs. The
- * Java documentation claims an InterruptedIOException is thrown
- * on a DatagramSocket timeout, but in practice we find a
- * SocketException is thrown. You should catch both to be safe.
- * @exception SocketException If a socket timeout occurs. The
- * Java documentation claims an InterruptedIOException is thrown
- * on a DatagramSocket timeout, but in practice we find a
- * SocketException is thrown. You should catch both to be safe.
- * @exception IOException If some other I/O error occurs.
- * @exception TFTPPacketException If an invalid TFTP packet is received.
- ***/
- public final TFTPPacket receive() throws IOException, InterruptedIOException,
- SocketException, TFTPPacketException
- {
- DatagramPacket packet;
-
- packet = new DatagramPacket(new byte[PACKET_SIZE], PACKET_SIZE);
-
- _socket_.receive(packet);
-
- return TFTPPacket.newTFTPPacket(packet);
- }
-
-
-}
diff --git a/org/apache/commons/net/tftp/TFTPAckPacket.java b/org/apache/commons/net/tftp/TFTPAckPacket.java
deleted file mode 100644
index a0fe7f9..0000000
--- a/org/apache/commons/net/tftp/TFTPAckPacket.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.tftp;
-
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-/***
- * A final class derived from TFTPPacket definiing the TFTP Acknowledgement
- * packet type.
- *
- * Details regarding the TFTP protocol and the format of TFTP packets can
- * be found in RFC 783. But the point of these classes is to keep you
- * from having to worry about the internals. Additionally, only very
- * few people should have to care about any of the TFTPPacket classes
- * or derived classes. Almost all users should only be concerned with the
- * {@link org.apache.commons.net.tftp.TFTPClient} class
- * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
- * and
- * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
- * methods.
- *
- *
- * @author Daniel F. Savarese
- * @see TFTPPacket
- * @see TFTPPacketException
- * @see TFTP
- ***/
-
-public final class TFTPAckPacket extends TFTPPacket
-{
- /*** The block number being acknowledged by the packet. ***/
- int _blockNumber;
-
- /***
- * Creates an acknowledgment packet to be sent to a host at a given port
- * acknowledging receipt of a block.
- *
- * @param destination The host to which the packet is going to be sent.
- * @param port The port to which the packet is going to be sent.
- * @param blockNumber The block number being acknowledged.
- ***/
- public TFTPAckPacket(InetAddress destination, int port, int blockNumber)
- {
- super(TFTPPacket.ACKNOWLEDGEMENT, destination, port);
- _blockNumber = blockNumber;
- }
-
- /***
- * Creates an acknowledgement packet based from a received
- * datagram. Assumes the datagram is at least length 4, else an
- * ArrayIndexOutOfBoundsException may be thrown.
- *
- * @param datagram The datagram containing the received acknowledgement.
- * @throws TFTPPacketException If the datagram isn't a valid TFTP
- * acknowledgement packet.
- ***/
- TFTPAckPacket(DatagramPacket datagram) throws TFTPPacketException
- {
- super(TFTPPacket.ACKNOWLEDGEMENT, datagram.getAddress(),
- datagram.getPort());
- byte[] data;
-
- data = datagram.getData();
-
- if (getType() != data[1])
- throw new TFTPPacketException("TFTP operator code does not match type.");
-
- _blockNumber = (((data[2] & 0xff) << 8) | (data[3] & 0xff));
- }
-
- /***
- * This is a method only available within the package for
- * implementing efficient datagram transport by elminating buffering.
- * It takes a datagram as an argument, and a byte buffer in which
- * to store the raw datagram data. Inside the method, the data
- * is set as the datagram's data and the datagram returned.
- *
- * @param datagram The datagram to create.
- * @param data The buffer to store the packet and to use in the datagram.
- * @return The datagram argument.
- ***/
- @Override
- DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data)
- {
- data[0] = 0;
- data[1] = (byte)_type;
- data[2] = (byte)((_blockNumber & 0xffff) >> 8);
- data[3] = (byte)(_blockNumber & 0xff);
-
- datagram.setAddress(_address);
- datagram.setPort(_port);
- datagram.setData(data);
- datagram.setLength(4);
-
- return datagram;
- }
-
-
- /***
- * Creates a UDP datagram containing all the TFTP
- * acknowledgement packet data in the proper format.
- * This is a method exposed to the programmer in case he
- * wants to implement his own TFTP client instead of using
- * the {@link org.apache.commons.net.tftp.TFTPClient}
- * class. Under normal circumstances, you should not have a need to call this
- * method.
- *
- * @return A UDP datagram containing the TFTP acknowledgement packet.
- ***/
- @Override
- public DatagramPacket newDatagram()
- {
- byte[] data;
-
- data = new byte[4];
- data[0] = 0;
- data[1] = (byte)_type;
- data[2] = (byte)((_blockNumber & 0xffff) >> 8);
- data[3] = (byte)(_blockNumber & 0xff);
-
- return new DatagramPacket(data, data.length, _address, _port);
- }
-
-
- /***
- * Returns the block number of the acknowledgement.
- *
- * @return The block number of the acknowledgement.
- ***/
- public int getBlockNumber()
- {
- return _blockNumber;
- }
-
-
- /*** Sets the block number of the acknowledgement. ***/
- public void setBlockNumber(int blockNumber)
- {
- _blockNumber = blockNumber;
- }
-}
-
diff --git a/org/apache/commons/net/tftp/TFTPClient.java b/org/apache/commons/net/tftp/TFTPClient.java
deleted file mode 100644
index 71d4ec6..0000000
--- a/org/apache/commons/net/tftp/TFTPClient.java
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.tftp;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import org.apache.commons.net.io.FromNetASCIIOutputStream;
-import org.apache.commons.net.io.ToNetASCIIInputStream;
-
-/***
- * The TFTPClient class encapsulates all the aspects of the TFTP protocol
- * necessary to receive and send files through TFTP. It is derived from
- * the {@link org.apache.commons.net.tftp.TFTP} because
- * it is more convenient than using aggregation, and as a result exposes
- * the same set of methods to allow you to deal with the TFTP protocol
- * directly. However, almost every user should only be concerend with the
- * the {@link org.apache.commons.net.DatagramSocketClient#open open() },
- * {@link org.apache.commons.net.DatagramSocketClient#close close() },
- * {@link #sendFile sendFile() }, and
- * {@link #receiveFile receiveFile() } methods. Additionally, the
- * {@link #setMaxTimeouts setMaxTimeouts() } and
- * {@link org.apache.commons.net.DatagramSocketClient#setDefaultTimeout setDefaultTimeout() }
- * methods may be of importance for performance
- * tuning.
- *
- * Details regarding the TFTP protocol and the format of TFTP packets can
- * be found in RFC 783. But the point of these classes is to keep you
- * from having to worry about the internals.
- *
- *
- * @author Daniel F. Savarese
- * @see TFTP
- * @see TFTPPacket
- * @see TFTPPacketException
- ***/
-
-public class TFTPClient extends TFTP
-{
- /***
- * The default number of times a receive attempt is allowed to timeout
- * before ending attempts to retry the receive and failing. The default
- * is 5 timeouts.
- ***/
- public static final int DEFAULT_MAX_TIMEOUTS = 5;
-
- /*** The maximum number of timeouts allowed before failing. ***/
- private int __maxTimeouts;
-
- /***
- * Creates a TFTPClient instance with a default timeout of DEFAULT_TIMEOUT,
- * maximum timeouts value of DEFAULT_MAX_TIMEOUTS, a null socket,
- * and buffered operations disabled.
- ***/
- public TFTPClient()
- {
- __maxTimeouts = DEFAULT_MAX_TIMEOUTS;
- }
-
- /***
- * Sets the maximum number of times a receive attempt is allowed to
- * timeout during a receiveFile() or sendFile() operation before ending
- * attempts to retry the receive and failing.
- * The default is DEFAULT_MAX_TIMEOUTS.
- *
- * @param numTimeouts The maximum number of timeouts to allow. Values
- * less than 1 should not be used, but if they are, they are
- * treated as 1.
- ***/
- public void setMaxTimeouts(int numTimeouts)
- {
- if (numTimeouts < 1)
- __maxTimeouts = 1;
- else
- __maxTimeouts = numTimeouts;
- }
-
- /***
- * Returns the maximum number of times a receive attempt is allowed to
- * timeout before ending attempts to retry the receive and failing.
- *
- * @return The maximum number of timeouts allowed.
- ***/
- public int getMaxTimeouts()
- {
- return __maxTimeouts;
- }
-
-
- /***
- * Requests a named file from a remote host, writes the
- * file to an OutputStream, closes the connection, and returns the number
- * of bytes read. A local UDP socket must first be created by
- * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
- * invoking this method. This method will not close the OutputStream
- * containing the file; you must close it after the method invocation.
- *
- * @param filename The name of the file to receive.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param output The OutputStream to which the file should be written.
- * @param host The remote host serving the file.
- * @param port The port number of the remote TFTP server.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- ***/
- public int receiveFile(String filename, int mode, OutputStream output,
- InetAddress host, int port) throws IOException
- {
- int bytesRead, timeouts, lastBlock, block, hostPort, dataLength;
- TFTPPacket sent, received = null;
- TFTPErrorPacket error;
- TFTPDataPacket data;
- TFTPAckPacket ack = new TFTPAckPacket(host, port, 0);
-
- beginBufferedOps();
-
- dataLength = lastBlock = hostPort = bytesRead = 0;
- block = 1;
-
- if (mode == TFTP.ASCII_MODE)
- output = new FromNetASCIIOutputStream(output);
-
- sent =
- new TFTPReadRequestPacket(host, port, filename, mode);
-
-_sendPacket:
- do
- {
- bufferedSend(sent);
-
-_receivePacket:
- while (true)
- {
- timeouts = 0;
- while (timeouts < __maxTimeouts)
- {
- try
- {
- received = bufferedReceive();
- break;
- }
- catch (SocketException e)
- {
- if (++timeouts >= __maxTimeouts)
- {
- endBufferedOps();
- throw new IOException("Connection timed out.");
- }
- continue;
- }
- catch (InterruptedIOException e)
- {
- if (++timeouts >= __maxTimeouts)
- {
- endBufferedOps();
- throw new IOException("Connection timed out.");
- }
- continue;
- }
- catch (TFTPPacketException e)
- {
- endBufferedOps();
- throw new IOException("Bad packet: " + e.getMessage());
- }
- }
-
- // The first time we receive we get the port number and
- // answering host address (for hosts with multiple IPs)
- if (lastBlock == 0)
- {
- hostPort = received.getPort();
- ack.setPort(hostPort);
- if(!host.equals(received.getAddress()))
- {
- host = received.getAddress();
- ack.setAddress(host);
- sent.setAddress(host);
- }
- }
-
- // Comply with RFC 783 indication that an error acknowledgement
- // should be sent to originator if unexpected TID or host.
- if (host.equals(received.getAddress()) &&
- received.getPort() == hostPort)
- {
-
- switch (received.getType())
- {
- case TFTPPacket.ERROR:
- error = (TFTPErrorPacket)received;
- endBufferedOps();
- throw new IOException("Error code " + error.getError() +
- " received: " + error.getMessage());
- case TFTPPacket.DATA:
- data = (TFTPDataPacket)received;
- dataLength = data.getDataLength();
-
- lastBlock = data.getBlockNumber();
-
- if (lastBlock == block)
- {
- try
- {
- output.write(data.getData(), data.getDataOffset(),
- dataLength);
- }
- catch (IOException e)
- {
- error = new TFTPErrorPacket(host, hostPort,
- TFTPErrorPacket.OUT_OF_SPACE,
- "File write failed.");
- bufferedSend(error);
- endBufferedOps();
- throw e;
- }
- ++block;
- if (block > 65535)
- {
- // wrap the block number
- block = 0;
- }
-
- break _receivePacket;
- }
- else
- {
- discardPackets();
-
- if (lastBlock == (block == 0 ? 65535 : (block - 1)))
- continue _sendPacket; // Resend last acknowledgement.
-
- continue _receivePacket; // Start fetching packets again.
- }
- //break;
-
- default:
- endBufferedOps();
- throw new IOException("Received unexpected packet type.");
- }
- }
- else
- {
- error = new TFTPErrorPacket(received.getAddress(),
- received.getPort(),
- TFTPErrorPacket.UNKNOWN_TID,
- "Unexpected host or port.");
- bufferedSend(error);
- continue _sendPacket;
- }
-
- // We should never get here, but this is a safety to avoid
- // infinite loop. If only Java had the goto statement.
- //break;
- }
-
- ack.setBlockNumber(lastBlock);
- sent = ack;
- bytesRead += dataLength;
- } // First data packet less than 512 bytes signals end of stream.
-
- while (dataLength == TFTPPacket.SEGMENT_SIZE);
-
- bufferedSend(sent);
- endBufferedOps();
-
- return bytesRead;
- }
-
-
- /***
- * Requests a named file from a remote host, writes the
- * file to an OutputStream, closes the connection, and returns the number
- * of bytes read. A local UDP socket must first be created by
- * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
- * invoking this method. This method will not close the OutputStream
- * containing the file; you must close it after the method invocation.
- *
- * @param filename The name of the file to receive.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param output The OutputStream to which the file should be written.
- * @param hostname The name of the remote host serving the file.
- * @param port The port number of the remote TFTP server.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- public int receiveFile(String filename, int mode, OutputStream output,
- String hostname, int port)
- throws UnknownHostException, IOException
- {
- return receiveFile(filename, mode, output, InetAddress.getByName(hostname),
- port);
- }
-
-
- /***
- * Same as calling receiveFile(filename, mode, output, host, TFTP.DEFAULT_PORT).
- *
- * @param filename The name of the file to receive.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param output The OutputStream to which the file should be written.
- * @param host The remote host serving the file.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- ***/
- public int receiveFile(String filename, int mode, OutputStream output,
- InetAddress host)
- throws IOException
- {
- return receiveFile(filename, mode, output, host, DEFAULT_PORT);
- }
-
- /***
- * Same as calling receiveFile(filename, mode, output, hostname, TFTP.DEFAULT_PORT).
- *
- * @param filename The name of the file to receive.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param output The OutputStream to which the file should be written.
- * @param hostname The name of the remote host serving the file.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- public int receiveFile(String filename, int mode, OutputStream output,
- String hostname)
- throws UnknownHostException, IOException
- {
- return receiveFile(filename, mode, output, InetAddress.getByName(hostname),
- DEFAULT_PORT);
- }
-
-
- /***
- * Requests to send a file to a remote host, reads the file from an
- * InputStream, sends the file to the remote host, and closes the
- * connection. A local UDP socket must first be created by
- * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
- * invoking this method. This method will not close the InputStream
- * containing the file; you must close it after the method invocation.
- *
- * @param filename The name the remote server should use when creating
- * the file on its file system.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param host The remote host receiving the file.
- * @param port The port number of the remote TFTP server.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- ***/
- public void sendFile(String filename, int mode, InputStream input,
- InetAddress host, int port) throws IOException
- {
- int bytesRead, timeouts, lastBlock, block, hostPort, dataLength, offset, totalThisPacket;
- TFTPPacket sent, received = null;
- TFTPErrorPacket error;
- TFTPDataPacket data =
- new TFTPDataPacket(host, port, 0, _sendBuffer, 4, 0);
- TFTPAckPacket ack;
-
- boolean justStarted = true;
-
- beginBufferedOps();
-
- dataLength = lastBlock = hostPort = bytesRead = totalThisPacket = 0;
- block = 0;
- boolean lastAckWait = false;
-
- if (mode == TFTP.ASCII_MODE)
- input = new ToNetASCIIInputStream(input);
-
- sent =
- new TFTPWriteRequestPacket(host, port, filename, mode);
-
-_sendPacket:
- do
- {
- // first time: block is 0, lastBlock is 0, send a request packet.
- // subsequent: block is integer starting at 1, send data packet.
- bufferedSend(sent);
-
- // this is trying to receive an ACK
-_receivePacket:
- while (true)
- {
-
-
- timeouts = 0;
- while (timeouts < __maxTimeouts)
- {
- try
- {
- received = bufferedReceive();
- break;
- }
- catch (SocketException e)
- {
- if (++timeouts >= __maxTimeouts)
- {
- endBufferedOps();
- throw new IOException("Connection timed out.");
- }
- continue;
- }
- catch (InterruptedIOException e)
- {
- if (++timeouts >= __maxTimeouts)
- {
- endBufferedOps();
- throw new IOException("Connection timed out.");
- }
- continue;
- }
- catch (TFTPPacketException e)
- {
- endBufferedOps();
- throw new IOException("Bad packet: " + e.getMessage());
- }
- } // end of while loop over tries to receive
-
- // The first time we receive we get the port number and
- // answering host address (for hosts with multiple IPs)
- if (justStarted)
- {
- justStarted = false;
- hostPort = received.getPort();
- data.setPort(hostPort);
- if(!host.equals(received.getAddress()))
- {
- host = received.getAddress();
- data.setAddress(host);
- sent.setAddress(host);
- }
- }
-
- // Comply with RFC 783 indication that an error acknowledgement
- // should be sent to originator if unexpected TID or host.
- if (host.equals(received.getAddress()) &&
- received.getPort() == hostPort)
- {
-
- switch (received.getType())
- {
- case TFTPPacket.ERROR:
- error = (TFTPErrorPacket)received;
- endBufferedOps();
- throw new IOException("Error code " + error.getError() +
- " received: " + error.getMessage());
- case TFTPPacket.ACKNOWLEDGEMENT:
- ack = (TFTPAckPacket)received;
-
- lastBlock = ack.getBlockNumber();
-
- if (lastBlock == block)
- {
- ++block;
- if (block > 65535)
- {
- // wrap the block number
- block = 0;
- }
- if (lastAckWait) {
-
- break _sendPacket;
- }
- else {
- break _receivePacket;
- }
- }
- else
- {
- discardPackets();
-
- if (lastBlock == (block == 0 ? 65535 : (block - 1)))
- continue _sendPacket; // Resend last acknowledgement.
-
- continue _receivePacket; // Start fetching packets again.
- }
- //break;
-
- default:
- endBufferedOps();
- throw new IOException("Received unexpected packet type.");
- }
- }
- else
- {
- error = new TFTPErrorPacket(received.getAddress(),
- received.getPort(),
- TFTPErrorPacket.UNKNOWN_TID,
- "Unexpected host or port.");
- bufferedSend(error);
- continue _sendPacket;
- }
-
- // We should never get here, but this is a safety to avoid
- // infinite loop. If only Java had the goto statement.
- //break;
- }
-
- // OK, we have just gotten ACK about the last data we sent. Make another
- // and send it
-
- dataLength = TFTPPacket.SEGMENT_SIZE;
- offset = 4;
- totalThisPacket = 0;
- while (dataLength > 0 &&
- (bytesRead = input.read(_sendBuffer, offset, dataLength)) > 0)
- {
- offset += bytesRead;
- dataLength -= bytesRead;
- totalThisPacket += bytesRead;
- }
-
- if( totalThisPacket < TFTPPacket.SEGMENT_SIZE ) {
- /* this will be our last packet -- send, wait for ack, stop */
- lastAckWait = true;
- }
- data.setBlockNumber(block);
- data.setData(_sendBuffer, 4, totalThisPacket);
- sent = data;
- }
- while ( totalThisPacket > 0 || lastAckWait );
- // Note: this was looping while dataLength == 0 || lastAckWait,
- // which was discarding the last packet if it was not full size
- // Should send the packet.
-
- endBufferedOps();
- }
-
-
- /***
- * Requests to send a file to a remote host, reads the file from an
- * InputStream, sends the file to the remote host, and closes the
- * connection. A local UDP socket must first be created by
- * {@link org.apache.commons.net.DatagramSocketClient#open open()} before
- * invoking this method. This method will not close the InputStream
- * containing the file; you must close it after the method invocation.
- *
- * @param filename The name the remote server should use when creating
- * the file on its file system.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param hostname The name of the remote host receiving the file.
- * @param port The port number of the remote TFTP server.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- public void sendFile(String filename, int mode, InputStream input,
- String hostname, int port)
- throws UnknownHostException, IOException
- {
- sendFile(filename, mode, input, InetAddress.getByName(hostname), port);
- }
-
-
- /***
- * Same as calling sendFile(filename, mode, input, host, TFTP.DEFAULT_PORT).
- *
- * @param filename The name the remote server should use when creating
- * the file on its file system.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param host The name of the remote host receiving the file.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- public void sendFile(String filename, int mode, InputStream input,
- InetAddress host)
- throws IOException
- {
- sendFile(filename, mode, input, host, DEFAULT_PORT);
- }
-
- /***
- * Same as calling sendFile(filename, mode, input, hostname, TFTP.DEFAULT_PORT).
- *
- * @param filename The name the remote server should use when creating
- * the file on its file system.
- * @param mode The TFTP mode of the transfer (one of the MODE constants).
- * @param hostname The name of the remote host receiving the file.
- * @exception IOException If an I/O error occurs. The nature of the
- * error will be reported in the message.
- * @exception UnknownHostException If the hostname cannot be resolved.
- ***/
- public void sendFile(String filename, int mode, InputStream input,
- String hostname)
- throws UnknownHostException, IOException
- {
- sendFile(filename, mode, input, InetAddress.getByName(hostname),
- DEFAULT_PORT);
- }
-}
diff --git a/org/apache/commons/net/tftp/TFTPDataPacket.java b/org/apache/commons/net/tftp/TFTPDataPacket.java
deleted file mode 100644
index 24c0dd3..0000000
--- a/org/apache/commons/net/tftp/TFTPDataPacket.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.tftp;
-
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-/***
- * A final class derived from TFTPPacket definiing the TFTP Data
- * packet type.
- *
- * Details regarding the TFTP protocol and the format of TFTP packets can
- * be found in RFC 783. But the point of these classes is to keep you
- * from having to worry about the internals. Additionally, only very
- * few people should have to care about any of the TFTPPacket classes
- * or derived classes. Almost all users should only be concerned with the
- * {@link org.apache.commons.net.tftp.TFTPClient} class
- * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
- * and
- * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
- * methods.
- *
- *
- * @author Daniel F. Savarese
- * @see TFTPPacket
- * @see TFTPPacketException
- * @see TFTP
- ***/
-
-public final class TFTPDataPacket extends TFTPPacket
-{
- /*** The maximum number of bytes in a TFTP data packet (512) ***/
- public static final int MAX_DATA_LENGTH = 512;
-
- /*** The minimum number of bytes in a TFTP data packet (0) ***/
- public static final int MIN_DATA_LENGTH = 0;
-
- /*** The block number of the packet. ***/
- int _blockNumber;
-
- /*** The length of the data. ***/
- int _length;
-
- /*** The offset into the _data array at which the data begins. ***/
- int _offset;
-
- /*** The data stored in the packet. ***/
- byte[] _data;
-
- /***
- * Creates a data packet to be sent to a host at a given port
- * with a given block number. The actual data to be sent is passed as
- * an array, an offset, and a length. The offset is the offset into
- * the byte array where the data starts. The length is the length of
- * the data. If the length is greater than MAX_DATA_LENGTH, it is
- * truncated.
- *
- * @param destination The host to which the packet is going to be sent.
- * @param port The port to which the packet is going to be sent.
- * @param blockNumber The block number of the data.
- * @param data The byte array containing the data.
- * @param offset The offset into the array where the data starts.
- * @param length The length of the data.
- ***/
- public TFTPDataPacket(InetAddress destination, int port, int blockNumber,
- byte[] data, int offset, int length)
- {
- super(TFTPPacket.DATA, destination, port);
-
- _blockNumber = blockNumber;
- _data = data;
- _offset = offset;
-
- if (length > MAX_DATA_LENGTH)
- _length = MAX_DATA_LENGTH;
- else
- _length = length;
- }
-
- public TFTPDataPacket(InetAddress destination, int port, int blockNumber,
- byte[] data)
- {
- this(destination, port, blockNumber, data, 0, data.length);
- }
-
-
- /***
- * Creates a data packet based from a received
- * datagram. Assumes the datagram is at least length 4, else an
- * ArrayIndexOutOfBoundsException may be thrown.
- *
- * @param datagram The datagram containing the received data.
- * @throws TFTPPacketException If the datagram isn't a valid TFTP
- * data packet.
- ***/
- TFTPDataPacket(DatagramPacket datagram) throws TFTPPacketException
- {
- super(TFTPPacket.DATA, datagram.getAddress(), datagram.getPort());
-
- _data = datagram.getData();
- _offset = 4;
-
- if (getType() != _data[1])
- throw new TFTPPacketException("TFTP operator code does not match type.");
-
- _blockNumber = (((_data[2] & 0xff) << 8) | (_data[3] & 0xff));
-
- _length = datagram.getLength() - 4;
-
- if (_length > MAX_DATA_LENGTH)
- _length = MAX_DATA_LENGTH;
- }
-
- /***
- * This is a method only available within the package for
- * implementing efficient datagram transport by elminating buffering.
- * It takes a datagram as an argument, and a byte buffer in which
- * to store the raw datagram data. Inside the method, the data
- * is set as the datagram's data and the datagram returned.
- *
- * @param datagram The datagram to create.
- * @param data The buffer to store the packet and to use in the datagram.
- * @return The datagram argument.
- ***/
- @Override
- DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data)
- {
- data[0] = 0;
- data[1] = (byte)_type;
- data[2] = (byte)((_blockNumber & 0xffff) >> 8);
- data[3] = (byte)(_blockNumber & 0xff);
-
- // Doublecheck we're not the same
- if (data != _data)
- System.arraycopy(_data, _offset, data, 4, _length);
-
- datagram.setAddress(_address);
- datagram.setPort(_port);
- datagram.setData(data);
- datagram.setLength(_length + 4);
-
- return datagram;
- }
-
- /***
- * Creates a UDP datagram containing all the TFTP
- * data packet data in the proper format.
- * This is a method exposed to the programmer in case he
- * wants to implement his own TFTP client instead of using
- * the {@link org.apache.commons.net.tftp.TFTPClient}
- * class.
- * Under normal circumstances, you should not have a need to call this
- * method.
- *
- * @return A UDP datagram containing the TFTP data packet.
- ***/
- @Override
- public DatagramPacket newDatagram()
- {
- byte[] data;
-
- data = new byte[_length + 4];
- data[0] = 0;
- data[1] = (byte)_type;
- data[2] = (byte)((_blockNumber & 0xffff) >> 8);
- data[3] = (byte)(_blockNumber & 0xff);
-
- System.arraycopy(_data, _offset, data, 4, _length);
-
- return new DatagramPacket(data, _length + 4, _address, _port);
- }
-
- /***
- * Returns the block number of the data packet.
- *
- * @return The block number of the data packet.
- ***/
- public int getBlockNumber()
- {
- return _blockNumber;
- }
-
- /*** Sets the block number of the data packet. ***/
- public void setBlockNumber(int blockNumber)
- {
- _blockNumber = blockNumber;
- }
-
- /***
- * Sets the data for the data packet.
- *
- * @param data The byte array containing the data.
- * @param offset The offset into the array where the data starts.
- * @param length The length of the data.
- ***/
- public void setData(byte[] data, int offset, int length)
- {
- _data = data;
- _offset = offset;
- _length = length;
-
- if (length > MAX_DATA_LENGTH)
- _length = MAX_DATA_LENGTH;
- else
- _length = length;
- }
-
- /***
- * Returns the length of the data part of the data packet.
- *
- * @return The length of the data part of the data packet.
- ***/
- public int getDataLength()
- {
- return _length;
- }
-
- /***
- * Returns the offset into the byte array where the packet data actually
- * starts.
- *
- * @return The offset into the byte array where the packet data actually
- * starts.
- ***/
- public int getDataOffset()
- {
- return _offset;
- }
-
- /***
- * Returns the byte array containing the packet data.
- *
- * @return The byte array containing the packet data.
- ***/
- public byte[] getData()
- {
- return _data;
- }
-}
diff --git a/org/apache/commons/net/tftp/TFTPErrorPacket.java b/org/apache/commons/net/tftp/TFTPErrorPacket.java
deleted file mode 100644
index 2e7aec2..0000000
--- a/org/apache/commons/net/tftp/TFTPErrorPacket.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.tftp;
-
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-/***
- * A final class derived from TFTPPacket definiing the TFTP Error
- * packet type.
- *
- * Details regarding the TFTP protocol and the format of TFTP packets can
- * be found in RFC 783. But the point of these classes is to keep you
- * from having to worry about the internals. Additionally, only very
- * few people should have to care about any of the TFTPPacket classes
- * or derived classes. Almost all users should only be concerned with the
- * {@link org.apache.commons.net.tftp.TFTPClient} class
- * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
- * and
- * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
- * methods.
- *
- *
- * @author Daniel F. Savarese
- * @see TFTPPacket
- * @see TFTPPacketException
- * @see TFTP
- ***/
-
-public final class TFTPErrorPacket extends TFTPPacket
-{
- /*** The undefined error code according to RFC 783, value 0. ***/
- public static final int UNDEFINED = 0;
-
- /*** The file not found error code according to RFC 783, value 1. ***/
- public static final int FILE_NOT_FOUND = 1;
-
- /*** The access violation error code according to RFC 783, value 2. ***/
- public static final int ACCESS_VIOLATION = 2;
-
- /*** The disk full error code according to RFC 783, value 3. ***/
- public static final int OUT_OF_SPACE = 3;
-
- /***
- * The illegal TFTP operation error code according to RFC 783, value 4.
- ***/
- public static final int ILLEGAL_OPERATION = 4;
-
- /*** The unknown transfer id error code according to RFC 783, value 5. ***/
- public static final int UNKNOWN_TID = 5;
-
- /*** The file already exists error code according to RFC 783, value 6. ***/
- public static final int FILE_EXISTS = 6;
-
- /*** The no such user error code according to RFC 783, value 7. ***/
- public static final int NO_SUCH_USER = 7;
-
- /*** The error code of this packet. ***/
- int _error;
-
- /*** The error message of this packet. ***/
- String _message;
-
- /***
- * Creates an error packet to be sent to a host at a given port
- * with an error code and error message.
- *
- * @param destination The host to which the packet is going to be sent.
- * @param port The port to which the packet is going to be sent.
- * @param error The error code of the packet.
- * @param message The error message of the packet.
- ***/
- public TFTPErrorPacket(InetAddress destination, int port,
- int error, String message)
- {
- super(TFTPPacket.ERROR, destination, port);
-
- _error = error;
- _message = message;
- }
-
- /***
- * Creates an error packet based from a received
- * datagram. Assumes the datagram is at least length 4, else an
- * ArrayIndexOutOfBoundsException may be thrown.
- *
- * @param datagram The datagram containing the received error.
- * @throws TFTPPacketException If the datagram isn't a valid TFTP
- * error packet.
- ***/
- TFTPErrorPacket(DatagramPacket datagram) throws TFTPPacketException
- {
- super(TFTPPacket.ERROR, datagram.getAddress(), datagram.getPort());
- int index, length;
- byte[] data;
- StringBuffer buffer;
-
- data = datagram.getData();
- length = datagram.getLength();
-
- if (getType() != data[1])
- throw new TFTPPacketException("TFTP operator code does not match type.");
-
- _error = (((data[2] & 0xff) << 8) | (data[3] & 0xff));
-
- if (length < 5)
- throw new TFTPPacketException("Bad error packet. No message.");
-
- index = 4;
- buffer = new StringBuffer();
-
- while (index < length && data[index] != 0)
- {
- buffer.append((char)data[index]);
- ++index;
- }
-
- _message = buffer.toString();
- }
-
- /***
- * This is a method only available within the package for
- * implementing efficient datagram transport by elminating buffering.
- * It takes a datagram as an argument, and a byte buffer in which
- * to store the raw datagram data. Inside the method, the data
- * is set as the datagram's data and the datagram returned.
- *
- * @param datagram The datagram to create.
- * @param data The buffer to store the packet and to use in the datagram.
- * @return The datagram argument.
- ***/
- @Override
- DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data)
- {
- int length;
-
- length = _message.length();
-
- data[0] = 0;
- data[1] = (byte)_type;
- data[2] = (byte)((_error & 0xffff) >> 8);
- data[3] = (byte)(_error & 0xff);
-
- System.arraycopy(_message.getBytes(), 0, data, 4, length);
-
- data[length + 4] = 0;
-
- datagram.setAddress(_address);
- datagram.setPort(_port);
- datagram.setData(data);
- datagram.setLength(length + 4);
-
- return datagram;
- }
-
-
- /***
- * Creates a UDP datagram containing all the TFTP
- * error packet data in the proper format.
- * This is a method exposed to the programmer in case he
- * wants to implement his own TFTP client instead of using
- * the {@link org.apache.commons.net.tftp.TFTPClient}
- * class.
- * Under normal circumstances, you should not have a need to call this
- * method.
- *
- * @return A UDP datagram containing the TFTP error packet.
- ***/
- @Override
- public DatagramPacket newDatagram()
- {
- byte[] data;
- int length;
-
- length = _message.length();
-
- data = new byte[length + 5];
- data[0] = 0;
- data[1] = (byte)_type;
- data[2] = (byte)((_error & 0xffff) >> 8);
- data[3] = (byte)(_error & 0xff);
-
- System.arraycopy(_message.getBytes(), 0, data, 4, length);
-
- data[length + 4] = 0;
-
- return new DatagramPacket(data, data.length, _address, _port);
- }
-
-
- /***
- * Returns the error code of the packet.
- *
- * @return The error code of the packet.
- ***/
- public int getError()
- {
- return _error;
- }
-
-
- /***
- * Returns the error message of the packet.
- *
- * @return The error message of the packet.
- ***/
- public String getMessage()
- {
- return _message;
- }
-}
diff --git a/org/apache/commons/net/tftp/TFTPPacket.java b/org/apache/commons/net/tftp/TFTPPacket.java
deleted file mode 100644
index e1dc5f1..0000000
--- a/org/apache/commons/net/tftp/TFTPPacket.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.tftp;
-
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-/***
- * TFTPPacket is an abstract class encapsulating the functionality common
- * to the 5 types of TFTP packets. It also provides a static factory
- * method that will create the correct TFTP packet instance from a
- * datagram. This relieves the programmer from having to figure out what
- * kind of TFTP packet is contained in a datagram and create it himself.
- *
- * Details regarding the TFTP protocol and the format of TFTP packets can
- * be found in RFC 783. But the point of these classes is to keep you
- * from having to worry about the internals. Additionally, only very
- * few people should have to care about any of the TFTPPacket classes
- * or derived classes. Almost all users should only be concerned with the
- * {@link org.apache.commons.net.tftp.TFTPClient} class
- * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
- * and
- * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
- * methods.
- *
- *
- * @author Daniel F. Savarese
- * @see TFTPPacketException
- * @see TFTP
- ***/
-
-public abstract class TFTPPacket
-{
- /***
- * The minimum size of a packet. This is 4 bytes. It is enough
- * to store the opcode and blocknumber or other required data
- * depending on the packet type.
- ***/
- static final int MIN_PACKET_SIZE = 4;
-
- /***
- * This is the actual TFTP spec
- * identifier and is equal to 1.
- * Identifier returned by {@link #getType getType()}
- * indicating a read request packet.
- ***/
- public static final int READ_REQUEST = 1;
-
- /***
- * This is the actual TFTP spec
- * identifier and is equal to 2.
- * Identifier returned by {@link #getType getType()}
- * indicating a write request packet.
- ***/
- public static final int WRITE_REQUEST = 2;
-
- /***
- * This is the actual TFTP spec
- * identifier and is equal to 3.
- * Identifier returned by {@link #getType getType()}
- * indicating a data packet.
- ***/
- public static final int DATA = 3;
-
- /***
- * This is the actual TFTP spec
- * identifier and is equal to 4.
- * Identifier returned by {@link #getType getType()}
- * indicating an acknowledgement packet.
- ***/
- public static final int ACKNOWLEDGEMENT = 4;
-
- /***
- * This is the actual TFTP spec
- * identifier and is equal to 5.
- * Identifier returned by {@link #getType getType()}
- * indicating an error packet.
- ***/
- public static final int ERROR = 5;
-
- /***
- * The TFTP data packet maximum segment size in bytes. This is 512
- * and is useful for those familiar with the TFTP protocol who want
- * to use the {@link org.apache.commons.net.tftp.TFTP}
- * class methods to implement their own TFTP servers or clients.
- ***/
- public static final int SEGMENT_SIZE = 512;
-
- /*** The type of packet. ***/
- int _type;
-
- /*** The port the packet came from or is going to. ***/
- int _port;
-
- /*** The host the packet is going to be sent or where it came from. ***/
- InetAddress _address;
-
- /***
- * When you receive a datagram that you expect to be a TFTP packet, you use
- * this factory method to create the proper TFTPPacket object
- * encapsulating the data contained in that datagram. This method is the
- * only way you can instantiate a TFTPPacket derived class from a
- * datagram.
- *
- * @param datagram The datagram containing a TFTP packet.
- * @return The TFTPPacket object corresponding to the datagram.
- * @exception TFTPPacketException If the datagram does not contain a valid
- * TFTP packet.
- ***/
- public final static TFTPPacket newTFTPPacket(DatagramPacket datagram)
- throws TFTPPacketException
- {
- byte[] data;
- TFTPPacket packet = null;
-
- if (datagram.getLength() < MIN_PACKET_SIZE)
- throw new TFTPPacketException(
- "Bad packet. Datagram data length is too short.");
-
- data = datagram.getData();
-
- switch (data[1])
- {
- case READ_REQUEST:
- packet = new TFTPReadRequestPacket(datagram);
- break;
- case WRITE_REQUEST:
- packet = new TFTPWriteRequestPacket(datagram);
- break;
- case DATA:
- packet = new TFTPDataPacket(datagram);
- break;
- case ACKNOWLEDGEMENT:
- packet = new TFTPAckPacket(datagram);
- break;
- case ERROR:
- packet = new TFTPErrorPacket(datagram);
- break;
- default:
- throw new TFTPPacketException(
- "Bad packet. Invalid TFTP operator code.");
- }
-
- return packet;
- }
-
- /***
- * This constructor is not visible outside of the package. It is used
- * by subclasses within the package to initialize base data.
- *
- * @param type The type of the packet.
- * @param address The host the packet came from or is going to be sent.
- * @param port The port the packet came from or is going to be sent.
- **/
- TFTPPacket(int type, InetAddress address, int port)
- {
- _type = type;
- _address = address;
- _port = port;
- }
-
- /***
- * This is an abstract method only available within the package for
- * implementing efficient datagram transport by elminating buffering.
- * It takes a datagram as an argument, and a byte buffer in which
- * to store the raw datagram data. Inside the method, the data
- * should be set as the datagram's data and the datagram returned.
- *
- * @param datagram The datagram to create.
- * @param data The buffer to store the packet and to use in the datagram.
- * @return The datagram argument.
- ***/
- abstract DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data);
-
- /***
- * Creates a UDP datagram containing all the TFTP packet
- * data in the proper format.
- * This is an abstract method, exposed to the programmer in case he
- * wants to implement his own TFTP client instead of using
- * the {@link org.apache.commons.net.tftp.TFTPClient}
- * class.
- * Under normal circumstances, you should not have a need to call this
- * method.
- *
- * @return A UDP datagram containing the TFTP packet.
- ***/
- public abstract DatagramPacket newDatagram();
-
- /***
- * Returns the type of the packet.
- *
- * @return The type of the packet.
- ***/
- public final int getType()
- {
- return _type;
- }
-
- /***
- * Returns the address of the host where the packet is going to be sent
- * or where it came from.
- *
- * @return The type of the packet.
- ***/
- public final InetAddress getAddress()
- {
- return _address;
- }
-
- /***
- * Returns the port where the packet is going to be sent
- * or where it came from.
- *
- * @return The port where the packet came from or where it is going.
- ***/
- public final int getPort()
- {
- return _port;
- }
-
- /*** Sets the port where the packet is going to be sent. ***/
- public final void setPort(int port)
- {
- _port = port;
- }
-
- /*** Sets the host address where the packet is going to be sent. ***/
- public final void setAddress(InetAddress address)
- {
- _address = address;
- }
-}
diff --git a/org/apache/commons/net/tftp/TFTPPacketException.java b/org/apache/commons/net/tftp/TFTPPacketException.java
deleted file mode 100644
index 286fa3a..0000000
--- a/org/apache/commons/net/tftp/TFTPPacketException.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.tftp;
-
-/***
- * A class used to signify the occurrence of an error in the creation of
- * a TFTP packet. It is not declared final so that it may be subclassed
- * to identify more specific errors. You would only want to do this if
- * you were building your own TFTP client or server on top of the
- * {@link org.apache.commons.net.tftp.TFTP}
- * class if you
- * wanted more functionality than the
- * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
- * and
- * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
- * methods provide.
- *
- *
- * @author Daniel F. Savarese
- * @see TFTPPacket
- * @see TFTP
- ***/
-
-public class TFTPPacketException extends Exception
-{
-
- /***
- * Simply calls the corresponding constructor of its superclass.
- ***/
- public TFTPPacketException()
- {
- super();
- }
-
- /***
- * Simply calls the corresponding constructor of its superclass.
- ***/
- public TFTPPacketException(String message)
- {
- super(message);
- }
-}
diff --git a/org/apache/commons/net/tftp/TFTPReadRequestPacket.java b/org/apache/commons/net/tftp/TFTPReadRequestPacket.java
deleted file mode 100644
index 2669df6..0000000
--- a/org/apache/commons/net/tftp/TFTPReadRequestPacket.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.tftp;
-
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-/***
- * A class derived from TFTPRequestPacket definiing a TFTP read request
- * packet type.
- *
- * Details regarding the TFTP protocol and the format of TFTP packets can
- * be found in RFC 783. But the point of these classes is to keep you
- * from having to worry about the internals. Additionally, only very
- * few people should have to care about any of the TFTPPacket classes
- * or derived classes. Almost all users should only be concerned with the
- * {@link org.apache.commons.net.tftp.TFTPClient} class
- * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
- * and
- * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
- * methods.
- *
- *
- * @author Daniel F. Savarese
- * @see TFTPPacket
- * @see TFTPRequestPacket
- * @see TFTPPacketException
- * @see TFTP
- ***/
-
-public final class TFTPReadRequestPacket extends TFTPRequestPacket
-{
-
- /***
- * Creates a read request packet to be sent to a host at a
- * given port with a filename and transfer mode request.
- *
- * @param destination The host to which the packet is going to be sent.
- * @param port The port to which the packet is going to be sent.
- * @param filename The requested filename.
- * @param mode The requested transfer mode. This should be on of the TFTP
- * class MODE constants (e.g., TFTP.NETASCII_MODE).
- ***/
- public TFTPReadRequestPacket(InetAddress destination, int port,
- String filename, int mode)
- {
- super(destination, port, TFTPPacket.READ_REQUEST, filename, mode);
- }
-
- /***
- * Creates a read request packet of based on a received
- * datagram and assumes the datagram has already been identified as a
- * read request. Assumes the datagram is at least length 4, else an
- * ArrayIndexOutOfBoundsException may be thrown.
- *
- * @param datagram The datagram containing the received request.
- * @throws TFTPPacketException If the datagram isn't a valid TFTP
- * request packet.
- ***/
- TFTPReadRequestPacket(DatagramPacket datagram) throws TFTPPacketException
- {
- super(TFTPPacket.READ_REQUEST, datagram);
- }
-
-}
diff --git a/org/apache/commons/net/tftp/TFTPRequestPacket.java b/org/apache/commons/net/tftp/TFTPRequestPacket.java
deleted file mode 100644
index a0f4407..0000000
--- a/org/apache/commons/net/tftp/TFTPRequestPacket.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.tftp;
-
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-/***
- * An abstract class derived from TFTPPacket definiing a TFTP Request
- * packet type. It is subclassed by the
- * {@link org.apache.commons.net.tftp.TFTPReadRequestPacket}
- * and
- * {@link org.apache.commons.net.tftp.TFTPWriteRequestPacket}
- * classes.
- *
- * Details regarding the TFTP protocol and the format of TFTP packets can
- * be found in RFC 783. But the point of these classes is to keep you
- * from having to worry about the internals. Additionally, only very
- * few people should have to care about any of the TFTPPacket classes
- * or derived classes. Almost all users should only be concerned with the
- * {@link org.apache.commons.net.tftp.TFTPClient} class
- * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
- * and
- * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
- * methods.
- *
- *
- * @author Daniel F. Savarese
- * @see TFTPPacket
- * @see TFTPReadRequestPacket
- * @see TFTPWriteRequestPacket
- * @see TFTPPacketException
- * @see TFTP
- ***/
-
-public abstract class TFTPRequestPacket extends TFTPPacket
-{
- /***
- * An array containing the string names of the transfer modes and indexed
- * by the transfer mode constants.
- ***/
- static final String[] _modeStrings = { "netascii", "octet" };
-
- /***
- * A null terminated byte array representation of the ascii names of the
- * transfer mode constants. This is convenient for creating the TFTP
- * request packets.
- ***/
- static final byte[] _modeBytes[] = {
- { (byte)'n', (byte)'e', (byte)'t', (byte)'a', (byte)'s', (byte)'c',
- (byte)'i', (byte)'i', 0 },
- { (byte)'o', (byte)'c', (byte)'t', (byte)'e', (byte)'t', 0 }
- };
-
- /*** The transfer mode of the request. ***/
- int _mode;
-
- /*** The filename of the request. ***/
- String _filename;
-
- /***
- * Creates a request packet of a given type to be sent to a host at a
- * given port with a filename and transfer mode request.
- *
- * @param destination The host to which the packet is going to be sent.
- * @param port The port to which the packet is going to be sent.
- * @param type The type of the request (either TFTPPacket.READ_REQUEST or
- * TFTPPacket.WRITE_REQUEST).
- * @param filename The requested filename.
- * @param mode The requested transfer mode. This should be on of the TFTP
- * class MODE constants (e.g., TFTP.NETASCII_MODE).
- ***/
- TFTPRequestPacket(InetAddress destination, int port,
- int type, String filename, int mode)
- {
- super(type, destination, port);
-
- _filename = filename;
- _mode = mode;
- }
-
- /***
- * Creates a request packet of a given type based on a received
- * datagram. Assumes the datagram is at least length 4, else an
- * ArrayIndexOutOfBoundsException may be thrown.
- *
- * @param type The type of the request (either TFTPPacket.READ_REQUEST or
- * TFTPPacket.WRITE_REQUEST).
- * @param datagram The datagram containing the received request.
- * @throws TFTPPacketException If the datagram isn't a valid TFTP
- * request packet of the appropriate type.
- ***/
- TFTPRequestPacket(int type, DatagramPacket datagram)
- throws TFTPPacketException
- {
- super(type, datagram.getAddress(), datagram.getPort());
-
- byte[] data;
- int index, length;
- String mode;
- StringBuffer buffer;
-
- data = datagram.getData();
-
- if (getType() != data[1])
- throw new TFTPPacketException("TFTP operator code does not match type.");
-
- buffer = new StringBuffer();
-
- index = 2;
- length = datagram.getLength();
-
- while (index < length && data[index] != 0)
- {
- buffer.append((char)data[index]);
- ++index;
- }
-
- _filename = buffer.toString();
-
- if (index >= length)
- throw new TFTPPacketException("Bad filename and mode format.");
-
- buffer.setLength(0);
- ++index; // need to advance beyond the end of string marker
- while (index < length && data[index] != 0)
- {
- buffer.append((char)data[index]);
- ++index;
- }
-
- mode = buffer.toString().toLowerCase(java.util.Locale.ENGLISH);
- length = _modeStrings.length;
-
- for (index = 0; index < length; index++)
- {
- if (mode.equals(_modeStrings[index]))
- {
- _mode = index;
- break;
- }
- }
-
- if (index >= length)
- {
- throw new TFTPPacketException("Unrecognized TFTP transfer mode: " + mode);
- // May just want to default to binary mode instead of throwing
- // exception.
- //_mode = TFTP.OCTET_MODE;
- }
- }
-
-
- /***
- * This is a method only available within the package for
- * implementing efficient datagram transport by elminating buffering.
- * It takes a datagram as an argument, and a byte buffer in which
- * to store the raw datagram data. Inside the method, the data
- * is set as the datagram's data and the datagram returned.
- *
- * @param datagram The datagram to create.
- * @param data The buffer to store the packet and to use in the datagram.
- * @return The datagram argument.
- ***/
- @Override
- final DatagramPacket _newDatagram(DatagramPacket datagram, byte[] data)
- {
- int fileLength, modeLength;
-
- fileLength = _filename.length();
- modeLength = _modeBytes[_mode].length;
-
- data[0] = 0;
- data[1] = (byte)_type;
- System.arraycopy(_filename.getBytes(), 0, data, 2, fileLength);
- data[fileLength + 2] = 0;
- System.arraycopy(_modeBytes[_mode], 0, data, fileLength + 3,
- modeLength);
-
- datagram.setAddress(_address);
- datagram.setPort(_port);
- datagram.setData(data);
- datagram.setLength(fileLength + modeLength + 3);
-
- return datagram;
- }
-
- /***
- * Creates a UDP datagram containing all the TFTP
- * request packet data in the proper format.
- * This is a method exposed to the programmer in case he
- * wants to implement his own TFTP client instead of using
- * the {@link org.apache.commons.net.tftp.TFTPClient}
- * class. Under normal circumstances, you should not have a need to call
- * this method.
- *
- * @return A UDP datagram containing the TFTP request packet.
- ***/
- @Override
- public final DatagramPacket newDatagram()
- {
- int fileLength, modeLength;
- byte[] data;
-
- fileLength = _filename.length();
- modeLength = _modeBytes[_mode].length;
-
- data = new byte[fileLength + modeLength + 4];
- data[0] = 0;
- data[1] = (byte)_type;
- System.arraycopy(_filename.getBytes(), 0, data, 2, fileLength);
- data[fileLength + 2] = 0;
- System.arraycopy(_modeBytes[_mode], 0, data, fileLength + 3,
- modeLength);
-
- return new DatagramPacket(data, data.length, _address, _port);
- }
-
- /***
- * Returns the transfer mode of the request.
- *
- * @return The transfer mode of the request.
- ***/
- public final int getMode()
- {
- return _mode;
- }
-
- /***
- * Returns the requested filename.
- *
- * @return The requested filename.
- ***/
- public final String getFilename()
- {
- return _filename;
- }
-}
diff --git a/org/apache/commons/net/tftp/TFTPWriteRequestPacket.java b/org/apache/commons/net/tftp/TFTPWriteRequestPacket.java
deleted file mode 100644
index b545b2d..0000000
--- a/org/apache/commons/net/tftp/TFTPWriteRequestPacket.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.tftp;
-
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-
-/***
- * A class derived from TFTPRequestPacket definiing a TFTP write request
- * packet type.
- *
- * Details regarding the TFTP protocol and the format of TFTP packets can
- * be found in RFC 783. But the point of these classes is to keep you
- * from having to worry about the internals. Additionally, only very
- * few people should have to care about any of the TFTPPacket classes
- * or derived classes. Almost all users should only be concerned with the
- * {@link org.apache.commons.net.tftp.TFTPClient} class
- * {@link org.apache.commons.net.tftp.TFTPClient#receiveFile receiveFile()}
- * and
- * {@link org.apache.commons.net.tftp.TFTPClient#sendFile sendFile()}
- * methods.
- *
- *
- * @author Daniel F. Savarese
- * @see TFTPPacket
- * @see TFTPRequestPacket
- * @see TFTPPacketException
- * @see TFTP
- ***/
-
-public final class TFTPWriteRequestPacket extends TFTPRequestPacket
-{
-
- /***
- * Creates a write request packet to be sent to a host at a
- * given port with a filename and transfer mode request.
- *
- * @param destination The host to which the packet is going to be sent.
- * @param port The port to which the packet is going to be sent.
- * @param filename The requested filename.
- * @param mode The requested transfer mode. This should be on of the TFTP
- * class MODE constants (e.g., TFTP.NETASCII_MODE).
- ***/
- public TFTPWriteRequestPacket(InetAddress destination, int port,
- String filename, int mode)
- {
- super(destination, port, TFTPPacket.WRITE_REQUEST, filename, mode);
- }
-
- /***
- * Creates a write request packet of based on a received
- * datagram and assumes the datagram has already been identified as a
- * write request. Assumes the datagram is at least length 4, else an
- * ArrayIndexOutOfBoundsException may be thrown.
- *
- * @param datagram The datagram containing the received request.
- * @throws TFTPPacketException If the datagram isn't a valid TFTP
- * request packet.
- ***/
- TFTPWriteRequestPacket(DatagramPacket datagram) throws TFTPPacketException
- {
- super(TFTPPacket.WRITE_REQUEST, datagram);
- }
-}
diff --git a/org/apache/commons/net/time/TimeTCPClient.java b/org/apache/commons/net/time/TimeTCPClient.java
deleted file mode 100644
index ad10ba5..0000000
--- a/org/apache/commons/net/time/TimeTCPClient.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.time;
-
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.util.Date;
-
-import org.apache.commons.net.SocketClient;
-
-/***
- * The TimeTCPClient class is a TCP implementation of a client for the
- * Time protocol described in RFC 868. To use the class, merely
- * establish a connection with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * and call either {@link #getTime getTime() } or
- * {@link #getDate getDate() } to retrieve the time, then
- * call {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * to close the connection properly.
- *
- *
- * @author Daniel F. Savarese
- * @see TimeUDPClient
- ***/
-
-public final class TimeTCPClient extends SocketClient
-{
- /*** The default time port. It is set to 37 according to RFC 868. ***/
- public static final int DEFAULT_PORT = 37;
-
- /***
- * The number of seconds between 00:00 1 January 1900 and
- * 00:00 1 January 1970. This value can be useful for converting
- * time values to other formats.
- ***/
- public static final long SECONDS_1900_TO_1970 = 2208988800L;
-
- /***
- * The default TimeTCPClient constructor. It merely sets the default
- * port to
- * The server will have closed the connection at this point, so you should
- * call
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * after calling this method. To retrieve another time, you must
- * initiate another connection with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * before calling
- * @return The time value retrieved from the server.
- * @exception IOException If an error occurs while fetching the time.
- ***/
- public long getTime() throws IOException
- {
- DataInputStream input;
- input = new DataInputStream(_input_);
- return (input.readInt() & 0xffffffffL);
- }
-
- /***
- * Retrieves the time from the server and returns a Java Date
- * containing the time converted to the local timezone.
- *
- * The server will have closed the connection at this point, so you should
- * call
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * after calling this method. To retrieve another time, you must
- * initiate another connection with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * before calling
- * @return A Date value containing the time retrieved from the server
- * converted to the local timezone.
- * @exception IOException If an error occurs while fetching the time.
- ***/
- public Date getDate() throws IOException
- {
- return new Date((getTime() - SECONDS_1900_TO_1970)*1000L);
- }
-
-}
-
diff --git a/org/apache/commons/net/time/TimeUDPClient.java b/org/apache/commons/net/time/TimeUDPClient.java
deleted file mode 100644
index f58d96e..0000000
--- a/org/apache/commons/net/time/TimeUDPClient.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.time;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.InetAddress;
-import java.util.Date;
-
-import org.apache.commons.net.DatagramSocketClient;
-
-/***
- * The TimeUDPClient class is a UDP implementation of a client for the
- * Time protocol described in RFC 868. To use the class, merely
- * open a local datagram socket with
- * {@link org.apache.commons.net.DatagramSocketClient#open open }
- * and call {@link #getTime getTime } or
- * {@link #getTime getDate } to retrieve the time. Then call
- * {@link org.apache.commons.net.DatagramSocketClient#close close }
- * to close the connection properly. Unlike
- * {@link org.apache.commons.net.time.TimeTCPClient},
- * successive calls to {@link #getTime getTime } or
- * {@link #getDate getDate } are permitted
- * without re-establishing a connection. That is because UDP is a
- * connectionless protocol and the Time protocol is stateless.
- *
- *
- * @author Daniel F. Savarese
- * @see TimeTCPClient
- ***/
-
-public final class TimeUDPClient extends DatagramSocketClient
-{
- /*** The default time port. It is set to 37 according to RFC 868. ***/
- public static final int DEFAULT_PORT = 37;
-
- /***
- * The number of seconds between 00:00 1 January 1900 and
- * 00:00 1 January 1970. This value can be useful for converting
- * time values to other formats.
- ***/
- public static final long SECONDS_1900_TO_1970 = 2208988800L;
-
- private byte[] __dummyData = new byte[1];
- private byte[] __timeData = new byte[4];
-
- /***
- * Retrieves the time from the specified server and port and
- * returns it. The time is the number of seconds since
- * 00:00 (midnight) 1 January 1900 GMT, as specified by RFC 868.
- * This method reads the raw 32-bit big-endian
- * unsigned integer from the server, converts it to a Java long, and
- * returns the value.
- *
- * @param host The address of the server.
- * @param port The port of the service.
- * @return The time value retrieved from the server.
- * @exception IOException If an error occurs while retrieving the time.
- ***/
- public long getTime(InetAddress host, int port) throws IOException
- {
- long time;
- DatagramPacket sendPacket, receivePacket;
-
- sendPacket =
- new DatagramPacket(__dummyData, __dummyData.length, host, port);
- receivePacket = new DatagramPacket(__timeData, __timeData.length);
-
- _socket_.send(sendPacket);
- _socket_.receive(receivePacket);
-
- time = 0L;
- time |= (((__timeData[0] & 0xff) << 24) & 0xffffffffL);
- time |= (((__timeData[1] & 0xff) << 16) & 0xffffffffL);
- time |= (((__timeData[2] & 0xff) << 8) & 0xffffffffL);
- time |= ((__timeData[3] & 0xff) & 0xffffffffL);
-
- return time;
- }
-
- /*** Same as
- * @param host The address of the server.
- * @param port The port of the service.
- * @return A Date value containing the time retrieved from the server
- * converted to the local timezone.
- * @exception IOException If an error occurs while fetching the time.
- ***/
- public Date getDate(InetAddress host, int port) throws IOException
- {
- return new Date((getTime(host, port) - SECONDS_1900_TO_1970)*1000L);
- }
-
-
- /*** Same as
- *
- * @author Daniel F. Savarese
- ***/
-
-public final class WhoisClient extends FingerClient
-{
- /***
- * The default whois host to query. It is set to whois.internic.net.
- ***/
- public static final String DEFAULT_HOST = "whois.internic.net";
-
- /***
- * The default whois port. It is set to 43 according to RFC 954.
- ***/
- public static final int DEFAULT_PORT = 43;
-
-
- /***
- * The default whois constructor. Initializes the
- * default port to
- * @param handle The handle to lookup.
- * @return The result of the whois query.
- * @exception IOException If an I/O error occurs during the operation.
- ***/
- public String query(String handle) throws IOException
- {
- return query(false, handle);
- }
-
-
- /***
- * Queries the connected whois server for information regarding
- * the given handle and returns the InputStream of the network connection.
- * It is up to the programmer to be familiar with the handle syntax
- * of the whois server. You must first connect to a finger server before
- * calling this method, and you should disconnect after finishing reading
- * the stream.
- *
- * @param handle The handle to lookup.
- * @return The InputStream of the network connection of the whois query.
- * Can be read to obtain whois results.
- * @exception IOException If an I/O error occurs during the operation.
- ***/
- public InputStream getInputStream(String handle) throws IOException
- {
- return getInputStream(false, handle);
- }
-
-}
-
--
cgit v1.2.3
original
unmodified.
+ */
+ public ListreadNextEntry()
- which handles the issue of
+ * what delimits one entry from another, usually but not always a line
+ * feed and preParse()
- which handles removal of
+ * extraneous matter such as the preliminary lines of a listing, removal
+ * of duplicates on versioning systems, etc.
+ * getNext()
and
+ * getPrevious()
methods to provide "paged" output of less
+ * than the whole list at one time, or by calling the
+ * getFiles()
method to return the entire list.
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPListParseEngine engine = f.initiateListParsing(directory);
+ *
+ * while (engine.hasNext()) {
+ * FTPFile[] files = engine.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ * entries
list.
+ * After this method has completed, entries
will contain a
+ * collection of entries (as defined by
+ * FTPFileEntryParser.readNextEntry()
), but this may contain
+ * various non-entry preliminary lines from the server output, duplicates,
+ * and other data that will not be part of the final listing.
+ *
+ * @param stream The socket stream on which the input will be read.
+ * @param encoding The encoding to use.
+ *
+ * @exception IOException
+ * thrown on any failure to read the stream
+ */
+ private void readStream(InputStream stream, String encoding) throws IOException
+ {
+ BufferedReader reader;
+ if (encoding == null)
+ {
+ reader = new BufferedReader(new InputStreamReader(stream));
+ }
+ else
+ {
+ reader = new BufferedReader(new InputStreamReader(stream, encoding));
+ }
+
+ String line = this.parser.readNextEntry(reader);
+
+ while (line != null)
+ {
+ this.entries.add(line);
+ line = this.parser.readNextEntry(reader);
+ }
+ reader.close();
+ }
+
+ /**
+ * Returns an array of at most quantityRequested
FTPFile
+ * objects starting at this object's internal iterator's current position.
+ * If fewer than quantityRequested
such
+ * elements are available, the returned array will have a length equal
+ * to the number of entries at and after after the current position.
+ * If no such entries are found, this array will have a length of 0.
+ *
+ * After this method is called this object's internal iterator is advanced
+ * by a number of positions equal to the size of the array returned.
+ *
+ * @param quantityRequested
+ * the maximum number of entries we want to get.
+ *
+ * @return an array of at most quantityRequested
FTPFile
+ * objects starting at the current position of this iterator within its
+ * list and at least the number of elements which exist in the list at
+ * and after its current position.
+ * quantityRequested
FTPFile
+ * objects starting at this object's internal iterator's current position,
+ * and working back toward the beginning.
+ *
+ * If fewer than quantityRequested
such
+ * elements are available, the returned array will have a length equal
+ * to the number of entries at and after after the current position.
+ * If no such entries are found, this array will have a length of 0.
+ *
+ * After this method is called this object's internal iterator is moved
+ * back by a number of positions equal to the size of the array returned.
+ *
+ * @param quantityRequested
+ * the maximum number of entries we want to get.
+ *
+ * @return an array of at most quantityRequested
FTPFile
+ * objects starting at the current position of this iterator within its
+ * list and at least the number of elements which exist in the list at
+ * and after its current position. This array will be in the same order
+ * as the underlying list (not reversed).
+ * timestampParser
for extracting the timestamp.
+ * @return a java.util.Calendar
containing results of the
+ * timestamp parse.
+ */
+ public Calendar parseTimestamp(String timestampStr) throws ParseException {
+ return this.timestampParser.parseTimestamp(timestampStr);
+ }
+
+
+ /**
+ * Implementation of the {@link Configurable Configurable}
+ * interface. Configures this parser by delegating to the
+ * underlying Configurable FTPTimestampParser implementation, '
+ * passing it the supplied {@link FTPClientConfig FTPClientConfig}
+ * if that is non-null or a default configuration defined by
+ * each concrete subclass.
+ * key
is not recognized as a fully qualified
+ * classname known to the system, this method will then attempt
+ * to see whether it contains a string identifying one of
+ * the known parsers. This comparison is case-insensitive.
+ * The intent here is where possible, to select as keys strings
+ * which are returned by the SYST command on the systems which
+ * the corresponding parser successfully parses. This enables
+ * this factory to be used in the auto-detection system.
+ *
+ *
+ * @param key should be a fully qualified classname corresponding to
+ * a class implementing the FTPFileEntryParser interface
+ * OR
+ * a string containing (case-insensitively) one of the
+ * following keywords:
+ *
+ *
+ * @return the FTPFileEntryParser corresponding to the supplied key.
+ * @throws ParserInitializationException thrown if for any reason the factory cannot resolve
+ * the supplied key into an FTPFileEntryParser.
+ * @see FTPFileEntryParser
+ */
+ public FTPFileEntryParser createFileEntryParser(String key)
+ {
+ if (key == null)
+ throw new ParserInitializationException("Parser key cannot be null");
+
+ Class> parserClass = null;
+ FTPFileEntryParser parser = null;
+ try
+ {
+ parserClass = Class.forName(key);
+ parser = (FTPFileEntryParser) parserClass.newInstance();
+ }
+ catch (ClassNotFoundException e)
+ {
+ try
+ {
+ String ukey = null;
+ if (null != key)
+ {
+ ukey = key.toUpperCase(java.util.Locale.ENGLISH);
+ }
+ if ((ukey.indexOf(FTPClientConfig.SYST_UNIX) >= 0)
+ || (ukey.indexOf(FTPClientConfig.SYST_L8) >= 0))
+ {
+ parser = createUnixFTPEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_VMS) >= 0)
+ {
+ parser = createVMSVersioningFTPEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_NT) >= 0)
+ {
+ parser = createNTFTPEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_OS2) >= 0)
+ {
+ parser = createOS2FTPEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_OS400) >= 0 ||
+ ukey.indexOf(FTPClientConfig.SYST_AS400) >= 0)
+ {
+ parser = createOS400FTPEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_MVS) >= 0)
+ {
+ parser = createMVSEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_NETWARE) >= 0)
+ {
+ parser = createNetwareFTPEntryParser();
+ }
+ else
+ {
+ throw new ParserInitializationException("Unknown parser type: " + key);
+ }
+ }
+ catch (NoClassDefFoundError nf) {
+ throw new ParserInitializationException("Error initializing parser", nf);
+ }
+
+ }
+ catch (NoClassDefFoundError e)
+ {
+ throw new ParserInitializationException("Error initializing parser", e);
+ }
+ catch (ClassCastException e)
+ {
+ throw new ParserInitializationException(parserClass.getName()
+ + " does not implement the interface "
+ + "org.apache.commons.net.ftp.FTPFileEntryParser.", e);
+ }
+ catch (Throwable e)
+ {
+ throw new ParserInitializationException("Error initializing parser", e);
+ }
+
+ if (parser instanceof Configurable) {
+ ((Configurable)parser).configure(this.config);
+ }
+ return parser;
+ }
+
+ /**
+ * FTPFile
instance. If
+ * the file listing line doesn't describe a file, null
is
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ *
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry)
+ {
+
+ FTPFile file = new FTPFile();
+ file.setRawListing(entry);
+
+ if (matches(entry))
+ {
+ String usr = group(14);
+ String grp = group(15);
+ String filesize = group(16);
+ String mo = group(17);
+ String da = group(18);
+ String yr = group(20);
+ String hr = group(21);
+ String min = group(22);
+ String name = group(23);
+
+ file.setType(FTPFile.FILE_TYPE);
+ file.setUser(usr);
+ file.setGroup(grp);
+ try
+ {
+ file.setSize(Long.parseLong(filesize));
+ }
+ catch (NumberFormatException e)
+ {
+ // intentionally do nothing
+ }
+
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.MILLISECOND, 0);
+ cal.set(Calendar.SECOND,
+ 0);
+ cal.set(Calendar.MINUTE,
+ 0);
+ cal.set(Calendar.HOUR_OF_DAY,
+ 0);
+ try
+ {
+
+ int pos = MONTHS.indexOf(mo);
+ int month = pos / 4;
+ if (yr != null)
+ {
+ // it's a year
+ cal.set(Calendar.YEAR,
+ Integer.parseInt(yr));
+ }
+ else
+ {
+ // it must be hour/minute or we wouldn't have matched
+ int year = cal.get(Calendar.YEAR);
+
+ // if the month we're reading is greater than now, it must
+ // be last year
+ if (cal.get(Calendar.MONTH) < month)
+ {
+ year--;
+ }
+ cal.set(Calendar.YEAR,
+ year);
+ cal.set(Calendar.HOUR_OF_DAY,
+ Integer.parseInt(hr));
+ cal.set(Calendar.MINUTE,
+ Integer.parseInt(min));
+ }
+ cal.set(Calendar.MONTH,
+ month);
+ cal.set(Calendar.DATE,
+ Integer.parseInt(da));
+ file.setTimestamp(cal);
+ }
+ catch (NumberFormatException e)
+ {
+ // do nothing, date will be uninitialized
+ }
+ file.setName(name);
+
+ return file;
+ }
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.class b/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.class
new file mode 100644
index 0000000..f1bdf1b
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.class differ
diff --git a/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java b/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
new file mode 100644
index 0000000..e80ec0d
--- /dev/null
+++ b/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFileEntryParser;
+
+/**
+ * The interface describes a factory for creating FTPFileEntryParsers.
+ * @since 1.2
+ */
+public interface FTPFileEntryParserFactory
+{
+ /**
+ * Implementation should be a method that decodes the
+ * supplied key and creates an object implementing the
+ * interface FTPFileEntryParser.
+ *
+ * @param key A string that somehow identifies an
+ * FTPFileEntryParser to be created.
+ *
+ * @return the FTPFileEntryParser created.
+ * @exception ParserInitializationException
+ * Thrown on any exception in instantiation
+ */
+ public FTPFileEntryParser createFileEntryParser(String key)
+ throws ParserInitializationException;
+
+ /**
+ *java.util.Calendar
object initialized to the date
+ * parsed by the parser
+ * @throws ParseException if none of the parser mechanisms belonging to
+ * the implementor can parse the input.
+ */
+ public Calendar parseTimestamp(String timestampStr) throws ParseException;
+
+}
diff --git a/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.class b/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.class
new file mode 100644
index 0000000..0ae3067
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.class differ
diff --git a/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java b/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
new file mode 100644
index 0000000..02a0cc8
--- /dev/null
+++ b/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
@@ -0,0 +1,301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+
+import java.text.DateFormatSymbols;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.apache.commons.net.ftp.Configurable;
+import org.apache.commons.net.ftp.FTPClientConfig;
+
+/**
+ * Default implementation of the {@link FTPTimestampParser FTPTimestampParser}
+ * interface also implements the {@link org.apache.commons.net.ftp.Configurable Configurable}
+ * interface to allow the parsing to be configured from the outside.
+ *
+ * @see ConfigurableFTPFileEntryParserImpl
+ * @since 1.4
+ */
+public class FTPTimestampParserImpl implements
+ FTPTimestampParser, Configurable
+{
+
+
+ private SimpleDateFormat defaultDateFormat;
+ private SimpleDateFormat recentDateFormat;
+ private boolean lenientFutureDates = false;
+
+
+ /**
+ * The only constructor for this class.
+ */
+ public FTPTimestampParserImpl() {
+ setDefaultDateFormat(DEFAULT_SDF);
+ setRecentDateFormat(DEFAULT_RECENT_SDF);
+ }
+
+ /**
+ * Implements the one {@link FTPTimestampParser#parseTimestamp(String) method}
+ * in the {@link FTPTimestampParser FTPTimestampParser} interface
+ * according to this algorithm:
+ *
+ * If the recentDateFormat member has been defined, try to parse the
+ * supplied string with that. If that parse fails, or if the recentDateFormat
+ * member has not been defined, attempt to parse with the defaultDateFormat
+ * member. If that fails, throw a ParseException.
+ *
+ * This method allows a {@link Calendar} instance to be passed in which represents the
+ * current (system) time.
+ *
+ * @see org.apache.commons.net.ftp.parser.FTPTimestampParser#parseTimestamp(java.lang.String)
+ *
+ * @param timestampStr The timestamp to be parsed
+ */
+ public Calendar parseTimestamp(String timestampStr) throws ParseException {
+ Calendar now = Calendar.getInstance();
+ return parseTimestamp(timestampStr, now);
+ }
+
+ /**
+ * Implements the one {@link FTPTimestampParser#parseTimestamp(String) method}
+ * in the {@link FTPTimestampParser FTPTimestampParser} interface
+ * according to this algorithm:
+ *
+ * If the recentDateFormat member has been defined, try to parse the
+ * supplied string with that. If that parse fails, or if the recentDateFormat
+ * member has not been defined, attempt to parse with the defaultDateFormat
+ * member. If that fails, throw a ParseException.
+ *
+ * @see org.apache.commons.net.ftp.parser.FTPTimestampParser#parseTimestamp(java.lang.String)
+ * @param timestampStr The timestamp to be parsed
+ * @param serverTime The current time for the server
+ * @since 1.5
+ */
+ public Calendar parseTimestamp(String timestampStr, Calendar serverTime) throws ParseException {
+ Calendar now = (Calendar) serverTime.clone();// Copy this, because we may change it
+ now.setTimeZone(this.getServerTimeZone());
+ Calendar working = (Calendar) now.clone();
+ working.setTimeZone(getServerTimeZone());
+ ParsePosition pp = new ParsePosition(0);
+
+ Date parsed = null;
+ if (recentDateFormat != null) {
+ if (lenientFutureDates) {
+ // add a day to "now" so that "slop" doesn't cause a date
+ // slightly in the future to roll back a full year. (Bug 35181)
+ now.add(Calendar.DATE, 1);
+ }
+ parsed = recentDateFormat.parse(timestampStr, pp);
+ }
+ if (parsed != null && pp.getIndex() == timestampStr.length())
+ {
+ working.setTime(parsed);
+ working.set(Calendar.YEAR, now.get(Calendar.YEAR));
+
+ if (working.after(now)) {
+ working.add(Calendar.YEAR, -1);
+ }
+ } else {
+ // Temporarily add the current year to the short date time
+ // to cope with short-date leap year strings.
+ // e.g. Java's DateFormatter will assume that "Feb 29 12:00" refers to
+ // Feb 29 1970 (an invalid date) rather than a potentially valid leap year date.
+ // This is pretty bad hack to work around the deficiencies of the JDK date/time classes.
+ if (recentDateFormat != null) {
+ pp = new ParsePosition(0);
+ int year = now.get(Calendar.YEAR);
+ String timeStampStrPlusYear = timestampStr + " " + year;
+ SimpleDateFormat hackFormatter = new SimpleDateFormat(recentDateFormat.toPattern() + " yyyy",
+ recentDateFormat.getDateFormatSymbols());
+ hackFormatter.setLenient(false);
+ hackFormatter.setTimeZone(recentDateFormat.getTimeZone());
+ parsed = hackFormatter.parse(timeStampStrPlusYear, pp);
+ }
+ if (parsed != null && pp.getIndex() == timestampStr.length() + 5) {
+ working.setTime(parsed);
+ }
+ else {
+ pp = new ParsePosition(0);
+ parsed = defaultDateFormat.parse(timestampStr, pp);
+ // note, length checks are mandatory for us since
+ // SimpleDateFormat methods will succeed if less than
+ // full string is matched. They will also accept,
+ // despite "leniency" setting, a two-digit number as
+ // a valid year (e.g. 22:04 will parse as 22 A.D.)
+ // so could mistakenly confuse an hour with a year,
+ // if we don't insist on full length parsing.
+ if (parsed != null && pp.getIndex() == timestampStr.length()) {
+ working.setTime(parsed);
+ } else {
+ throw new ParseException(
+ "Timestamp could not be parsed with older or recent DateFormat",
+ pp.getIndex());
+ }
+ }
+ }
+ return working;
+ }
+
+ /**
+ * @return Returns the defaultDateFormat.
+ */
+ public SimpleDateFormat getDefaultDateFormat() {
+ return defaultDateFormat;
+ }
+ /**
+ * @return Returns the defaultDateFormat pattern string.
+ */
+ public String getDefaultDateFormatString() {
+ return defaultDateFormat.toPattern();
+ }
+ /**
+ * @param defaultDateFormat The defaultDateFormat to be set.
+ */
+ private void setDefaultDateFormat(String format) {
+ if (format != null) {
+ this.defaultDateFormat = new SimpleDateFormat(format);
+ this.defaultDateFormat.setLenient(false);
+ }
+ }
+ /**
+ * @return Returns the recentDateFormat.
+ */
+ public SimpleDateFormat getRecentDateFormat() {
+ return recentDateFormat;
+ }
+ /**
+ * @return Returns the recentDateFormat.
+ */
+ public String getRecentDateFormatString() {
+ return recentDateFormat.toPattern();
+ }
+ /**
+ * @param recentDateFormat The recentDateFormat to set.
+ */
+ private void setRecentDateFormat(String format) {
+ if (format != null) {
+ this.recentDateFormat = new SimpleDateFormat(format);
+ this.recentDateFormat.setLenient(false);
+ }
+ }
+
+ /**
+ * @return returns an array of 12 strings representing the short
+ * month names used by this parse.
+ */
+ public String[] getShortMonths() {
+ return defaultDateFormat.getDateFormatSymbols().getShortMonths();
+ }
+
+
+ /**
+ * @return Returns the serverTimeZone used by this parser.
+ */
+ public TimeZone getServerTimeZone() {
+ return this.defaultDateFormat.getTimeZone();
+ }
+ /**
+ * sets a TimeZone represented by the supplied ID string into all
+ * of the parsers used by this server.
+ * @param serverTimeZone Time Id java.util.TimeZone id used by
+ * the ftp server. If null the client's local time zone is assumed.
+ */
+ private void setServerTimeZone(String serverTimeZoneId) {
+ TimeZone serverTimeZone = TimeZone.getDefault();
+ if (serverTimeZoneId != null) {
+ serverTimeZone = TimeZone.getTimeZone(serverTimeZoneId);
+ }
+ this.defaultDateFormat.setTimeZone(serverTimeZone);
+ if (this.recentDateFormat != null) {
+ this.recentDateFormat.setTimeZone(serverTimeZone);
+ }
+ }
+
+ /**
+ * Implementation of the {@link Configurable Configurable}
+ * interface. Configures this FTPTimestampParser
according
+ * to the following logic:
+ *
+ *
config
, use that to parse parse timestamps.config
, use the month names represented
+ * by that {@link FTPClientConfig#lookupDateFormatSymbols(String) language}
+ * to parse timestamps. FTPFile
instance.
+ * If the file listing line doesn't describe a file, then
+ * null
is returned. Otherwise a FTPFile
+ * instance representing the file is returned.
+ *
+ * @param entry
+ * A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry) {
+ boolean isParsed = false;
+ FTPFile f = new FTPFile();
+
+ if (isType == FILE_LIST_TYPE)
+ isParsed = parseFileList(f, entry);
+ else if (isType == MEMBER_LIST_TYPE) {
+ isParsed = parseMemberList(f, entry);
+ if (!isParsed)
+ isParsed = parseSimpleEntry(f, entry);
+ } else if (isType == UNIX_LIST_TYPE) {
+ isParsed = parseUnixList(f, entry);
+ } else if (isType == JES_LEVEL_1_LIST_TYPE) {
+ isParsed = parseJeslevel1List(f, entry);
+ } else if (isType == JES_LEVEL_2_LIST_TYPE) {
+ isParsed = parseJeslevel2List(f, entry);
+ }
+
+ if (!isParsed)
+ f = null;
+
+ return f;
+ }
+
+ /**
+ * Parse entries representing a dataset list. Only datasets with DSORG PS or
+ * PO or PO-E and with RECFM F* or V* will be parsed.
+ *
+ * Format of ZOS/MVS file list: 1 2 3 4 5 6 7 8 9 10 Volume Unit Referred
+ * Ext Used Recfm Lrecl BlkSz Dsorg Dsname B10142 3390 2006/03/20 2 31 F 80
+ * 80 PS MDI.OKL.WORK ARCIVE Not Direct Access Device
+ * KJ.IOP998.ERROR.PL.UNITTEST B1N231 3390 2006/03/20 1 15 VB 256 27998 PO
+ * PLU B1N231 3390 2006/03/20 1 15 VB 256 27998 PO-E PLB
+ *
+ * ----------------------------------- Group within Regex [1] Volume [2]
+ * Unit [3] Referred [4] Ext: number of extents [5] Used [6] Recfm: Record
+ * format [7] Lrecl: Logical record length [8] BlkSz: Block size [9] Dsorg:
+ * Dataset organisation. Many exists but only support: PS, PO, PO-E [10]
+ * Dsname: Dataset name
+ *
+ * Note: When volume is ARCIVE, it means the dataset is stored somewhere in
+ * a tape archive. These entries is currently not supported by this parser.
+ * A null value is returned.
+ *
+ * @param file
+ * will be updated with Name, Type, Timestamp if parsed.
+ * @param entry zosDirectoryEntry
+ * @return true: entry was parsed, false: entry was not parsed.
+ */
+ private boolean parseFileList(FTPFile file, String entry) {
+ if (matches(entry)) {
+ file.setRawListing(entry);
+ String name = group(2);
+ String dsorg = group(1);
+ file.setName(name);
+
+ // DSORG
+ if ("PS".equals(dsorg)) {
+ file.setType(FTPFile.FILE_TYPE);
+ }
+ else if ("PO".equals(dsorg) || "PO-E".equals(dsorg)) {
+ // regex already ruled out anything other than PO or PO-E
+ file.setType(FTPFile.DIRECTORY_TYPE);
+ }
+ else {
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Parse entries within a partitioned dataset.
+ *
+ * Format of a memberlist within a PDS: 1 2 3 4 5 6 7 8 9 Name VV.MM Created
+ * Changed Size Init Mod Id TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11
+ * 0 KIL001 TBTOOL 01.12 2002/09/12 2004/11/26 19:54 51 28 0 KIL001
+ *
+ * ------------------------------------------- [1] Name [2] VV.MM: Version .
+ * modification [3] Created: yyyy / MM / dd [4,5] Changed: yyyy / MM / dd
+ * HH:mm [6] Size: number of lines [7] Init: number of lines when first
+ * created [8] Mod: number of modified lines a last save [9] Id: User id for
+ * last update
+ *
+ *
+ * @param file
+ * will be updated with Name, Type and Timestamp if parsed.
+ * @param entry zosDirectoryEntry
+ * @return true: entry was parsed, false: entry was not parsed.
+ */
+ private boolean parseMemberList(FTPFile file, String entry) {
+ if (matches(entry)) {
+ file.setRawListing(entry);
+ String name = group(1);
+ String datestr = group(2) + " " + group(3);
+ file.setName(name);
+ file.setType(FTPFile.FILE_TYPE);
+ try {
+ file.setTimestamp(super.parseTimestamp(datestr));
+ } catch (ParseException e) {
+ e.printStackTrace();
+ // just ignore parsing errors.
+ // TODO check this is ok
+ return false; // this is a parsing failure too.
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Assigns the name to the first word of the entry. Only to be used from a
+ * safe context, for example from a memberlist, where the regex for some
+ * reason fails. Then just assign the name field of FTPFile.
+ *
+ * @param file
+ * @param entry
+ * @return
+ */
+ private boolean parseSimpleEntry(FTPFile file, String entry) {
+ if (entry != null && entry.length() > 0) {
+ file.setRawListing(entry);
+ String name = entry.split(" ")[0];
+ file.setName(name);
+ file.setType(FTPFile.FILE_TYPE);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Parse the entry as a standard unix file. Using the UnixFTPEntryParser.
+ *
+ * @param file
+ * @param entry
+ * @return true: entry is parsed, false: entry could not be parsed.
+ */
+ private boolean parseUnixList(FTPFile file, String entry) {
+ file = unixFTPEntryParser.parseFTPEntry(entry);
+ if (file == null)
+ return false;
+ return true;
+ }
+
+ /**
+ * Matches these entries, note: no header: [1] [2] [3] [4] [5] IBMUSER1
+ * JOB01906 OUTPUT 3 Spool Files
+ * 012345678901234567890123456789012345678901234 1 2 3 4
+ * ------------------------------------------- Group in regex [1] Job name
+ * [2] Job number [3] Job status (INPUT,ACTIVE,OUTPUT) [4] Number of sysout
+ * files [5] The string "Spool Files"
+ *
+ *
+ * @param file
+ * will be updated with Name, Type and Timestamp if parsed.
+ * @param entry zosDirectoryEntry
+ * @return true: entry was parsed, false: entry was not parsed.
+ */
+ private boolean parseJeslevel1List(FTPFile file, String entry) {
+ if (matches(entry)) {
+ if (group(3).equalsIgnoreCase("OUTPUT")) {
+ file.setRawListing(entry);
+ String name = group(2); /* Job Number, used by GET */
+ file.setName(name);
+ file.setType(FTPFile.FILE_TYPE);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Matches these entries, note: no header: [1] [2] [3] [4] [5] JOBNAME JOBID
+ * OWNER STATUS CLASS IBMUSER1 JOB01906 IBMUSER OUTPUT A RC=0000 3 spool
+ * files IBMUSER TSU01830 IBMUSER OUTPUT TSU ABEND=522 3 spool files
+ * 012345678901234567890123456789012345678901234 1 2 3 4
+ * ------------------------------------------- Group in regex [1] Job name
+ * [2] Job number [3] Owner [4] Job status (INPUT,ACTIVE,OUTPUT) [5] Job
+ * Class [6] The rest
+ *
+ *
+ * @param file
+ * will be updated with Name, Type and Timestamp if parsed.
+ * @param entry zosDirectoryEntry
+ * @return true: entry was parsed, false: entry was not parsed.
+ */
+ private boolean parseJeslevel2List(FTPFile file, String entry) {
+ if (matches(entry)) {
+ if (group(4).equalsIgnoreCase("OUTPUT")) {
+ file.setRawListing(entry);
+ String name = group(2); /* Job Number, used by GET */
+ file.setName(name);
+ file.setType(FTPFile.FILE_TYPE);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * preParse is called as part of the interface. Per definition is is called
+ * before the parsing takes place. Three kind of lists is recognize:
+ * z/OS-MVS File lists z/OS-MVS Member lists unix file lists
+ * @since 2.0
+ */
+ @Override
+ public ListREGEX
is not a valid regular expression.
+ */
+ public NTFTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of an NTFTPEntryParser object
+ * with something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public NTFTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+ /**
+ * Parses a line of an NT FTP server file listing and converts it into a
+ * usable format in the form of an FTPFile
instance. If the
+ * file listing line doesn't describe a file, null
is
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ * REGEX
is not a valid regular expression.
+ */
+ public NetwareFTPEntryParser() {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of an NetwareFTPEntryParser object
+ * with something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public NetwareFTPEntryParser(FTPClientConfig config) {
+ super(REGEX);
+ configure(config);
+ }
+
+ /**
+ * Parses a line of an NetwareFTP server file listing and converts it into a
+ * usable format in the form of an FTPFile
instance. If the
+ * file listing line doesn't describe a file, null
is
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ *
+ *
+ *
+ * See here
+ * for more details
+ *
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry) {
+
+ FTPFile f = new FTPFile();
+ if (matches(entry)) {
+ String dirString = group(1);
+ String attrib = group(2);
+ String user = group(3);
+ String size = group(4);
+ String datestr = group(5);
+ String name = group(9);
+
+ try {
+ f.setTimestamp(super.parseTimestamp(datestr));
+ } catch (ParseException e) {
+ // intentionally do nothing
+ }
+
+ //is it a DIR or a file
+ if (dirString.trim().equals("d")) {
+ f.setType(FTPFile.DIRECTORY_TYPE);
+ } else // Should be "-"
+ {
+ f.setType(FTPFile.FILE_TYPE);
+ }
+
+ f.setUser(user);
+
+ //set the name
+ f.setName(name.trim());
+
+ //set the size
+ f.setSize(Long.parseLong(size.trim()));
+
+ // Now set the permissions (or at least a subset thereof - full permissions would probably require
+ // subclassing FTPFile and adding extra metainformation there)
+ if (attrib.indexOf("R") != -1) {
+ f.setPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION,
+ true);
+ }
+ if (attrib.indexOf("W") != -1) {
+ f.setPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION,
+ true);
+ }
+
+ return (f);
+ }
+ return null;
+
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(FTPClientConfig.SYST_NETWARE,
+ DEFAULT_DATE_FORMAT, DEFAULT_RECENT_DATE_FORMAT, null, null,
+ null);
+ }
+
+}
diff --git a/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.class b/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.class
new file mode 100644
index 0000000..332ae30
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.class differ
diff --git a/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java b/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
new file mode 100644
index 0000000..dc02ffb
--- /dev/null
+++ b/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+import java.text.ParseException;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFile;
+
+/**
+ * Implementation of FTPFileEntryParser and FTPFileListParser for OS2 Systems.
+ *
+ * @author Winston Ojeda
+ * @author Steve Cohen
+ * @version $Id: OS2FTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ */
+public class OS2FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
+
+{
+
+ private static final String DEFAULT_DATE_FORMAT
+ = "MM-dd-yy HH:mm"; //11-09-01 12:30
+ /**
+ * this is the regular expression used by this parser.
+ */
+ private static final String REGEX =
+ "\\s*([0-9]+)\\s*"
+ + "(\\s+|[A-Z]+)\\s*"
+ + "(DIR|\\s+)\\s*"
+ + "(\\S+)\\s+(\\S+)\\s+" /* date stuff */
+ + "(\\S.*)";
+
+ /**
+ * The default constructor for a OS2FTPEntryParser object.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ */
+ public OS2FTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of an OS2FTPEntryParser object
+ * with something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public OS2FTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+ /**
+ * Parses a line of an OS2 FTP server file listing and converts it into a
+ * usable format in the form of an FTPFile
instance. If the
+ * file listing line doesn't describe a file, null
is
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ * REGEX
is not a valid regular expression.
+ */
+ public OS400FTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of an OS400FTPEntryParser object
+ * with something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public OS400FTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+
+ public FTPFile parseFTPEntry(String entry)
+ {
+
+ FTPFile file = new FTPFile();
+ file.setRawListing(entry);
+ int type;
+
+ if (matches(entry))
+ {
+ String usr = group(1);
+ String filesize = group(2);
+ String datestr = group(3)+" "+group(4);
+ String typeStr = group(5);
+ String name = group(6);
+
+ try
+ {
+ file.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+
+ if (typeStr.equalsIgnoreCase("*STMF"))
+ {
+ type = FTPFile.FILE_TYPE;
+ }
+ else if (typeStr.equalsIgnoreCase("*DIR"))
+ {
+ type = FTPFile.DIRECTORY_TYPE;
+ }
+ else
+ {
+ type = FTPFile.UNKNOWN_TYPE;
+ }
+
+ file.setType(type);
+
+ file.setUser(usr);
+
+ try
+ {
+ file.setSize(Long.parseLong(filesize));
+ }
+ catch (NumberFormatException e)
+ {
+ // intentionally do nothing
+ }
+
+ if (name.endsWith("/"))
+ {
+ name = name.substring(0, name.length() - 1);
+ }
+ int pos = name.lastIndexOf('/');
+ if (pos > -1)
+ {
+ name = name.substring(pos + 1);
+ }
+
+ file.setName(name);
+
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_OS400,
+ DEFAULT_DATE_FORMAT,
+ null, null, null, null);
+ }
+
+}
diff --git a/org/apache/commons/net/ftp/parser/ParserInitializationException.class b/org/apache/commons/net/ftp/parser/ParserInitializationException.class
new file mode 100644
index 0000000..4f7fb6f
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/ParserInitializationException.class differ
diff --git a/org/apache/commons/net/ftp/parser/ParserInitializationException.java b/org/apache/commons/net/ftp/parser/ParserInitializationException.java
new file mode 100644
index 0000000..8af9261
--- /dev/null
+++ b/org/apache/commons/net/ftp/parser/ParserInitializationException.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+
+/**
+ * This class encapsulates all errors that may be thrown by
+ * the process of an FTPFileEntryParserFactory creating and
+ * instantiating an FTPFileEntryParser.
+ */
+public class ParserInitializationException extends RuntimeException {
+
+ /**
+ * Root exception that caused this to be thrown
+ */
+ private final Throwable rootCause;
+
+ /**
+ * Constucts a ParserInitializationException with just a message
+ *
+ * @param message Exception message
+ */
+ public ParserInitializationException(String message) {
+ super(message);
+ this.rootCause = null;
+ }
+
+ /**
+ * Constucts a ParserInitializationException with a message
+ * and a root cause.
+ *
+ * @param message Exception message
+ * @param rootCause root cause throwable that caused
+ * this to be thrown
+ */
+ public ParserInitializationException(String message, Throwable rootCause) {
+ super(message);
+ this.rootCause = rootCause;
+ }
+
+ /**
+ * returns the root cause of this exception or null
+ * if no root cause was specified.
+ *
+ * @return the root cause of this exception being thrown
+ */
+ public Throwable getRootCause() {
+ return this.rootCause;
+ }
+
+}
diff --git a/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.class b/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.class
new file mode 100644
index 0000000..3cd32f0
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.class differ
diff --git a/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java b/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java
new file mode 100644
index 0000000..5277444
--- /dev/null
+++ b/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.net.ftp.parser;
+
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.commons.net.ftp.FTPFileEntryParserImpl;
+
+/**
+ * This abstract class implements both the older FTPFileListParser and
+ * newer FTPFileEntryParser interfaces with default functionality.
+ * All the classes in the parser subpackage inherit from this.
+ *
+ * This is the base for all regular based FTPFileEntryParser
+ *
+ * @author Steve Cohen matchnum'th
group of the internal
+ * match or null if this method is called without a match having
+ * been made.
+ */
+ public String group(int matchnum) {
+ if (this.result == null) {
+ return null;
+ }
+ return this.result.group(matchnum);
+ }
+
+ /**
+ * For debugging purposes - returns a string shows each match group by
+ * number.
+ *
+ * @return a string shows each match group by number.
+ */
+
+ public String getGroupsAsString() {
+ StringBuffer b = new StringBuffer();
+ for (int i = 1; i <= this.result.groupCount(); i++) {
+ b.append(i).append(") ").append(this.result.group(i)).append(
+ System.getProperty("line.separator"));
+ }
+ return b.toString();
+ }
+
+ /**
+ * Alter the current regular expression being utilised for entry parsing
+ * and create a new {@link Pattern} instance.
+ * @param regex The new regular expression
+ * @return
+ * @since 2.0
+ */
+ public boolean setRegex(String regex) {
+ try {
+ pattern = Pattern.compile(regex);
+ } catch (PatternSyntaxException pse) {
+ throw new IllegalArgumentException("Unparseable regex supplied: "
+ + regex);
+ }
+ return (pattern != null);
+ }
+
+}
diff --git a/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.class b/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.class
new file mode 100644
index 0000000..27a082b
Binary files /dev/null and b/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.class differ
diff --git a/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java b/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
new file mode 100644
index 0000000..2a2a909
--- /dev/null
+++ b/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
@@ -0,0 +1,295 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+import java.text.ParseException;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFile;
+
+/**
+ * Implementation FTPFileEntryParser and FTPFileListParser for standard
+ * Unix Systems.
+ *
+ * This class is based on the logic of Daniel Savarese's
+ * DefaultFTPListParser, but adapted to use regular expressions and to fit the
+ * new FTPFileEntryParser interface.
+ * @version $Id: UnixFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ */
+public class UnixFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
+{
+
+ static final String DEFAULT_DATE_FORMAT
+ = "MMM d yyyy"; //Nov 9 2001
+
+ static final String DEFAULT_RECENT_DATE_FORMAT
+ = "MMM d HH:mm"; //Nov 9 20:06
+
+ static final String NUMERIC_DATE_FORMAT
+ = "yyyy-MM-dd HH:mm"; //2001-11-09 20:06
+
+ /**
+ * Some Linux distributions are now shipping an FTP server which formats
+ * file listing dates in an all-numeric format:
+ *
"yyyy-MM-dd HH:mm
.
+ * This is a very welcome development, and hopefully it will soon become
+ * the standard. However, since it is so new, for now, and possibly
+ * forever, we merely accomodate it, but do not make it the default.
+ * UnixFTPEntryParser(FTPClientConfig)
.
+ * Steve Cohen - 2005-04-17
+ */
+ public static final FTPClientConfig NUMERIC_DATE_CONFIG =
+ new FTPClientConfig(
+ FTPClientConfig.SYST_UNIX,
+ NUMERIC_DATE_FORMAT,
+ null, null, null, null);
+
+ /**
+ * this is the regular expression used by this parser.
+ *
+ * Permissions:
+ * r the file is readable
+ * w the file is writable
+ * x the file is executable
+ * - the indicated permission is not granted
+ * L mandatory locking occurs during access (the set-group-ID bit is
+ * on and the group execution bit is off)
+ * s the set-user-ID or set-group-ID bit is on, and the corresponding
+ * user or group execution bit is also on
+ * S undefined bit-state (the set-user-ID bit is on and the user
+ * execution bit is off)
+ * t the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and
+ * execution is on
+ * T the 1000 bit is turned on, and execution is off (undefined bit-
+ * state)
+ * e z/OS external link bit
+ */
+ private static final String REGEX =
+ "([bcdelfmpSs-])"
+ +"(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))\\+?\\s+"
+ + "(\\d+)\\s+"
+ + "(?:(\\S+(?:\\s\\S+)*?)\\s+)?" // owner name (optional spaces)
+ + "(?:(\\S+(?:\\s\\S+)*)\\s+)?" // group name (optional spaces)
+ + "(\\d+(?:,\\s*\\d+)?)\\s+"
+
+ /*
+ numeric or standard format date
+ */
+ + "((?:\\d+[-/]\\d+[-/]\\d+)|(?:\\S+\\s+\\S+))\\s+"
+
+ /*
+ year (for non-recent standard format)
+ or time (for numeric or recent standard format
+ */
+ + "(\\d+(?::\\d+)?)\\s+"
+
+ + "(\\S*)(\\s*.*)";
+
+
+ /**
+ * The default constructor for a UnixFTPEntryParser object.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ */
+ public UnixFTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of a UnixFTPEntryParser object with
+ * something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public UnixFTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+
+ /**
+ * Parses a line of a unix (standard) FTP server file listing and converts
+ * it into a usable format in the form of an FTPFile
+ * instance. If the file listing line doesn't describe a file,
+ * null
is returned, otherwise a FTPFile
+ * instance representing the files in the directory is returned.
+ * REGEX
is not a valid regular expression.
+ */
+ public VMSFTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of a VMSFTPEntryParser object with
+ * something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public VMSFTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+
+
+ /***
+ * Parses an FTP server file listing and converts it into a usable format
+ * in the form of an array of FTPFile
instances. If the
+ * file list contains no files, null
should be
+ * returned, otherwise an array of FTPFile
instances
+ * representing the files in the directory is returned.
+ * FTPFile
instance. If the
+ * file listing line doesn't describe a file, null
is
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ * REGEX
is not a valid regular expression.
+ */
+ public VMSVersioningFTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of a VMSVersioningFTPEntryParser
+ * object with something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public VMSVersioningFTPEntryParser(FTPClientConfig config)
+ {
+ super();
+ configure(config);
+ try
+ {
+ //_preparse_matcher_ = new Perl5Matcher();
+ _preparse_pattern_ = Pattern.compile(PRE_PARSE_REGEX);
+ }
+ catch (PatternSyntaxException pse)
+ {
+ throw new IllegalArgumentException (
+ "Unparseable regex supplied: " + PRE_PARSE_REGEX);
+ }
+
+ }
+
+
+
+ private static class NameVersion {
+ String name;
+ int versionNumber;
+ NameVersion(String name, String vers) {
+ this.name = name;
+ this.versionNumber = Integer.parseInt(vers);
+ }
+ }
+
+ /**
+ * Implement hook provided for those implementers (such as
+ * VMSVersioningFTPEntryParser, and possibly others) which return
+ * multiple files with the same name to remove the duplicates ..
+ *
+ * @param original Original list
+ *
+ * @return Original list purged of duplicates
+ */
+ @Override
+ public ListUNKNOWN_STREAM_SIZE
if the
+ * size is unknown.
+ */
+ public CopyStreamEvent(Object source, long totalBytesTransferred,
+ int bytesTransferred, long streamSize)
+ {
+ super(source);
+ this.bytesTransferred = bytesTransferred;
+ this.totalBytesTransferred = totalBytesTransferred;
+ this.streamSize = streamSize;
+ }
+
+ /**
+ * Returns the number of bytes transferred by the write that triggered
+ * the event.
+ * @return The number of bytes transferred by the write that triggered
+ * the vent.
+ */
+ public int getBytesTransferred()
+ {
+ return bytesTransferred;
+ }
+
+ /**
+ * Returns the total number of bytes transferred so far by the copy
+ * operation.
+ * @return The total number of bytes transferred so far by the copy
+ * operation.
+ */
+ public long getTotalBytesTransferred()
+ {
+ return totalBytesTransferred;
+ }
+
+ /**
+ * Returns the size of the stream being copied.
+ * This may be set to UNKNOWN_STREAM_SIZE
if the
+ * size is unknown.
+ * @return The size of the stream being copied.
+ */
+ public long getStreamSize()
+ {
+ return streamSize;
+ }
+}
diff --git a/org/apache/commons/net/io/CopyStreamException.class b/org/apache/commons/net/io/CopyStreamException.class
new file mode 100644
index 0000000..adf2ebb
Binary files /dev/null and b/org/apache/commons/net/io/CopyStreamException.class differ
diff --git a/org/apache/commons/net/io/CopyStreamException.java b/org/apache/commons/net/io/CopyStreamException.java
new file mode 100644
index 0000000..8d34145
--- /dev/null
+++ b/org/apache/commons/net/io/CopyStreamException.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.IOException;
+
+/**
+ * The CopyStreamException class is thrown by the org.apache.commons.io.Util
+ * copyStream() methods. It stores the number of bytes confirmed to
+ * have been transferred before an I/O error as well as the IOException
+ * responsible for the failure of a copy operation.
+ * @see Util
+ * @author Daniel F. Savarese
+ * @version $Id: CopyStreamException.java 489397 2006-12-21 16:28:51Z rwinston $
+ */
+public class CopyStreamException extends IOException
+{
+ private long totalBytesTransferred;
+ private IOException ioException;
+
+ /**
+ * Creates a new CopyStreamException instance.
+ * @param message A message describing the error.
+ * @param bytesTransferred The total number of bytes transferred before
+ * an exception was thrown in a copy operation.
+ * @param exception The IOException thrown during a copy operation.
+ */
+ public CopyStreamException(String message,
+ long bytesTransferred,
+ IOException exception)
+ {
+ super(message);
+ totalBytesTransferred = bytesTransferred;
+ ioException = exception;
+ }
+
+ /**
+ * Returns the total number of bytes confirmed to have
+ * been transferred by a failed copy operation.
+ * @return The total number of bytes confirmed to have
+ * been transferred by a failed copy operation.
+ */
+ public long getTotalBytesTransferred()
+ {
+ return totalBytesTransferred;
+ }
+
+ /**
+ * Returns the IOException responsible for the failure of a copy operation.
+ * @return The IOException responsible for the failure of a copy operation.
+ */
+ public IOException getIOException()
+ {
+ return ioException;
+ }
+}
diff --git a/org/apache/commons/net/io/CopyStreamListener.class b/org/apache/commons/net/io/CopyStreamListener.class
new file mode 100644
index 0000000..3d5bb08
Binary files /dev/null and b/org/apache/commons/net/io/CopyStreamListener.class differ
diff --git a/org/apache/commons/net/io/CopyStreamListener.java b/org/apache/commons/net/io/CopyStreamListener.java
new file mode 100644
index 0000000..9e97fb9
--- /dev/null
+++ b/org/apache/commons/net/io/CopyStreamListener.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.util.EventListener;
+
+/**
+ * The CopyStreamListener class can accept CopyStreamEvents to keep track
+ * of the progress of a stream copying operation. However, it is currently
+ * not used that way within NetComponents for performance reasons. Rather
+ * the bytesTransferred(long, int) method is called directly rather than
+ * passing an event to bytesTransferred(CopyStreamEvent), saving the creation
+ * of a CopyStreamEvent instance. Also, the only place where
+ * CopyStreamListener is currently used within NetComponents is in the
+ * static methods of the uninstantiable org.apache.commons.io.Util class, which
+ * would preclude the use of addCopyStreamListener and
+ * removeCopyStreamListener methods. However, future additions may use the
+ * JavaBean event model, which is why the hooks have been included from the
+ * beginning.
+ * flush()
will
+ * not flush the last byte written if that byte was a carriage
+ * return. A call to {@link #close close() }, however, will
+ * flush the carriage return.
+ * copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE);
+ ***/
+ public static final long copyStream(InputStream source, OutputStream dest)
+ throws CopyStreamException
+ {
+ return copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE);
+ }
+
+
+ /***
+ * Copies the contents of a Reader to a Writer using a
+ * copy buffer of a given size and notifies the provided
+ * CopyStreamListener of the progress of the copy operation by calling
+ * its bytesTransferred(long, int) method after each write to the
+ * destination. If you wish to notify more than one listener you should
+ * use a CopyStreamAdapter as the listener and register the additional
+ * listeners with the CopyStreamAdapter.
+ * copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE);
+ ***/
+ public static final long copyReader(Reader source, Writer dest)
+ throws CopyStreamException
+ {
+ return copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE);
+ }
+
+}
diff --git a/org/apache/commons/net/nntp/Article.java b/org/apache/commons/net/nntp/Article.java
new file mode 100644
index 0000000..cccba3b
--- /dev/null
+++ b/org/apache/commons/net/nntp/Article.java
@@ -0,0 +1,253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.nntp;
+
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+/**
+ * This is a class that contains the basic state needed for message retrieval and threading.
+ * With thanks to Jamie Zawinski NNTPConectionClosedException
+ * is a subclass of IOException
and therefore need not be
+ * caught separately, but if you are going to catch it separately, its
+ * catch block must appear before the more general IOException
+ * catch block. When you encounter an
+ * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
+ * , you must disconnect the connection with
+ * {@link #disconnect disconnect() } to properly clean up the
+ * system resources used by NNTP. Before disconnecting, you may check the
+ * last reply code and text with
+ * {@link #getReplyCode getReplyCode } and
+ * {@link #getReplyString getReplyString }.
+ * DEFAULT_PORT
and initializes internal data structures
+ * for saving NNTP reply information.
+ ***/
+ public NNTP()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ __commandBuffer = new StringBuffer();
+ _replyString = null;
+ _reader_ = null;
+ _writer_ = null;
+ _isAllowedToPost = false;
+ _commandSupport_ = new ProtocolCommandSupport(this);
+ }
+
+ private void __getReply() throws IOException
+ {
+ _replyString = _reader_.readLine();
+
+ if (_replyString == null)
+ throw new NNTPConnectionClosedException(
+ "Connection closed without indication.");
+
+ // In case we run into an anomaly we don't want fatal index exceptions
+ // to be thrown.
+ if (_replyString.length() < 3)
+ throw new MalformedServerReplyException(
+ "Truncated server reply: " + _replyString);
+ try
+ {
+ _replyCode = Integer.parseInt(_replyString.substring(0, 3));
+ }
+ catch (NumberFormatException e)
+ {
+ throw new MalformedServerReplyException(
+ "Could not parse response code.\nServer Reply: " + _replyString);
+ }
+
+ if (_commandSupport_.getListenerCount() > 0)
+ _commandSupport_.fireReplyReceived(_replyCode, _replyString +
+ SocketClient.NETASCII_EOL);
+
+ if (_replyCode == NNTPReply.SERVICE_DISCONTINUED)
+ throw new NNTPConnectionClosedException(
+ "NNTP response 400 received. Server closed connection.");
+ }
+
+ /***
+ * Initiates control connections and gets initial reply, determining
+ * if the client is allowed to post to the server. Initializes
+ * {@link #_reader_} and {@link #_writer_} to wrap
+ * {@link SocketClient#_input_} and {@link SocketClient#_output_}.
+ ***/
+ @Override
+ protected void _connectAction_() throws IOException
+ {
+ super._connectAction_();
+ _reader_ =
+ new BufferedReader(new InputStreamReader(_input_,
+ __DEFAULT_ENCODING));
+ _writer_ =
+ new BufferedWriter(new OutputStreamWriter(_output_,
+ __DEFAULT_ENCODING));
+ __getReply();
+
+ _isAllowedToPost = (_replyCode == NNTPReply.SERVER_READY_POSTING_ALLOWED);
+ }
+
+ /***
+ * Adds a ProtocolCommandListener. Delegates this task to
+ * {@link #_commandSupport_ _commandSupport_ }.
+ * connect
is of type void.
+ * NNTPConectionClosedException
+ * is a subclass of IOException
and therefore need not be
+ * caught separately, but if you are going to catch it separately, its
+ * catch block must appear before the more general IOException
+ * catch block. When you encounter an
+ * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
+ * , you must disconnect the connection with
+ * {@link org.apache.commons.net.nntp.NNTP#disconnect disconnect() }
+ * to properly clean up the
+ * system resources used by NNTP. Before disconnecting, you may check the
+ * last reply code and text with
+ * {@link org.apache.commons.net.nntp.NNTP#getReplyCode getReplyCode } and
+ * {@link org.apache.commons.net.nntp.NNTP#getReplyString getReplyString }.
+ * articleId
+ * field of the ArticlePointer cannot always be trusted because some
+ * NNTP servers do not correctly follow the RFC 977 reply format.
+ * retrieveArticle(articleId, null)
***/
+ public Reader retrieveArticle(String articleId) throws IOException
+ {
+ return retrieveArticle(articleId, null);
+ }
+
+ /*** Same as retrieveArticle(null)
***/
+ public Reader retrieveArticle() throws IOException
+ {
+ return retrieveArticle(null);
+ }
+
+
+ /***
+ * Retrieves an article from the currently selected newsgroup. The
+ * article is referenced by its article number.
+ * The article number and identifier contained in the server reply
+ * are returned through an ArticlePointer. The articleId
+ * field of the ArticlePointer cannot always be trusted because some
+ * NNTP servers do not correctly follow the RFC 977 reply format.
+ * retrieveArticle(articleNumber, null)
***/
+ public Reader retrieveArticle(int articleNumber) throws IOException
+ {
+ return retrieveArticle(articleNumber, null);
+ }
+
+
+
+ /***
+ * Retrieves an article header from the NNTP server. The article is
+ * referenced
+ * by its unique article identifier (including the enclosing < and >).
+ * The article number and identifier contained in the server reply
+ * are returned through an ArticlePointer. The articleId
+ * field of the ArticlePointer cannot always be trusted because some
+ * NNTP servers do not correctly follow the RFC 977 reply format.
+ * retrieveArticleHeader(articleId, null)
***/
+ public Reader retrieveArticleHeader(String articleId) throws IOException
+ {
+ return retrieveArticleHeader(articleId, null);
+ }
+
+ /*** Same as retrieveArticleHeader(null)
***/
+ public Reader retrieveArticleHeader() throws IOException
+ {
+ return retrieveArticleHeader(null);
+ }
+
+
+ /***
+ * Retrieves an article header from the currently selected newsgroup. The
+ * article is referenced by its article number.
+ * The article number and identifier contained in the server reply
+ * are returned through an ArticlePointer. The articleId
+ * field of the ArticlePointer cannot always be trusted because some
+ * NNTP servers do not correctly follow the RFC 977 reply format.
+ * retrieveArticleHeader(articleNumber, null)
***/
+ public Reader retrieveArticleHeader(int articleNumber) throws IOException
+ {
+ return retrieveArticleHeader(articleNumber, null);
+ }
+
+
+
+ /***
+ * Retrieves an article body from the NNTP server. The article is
+ * referenced
+ * by its unique article identifier (including the enclosing < and >).
+ * The article number and identifier contained in the server reply
+ * are returned through an ArticlePointer. The articleId
+ * field of the ArticlePointer cannot always be trusted because some
+ * NNTP servers do not correctly follow the RFC 977 reply format.
+ * retrieveArticleBody(articleId, null)
***/
+ public Reader retrieveArticleBody(String articleId) throws IOException
+ {
+ return retrieveArticleBody(articleId, null);
+ }
+
+ /*** Same as retrieveArticleBody(null)
***/
+ public Reader retrieveArticleBody() throws IOException
+ {
+ return retrieveArticleBody(null);
+ }
+
+
+ /***
+ * Retrieves an article body from the currently selected newsgroup. The
+ * article is referenced by its article number.
+ * The article number and identifier contained in the server reply
+ * are returned through an ArticlePointer. The articleId
+ * field of the ArticlePointer cannot always be trusted because some
+ * NNTP servers do not correctly follow the RFC 977 reply format.
+ * retrieveArticleBody(articleNumber, null)
***/
+ public Reader retrieveArticleBody(int articleNumber) throws IOException
+ {
+ return retrieveArticleBody(articleNumber, null);
+ }
+
+
+ /***
+ * Select the specified newsgroup to be the target of for future article
+ * retrieval and posting operations. Also return the newsgroup
+ * information contained in the server reply through the info parameter.
+ * selectNewsgroup(newsgroup, null)
***/
+ public boolean selectNewsgroup(String newsgroup) throws IOException
+ {
+ return selectNewsgroup(newsgroup, null);
+ }
+
+ /***
+ * List the command help from the server.
+ * selectArticle(articleId, null)
***/
+ public boolean selectArticle(String articleId) throws IOException
+ {
+ return selectArticle(articleId, null);
+ }
+
+ /****
+ * Same as selectArticle(null, articleId)
. Useful
+ * for retrieving the current article number.
+ ***/
+ public boolean selectArticle(ArticlePointer pointer) throws IOException
+ {
+ return selectArticle(null, pointer);
+ }
+
+
+ /***
+ * Select an article in the currently selected newsgroup by its number.
+ * and return its article number and id through the
+ * pointer parameter. This is achieved through the STAT command.
+ * According to RFC 977, this WILL set the current article pointer
+ * on the server. Use this command to select an article before retrieving
+ * it, or to obtain an article's unique identifier given its number.
+ * selectArticle(articleNumber, null)
***/
+ public boolean selectArticle(int articleNumber) throws IOException
+ {
+ return selectArticle(articleNumber, null);
+ }
+
+
+ /***
+ * Select the article preceeding the currently selected article in the
+ * currently selected newsgroup and return its number and unique id
+ * through the pointer parameter. Because of deviating server
+ * implementations, the articleId information cannot be trusted. To
+ * obtain the article identifier, issue a
+ * selectArticle(pointer.articleNumber, pointer)
immediately
+ * afterward.
+ * selectPreviousArticle(null)
***/
+ public boolean selectPreviousArticle() throws IOException
+ {
+ return selectPreviousArticle(null);
+ }
+
+
+ /***
+ * Select the article following the currently selected article in the
+ * currently selected newsgroup and return its number and unique id
+ * through the pointer parameter. Because of deviating server
+ * implementations, the articleId information cannot be trusted. To
+ * obtain the article identifier, issue a
+ * selectArticle(pointer.articleNumber, pointer)
immediately
+ * afterward.
+ * selectNextArticle(null)
***/
+ public boolean selectNextArticle() throws IOException
+ {
+ return selectNextArticle(null);
+ }
+
+
+ /***
+ * List all newsgroups served by the NNTP server. If no newsgroups
+ * are served, a zero length array will be returned. If the command
+ * fails, null will be returned.
+ *
+ * writer = client.postArticle();
+ * if(writer == null) // failure
+ * return false;
+ * header = new SimpleNNTPHeader("foobar@foo.com", "Just testing");
+ * header.addNewsgroup("alt.test");
+ * writer.write(header.toString());
+ * writer.write("This is just a test");
+ * writer.close();
+ * if(!client.completePendingCommand()) // failure
+ * return false;
+ *
+ *
+ * query = new NewsGroupsOrNewsQuery(new GregorianCalendar(97, 11, 15), false);
+ * query.addDistribution("comp");
+ * NewsgroupInfo[] newsgroups = client.listNewgroups(query);
+ *
+ * This will retrieve the list of newsgroups starting with the comp.
+ * distribution prefix created since midnight 11/15/97.
+ * *
wildcard, as in
+ * comp.lang.*
or comp.lang.java.*
. Adding
+ * at least one newsgroup is mandatory for the NEWNEWS command.
+ * *
wildcard, as in
+ * comp.lang.*
or comp.lang.java.*
.
+ *
+ * query.addNewsgroup("comp.lang.java.*");
+ * query.omitNewsgroup("comp.lang.java.advocacy");
+ *
+ * POSTING_PERMISSION
constants.
+ *
+ * writer = client.postArticle();
+ * if(writer == null) // failure
+ * return false;
+ * header = new SimpleNNTPHeader("foobar@foo.com", "Just testing");
+ * header.addNewsgroup("alt.test");
+ * header.addHeaderField("Organization", "Foobar, Inc.");
+ * writer.write(header.toString());
+ * writer.write("This is just a test");
+ * writer.close();
+ * if(!client.completePendingCommand()) // failure
+ * return false;
+ *
+ * From:
header field. This
+ * should be the article poster's email address.
+ * @param subject The value of the Subject:
header field.
+ * This should be the subject of the article.
+ ***/
+ public SimpleNNTPHeader(String from, String subject)
+ {
+ __from = from;
+ __subject = subject;
+ __newsgroups = new StringBuilder();
+ __headerFields = new StringBuilder();
+ __newsgroupCount = 0;
+ }
+
+ /***
+ * Adds a newsgroup to the article Newsgroups:
field.
+ *
+ * header.addHeaderField("Organization", "Foobar, Inc.");
+ *
+ * From:
header field.
+ * Subject:
header field.
+ * Newsgroups:
header field.
+ * ts
is null then zero time is used.
+ *
+ * @param ts NTP timestamp
+ */
+ public void setTransmitTime(TimeStamp ts)
+ {
+ setTimestamp(TRANSMIT_TIMESTAMP_INDEX, ts);
+ }
+
+ /***
+ * Set originate timestamp given NTP TimeStamp object.
+ * If ts
is null then zero time is used.
+ *
+ * @param ts NTP timestamp
+ */
+ public void setOriginateTimeStamp(TimeStamp ts)
+ {
+ setTimestamp(ORIGINATE_TIMESTAMP_INDEX, ts);
+ }
+
+ /***
+ * Returns the originate time as defined in RFC-1305.
+ *
+ * @return the originate time.
+ * Never returns null.
+ */
+ public TimeStamp getOriginateTimeStamp()
+ {
+ return getTimestamp(ORIGINATE_TIMESTAMP_INDEX);
+ }
+
+ /***
+ * Returns the reference time as defined in RFC-1305.
+ *
+ * @return the reference time as TimeStamp
object.
+ * Never returns null.
+ */
+ public TimeStamp getReferenceTimeStamp()
+ {
+ return getTimestamp(REFERENCE_TIMESTAMP_INDEX);
+ }
+
+ /***
+ * Set Reference time with NTP timestamp. If ts
is null
+ * then zero time is used.
+ *
+ * @param ts NTP timestamp
+ */
+ public void setReferenceTime(TimeStamp ts)
+ {
+ setTimestamp(REFERENCE_TIMESTAMP_INDEX, ts);
+ }
+
+ /***
+ * Returns receive timestamp as defined in RFC-1305.
+ *
+ * @return the receive time.
+ * Never returns null.
+ */
+ public TimeStamp getReceiveTimeStamp()
+ {
+ return getTimestamp(RECEIVE_TIMESTAMP_INDEX);
+ }
+
+ /***
+ * Set receive timestamp given NTP TimeStamp object.
+ * If ts
is null then zero time is used.
+ *
+ * @param ts timestamp
+ */
+ public void setReceiveTimeStamp(TimeStamp ts)
+ {
+ setTimestamp(RECEIVE_TIMESTAMP_INDEX, ts);
+ }
+
+ /***
+ * Return type of time packet. The values (e.g. NTP, TIME, ICMP, ...)
+ * correspond to the protocol used to obtain the timing information.
+ *
+ * @return packet type string identifier which in this case is "NTP".
+ */
+ public String getType()
+ {
+ return "NTP";
+ }
+
+ /***
+ * @return 4 bytes as 32-bit int
+ */
+ private int getInt(int index)
+ {
+ int i = ui(buf[index]) << 24 |
+ ui(buf[index + 1]) << 16 |
+ ui(buf[index + 2]) << 8 |
+ ui(buf[index + 3]);
+
+ return i;
+ }
+
+ /***
+ * Get NTP Timestamp at specified starting index.
+ *
+ * @param index index into data array
+ * @return TimeStamp object for 64 bits starting at index
+ */
+ private TimeStamp getTimestamp(int index)
+ {
+ return new TimeStamp(getLong(index));
+ }
+
+ /***
+ * Get Long value represented by bits starting at specified index.
+ *
+ * @return 8 bytes as 64-bit long
+ */
+ private long getLong(int index)
+ {
+ long i = ul(buf[index]) << 56 |
+ ul(buf[index + 1]) << 48 |
+ ul(buf[index + 2]) << 40 |
+ ul(buf[index + 3]) << 32 |
+ ul(buf[index + 4]) << 24 |
+ ul(buf[index + 5]) << 16 |
+ ul(buf[index + 6]) << 8 |
+ ul(buf[index + 7]);
+ return i;
+ }
+
+ /***
+ * Sets the NTP timestamp at the given array index.
+ *
+ * @param index index into the byte array.
+ * @param t TimeStamp.
+ */
+ private void setTimestamp(int index, TimeStamp t)
+ {
+ long ntpTime = (t == null) ? 0 : t.ntpValue();
+ // copy 64-bits from Long value into 8 x 8-bit bytes of array
+ // one byte at a time shifting 8-bits for each position.
+ for (int i = 7; i >= 0; i--) {
+ buf[index + i] = (byte) (ntpTime & 0xFF);
+ ntpTime >>>= 8; // shift to next byte
+ }
+ // buf[index] |= 0x80; // only set if 1900 baseline....
+ }
+
+ /***
+ * Returns the datagram packet with the NTP details already filled in.
+ *
+ * @return a datagram packet.
+ */
+ public synchronized DatagramPacket getDatagramPacket()
+ {
+ if (dp == null) {
+ dp = new DatagramPacket(buf, buf.length);
+ dp.setPort(NTP_PORT);
+ }
+ return dp;
+ }
+
+ /***
+ * Set the contents of this object from source datagram packet.
+ *
+ * @param srcDp source DatagramPacket to copy contents from.
+ */
+ public void setDatagramPacket(DatagramPacket srcDp)
+ {
+ byte[] incomingBuf = srcDp.getData();
+ int len = srcDp.getLength();
+ if (len > buf.length)
+ len = buf.length;
+
+ System.arraycopy(incomingBuf, 0, buf, 0, len);
+ }
+
+ /***
+ * Convert byte to unsigned integer.
+ * Java only has signed types so we have to do
+ * more work to get unsigned ops.
+ *
+ * @param b
+ * @return unsigned int value of byte
+ */
+ protected final static int ui(byte b)
+ {
+ int i = b & 0xFF;
+ return i;
+ }
+
+ /***
+ * Convert byte to unsigned long.
+ * Java only has signed types so we have to do
+ * more work to get unsigned ops
+ *
+ * @param b
+ * @return unsigned long value of byte
+ */
+ protected final static long ul(byte b)
+ {
+ long i = b & 0xFF;
+ return i;
+ }
+
+ /***
+ * Returns details of NTP packet as a string.
+ *
+ * @return details of NTP packet as a string.
+ */
+ @Override
+ public String toString()
+ {
+ return "[" +
+ "version:" + getVersion() +
+ ", mode:" + getMode() +
+ ", poll:" + getPoll() +
+ ", precision:" + getPrecision() +
+ ", delay:" + getRootDelay() +
+ ", dispersion(ms):" + getRootDispersionInMillisDouble() +
+ ", id:" + getReferenceIdString() +
+ ", xmitTime:" + getTransmitTimeStamp().toDateString() +
+ " ]";
+ }
+
+}
diff --git a/org/apache/commons/net/ntp/NtpV3Packet.java b/org/apache/commons/net/ntp/NtpV3Packet.java
new file mode 100644
index 0000000..52c828b
--- /dev/null
+++ b/org/apache/commons/net/ntp/NtpV3Packet.java
@@ -0,0 +1,236 @@
+package org.apache.commons.net.ntp;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import java.net.DatagramPacket;
+
+/**
+ * Interface for a NtpV3Packet with get/set methods corresponding to the fields
+ * in the NTP Data Message Header described in RFC 1305.
+ *
+ * @author Naz Irizarry, MITRE Corp
+ * @author Jason Mathews, MITRE Corp
+ * @version $Revision: 489397 $ $Date: 2006-12-21 16:28:51 +0000 (Thu, 21 Dec 2006) $
+ */
+public interface NtpV3Packet
+{
+
+ /**
+ * Standard NTP UDP port
+ */
+ public static final int NTP_PORT = 123;
+
+ public static final int LI_NO_WARNING = 0;
+ public static final int LI_LAST_MINUTE_HAS_61_SECONDS = 1;
+ public static final int LI_LAST_MINUTE_HAS_59_SECONDS = 2;
+ public static final int LI_ALARM_CONDITION = 3;
+
+ /* mode options */
+ public static final int MODE_RESERVED = 0;
+ public static final int MODE_SYMMETRIC_ACTIVE = 1;
+ public static final int MODE_SYMMETRIC_PASSIVE = 2;
+ public static final int MODE_CLIENT = 3;
+ public static final int MODE_SERVER = 4;
+ public static final int MODE_BROADCAST = 5;
+ public static final int MODE_CONTROL_MESSAGE = 6;
+ public static final int MODE_PRIVATE = 7;
+
+ public static final int NTP_MINPOLL = 4; // 16 seconds
+ public static final int NTP_MAXPOLL = 14; // 16284 seconds
+
+ public static final int NTP_MINCLOCK = 1;
+ public static final int NTP_MAXCLOCK = 10;
+
+ public static final int VERSION_3 = 3;
+ public static final int VERSION_4 = 4;
+
+ /* possible getType values such that other time-related protocols can
+ * have its information represented as NTP packets
+ */
+ public static final String TYPE_NTP = "NTP"; // RFC-1305/2030
+ public static final String TYPE_ICMP = "ICMP"; // RFC-792
+ public static final String TYPE_TIME = "TIME"; // RFC-868
+ public static final String TYPE_DAYTIME = "DAYTIME"; // RFC-867
+
+ /**
+ * @return a datagram packet with the NTP parts already filled in
+ */
+ public DatagramPacket getDatagramPacket();
+
+ /**
+ * Set the contents of this object from the datagram packet
+ */
+ public void setDatagramPacket(DatagramPacket dp);
+
+ /**
+ * @return leap indicator as defined in RFC-1305
+ */
+ public int getLeapIndicator();
+
+ /**
+ * Set leap indicator.
+ * @param li - leap indicator code
+ */
+ public void setLeapIndicator(int li);
+
+ /**
+ * @return mode as defined in RFC-1305
+ */
+ public int getMode();
+
+ /**
+ * @return mode as human readable string; e.g. 3=Client
+ */
+ public String getModeName();
+
+ /**
+ * Set mode as defined in RFC-1305
+ */
+ public void setMode(int mode);
+
+ /**
+ * @return poll interval as defined in RFC-1305.
+ * Field range between NTP_MINPOLL and NTP_MAXPOLL.
+ */
+ public int getPoll();
+
+ /**
+ * Set poll interval as defined in RFC-1305.
+ * Field range between NTP_MINPOLL and NTP_MAXPOLL.
+ */
+ public void setPoll(int poll);
+
+ /**
+ * @return precision as defined in RFC-1305
+ */
+ public int getPrecision();
+
+ /**
+ * @return root delay as defined in RFC-1305
+ */
+ public int getRootDelay();
+
+ /**
+ * @return root delay in milliseconds
+ */
+ public double getRootDelayInMillisDouble();
+
+ /**
+ * @return root dispersion as defined in RFC-1305
+ */
+ public int getRootDispersion();
+
+ /**
+ * @return root dispersion in milliseconds
+ */
+ public long getRootDispersionInMillis();
+
+ /**
+ * @return root dispersion in milliseconds
+ */
+ public double getRootDispersionInMillisDouble();
+
+ /**
+ * @return version as defined in RFC-1305
+ */
+ public int getVersion();
+
+ /**
+ * Set version as defined in RFC-1305
+ */
+ public void setVersion(int mode);
+
+ /**
+ * @return stratum as defined in RFC-1305
+ */
+ public int getStratum();
+
+ /**
+ * Set stratum as defined in RFC-1305
+ */
+ public void setStratum(int stratum);
+
+ /**
+ * @return the reference id string
+ */
+ public String getReferenceIdString();
+
+ /**
+ * @return the reference id (32-bit code) as defined in RFC-1305
+ */
+ public int getReferenceId();
+
+ /**
+ * Set reference clock identifier field.
+ * @param refId
+ */
+ public void setReferenceId(int refId);
+
+ /**
+ * @return the transmit timestamp as defined in RFC-1305
+ */
+ public TimeStamp getTransmitTimeStamp();
+
+ /**
+ * @return the reference time as defined in RFC-1305
+ */
+ public TimeStamp getReferenceTimeStamp();
+
+ /**
+ * @return the originate time as defined in RFC-1305
+ */
+ public TimeStamp getOriginateTimeStamp();
+
+ /**
+ * @return the receive time as defined in RFC-1305
+ */
+ public TimeStamp getReceiveTimeStamp();
+
+ /**
+ * Set the transmit timestamp given NTP TimeStamp object.
+ * @param ts - timestamp
+ */
+ public void setTransmitTime(TimeStamp ts);
+
+ /**
+ * Set the reference timestamp given NTP TimeStamp object.
+ * @param ts - timestamp
+ */
+ public void setReferenceTime(TimeStamp ts);
+
+ /**
+ * Set originate timestamp given NTP TimeStamp object.
+ * @param ts - timestamp
+ */
+ public void setOriginateTimeStamp(TimeStamp ts);
+
+ /**
+ * Set receive timestamp given NTP TimeStamp object.
+ * @param ts - timestamp
+ */
+ public void setReceiveTimeStamp(TimeStamp ts);
+
+ /**
+ * Return type of time packet. The values (e.g. NTP, TIME, ICMP, ...)
+ * correspond to the protocol used to obtain the timing information.
+ *
+ * @return packet type string identifier
+ */
+ public String getType();
+
+}
diff --git a/org/apache/commons/net/ntp/TimeInfo.java b/org/apache/commons/net/ntp/TimeInfo.java
new file mode 100644
index 0000000..4ef17fd
--- /dev/null
+++ b/org/apache/commons/net/ntp/TimeInfo.java
@@ -0,0 +1,295 @@
+package org.apache.commons.net.ntp;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Wrapper class to network time packet messages (NTP, etc) that computes
+ * related timing info and stats.
+ *
+ * @author Jason Mathews, MITRE Corp
+ *
+ * @version $Revision: 658518 $ $Date: 2008-05-21 02:04:30 +0100 (Wed, 21 May 2008) $
+ */
+public class TimeInfo {
+
+ private NtpV3Packet _message;
+ private Listjava.text.SimpleDateFormat
for code descriptions.
+ */
+ public final static String NTP_DATE_FORMAT = "EEE, MMM dd yyyy HH:mm:ss.SSS";
+
+ /*
+ * Caches for the DateFormatters used by various toString methods.
+ */
+ private static SoftReferencelong
value
+ * represented by this TimeStamp
object. That is, the hashcode
+ * is the value of the expression:
+ *
+ *
+ * @return a hash code value for this object.
+ */
+ @Override
+ public int hashCode()
+ {
+ return (int) (ntpTime ^ (ntpTime >>> 32));
+ }
+
+ /***
+ * Compares this object against the specified object.
+ * The result is
+ * (int)(this.ntpValue()^(this.ntpValue() >>> 32))
+ *
true
if and only if the argument is
+ * not null
and is a Long
object that
+ * contains the same long
value as this object.
+ *
+ * @param obj the object to compare with.
+ * @return true
if the objects are the same;
+ * false
otherwise.
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof TimeStamp) {
+ return ntpTime == ((TimeStamp) obj).ntpValue();
+ }
+ return false;
+ }
+
+ /***
+ * Converts this TimeStamp
object to a String
.
+ * The NTP timestamp 64-bit long value is represented as hex string with
+ * seconds separated by fractional seconds by a decimal point;
+ * e.g. c1a089bd.fc904f6d <=> Tue, Dec 10 2002 10:41:49.986
+ *
+ * @return NTP timestamp 64-bit long value as hex string with seconds
+ * separated by fractional seconds.
+ */
+ @Override
+ public String toString()
+ {
+ return toString(ntpTime);
+ }
+
+ /***
+ * Left-pad 8-character hex string with 0's
+ *
+ * @param buf - StringBuffer which is appended with leading 0's.
+ * @param l - a long.
+ */
+ private static void appendHexString(StringBuffer buf, long l)
+ {
+ String s = Long.toHexString(l);
+ for (int i = s.length(); i < 8; i++)
+ buf.append('0');
+ buf.append(s);
+ }
+
+ /***
+ * Converts 64-bit NTP timestamp value to a String
.
+ * The NTP timestamp value is represented as hex string with
+ * seconds separated by fractional seconds by a decimal point;
+ * e.g. c1a089bd.fc904f6d <=> Tue, Dec 10 2002 10:41:49.986
+ *
+ * @return NTP timestamp 64-bit long value as hex string with seconds
+ * separated by fractional seconds.
+ */
+ public static String toString(long ntpTime)
+ {
+ StringBuffer buf = new StringBuffer();
+ // high-order second bits (32..63) as hexstring
+ appendHexString(buf, (ntpTime >>> 32) & 0xffffffffL);
+
+ // low-order fractional seconds bits (0..31) as hexstring
+ buf.append('.');
+ appendHexString(buf, ntpTime & 0xffffffffL);
+
+ return buf.toString();
+ }
+
+ /***
+ * Converts this TimeStamp
object to a String
+ * of the form:
+ *
+ * See java.text.SimpleDataFormat for code descriptions.
+ *
+ * @return a string representation of this date.
+ */
+ public String toDateString()
+ {
+ DateFormat formatter = null;
+ if (simpleFormatter != null) {
+ formatter = simpleFormatter.get();
+ }
+ if (formatter == null) {
+ // No cache yet, or cached formatter GC'd
+ formatter = new SimpleDateFormat(NTP_DATE_FORMAT, Locale.US);
+ formatter.setTimeZone(TimeZone.getDefault());
+ simpleFormatter = new SoftReference
+ * EEE, MMM dd yyyy HH:mm:ss.SSS
TimeStamp
object to a String
+ * of the form:
+ *
+ * See java.text.SimpleDataFormat for code descriptions.
+ *
+ * @return a string representation of this date in UTC.
+ */
+ public String toUTCString()
+ {
+ DateFormat formatter = null;
+ if (utcFormatter != null)
+ formatter = utcFormatter.get();
+ if (formatter == null) {
+ // No cache yet, or cached formatter GC'd
+ formatter = new SimpleDateFormat(NTP_DATE_FORMAT + " 'UTC'",
+ Locale.US);
+ formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+ utcFormatter = new SoftReference
+ * EEE, MMM dd yyyy HH:mm:ss.SSS UTC
TimeStamp
to be compared.
+ * @return the value 0
if the argument TimeStamp is equal to
+ * this TimeStamp; a value less than 0
if this TimeStamp
+ * is numerically less than the TimeStamp argument; and a
+ * value greater than 0
if this TimeStamp is
+ * numerically greater than the TimeStamp argument
+ * (signed comparison).
+ */
+ public int compareTo(TimeStamp anotherTimeStamp)
+ {
+ long thisVal = this.ntpTime;
+ long anotherVal = anotherTimeStamp.ntpTime;
+ return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
+ }
+
+ /***
+ * Compares this TimeStamp to another Object. If the Object is a TimeStamp,
+ * this function behaves like compareTo(TimeStamp)
. Otherwise,
+ * it throws a ClassCastException
(as TimeStamps are comparable
+ * only to other TimeStamps).
+ *
+ * @param o the Object
to be compared.
+ * @return the value 0
if the argument is a TimeStamp
+ * numerically equal to this TimeStamp; a value less than
+ * 0
if the argument is a TimeStamp numerically
+ * greater than this TimeStamp; and a value greater than
+ * 0
if the argument is a TimeStamp numerically
+ * less than this TimeStamp.
+ * @exception ClassCastException if the argument is not a
+ * TimeStamp
.
+ * @see java.lang.Comparable
+ */
+ public int compareTo(Object o)
+ {
+ return compareTo((TimeStamp) o);
+ }
+
+}
diff --git a/org/apache/commons/net/pop3/POP3.java b/org/apache/commons/net/pop3/POP3.java
new file mode 100644
index 0000000..80033ab
--- /dev/null
+++ b/org/apache/commons/net/pop3/POP3.java
@@ -0,0 +1,358 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.pop3;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.commons.net.MalformedServerReplyException;
+import org.apache.commons.net.ProtocolCommandListener;
+import org.apache.commons.net.ProtocolCommandSupport;
+import org.apache.commons.net.SocketClient;
+
+/***
+ * The POP3 class is not meant to be used by itself and is provided
+ * only so that you may easily implement your own POP3 client if
+ * you so desire. If you have no need to perform your own implementation,
+ * you should use {@link org.apache.commons.net.pop3.POP3Client}.
+ * DISCONNECTED_STATE
.
+ ***/
+ public POP3()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ __commandBuffer = new StringBuffer();
+ __popState = DISCONNECTED_STATE;
+ _reader = null;
+ __writer = null;
+ _replyLines = new Vector AUTHORIZATION_STATE
.
+ ***/
+ @Override
+ protected void _connectAction_() throws IOException
+ {
+ super._connectAction_();
+ _reader =
+ new BufferedReader(new InputStreamReader(_input_,
+ __DEFAULT_ENCODING));
+ __writer =
+ new BufferedWriter(new OutputStreamWriter(_output_,
+ __DEFAULT_ENCODING));
+ __getReply();
+ setState(AUTHORIZATION_STATE);
+ }
+
+
+ /***
+ * Adds a ProtocolCommandListener. Delegates this task to
+ * {@link #_commandSupport_ _commandSupport_ }.
+ * _STATE
constants.
+ * DISCONNECTED_STATE
. The reply text information
+ * from the last issued command is voided to allow garbage collection
+ * of the memory used to store that information.
+ * getReplyStrings
+ * again. You only have to worry about this if you are implementing
+ * your own client using the {@link #sendCommand sendCommand } methods.
+ * getReplyString
+ * again. You only have to worry about this if you are implementing
+ * your own client using the {@link #sendCommand sendCommand } methods.
+ * number
+ * contains the number of messages in the mailbox, size
+ * contains the size of the mailbox in bytes, and identifier
+ * is null.
+ * number
+ * contains the message number, size
contains the
+ * size of the message in bytes, and identifier
is null.
+ * number
contains
+ * the message number, size
is undefined, and
+ * identifier
contains the message's unique identifier.
+ * number
and
+ * size
set to 0, and identifier
set to
+ * null.
+ ***/
+ public POP3MessageInfo()
+ {
+ number = size = 0;
+ identifier = null;
+ }
+
+ /***
+ * Creates a POP3MessageInfo instance with number
set
+ * to num
, size
set to octets
,
+ * and identifier
set to null.
+ ***/
+ public POP3MessageInfo(int num, int octets)
+ {
+ number = num;
+ size = octets;
+ identifier = null;
+ }
+
+ /***
+ * Creates a POP3MessageInfo instance with number
set
+ * to num
, size
undefined,
+ * and identifier
set to uid
.
+ ***/
+ public POP3MessageInfo(int num, String uid)
+ {
+ number = num;
+ size = -1;
+ identifier = uid;
+ }
+}
diff --git a/org/apache/commons/net/pop3/POP3Reply.java b/org/apache/commons/net/pop3/POP3Reply.java
new file mode 100644
index 0000000..08e4246
--- /dev/null
+++ b/org/apache/commons/net/pop3/POP3Reply.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.pop3;
+
+/***
+ * POP3Reply stores POP3 reply code constants.
+ * < @bar.com,@foo.com:foobar@foo.com >
+ *
+ * path = new RelayPath("foobar@foo.com");
+ * path.addRelay("bar.com");
+ * path.addRelay("foo.com");
+ *
+ * SMTPConectionClosedException
+ * is a subclass of IOException
and therefore need not be
+ * caught separately, but if you are going to catch it separately, its
+ * catch block must appear before the more general IOException
+ * catch block. When you encounter an
+ * {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
+ * , you must disconnect the connection with
+ * {@link org.apache.commons.net.SocketClient#disconnect disconnect() }
+ * to properly clean up the system resources used by SMTP. Before
+ * disconnecting, you may check the
+ * last reply code and text with
+ * {@link #getReplyCode getReplyCode },
+ * {@link #getReplyString getReplyString },
+ * and {@link #getReplyStrings getReplyStrings}.
+ * DEFAULT_PORT
and initializes internal data structures
+ * for saving SMTP reply information.
+ ***/
+ public SMTP()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ __commandBuffer = new StringBuffer();
+ _replyLines = new ArrayList connect
is of type void.
+ *
+ * try {
+ * int reply;
+ * client.connect("mail.foobar.com");
+ * System.out.print(client.getReplyString());
+ *
+ * // After connection attempt, you should check the reply code to verify
+ * // success.
+ * reply = client.getReplyCode();
+ *
+ * if(!SMTPReply.isPositiveCompletion(reply)) {
+ * client.disconnect();
+ * System.err.println("SMTP server refused connection.");
+ * System.exit(1);
+ * }
+ *
+ * // Do useful stuff here.
+ * ...
+ * } catch(IOException e) {
+ * if(client.isConnected()) {
+ * try {
+ * client.disconnect();
+ * } catch(IOException f) {
+ * // do nothing
+ * }
+ * }
+ * System.err.println("Could not connect to server.");
+ * e.printStackTrace();
+ * System.exit(1);
+ * }
+ *
+ * SMTPConectionClosedException
+ * is a subclass of IOException
and therefore need not be
+ * caught separately, but if you are going to catch it separately, its
+ * catch block must appear before the more general IOException
+ * catch block. When you encounter an
+ * {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
+ * , you must disconnect the connection with
+ * {@link #disconnect disconnect() } to properly clean up the
+ * system resources used by SMTPClient. Before disconnecting, you may check
+ * the last reply code and text with
+ * {@link org.apache.commons.net.smtp.SMTP#getReplyCode getReplyCode },
+ * {@link org.apache.commons.net.smtp.SMTP#getReplyString getReplyString },
+ * and
+ * {@link org.apache.commons.net.smtp.SMTP#getReplyStrings getReplyStrings}.
+ *
+ * writer = client.sendMessage();
+ * if(writer == null) // failure
+ * return false;
+ * header =
+ * new SimpleSMTPHeader("foobar@foo.com", "foo@foobar.com", "Re: Foo");
+ * writer.write(header.toString());
+ * writer.write("This is just a test");
+ * writer.close();
+ * if(!client.completePendingCommand()) // failure
+ * return false;
+ *
+ *
+ * writer = client.sendMessageData();
+ * if(writer == null) // failure
+ * return false;
+ * header =
+ * new SimpleSMTPHeader("foobar@foo.com", "foo@bar.com" "Just testing");
+ * header.addCC("bar@foo.com");
+ * header.addHeaderField("Organization", "Foobar, Inc.");
+ * writer.write(header.toString());
+ * writer.write("This is just a test");
+ * writer.close();
+ * if(!client.completePendingCommand()) // failure
+ * return false;
+ *
+ * From:
header field. This
+ * should be the sender's email address.
+ * @param to The value of the To:
header field. This
+ * should be the recipient's email address.
+ * @param subject The value of the Subject:
header field.
+ * This should be the subject of the message.
+ ***/
+ public SimpleSMTPHeader(String from, String to, String subject)
+ {
+ __to = to;
+ __from = from;
+ __subject = subject;
+ __headerFields = new StringBuffer();
+ __cc = null;
+ }
+
+ /***
+ * Adds an arbitrary header field with the given value to the article
+ * header. These headers will be written before the From, To, Subject, and
+ * Cc fields when the SimpleSMTPHeader is convertered to a string.
+ * An example use would be:
+ *
+ * header.addHeaderField("Organization", "Foobar, Inc.");
+ *
+ * DEFAULT_PORT
.
+ ***/
+ public TimeTCPClient ()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+ /***
+ * Retrieves the time from the server and returns it. The time
+ * is the number of seconds since 00:00 (midnight) 1 January 1900 GMT,
+ * as specified by RFC 868. This method reads the raw 32-bit big-endian
+ * unsigned integer from the server, converts it to a Java long, and
+ * returns the value.
+ * getTime()
again.
+ * getDate()
again.
+ * getTime(host, DEFAULT_PORT);
***/
+ public long getTime(InetAddress host) throws IOException
+ {
+ return getTime(host, DEFAULT_PORT);
+ }
+
+
+ /***
+ * Retrieves the time from the server and returns a Java Date
+ * containing the time converted to the local timezone.
+ * getTime(host, DEFAULT_PORT);
***/
+ public Date getDate(InetAddress host) throws IOException
+ {
+ return new Date((getTime(host, DEFAULT_PORT) -
+ SECONDS_1900_TO_1970)*1000L);
+ }
+
+}
+
diff --git a/org/apache/commons/net/util/ListenerList.class b/org/apache/commons/net/util/ListenerList.class
new file mode 100644
index 0000000..f05ebb5
Binary files /dev/null and b/org/apache/commons/net/util/ListenerList.class differ
diff --git a/org/apache/commons/net/util/ListenerList.java b/org/apache/commons/net/util/ListenerList.java
new file mode 100644
index 0000000..796fb78
--- /dev/null
+++ b/org/apache/commons/net/util/ListenerList.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.util;
+
+import java.io.Serializable;
+import java.util.EventListener;
+import java.util.Iterator;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * @author Daniel F. Savarese
+ */
+
+public class ListenerList implements Serializable, Iterable
+ * WhoisClient whois;
+ *
+ * whois = new WhoisClient();
+ *
+ * try {
+ * whois.connect(WhoisClient.DEFAULT_HOST);
+ * System.out.println(whois.query("foobar"));
+ * whois.disconnect();
+ * } catch(IOException e) {
+ * System.err.println("Error I/O exception: " + e.getMessage());
+ * return;
+ * }
+ *
+ *
+ * DEFAULT_PORT
.
+ ***/
+ public WhoisClient()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ }
+
+ /***
+ * Queries the connected whois server for information regarding
+ * the given handle. It is up to the programmer to be familiar with the
+ * handle syntax of the whois server. You must first connect to a whois
+ * server before calling this method, and you should disconnect afterward.
+ * super._connectAction_()
first to ensure the
+ * initialization of the aforementioned protected variables.
+ */
+ protected void _connectAction_() throws IOException
+ {
+ _socket_.setSoTimeout(_timeout_);
+ _input_ = _socket_.getInputStream();
+ _output_ = _socket_.getOutputStream();
+ }
+
+
+ /**
+ * Opens a Socket connected to a remote host at the specified port and
+ * originating from the current host at a system assigned port.
+ * Before returning, {@link #_connectAction_ _connectAction_() }
+ * is called to perform connection initialization actions.
+ * config
are somehow inadequate to configure the
+ * Configurable object.
+ */
+ public void configure(FTPClientConfig config);
+}
diff --git a/src/org/apache/commons/net/ftp/FTP.java b/src/org/apache/commons/net/ftp/FTP.java
new file mode 100644
index 0000000..6e2eff8
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/FTP.java
@@ -0,0 +1,1513 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.apache.commons.net.MalformedServerReplyException;
+import org.apache.commons.net.ProtocolCommandListener;
+import org.apache.commons.net.ProtocolCommandSupport;
+import org.apache.commons.net.SocketClient;
+
+/***
+ * FTP provides the basic the functionality necessary to implement your
+ * own FTP client. It extends org.apache.commons.net.SocketClient since
+ * extending TelnetClient was causing unwanted behavior (like connections
+ * that did not time out properly).
+ * FTPConectionClosedException
+ * is a subclass of IOException
and therefore need not be
+ * caught separately, but if you are going to catch it separately, its
+ * catch block must appear before the more general IOException
+ * catch block. When you encounter an
+ * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
+ * , you must disconnect the connection with
+ * {@link #disconnect disconnect() } to properly clean up the
+ * system resources used by FTP. Before disconnecting, you may check the
+ * last reply code and text with
+ * {@link #getReplyCode getReplyCode },
+ * {@link #getReplyString getReplyString },
+ * and {@link #getReplyStrings getReplyStrings}.
+ * You may avoid server disconnections while the client is idle by
+ * periodicaly sending NOOP commands to the server.
+ * FILE_TYPE
are used to indicate file types.
+ ***/
+ public static final int ASCII_FILE_TYPE = 0;
+
+ /***
+ * A constant used to indicate the file(s) being transfered should
+ * be treated as EBCDIC. Note however that there are several different
+ * EBCDIC formats. All constants ending in FILE_TYPE
+ * are used to indicate file types.
+ ***/
+ public static final int EBCDIC_FILE_TYPE = 1;
+
+
+ /***
+ * A constant used to indicate the file(s) being transfered should
+ * be treated as a binary image, i.e., no translations should be
+ * performed. All constants ending in FILE_TYPE
are used to
+ * indicate file types.
+ ***/
+ public static final int BINARY_FILE_TYPE = 2;
+
+ /***
+ * A constant used to indicate the file(s) being transfered should
+ * be treated as a local type. All constants ending in
+ * FILE_TYPE
are used to indicate file types.
+ ***/
+ public static final int LOCAL_FILE_TYPE = 3;
+
+ /***
+ * A constant used for text files to indicate a non-print text format.
+ * This is the default format.
+ * All constants ending in TEXT_FORMAT
are used to indicate
+ * text formatting for text transfers (both ASCII and EBCDIC).
+ ***/
+ public static final int NON_PRINT_TEXT_FORMAT = 4;
+
+ /***
+ * A constant used to indicate a text file contains format vertical format
+ * control characters.
+ * All constants ending in TEXT_FORMAT
are used to indicate
+ * text formatting for text transfers (both ASCII and EBCDIC).
+ ***/
+ public static final int TELNET_TEXT_FORMAT = 5;
+
+ /***
+ * A constant used to indicate a text file contains ASA vertical format
+ * control characters.
+ * All constants ending in TEXT_FORMAT
are used to indicate
+ * text formatting for text transfers (both ASCII and EBCDIC).
+ ***/
+ public static final int CARRIAGE_CONTROL_TEXT_FORMAT = 6;
+
+ /***
+ * A constant used to indicate a file is to be treated as a continuous
+ * sequence of bytes. This is the default structure. All constants ending
+ * in _STRUCTURE
are used to indicate file structure for
+ * file transfers.
+ ***/
+ public static final int FILE_STRUCTURE = 7;
+
+ /***
+ * A constant used to indicate a file is to be treated as a sequence
+ * of records. All constants ending in _STRUCTURE
+ * are used to indicate file structure for file transfers.
+ ***/
+ public static final int RECORD_STRUCTURE = 8;
+
+ /***
+ * A constant used to indicate a file is to be treated as a set of
+ * independent indexed pages. All constants ending in
+ * _STRUCTURE
are used to indicate file structure for file
+ * transfers.
+ ***/
+ public static final int PAGE_STRUCTURE = 9;
+
+ /***
+ * A constant used to indicate a file is to be transfered as a stream
+ * of bytes. This is the default transfer mode. All constants ending
+ * in TRANSFER_MODE
are used to indicate file transfer
+ * modes.
+ ***/
+ public static final int STREAM_TRANSFER_MODE = 10;
+
+ /***
+ * A constant used to indicate a file is to be transfered as a series
+ * of blocks. All constants ending in TRANSFER_MODE
are used
+ * to indicate file transfer modes.
+ ***/
+ public static final int BLOCK_TRANSFER_MODE = 11;
+
+ /***
+ * A constant used to indicate a file is to be transfered as FTP
+ * compressed data. All constants ending in TRANSFER_MODE
+ * are used to indicate file transfer modes.
+ ***/
+ public static final int COMPRESSED_TRANSFER_MODE = 12;
+
+ // We have to ensure that the protocol communication is in ASCII
+ // but we use ISO-8859-1 just in case 8-bit characters cross
+ // the wire.
+ /**
+ * The default character encoding used for communicating over an
+ * FTP control connection. The default encoding is an
+ * ASCII-compatible encoding. Some FTP servers expect other
+ * encodings. You can change the encoding used by an FTP instance
+ * with {@link #setControlEncoding setControlEncoding}.
+ */
+ public static final String DEFAULT_CONTROL_ENCODING = "ISO-8859-1";
+ private static final String __modes = "AEILNTCFRPSBC";
+
+ private StringBuilder __commandBuffer = new StringBuilder();
+
+ protected int _replyCode;
+ protected ArrayListDEFAULT_PORT
and initializes internal data structures
+ * for saving FTP reply information.
+ ***/
+ public FTP()
+ {
+ super();
+ setDefaultPort(DEFAULT_PORT);
+ _replyLines = new ArrayList connect
is of type void.
+ * FILE_TYPE
+ * constants).
+ * @param formatOrByteSize The format of the file (one of the
+ * _FORMAT
constants. In the case of
+ * LOCAL_FILE_TYPE
, the byte size.
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int type(int fileType, int formatOrByteSize) throws IOException
+ {
+ StringBuffer arg = new StringBuffer();
+
+ arg.append(__modes.charAt(fileType));
+ arg.append(' ');
+ if (fileType == LOCAL_FILE_TYPE)
+ arg.append(formatOrByteSize);
+ else
+ arg.append(__modes.charAt(formatOrByteSize));
+
+ return sendCommand(FTPCommand.TYPE, arg.toString());
+ }
+
+
+ /**
+ * A convenience method to send the FTP TYPE command to the server,
+ * receive the reply, and return the reply code.
+ * FILE_TYPE
+ * constants).
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ */
+ public int type(int fileType) throws IOException
+ {
+ return sendCommand(FTPCommand.TYPE,
+ __modes.substring(fileType, fileType + 1));
+ }
+
+ /***
+ * A convenience method to send the FTP STRU command to the server,
+ * receive the reply, and return the reply code.
+ * _STRUCTURE
constants).
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int stru(int structure) throws IOException
+ {
+ return sendCommand(FTPCommand.STRU,
+ __modes.substring(structure, structure + 1));
+ }
+
+ /***
+ * A convenience method to send the FTP MODE command to the server,
+ * receive the reply, and return the reply code.
+ * TRANSFER_MODE
constants).
+ * @return The reply code received from the server.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending the
+ * command or receiving the server reply.
+ ***/
+ public int mode(int mode) throws IOException
+ {
+ return sendCommand(FTPCommand.MODE,
+ __modes.substring(mode, mode + 1));
+ }
+
+ /***
+ * A convenience method to send the FTP RETR command to the server,
+ * receive the reply, and return the reply code. Remember, it is up
+ * to you to manage the data connection. If you don't need this low
+ * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
+ * , which will handle all low level details for you.
+ *
+ * boolean error = false;
+ * try {
+ * int reply;
+ * ftp.connect("ftp.foobar.com");
+ * System.out.println("Connected to " + server + ".");
+ * System.out.print(ftp.getReplyString());
+ *
+ * // After connection attempt, you should check the reply code to verify
+ * // success.
+ * reply = ftp.getReplyCode();
+ *
+ * if(!FTPReply.isPositiveCompletion(reply)) {
+ * ftp.disconnect();
+ * System.err.println("FTP server refused connection.");
+ * System.exit(1);
+ * }
+ * ... // transfer files
+ * ftp.logout();
+ * } catch(IOException e) {
+ * error = true;
+ * e.printStackTrace();
+ * } finally {
+ * if(ftp.isConnected()) {
+ * try {
+ * ftp.disconnect();
+ * } catch(IOException ioe) {
+ * // do nothing
+ * }
+ * }
+ * System.exit(error ? 1 : 0);
+ * }
+ *
+ * FTP.ASCII_FILE_TYPE
,
+ * FTP.NON_PRINT_TEXT_FORMAT
,
+ * FTP.STREAM_TRANSFER_MODE
, and
+ * FTP.FILE_STRUCTURE
. The only file types directly supported
+ * are FTP.ASCII_FILE_TYPE
and
+ * FTP.BINARY_FILE_TYPE
. Because there are at least 4
+ * different EBCDIC encodings, we have opted not to provide direct support
+ * for EBCDIC. To transfer EBCDIC and other unsupported file types you
+ * must create your own filter InputStreams and OutputStreams and wrap
+ * them around the streams returned or required by the FTPClient methods.
+ * FTPClient uses the {@link ToNetASCIIOutputStream NetASCII}
+ * filter streams to provide transparent handling of ASCII files. We will
+ * consider incorporating EBCDIC support if there is enough demand.
+ * FTP.NON_PRINT_TEXT_FORMAT
,
+ * FTP.STREAM_TRANSFER_MODE
, and
+ * FTP.FILE_STRUCTURE
are the only supported formats,
+ * transfer modes, and file structures.
+ * FTPConnectionClosedException
+ * is a subclass of IOException
and therefore need not be
+ * caught separately, but if you are going to catch it separately, its
+ * catch block must appear before the more general IOException
+ * catch block. When you encounter an
+ * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
+ * , you must disconnect the connection with
+ * {@link #disconnect disconnect() } to properly clean up the
+ * system resources used by FTPClient. Before disconnecting, you may check the
+ * last reply code and text with
+ * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode },
+ * {@link org.apache.commons.net.ftp.FTP#getReplyString getReplyString },
+ * and
+ * {@link org.apache.commons.net.ftp.FTP#getReplyStrings getReplyStrings}.
+ * You may avoid server disconnections while the client is idle by
+ * periodicaly sending NOOP commands to the server.
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = listFiles(directory);
+ *
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPListParseEngine engine =
+ * f.initiateListParsing("com.whatever.YourOwnParser", directory);
+ *
+ * while (engine.hasNext()) {
+ * FTPFile[] files = engine.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPListParseEngine engine = f.initiateListParsing(directory);
+ *
+ * while (engine.hasNext()) {
+ * FTPFile[] files = engine.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ *
+ *
see {@link FTPClientConfig FTPClientConfig}.
+ * MM d yyyy
ACTIVE_LOCAL_DATA_CONNECTION_MODE
, the file type
+ * set to FTP.ASCII_FILE_TYPE
, the
+ * file format set to FTP.NON_PRINT_TEXT_FORMAT
,
+ * the file structure set to FTP.FILE_STRUCTURE
, and
+ * the transfer mode set to FTP.STREAM_TRANSFER_MODE
.
+ ***/
+ public FTPClient()
+ {
+ __initDefaults();
+ __dataTimeout = -1;
+ __remoteVerificationEnabled = true;
+ __parserFactory = new DefaultFTPFileEntryParserFactory();
+ __configuration = null;
+ __listHiddenFiles = false;
+ }
+
+
+ private void __initDefaults()
+ {
+ __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
+ __passiveHost = null;
+ __passivePort = -1;
+ __fileType = FTP.ASCII_FILE_TYPE;
+ __fileStructure = FTP.FILE_STRUCTURE;
+ __fileFormat = FTP.NON_PRINT_TEXT_FORMAT;
+ __fileTransferMode = FTP.STREAM_TRANSFER_MODE;
+ __restartOffset = 0;
+ __systemName = null;
+ __entryParser = null;
+ __bufferSize = Util.DEFAULT_COPY_BUFFER_SIZE;
+ }
+
+ private String __parsePathname(String reply)
+ {
+ int begin, end;
+
+ begin = reply.indexOf('"') + 1;
+ end = reply.indexOf('"', begin);
+
+ return reply.substring(begin, end);
+ }
+
+
+ private void __parsePassiveModeReply(String reply)
+ throws MalformedServerReplyException
+ {
+ java.util.regex.Matcher m = __parms_pat.matcher(reply);
+ if (!m.find()) {
+ throw new MalformedServerReplyException(
+ "Could not parse passive host information.\nServer Reply: " + reply);
+ }
+ reply = m.group();
+ String parts[] = m.group().split(",");
+
+ __passiveHost = parts[0] + '.' + parts[1] + '.' + parts[2] + '.' + parts[3];
+
+ try
+ {
+ int oct1 = Integer.parseInt(parts[4]);
+ int oct2 = Integer.parseInt(parts[5]);
+ __passivePort = (oct1 << 8) | oct2;
+ }
+ catch (NumberFormatException e)
+ {
+ throw new MalformedServerReplyException(
+ "Could not parse passive host information.\nServer Reply: " + reply);
+ }
+
+ }
+
+ private boolean __storeFile(int command, String remote, InputStream local)
+ throws IOException
+ {
+ OutputStream output;
+ Socket socket;
+
+ if ((socket = _openDataConnection_(command, remote)) == null)
+ return false;
+
+ output = new BufferedOutputStream(socket.getOutputStream(),
+ getBufferSize()
+ );
+ if (__fileType == ASCII_FILE_TYPE)
+ output = new ToNetASCIIOutputStream(output);
+ // Treat everything else as binary for now
+ try
+ {
+ Util.copyStream(local, output, getBufferSize(),
+ CopyStreamEvent.UNKNOWN_STREAM_SIZE, null,
+ false);
+ }
+ catch (IOException e)
+ {
+ try
+ {
+ socket.close();
+ }
+ catch (IOException f)
+ {}
+ throw e;
+ }
+ output.close();
+ socket.close();
+ return completePendingCommand();
+ }
+
+ private OutputStream __storeFileStream(int command, String remote)
+ throws IOException
+ {
+ OutputStream output;
+ Socket socket;
+
+ if ((socket = _openDataConnection_(command, remote)) == null)
+ return null;
+
+ output = socket.getOutputStream();
+ if (__fileType == ASCII_FILE_TYPE) {
+ // We buffer ascii transfers because the buffering has to
+ // be interposed between ToNetASCIIOutputSream and the underlying
+ // socket output stream. We don't buffer binary transfers
+ // because we don't want to impose a buffering policy on the
+ // programmer if possible. Programmers can decide on their
+ // own if they want to wrap the SocketOutputStream we return
+ // for file types other than ASCII.
+ output = new BufferedOutputStream(output,
+ getBufferSize());
+ output = new ToNetASCIIOutputStream(output);
+
+ }
+ return new org.apache.commons.net.io.SocketOutputStream(socket, output);
+ }
+
+
+ /**
+ * Establishes a data connection with the FTP server, returning
+ * a Socket for the connection if successful. If a restart
+ * offset has been set with {@link #setRestartOffset(long)},
+ * a REST command is issued to the server with the offset as
+ * an argument before establishing the data connection. Active
+ * mode connections also cause a local PORT command to be issued.
+ * ACTIVE_LOCAL_DATA_CONNECTION_MODE
. No communication
+ * with the FTP server is conducted, but this causes all future data
+ * transfers to require the FTP server to connect to the client's
+ * data port. Additionally, to accommodate differences between socket
+ * implementations on different platforms, this method causes the
+ * client to issue a PORT command before every data transfer.
+ ***/
+ public void enterLocalActiveMode()
+ {
+ __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
+ __passiveHost = null;
+ __passivePort = -1;
+ }
+
+
+ /***
+ * Set the current data connection mode to
+ * PASSIVE_LOCAL_DATA_CONNECTION_MODE
. Use this
+ * method only for data transfers between the client and server.
+ * This method causes a PASV command to be issued to the server
+ * before the opening of every data connection, telling the server to
+ * open a data port to which the client will connect to conduct
+ * data transfers. The FTPClient will stay in
+ * PASSIVE_LOCAL_DATA_CONNECTION_MODE
until the
+ * mode is changed by calling some other method such as
+ * {@link #enterLocalActiveMode enterLocalActiveMode() }
+ ***/
+ public void enterLocalPassiveMode()
+ {
+ __dataConnectionMode = PASSIVE_LOCAL_DATA_CONNECTION_MODE;
+ // These will be set when just before a data connection is opened
+ // in _openDataConnection_()
+ __passiveHost = null;
+ __passivePort = -1;
+ }
+
+
+ /***
+ * Set the current data connection mode to
+ * ACTIVE_REMOTE_DATA_CONNECTION
. Use this method only
+ * for server to server data transfers. This method issues a PORT
+ * command to the server, indicating the other server and port to which
+ * it should connect for data transfers. You must call this method
+ * before EVERY server to server transfer attempt. The FTPClient will
+ * NOT automatically continue to issue PORT commands. You also
+ * must remember to call
+ * {@link #enterLocalActiveMode enterLocalActiveMode() } if you
+ * wish to return to the normal data connection mode.
+ * PASSIVE_REMOTE_DATA_CONNECTION_MODE
. Use this
+ * method only for server to server data transfers.
+ * This method issues a PASV command to the server, telling it to
+ * open a data port to which the active server will connect to conduct
+ * data transfers. You must call this method
+ * before EVERY server to server transfer attempt. The FTPClient will
+ * NOT automatically continue to issue PASV commands. You also
+ * must remember to call
+ * {@link #enterLocalActiveMode enterLocalActiveMode() } if you
+ * wish to return to the normal data connection mode.
+ * _DATA_CONNECTION_MODE
constants.
+ * _DATA_CONNECTION_MODE
constants.
+ ***/
+ public int getDataConnectionMode()
+ {
+ return __dataConnectionMode;
+ }
+
+
+ /***
+ * Sets the file type to be transferred. This should be one of
+ * FTP.ASCII_FILE_TYPE
, FTP.BINARY_FILE_TYPE
,
+ * etc. The file type only needs to be set when you want to change the
+ * type. After changing it, the new type stays in effect until you change
+ * it again. The default file type is FTP.ASCII_FILE_TYPE
+ * if this method is never called.
+ * _FILE_TYPE
constant indcating the
+ * type of file.
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean setFileType(int fileType) throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(type(fileType)))
+ {
+ __fileType = fileType;
+ __fileFormat = FTP.NON_PRINT_TEXT_FORMAT;
+ return true;
+ }
+ return false;
+ }
+
+
+ /***
+ * Sets the file type to be transferred and the format. The type should be
+ * one of FTP.ASCII_FILE_TYPE
,
+ * FTP.BINARY_FILE_TYPE
, etc. The file type only needs to
+ * be set when you want to change the type. After changing it, the new
+ * type stays in effect until you change it again. The default file type
+ * is FTP.ASCII_FILE_TYPE
if this method is never called.
+ * The format should be one of the FTP class TEXT_FORMAT
+ * constants, or if the type is FTP.LOCAL_FILE_TYPE
, the
+ * format should be the byte size for that type. The default format
+ * is FTP.NON_PRINT_TEXT_FORMAT
if this method is never
+ * called.
+ * _FILE_TYPE
constant indcating the
+ * type of file.
+ * @param formatOrByteSize The format of the file (one of the
+ * _FORMAT
constants. In the case of
+ * LOCAL_FILE_TYPE
, the byte size.
+ * FTP.FILE_STRUCTURE
if this method is never called.
+ * _STRUCTURE
constants).
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean setFileStructure(int structure) throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(stru(structure)))
+ {
+ __fileStructure = structure;
+ return true;
+ }
+ return false;
+ }
+
+
+ /***
+ * Sets the transfer mode. The default transfer mode
+ * FTP.STREAM_TRANSFER_MODE
if this method is never called.
+ * _TRANSFER_MODE
constants).
+ * @return True if successfully completed, false if not.
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ ***/
+ public boolean setFileTransferMode(int mode) throws IOException
+ {
+ if (FTPReply.isPositiveCompletion(mode(mode)))
+ {
+ __fileTransferMode = mode;
+ return true;
+ }
+ return false;
+ }
+
+
+ /***
+ * Initiate a server to server file transfer. This method tells the
+ * server to which the client is connected to retrieve a given file from
+ * the other server.
+ * remoteRetrieve
issued to it by another
+ * FTPClient.
+ * remoteRetrieve
issued
+ * to it by another FTPClient.
+ * remoteRetrieve
issued
+ * to it by another FTPClient. Many FTP servers require that a base
+ * filename be given from which the unique filename can be derived. For
+ * those servers use the other version of remoteStoreUnique
+ * remoteRetrieve
issued to it by another FTPClient.
+ *
+ * InputStream input;
+ * OutputStream output;
+ * input = new FileInputStream("foobaz.txt");
+ * output = ftp.storeFileStream("foobar.txt")
+ * if(!FTPReply.isPositiveIntermediate(ftp.getReplyCode())) {
+ * input.close();
+ * output.close();
+ * ftp.logout();
+ * ftp.disconnect();
+ * System.err.println("File transfer failed.");
+ * System.exit(1);
+ * }
+ * Util.copyStream(input, output);
+ * input.close();
+ * output.close();
+ * // Must call completePendingCommand() to finish command.
+ * if(!ftp.completePendingCommand()) {
+ * ftp.logout();
+ * ftp.disconnect();
+ * System.err.println("File transfer failed.");
+ * System.exit(1);
+ * }
+ *
+ * STREAM_TRANSFER_MODE
file transfer starting
+ * from the given offset. This will only work on FTP servers supporting
+ * the REST comand for the stream transfer mode. However, most FTP
+ * servers support this. Any subsequent file transfer will start
+ * reading or writing the remote file from the indicated offset.
+ * FTPFileEntryParser
+ * used.
+ * FTPFileEntryParser
+ * used.
+ * FTPFileEntryParser
used.
+ * parser
parameter. Null will be
+ * returned if a data connection cannot be opened. If the current working
+ * directory contains no files, an empty array will be the return.
+ *
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ * @exception ParserInitializationException
+ * Thrown if the autodetect mechanism cannot
+ * resolve the type of system we are connected with.
+ * @see FTPListParseEngine
+ */
+ public FTPListParseEngine initiateListParsing()
+ throws IOException
+ {
+ return initiateListParsing((String) null);
+ }
+
+ /**
+ * Using the default autodetect mechanism, initialize an FTPListParseEngine
+ * object containing a raw file information for the supplied directory.
+ * This information is obtained through the LIST command. This object
+ * is then capable of being iterated to return a sequence of FTPFile
+ * objects with information filled in by the
+ * FTPFileEntryParser
used.
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPListParseEngine engine = f.initiateListParsing(directory);
+ *
+ * while (engine.hasNext()) {
+ * FTPFile[] files = engine.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ *
+ * @return A FTPListParseEngine object that holds the raw information and
+ * is capable of providing parsed FTPFile objects, one for each file
+ * containing information contained in the given path in the format
+ * determined by the parser
parameter. Null will be
+ * returned if a data connection cannot be opened. If the current working
+ * directory contains no files, an empty array will be the return.
+ *
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ * @exception ParserInitializationException
+ * Thrown if the autodetect mechanism cannot
+ * resolve the type of system we are connected with.
+ * @see FTPListParseEngine
+ */
+ public FTPListParseEngine initiateListParsing(
+ String pathname)
+ throws IOException
+ {
+ String key = null;
+ return initiateListParsing(key, pathname);
+ }
+
+ /**
+ * Using the supplied parser key, initialize an FTPListParseEngine
+ * object containing a raw file information for the supplied directory.
+ * This information is obtained through the LIST command. This object
+ * is then capable of being iterated to return a sequence of FTPFile
+ * objects with information filled in by the
+ * FTPFileEntryParser
used.
+ * FTPFileEntryParser
that should be
+ * used to parse each server file listing.
+ *
+ * @return A FTPListParseEngine object that holds the raw information and
+ * is capable of providing parsed FTPFile objects, one for each file
+ * containing information contained in the given path in the format
+ * determined by the parser
parameter. Null will be
+ * returned if a data connection cannot be opened. If the current working
+ * directory contains no files, an empty array will be the return.
+ *
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ * @exception ParserInitializationException
+ * Thrown if the parserKey parameter cannot be
+ * resolved by the selected parser factory.
+ * In the DefaultFTPEntryParserFactory, this will
+ * happen when parserKey is neither
+ * the fully qualified class name of a class
+ * implementing the interface
+ * org.apache.commons.net.ftp.FTPFileEntryParser
+ * nor a string containing one of the recognized keys
+ * mapping to such a parser or if class loader
+ * security issues prevent its being loaded.
+ * @see FTPListParseEngine
+ */
+ public FTPListParseEngine initiateListParsing(
+ String parserKey, String pathname)
+ throws IOException
+ {
+ // We cache the value to avoid creation of a new object every
+ // time a file listing is generated.
+ if(__entryParser == null) {
+ if (null != parserKey) {
+ // if a parser key was supplied in the parameters,
+ // use that to create the paraser
+ __entryParser =
+ __parserFactory.createFileEntryParser(parserKey);
+
+ } else {
+ // if no parserKey was supplied, check for a configuration
+ // in the params, and if non-null, use that.
+ if (null != __configuration) {
+ __entryParser =
+ __parserFactory.createFileEntryParser(__configuration);
+ } else {
+ // if a parserKey hasn't been supplied, and a configuration
+ // hasn't been supplied, then autodetect by calling
+ // the SYST command and use that to choose the parser.
+ __entryParser =
+ __parserFactory.createFileEntryParser(getSystemName());
+ }
+ }
+ }
+
+ return initiateListParsing(__entryParser, pathname);
+
+ }
+
+
+ /**
+ * private method through which all listFiles() and
+ * initiateListParsing methods pass once a parser is determined.
+ *
+ * @exception FTPConnectionClosedException
+ * If the FTP server prematurely closes the connection as a result
+ * of the client being idle or some other reason causing the server
+ * to send FTP reply code 421. This exception may be caught either
+ * as an IOException or independently as itself.
+ * @exception IOException
+ * If an I/O error occurs while either sending a
+ * command to the server or receiving a reply from the server.
+ * @see FTPListParseEngine
+ */
+ private FTPListParseEngine initiateListParsing(
+ FTPFileEntryParser parser, String pathname)
+ throws IOException
+ {
+ Socket socket;
+
+ FTPListParseEngine engine = new FTPListParseEngine(parser);
+
+ if ((socket = _openDataConnection_(FTPCommand.LIST, getListArguments(pathname))) == null)
+ {
+ return engine;
+ }
+
+
+ try {
+ engine.readServerList(socket.getInputStream(), getControlEncoding());
+ }
+ finally {
+ socket.close();
+ }
+
+ completePendingCommand();
+ return engine;
+ }
+
+ /**
+ * @since 2.0
+ */
+ protected String getListArguments(String pathname) {
+ if (getListHiddenFiles())
+ {
+ StringBuffer sb = new StringBuffer(pathname.length() + 3);
+ sb.append("-a ");
+ sb.append(pathname);
+ return sb.toString();
+ }
+
+ return pathname;
+ }
+
+
+ /***
+ * Issue the FTP STAT command to the server.
+ * YYYYMMDDhhmmss
format.
+ * @throws IOException if an I/O error occurs.
+ * @since 2.0
+ */
+ public String getModificationTime(String pathname) throws IOException {
+ if (FTPReply.isPositiveCompletion(mdtm(pathname)))
+ return getReplyString();
+ return null;
+ }
+
+
+ /**
+ * Set the internal buffer size.
+ *
+ * @param bufSize The size of the buffer
+ */
+ public void setBufferSize(int bufSize) {
+ __bufferSize = bufSize;
+ }
+
+ /**
+ * Retrieve the current internal buffer size.
+ * @return The current buffer size.
+ */
+ public int getBufferSize() {
+ return __bufferSize;
+ }
+
+
+ /**
+ * Implementation of the {@link Configurable Configurable} interface.
+ * In the case of this class, configuring merely makes the config object available for the
+ * factory methods that construct parsers.
+ * @param config {@link FTPClientConfig FTPClientConfig} object used to
+ * provide non-standard configurations to the parser.
+ * @since 1.4
+ */
+ public void configure(FTPClientConfig config) {
+ this.__configuration = config;
+ }
+
+ /**
+ * You can set this to true if you would like to get hidden files when {@link #listFiles} too.
+ * A LIST -a
will be issued to the ftp server.
+ * It depends on your ftp server if you need to call this method, also dont expect to get rid
+ * of hidden files if you call this method with "false".
+ *
+ * @param listHiddenFiles true if hidden files should be listed
+ * @since 2.0
+ */
+ public void setListHiddenFiles(boolean listHiddenFiles) {
+ this.__listHiddenFiles = listHiddenFiles;
+ }
+
+ /**
+ * @see #setListHiddenFiles(boolean)
+ * @return the current state
+ * @since 2.0
+ */
+ public boolean getListHiddenFiles() {
+ return this.__listHiddenFiles;
+ }
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/src/org/apache/commons/net/ftp/FTPClientConfig.java b/src/org/apache/commons/net/ftp/FTPClientConfig.java
new file mode 100644
index 0000000..450eddc
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/FTPClientConfig.java
@@ -0,0 +1,580 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp;
+
+import java.text.DateFormatSymbols;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+
+/**
+ * Examples of use of FTPClientConfig
+ * Use cases:
+ * You are trying to access a server that
+ *
+ *
+ * MM dd yyyy
MMM d yyyy
date formatting
+ *
+ * FTPClient f=FTPClient();
+ * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
+ * conf.setServerLanguageCode("fr");
+ * f.configure(conf);
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = listFiles(directory);
+ *
+ *
+ * FTPClient f=FTPClient();
+ * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
+ * conf.setServerLanguageCode("da");
+ * conf.setDefaultDateFormat("d MMM yyyy");
+ * conf.setRecentDateFormat("d MMM HH:mm");
+ * conf.setTimeZoneId("Europe/Copenhagen");
+ * f.configure(conf);
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPListParseEngine engine =
+ * f.initiateListParsing("com.whatever.YourOwnParser", directory);
+ *
+ * while (engine.hasNext()) {
+ * FTPFile[] files = engine.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ * MMM d yyyy
date formatting
+ *
+ * FTPClient f=FTPClient();
+ * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_VMS);
+ * conf.setShortMonthNames(
+ * "jan|feb|mar|apr|ma\u00ED|j\u00FAn|j\u00FAl|\u00e1g\u00FA|sep|okt|n\u00F3v|des");
+ * f.configure(conf);
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = listFiles(directory);
+ *
+ *
+ * FTPClient f=FTPClient();
+ * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
+ * conf.setTimeZoneId("America/Denver");
+ * f.configure(conf);
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = listFiles(directory);
+ *
+ *
+ * FTPClient f=FTPClient();
+ * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
+ * conf.setTimeZoneId("America/Denver");
+ * f.configure(conf);
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = listFiles(directory);
+ *
+ * FTPClientConfig.SYST_*
codes
+ * or else the fully qualified class name of a parser implementing both
+ * the FTPFileEntryParser
and Configurable
+ * interfaces.
+ * @return Returns the serverSystemKey property.
+ */
+ public String getServerSystemKey() {
+ return serverSystemKey;
+ }
+
+ /**
+ * getter for the {@link #setDefaultDateFormatStr(String) defaultDateFormatStr}
+ * property.
+ * @return Returns the defaultDateFormatStr property.
+ */
+ public String getDefaultDateFormatStr() {
+ return defaultDateFormatStr;
+ }
+
+ /**
+ * getter for the {@link #setRecentDateFormatStr(String) recentDateFormatStr} property.
+ * @return Returns the recentDateFormatStr property.
+ */
+
+ public String getRecentDateFormatStr() {
+ return recentDateFormatStr;
+ }
+
+ /**
+ * getter for the {@link #setServerTimeZoneId(String) serverTimeZoneId} property.
+ * @return Returns the serverTimeZoneId property.
+ */
+ public String getServerTimeZoneId() {
+ return serverTimeZoneId;
+ }
+
+ /**
+ * en_US
locales.
+ * java.text.SimpleDateFormat
.
+ * property.
+ * java.text.SimpleDateFormat
.
+ * java.util.TimeZone
to refer to time zones, for example,
+ * America/Chicago
or Asia/Rangoon
.
+ * "jan|feb|mar|apr|maí|jún|júl|ágú|sep|okt|nóv|des"
.
+ * en_US
+ * month names will be used. We are supporting here those language
+ * codes which, when a java.util.Locale
is constucted
+ * using it, and a java.text.SimpleDateFormat
is
+ * constructed using that Locale, the array returned by the
+ * SimpleDateFormat's getShortMonths()
method consists
+ * solely of three 8-bit ASCII character strings. Additionally,
+ * languages which do not meet this requirement are included if a
+ * common alternative set of short month names is known to be used.
+ * This means that users who can tell us of additional such encodings
+ * may get them added to the list of supported languages by contacting
+ * the jakarta-commons-net team.
+ * en_US
date format
+ * orderings of MMM d yyyy
and MMM d HH:mm
+ * and attempting to deduce this automatically here would cause more
+ * problems than it would solve. The date format must be changed
+ * via the {@link #setDefaultDateFormatStr(String) defaultDateFormatStr} and/or
+ * {@link #setRecentDateFormatStr(String) recentDateFormatStr} parameters.
+ * Locale.US
+ * @param languageCode See {@link #setServerLanguageCode(String) serverLanguageCode}
+ * @return a DateFormatSymbols object configured with short month names
+ * corresponding to the supplied code, or with month names for
+ * Locale.US
if there is no corresponding entry in the internal
+ * table.
+ */
+ public static DateFormatSymbols lookupDateFormatSymbols(String languageCode)
+ {
+ Object lang = LANGUAGE_CODE_MAP.get(languageCode);
+ if (lang != null) {
+ if (lang instanceof Locale) {
+ return new DateFormatSymbols((Locale) lang);
+ } else if (lang instanceof String){
+ return getDateFormatSymbols((String) lang);
+ }
+ }
+ return new DateFormatSymbols(Locale.US);
+ }
+
+ /**
+ * Returns a DateFormatSymbols object configured with short month names
+ * as in the supplied string
+ * @param shortmonths This should be as described in
+ * {@link #setShortMonthNames(String) shortMonthNames}
+ * @return a DateFormatSymbols object configured with short month names
+ * as in the supplied string
+ */
+ public static DateFormatSymbols getDateFormatSymbols(String shortmonths)
+ {
+ String[] months = splitShortMonthString(shortmonths);
+ DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
+ dfs.setShortMonths(months);
+ return dfs;
+ }
+
+ private static String[] splitShortMonthString(String shortmonths) {
+ StringTokenizer st = new StringTokenizer(shortmonths, "|");
+ int monthcnt = st.countTokens();
+ if (12 != monthcnt) {
+ throw new IllegalArgumentException(
+ "expecting a pipe-delimited string containing 12 tokens");
+ }
+ String[] months = new String[13];
+ int pos = 0;
+ while(st.hasMoreTokens()) {
+ months[pos++] = st.nextToken();
+ }
+ months[pos]="";
+ return months;
+ }
+
+ /**
+ * Returns a Collection of all the language codes currently supported
+ * by this class. See {@link #setServerLanguageCode(String) serverLanguageCode}
+ * for a functional descrption of language codes within this system.
+ *
+ * @return a Collection of all the language codes currently supported
+ * by this class
+ */
+ public static CollectionDIRECTORY_TYPE
, false if
+ * not.
+ ***/
+ public boolean isDirectory()
+ {
+ return (_type == DIRECTORY_TYPE);
+ }
+
+ /***
+ * Determine if the file is a regular file.
+ * FILE_TYPE
, false if
+ * not.
+ ***/
+ public boolean isFile()
+ {
+ return (_type == FILE_TYPE);
+ }
+
+ /***
+ * Determine if the file is a symbolic link.
+ * UNKNOWN_TYPE
, false if
+ * not.
+ ***/
+ public boolean isSymbolicLink()
+ {
+ return (_type == SYMBOLIC_LINK_TYPE);
+ }
+
+ /***
+ * Determine if the type of the file is unknown.
+ * UNKNOWN_TYPE
, false if
+ * not.
+ ***/
+ public boolean isUnknown()
+ {
+ return (_type == UNKNOWN_TYPE);
+ }
+
+
+ /***
+ * Set the type of the file (DIRECTORY_TYPE
,
+ * FILE_TYPE
, etc.).
+ * _TYPE
constants),
+ * e.g., if it is a directory, a regular file, or a symbolic link.
+ * _ACCESS
+ * constants) has the given access permission (one of the
+ * _PERMISSION
constants) to the file.
+ * _ACCESS
+ * constants)
+ * @param permission The access permission (one of the
+ * _PERMISSION
constants)
+ * @param value True if permission is allowed, false if not.
+ ***/
+ public void setPermission(int access, int permission, boolean value)
+ {
+ _permissions[access][permission] = value;
+ }
+
+
+ /***
+ * Determines if the given access group (one of the _ACCESS
+ * constants) has the given access permission (one of the
+ * _PERMISSION
constants) to the file.
+ * _ACCESS
+ * constants)
+ * @param permission The access permission (one of the
+ * _PERMISSION
constants)
+ ***/
+ public boolean hasPermission(int access, int permission)
+ {
+ return _permissions[access][permission];
+ }
+
+
+ /***
+ * Returns a string representation of the FTPFile information. This
+ * will be the raw FTP server listing that was used to initialize the
+ * FTPFile instance.
+ * FTPFile
objects are not created until needed. This
+ * is suitable for paged displays. It requires that a parser object be created
+ * beforehand: parser
is an object (in the package
+ * org.apache.commons.net.ftp.parser
)
+ * implementing this inteface.
+ *
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFileList list = f.createFileList(directory, parser);
+ * FTPFileIterator iter = list.iterator();
+ *
+ * while (iter.hasNext()) {
+ * FTPFile[] files = iter.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ *
+ * The second example uses the revised FTPClient.listFiles()
+ * API to pull the whole list from the subfolder subfolder
in
+ * one call, attempting to automatically detect the parser type. This
+ * method, without a parserKey parameter, indicates that autodection should
+ * be used.
+ *
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = f.listFiles("subfolder");
+ *
+ *
+ * The third example uses the revised FTPClient.listFiles()
>
+ * API to pull the whole list from the current working directory in one call,
+ * but specifying by classname the parser to be used. For this particular
+ * parser class, this approach is necessary since there is no way to
+ * autodetect this server type.
+ *
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = f.listFiles(
+ * "org.apache.commons.net.ftp.parser.EnterpriseUnixFTPFileEntryParser",
+ * ".");
+ *
+ *
+ * The fourth example uses the revised FTPClient.listFiles()
+ * API to pull a single file listing in an arbitrary directory in one call,
+ * specifying by KEY the parser to be used, in this case, VMS.
+ *
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPFile[] files = f.listFiles("VMS", "subfolder/foo.java");
+ *
+ *
+ * @author Steve Cohen
+ * @version $Id: FTPFileEntryParser.java 636854 2008-03-13 19:55:01Z sebb $
+ * @see org.apache.commons.net.ftp.FTPFile
+ * @see org.apache.commons.net.ftp.FTPClient#createFileList
+ */
+public interface FTPFileEntryParser
+{
+ /**
+ * Parses a line of an FTP server file listing and converts it into a usable
+ * format in the form of an FTPFile
instance. If the
+ * file listing line doesn't describe a file, null
should be
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ * original
unmodified.
+ */
+ public ListreadNextEntry()
- which handles the issue of
+ * what delimits one entry from another, usually but not always a line
+ * feed and preParse()
- which handles removal of
+ * extraneous matter such as the preliminary lines of a listing, removal
+ * of duplicates on versioning systems, etc.
+ * getNext()
and
+ * getPrevious()
methods to provide "paged" output of less
+ * than the whole list at one time, or by calling the
+ * getFiles()
method to return the entire list.
+ *
+ * FTPClient f=FTPClient();
+ * f.connect(server);
+ * f.login(username, password);
+ * FTPListParseEngine engine = f.initiateListParsing(directory);
+ *
+ * while (engine.hasNext()) {
+ * FTPFile[] files = engine.getNext(25); // "page size" you want
+ * //do whatever you want with these files, display them, etc.
+ * //expensive FTPFile objects not created until needed.
+ * }
+ *
+ * entries
list.
+ * After this method has completed, entries
will contain a
+ * collection of entries (as defined by
+ * FTPFileEntryParser.readNextEntry()
), but this may contain
+ * various non-entry preliminary lines from the server output, duplicates,
+ * and other data that will not be part of the final listing.
+ *
+ * @param stream The socket stream on which the input will be read.
+ * @param encoding The encoding to use.
+ *
+ * @exception IOException
+ * thrown on any failure to read the stream
+ */
+ private void readStream(InputStream stream, String encoding) throws IOException
+ {
+ BufferedReader reader;
+ if (encoding == null)
+ {
+ reader = new BufferedReader(new InputStreamReader(stream));
+ }
+ else
+ {
+ reader = new BufferedReader(new InputStreamReader(stream, encoding));
+ }
+
+ String line = this.parser.readNextEntry(reader);
+
+ while (line != null)
+ {
+ this.entries.add(line);
+ line = this.parser.readNextEntry(reader);
+ }
+ reader.close();
+ }
+
+ /**
+ * Returns an array of at most quantityRequested
FTPFile
+ * objects starting at this object's internal iterator's current position.
+ * If fewer than quantityRequested
such
+ * elements are available, the returned array will have a length equal
+ * to the number of entries at and after after the current position.
+ * If no such entries are found, this array will have a length of 0.
+ *
+ * After this method is called this object's internal iterator is advanced
+ * by a number of positions equal to the size of the array returned.
+ *
+ * @param quantityRequested
+ * the maximum number of entries we want to get.
+ *
+ * @return an array of at most quantityRequested
FTPFile
+ * objects starting at the current position of this iterator within its
+ * list and at least the number of elements which exist in the list at
+ * and after its current position.
+ * quantityRequested
FTPFile
+ * objects starting at this object's internal iterator's current position,
+ * and working back toward the beginning.
+ *
+ * If fewer than quantityRequested
such
+ * elements are available, the returned array will have a length equal
+ * to the number of entries at and after after the current position.
+ * If no such entries are found, this array will have a length of 0.
+ *
+ * After this method is called this object's internal iterator is moved
+ * back by a number of positions equal to the size of the array returned.
+ *
+ * @param quantityRequested
+ * the maximum number of entries we want to get.
+ *
+ * @return an array of at most quantityRequested
FTPFile
+ * objects starting at the current position of this iterator within its
+ * list and at least the number of elements which exist in the list at
+ * and after its current position. This array will be in the same order
+ * as the underlying list (not reversed).
+ * timestampParser
for extracting the timestamp.
+ * @return a java.util.Calendar
containing results of the
+ * timestamp parse.
+ */
+ public Calendar parseTimestamp(String timestampStr) throws ParseException {
+ return this.timestampParser.parseTimestamp(timestampStr);
+ }
+
+
+ /**
+ * Implementation of the {@link Configurable Configurable}
+ * interface. Configures this parser by delegating to the
+ * underlying Configurable FTPTimestampParser implementation, '
+ * passing it the supplied {@link FTPClientConfig FTPClientConfig}
+ * if that is non-null or a default configuration defined by
+ * each concrete subclass.
+ * key
is not recognized as a fully qualified
+ * classname known to the system, this method will then attempt
+ * to see whether it contains a string identifying one of
+ * the known parsers. This comparison is case-insensitive.
+ * The intent here is where possible, to select as keys strings
+ * which are returned by the SYST command on the systems which
+ * the corresponding parser successfully parses. This enables
+ * this factory to be used in the auto-detection system.
+ *
+ *
+ * @param key should be a fully qualified classname corresponding to
+ * a class implementing the FTPFileEntryParser interface
+ * OR
+ * a string containing (case-insensitively) one of the
+ * following keywords:
+ *
+ *
+ * @return the FTPFileEntryParser corresponding to the supplied key.
+ * @throws ParserInitializationException thrown if for any reason the factory cannot resolve
+ * the supplied key into an FTPFileEntryParser.
+ * @see FTPFileEntryParser
+ */
+ public FTPFileEntryParser createFileEntryParser(String key)
+ {
+ if (key == null)
+ throw new ParserInitializationException("Parser key cannot be null");
+
+ Class> parserClass = null;
+ FTPFileEntryParser parser = null;
+ try
+ {
+ parserClass = Class.forName(key);
+ parser = (FTPFileEntryParser) parserClass.newInstance();
+ }
+ catch (ClassNotFoundException e)
+ {
+ try
+ {
+ String ukey = null;
+ if (null != key)
+ {
+ ukey = key.toUpperCase(java.util.Locale.ENGLISH);
+ }
+ if ((ukey.indexOf(FTPClientConfig.SYST_UNIX) >= 0)
+ || (ukey.indexOf(FTPClientConfig.SYST_L8) >= 0))
+ {
+ parser = createUnixFTPEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_VMS) >= 0)
+ {
+ parser = createVMSVersioningFTPEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_NT) >= 0)
+ {
+ parser = createNTFTPEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_OS2) >= 0)
+ {
+ parser = createOS2FTPEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_OS400) >= 0 ||
+ ukey.indexOf(FTPClientConfig.SYST_AS400) >= 0)
+ {
+ parser = createOS400FTPEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_MVS) >= 0)
+ {
+ parser = createMVSEntryParser();
+ }
+ else if (ukey.indexOf(FTPClientConfig.SYST_NETWARE) >= 0)
+ {
+ parser = createNetwareFTPEntryParser();
+ }
+ else
+ {
+ throw new ParserInitializationException("Unknown parser type: " + key);
+ }
+ }
+ catch (NoClassDefFoundError nf) {
+ throw new ParserInitializationException("Error initializing parser", nf);
+ }
+
+ }
+ catch (NoClassDefFoundError e)
+ {
+ throw new ParserInitializationException("Error initializing parser", e);
+ }
+ catch (ClassCastException e)
+ {
+ throw new ParserInitializationException(parserClass.getName()
+ + " does not implement the interface "
+ + "org.apache.commons.net.ftp.FTPFileEntryParser.", e);
+ }
+ catch (Throwable e)
+ {
+ throw new ParserInitializationException("Error initializing parser", e);
+ }
+
+ if (parser instanceof Configurable) {
+ ((Configurable)parser).configure(this.config);
+ }
+ return parser;
+ }
+
+ /**
+ * FTPFile
instance. If
+ * the file listing line doesn't describe a file, null
is
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ *
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry)
+ {
+
+ FTPFile file = new FTPFile();
+ file.setRawListing(entry);
+
+ if (matches(entry))
+ {
+ String usr = group(14);
+ String grp = group(15);
+ String filesize = group(16);
+ String mo = group(17);
+ String da = group(18);
+ String yr = group(20);
+ String hr = group(21);
+ String min = group(22);
+ String name = group(23);
+
+ file.setType(FTPFile.FILE_TYPE);
+ file.setUser(usr);
+ file.setGroup(grp);
+ try
+ {
+ file.setSize(Long.parseLong(filesize));
+ }
+ catch (NumberFormatException e)
+ {
+ // intentionally do nothing
+ }
+
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.MILLISECOND, 0);
+ cal.set(Calendar.SECOND,
+ 0);
+ cal.set(Calendar.MINUTE,
+ 0);
+ cal.set(Calendar.HOUR_OF_DAY,
+ 0);
+ try
+ {
+
+ int pos = MONTHS.indexOf(mo);
+ int month = pos / 4;
+ if (yr != null)
+ {
+ // it's a year
+ cal.set(Calendar.YEAR,
+ Integer.parseInt(yr));
+ }
+ else
+ {
+ // it must be hour/minute or we wouldn't have matched
+ int year = cal.get(Calendar.YEAR);
+
+ // if the month we're reading is greater than now, it must
+ // be last year
+ if (cal.get(Calendar.MONTH) < month)
+ {
+ year--;
+ }
+ cal.set(Calendar.YEAR,
+ year);
+ cal.set(Calendar.HOUR_OF_DAY,
+ Integer.parseInt(hr));
+ cal.set(Calendar.MINUTE,
+ Integer.parseInt(min));
+ }
+ cal.set(Calendar.MONTH,
+ month);
+ cal.set(Calendar.DATE,
+ Integer.parseInt(da));
+ file.setTimestamp(cal);
+ }
+ catch (NumberFormatException e)
+ {
+ // do nothing, date will be uninitialized
+ }
+ file.setName(name);
+
+ return file;
+ }
+ return null;
+ }
+}
diff --git a/src/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java b/src/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
new file mode 100644
index 0000000..e80ec0d
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFileEntryParser;
+
+/**
+ * The interface describes a factory for creating FTPFileEntryParsers.
+ * @since 1.2
+ */
+public interface FTPFileEntryParserFactory
+{
+ /**
+ * Implementation should be a method that decodes the
+ * supplied key and creates an object implementing the
+ * interface FTPFileEntryParser.
+ *
+ * @param key A string that somehow identifies an
+ * FTPFileEntryParser to be created.
+ *
+ * @return the FTPFileEntryParser created.
+ * @exception ParserInitializationException
+ * Thrown on any exception in instantiation
+ */
+ public FTPFileEntryParser createFileEntryParser(String key)
+ throws ParserInitializationException;
+
+ /**
+ *java.util.Calendar
object initialized to the date
+ * parsed by the parser
+ * @throws ParseException if none of the parser mechanisms belonging to
+ * the implementor can parse the input.
+ */
+ public Calendar parseTimestamp(String timestampStr) throws ParseException;
+
+}
diff --git a/src/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java b/src/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
new file mode 100644
index 0000000..02a0cc8
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
@@ -0,0 +1,301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+
+import java.text.DateFormatSymbols;
+import java.text.ParseException;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.apache.commons.net.ftp.Configurable;
+import org.apache.commons.net.ftp.FTPClientConfig;
+
+/**
+ * Default implementation of the {@link FTPTimestampParser FTPTimestampParser}
+ * interface also implements the {@link org.apache.commons.net.ftp.Configurable Configurable}
+ * interface to allow the parsing to be configured from the outside.
+ *
+ * @see ConfigurableFTPFileEntryParserImpl
+ * @since 1.4
+ */
+public class FTPTimestampParserImpl implements
+ FTPTimestampParser, Configurable
+{
+
+
+ private SimpleDateFormat defaultDateFormat;
+ private SimpleDateFormat recentDateFormat;
+ private boolean lenientFutureDates = false;
+
+
+ /**
+ * The only constructor for this class.
+ */
+ public FTPTimestampParserImpl() {
+ setDefaultDateFormat(DEFAULT_SDF);
+ setRecentDateFormat(DEFAULT_RECENT_SDF);
+ }
+
+ /**
+ * Implements the one {@link FTPTimestampParser#parseTimestamp(String) method}
+ * in the {@link FTPTimestampParser FTPTimestampParser} interface
+ * according to this algorithm:
+ *
+ * If the recentDateFormat member has been defined, try to parse the
+ * supplied string with that. If that parse fails, or if the recentDateFormat
+ * member has not been defined, attempt to parse with the defaultDateFormat
+ * member. If that fails, throw a ParseException.
+ *
+ * This method allows a {@link Calendar} instance to be passed in which represents the
+ * current (system) time.
+ *
+ * @see org.apache.commons.net.ftp.parser.FTPTimestampParser#parseTimestamp(java.lang.String)
+ *
+ * @param timestampStr The timestamp to be parsed
+ */
+ public Calendar parseTimestamp(String timestampStr) throws ParseException {
+ Calendar now = Calendar.getInstance();
+ return parseTimestamp(timestampStr, now);
+ }
+
+ /**
+ * Implements the one {@link FTPTimestampParser#parseTimestamp(String) method}
+ * in the {@link FTPTimestampParser FTPTimestampParser} interface
+ * according to this algorithm:
+ *
+ * If the recentDateFormat member has been defined, try to parse the
+ * supplied string with that. If that parse fails, or if the recentDateFormat
+ * member has not been defined, attempt to parse with the defaultDateFormat
+ * member. If that fails, throw a ParseException.
+ *
+ * @see org.apache.commons.net.ftp.parser.FTPTimestampParser#parseTimestamp(java.lang.String)
+ * @param timestampStr The timestamp to be parsed
+ * @param serverTime The current time for the server
+ * @since 1.5
+ */
+ public Calendar parseTimestamp(String timestampStr, Calendar serverTime) throws ParseException {
+ Calendar now = (Calendar) serverTime.clone();// Copy this, because we may change it
+ now.setTimeZone(this.getServerTimeZone());
+ Calendar working = (Calendar) now.clone();
+ working.setTimeZone(getServerTimeZone());
+ ParsePosition pp = new ParsePosition(0);
+
+ Date parsed = null;
+ if (recentDateFormat != null) {
+ if (lenientFutureDates) {
+ // add a day to "now" so that "slop" doesn't cause a date
+ // slightly in the future to roll back a full year. (Bug 35181)
+ now.add(Calendar.DATE, 1);
+ }
+ parsed = recentDateFormat.parse(timestampStr, pp);
+ }
+ if (parsed != null && pp.getIndex() == timestampStr.length())
+ {
+ working.setTime(parsed);
+ working.set(Calendar.YEAR, now.get(Calendar.YEAR));
+
+ if (working.after(now)) {
+ working.add(Calendar.YEAR, -1);
+ }
+ } else {
+ // Temporarily add the current year to the short date time
+ // to cope with short-date leap year strings.
+ // e.g. Java's DateFormatter will assume that "Feb 29 12:00" refers to
+ // Feb 29 1970 (an invalid date) rather than a potentially valid leap year date.
+ // This is pretty bad hack to work around the deficiencies of the JDK date/time classes.
+ if (recentDateFormat != null) {
+ pp = new ParsePosition(0);
+ int year = now.get(Calendar.YEAR);
+ String timeStampStrPlusYear = timestampStr + " " + year;
+ SimpleDateFormat hackFormatter = new SimpleDateFormat(recentDateFormat.toPattern() + " yyyy",
+ recentDateFormat.getDateFormatSymbols());
+ hackFormatter.setLenient(false);
+ hackFormatter.setTimeZone(recentDateFormat.getTimeZone());
+ parsed = hackFormatter.parse(timeStampStrPlusYear, pp);
+ }
+ if (parsed != null && pp.getIndex() == timestampStr.length() + 5) {
+ working.setTime(parsed);
+ }
+ else {
+ pp = new ParsePosition(0);
+ parsed = defaultDateFormat.parse(timestampStr, pp);
+ // note, length checks are mandatory for us since
+ // SimpleDateFormat methods will succeed if less than
+ // full string is matched. They will also accept,
+ // despite "leniency" setting, a two-digit number as
+ // a valid year (e.g. 22:04 will parse as 22 A.D.)
+ // so could mistakenly confuse an hour with a year,
+ // if we don't insist on full length parsing.
+ if (parsed != null && pp.getIndex() == timestampStr.length()) {
+ working.setTime(parsed);
+ } else {
+ throw new ParseException(
+ "Timestamp could not be parsed with older or recent DateFormat",
+ pp.getIndex());
+ }
+ }
+ }
+ return working;
+ }
+
+ /**
+ * @return Returns the defaultDateFormat.
+ */
+ public SimpleDateFormat getDefaultDateFormat() {
+ return defaultDateFormat;
+ }
+ /**
+ * @return Returns the defaultDateFormat pattern string.
+ */
+ public String getDefaultDateFormatString() {
+ return defaultDateFormat.toPattern();
+ }
+ /**
+ * @param defaultDateFormat The defaultDateFormat to be set.
+ */
+ private void setDefaultDateFormat(String format) {
+ if (format != null) {
+ this.defaultDateFormat = new SimpleDateFormat(format);
+ this.defaultDateFormat.setLenient(false);
+ }
+ }
+ /**
+ * @return Returns the recentDateFormat.
+ */
+ public SimpleDateFormat getRecentDateFormat() {
+ return recentDateFormat;
+ }
+ /**
+ * @return Returns the recentDateFormat.
+ */
+ public String getRecentDateFormatString() {
+ return recentDateFormat.toPattern();
+ }
+ /**
+ * @param recentDateFormat The recentDateFormat to set.
+ */
+ private void setRecentDateFormat(String format) {
+ if (format != null) {
+ this.recentDateFormat = new SimpleDateFormat(format);
+ this.recentDateFormat.setLenient(false);
+ }
+ }
+
+ /**
+ * @return returns an array of 12 strings representing the short
+ * month names used by this parse.
+ */
+ public String[] getShortMonths() {
+ return defaultDateFormat.getDateFormatSymbols().getShortMonths();
+ }
+
+
+ /**
+ * @return Returns the serverTimeZone used by this parser.
+ */
+ public TimeZone getServerTimeZone() {
+ return this.defaultDateFormat.getTimeZone();
+ }
+ /**
+ * sets a TimeZone represented by the supplied ID string into all
+ * of the parsers used by this server.
+ * @param serverTimeZone Time Id java.util.TimeZone id used by
+ * the ftp server. If null the client's local time zone is assumed.
+ */
+ private void setServerTimeZone(String serverTimeZoneId) {
+ TimeZone serverTimeZone = TimeZone.getDefault();
+ if (serverTimeZoneId != null) {
+ serverTimeZone = TimeZone.getTimeZone(serverTimeZoneId);
+ }
+ this.defaultDateFormat.setTimeZone(serverTimeZone);
+ if (this.recentDateFormat != null) {
+ this.recentDateFormat.setTimeZone(serverTimeZone);
+ }
+ }
+
+ /**
+ * Implementation of the {@link Configurable Configurable}
+ * interface. Configures this FTPTimestampParser
according
+ * to the following logic:
+ *
+ *
config
, use that to parse parse timestamps.config
, use the month names represented
+ * by that {@link FTPClientConfig#lookupDateFormatSymbols(String) language}
+ * to parse timestamps. FTPFile
instance.
+ * If the file listing line doesn't describe a file, then
+ * null
is returned. Otherwise a FTPFile
+ * instance representing the file is returned.
+ *
+ * @param entry
+ * A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry) {
+ boolean isParsed = false;
+ FTPFile f = new FTPFile();
+
+ if (isType == FILE_LIST_TYPE)
+ isParsed = parseFileList(f, entry);
+ else if (isType == MEMBER_LIST_TYPE) {
+ isParsed = parseMemberList(f, entry);
+ if (!isParsed)
+ isParsed = parseSimpleEntry(f, entry);
+ } else if (isType == UNIX_LIST_TYPE) {
+ isParsed = parseUnixList(f, entry);
+ } else if (isType == JES_LEVEL_1_LIST_TYPE) {
+ isParsed = parseJeslevel1List(f, entry);
+ } else if (isType == JES_LEVEL_2_LIST_TYPE) {
+ isParsed = parseJeslevel2List(f, entry);
+ }
+
+ if (!isParsed)
+ f = null;
+
+ return f;
+ }
+
+ /**
+ * Parse entries representing a dataset list. Only datasets with DSORG PS or
+ * PO or PO-E and with RECFM F* or V* will be parsed.
+ *
+ * Format of ZOS/MVS file list: 1 2 3 4 5 6 7 8 9 10 Volume Unit Referred
+ * Ext Used Recfm Lrecl BlkSz Dsorg Dsname B10142 3390 2006/03/20 2 31 F 80
+ * 80 PS MDI.OKL.WORK ARCIVE Not Direct Access Device
+ * KJ.IOP998.ERROR.PL.UNITTEST B1N231 3390 2006/03/20 1 15 VB 256 27998 PO
+ * PLU B1N231 3390 2006/03/20 1 15 VB 256 27998 PO-E PLB
+ *
+ * ----------------------------------- Group within Regex [1] Volume [2]
+ * Unit [3] Referred [4] Ext: number of extents [5] Used [6] Recfm: Record
+ * format [7] Lrecl: Logical record length [8] BlkSz: Block size [9] Dsorg:
+ * Dataset organisation. Many exists but only support: PS, PO, PO-E [10]
+ * Dsname: Dataset name
+ *
+ * Note: When volume is ARCIVE, it means the dataset is stored somewhere in
+ * a tape archive. These entries is currently not supported by this parser.
+ * A null value is returned.
+ *
+ * @param file
+ * will be updated with Name, Type, Timestamp if parsed.
+ * @param entry zosDirectoryEntry
+ * @return true: entry was parsed, false: entry was not parsed.
+ */
+ private boolean parseFileList(FTPFile file, String entry) {
+ if (matches(entry)) {
+ file.setRawListing(entry);
+ String name = group(2);
+ String dsorg = group(1);
+ file.setName(name);
+
+ // DSORG
+ if ("PS".equals(dsorg)) {
+ file.setType(FTPFile.FILE_TYPE);
+ }
+ else if ("PO".equals(dsorg) || "PO-E".equals(dsorg)) {
+ // regex already ruled out anything other than PO or PO-E
+ file.setType(FTPFile.DIRECTORY_TYPE);
+ }
+ else {
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Parse entries within a partitioned dataset.
+ *
+ * Format of a memberlist within a PDS: 1 2 3 4 5 6 7 8 9 Name VV.MM Created
+ * Changed Size Init Mod Id TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11
+ * 0 KIL001 TBTOOL 01.12 2002/09/12 2004/11/26 19:54 51 28 0 KIL001
+ *
+ * ------------------------------------------- [1] Name [2] VV.MM: Version .
+ * modification [3] Created: yyyy / MM / dd [4,5] Changed: yyyy / MM / dd
+ * HH:mm [6] Size: number of lines [7] Init: number of lines when first
+ * created [8] Mod: number of modified lines a last save [9] Id: User id for
+ * last update
+ *
+ *
+ * @param file
+ * will be updated with Name, Type and Timestamp if parsed.
+ * @param entry zosDirectoryEntry
+ * @return true: entry was parsed, false: entry was not parsed.
+ */
+ private boolean parseMemberList(FTPFile file, String entry) {
+ if (matches(entry)) {
+ file.setRawListing(entry);
+ String name = group(1);
+ String datestr = group(2) + " " + group(3);
+ file.setName(name);
+ file.setType(FTPFile.FILE_TYPE);
+ try {
+ file.setTimestamp(super.parseTimestamp(datestr));
+ } catch (ParseException e) {
+ e.printStackTrace();
+ // just ignore parsing errors.
+ // TODO check this is ok
+ return false; // this is a parsing failure too.
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Assigns the name to the first word of the entry. Only to be used from a
+ * safe context, for example from a memberlist, where the regex for some
+ * reason fails. Then just assign the name field of FTPFile.
+ *
+ * @param file
+ * @param entry
+ * @return
+ */
+ private boolean parseSimpleEntry(FTPFile file, String entry) {
+ if (entry != null && entry.length() > 0) {
+ file.setRawListing(entry);
+ String name = entry.split(" ")[0];
+ file.setName(name);
+ file.setType(FTPFile.FILE_TYPE);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Parse the entry as a standard unix file. Using the UnixFTPEntryParser.
+ *
+ * @param file
+ * @param entry
+ * @return true: entry is parsed, false: entry could not be parsed.
+ */
+ private boolean parseUnixList(FTPFile file, String entry) {
+ file = unixFTPEntryParser.parseFTPEntry(entry);
+ if (file == null)
+ return false;
+ return true;
+ }
+
+ /**
+ * Matches these entries, note: no header: [1] [2] [3] [4] [5] IBMUSER1
+ * JOB01906 OUTPUT 3 Spool Files
+ * 012345678901234567890123456789012345678901234 1 2 3 4
+ * ------------------------------------------- Group in regex [1] Job name
+ * [2] Job number [3] Job status (INPUT,ACTIVE,OUTPUT) [4] Number of sysout
+ * files [5] The string "Spool Files"
+ *
+ *
+ * @param file
+ * will be updated with Name, Type and Timestamp if parsed.
+ * @param entry zosDirectoryEntry
+ * @return true: entry was parsed, false: entry was not parsed.
+ */
+ private boolean parseJeslevel1List(FTPFile file, String entry) {
+ if (matches(entry)) {
+ if (group(3).equalsIgnoreCase("OUTPUT")) {
+ file.setRawListing(entry);
+ String name = group(2); /* Job Number, used by GET */
+ file.setName(name);
+ file.setType(FTPFile.FILE_TYPE);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Matches these entries, note: no header: [1] [2] [3] [4] [5] JOBNAME JOBID
+ * OWNER STATUS CLASS IBMUSER1 JOB01906 IBMUSER OUTPUT A RC=0000 3 spool
+ * files IBMUSER TSU01830 IBMUSER OUTPUT TSU ABEND=522 3 spool files
+ * 012345678901234567890123456789012345678901234 1 2 3 4
+ * ------------------------------------------- Group in regex [1] Job name
+ * [2] Job number [3] Owner [4] Job status (INPUT,ACTIVE,OUTPUT) [5] Job
+ * Class [6] The rest
+ *
+ *
+ * @param file
+ * will be updated with Name, Type and Timestamp if parsed.
+ * @param entry zosDirectoryEntry
+ * @return true: entry was parsed, false: entry was not parsed.
+ */
+ private boolean parseJeslevel2List(FTPFile file, String entry) {
+ if (matches(entry)) {
+ if (group(4).equalsIgnoreCase("OUTPUT")) {
+ file.setRawListing(entry);
+ String name = group(2); /* Job Number, used by GET */
+ file.setName(name);
+ file.setType(FTPFile.FILE_TYPE);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * preParse is called as part of the interface. Per definition is is called
+ * before the parsing takes place. Three kind of lists is recognize:
+ * z/OS-MVS File lists z/OS-MVS Member lists unix file lists
+ * @since 2.0
+ */
+ @Override
+ public ListREGEX
is not a valid regular expression.
+ */
+ public NTFTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of an NTFTPEntryParser object
+ * with something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public NTFTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+ /**
+ * Parses a line of an NT FTP server file listing and converts it into a
+ * usable format in the form of an FTPFile
instance. If the
+ * file listing line doesn't describe a file, null
is
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ * REGEX
is not a valid regular expression.
+ */
+ public NetwareFTPEntryParser() {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of an NetwareFTPEntryParser object
+ * with something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public NetwareFTPEntryParser(FTPClientConfig config) {
+ super(REGEX);
+ configure(config);
+ }
+
+ /**
+ * Parses a line of an NetwareFTP server file listing and converts it into a
+ * usable format in the form of an FTPFile
instance. If the
+ * file listing line doesn't describe a file, null
is
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ *
+ *
+ *
+ * See here
+ * for more details
+ *
+ * @param entry A line of text from the file listing
+ * @return An FTPFile instance corresponding to the supplied entry
+ */
+ public FTPFile parseFTPEntry(String entry) {
+
+ FTPFile f = new FTPFile();
+ if (matches(entry)) {
+ String dirString = group(1);
+ String attrib = group(2);
+ String user = group(3);
+ String size = group(4);
+ String datestr = group(5);
+ String name = group(9);
+
+ try {
+ f.setTimestamp(super.parseTimestamp(datestr));
+ } catch (ParseException e) {
+ // intentionally do nothing
+ }
+
+ //is it a DIR or a file
+ if (dirString.trim().equals("d")) {
+ f.setType(FTPFile.DIRECTORY_TYPE);
+ } else // Should be "-"
+ {
+ f.setType(FTPFile.FILE_TYPE);
+ }
+
+ f.setUser(user);
+
+ //set the name
+ f.setName(name.trim());
+
+ //set the size
+ f.setSize(Long.parseLong(size.trim()));
+
+ // Now set the permissions (or at least a subset thereof - full permissions would probably require
+ // subclassing FTPFile and adding extra metainformation there)
+ if (attrib.indexOf("R") != -1) {
+ f.setPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION,
+ true);
+ }
+ if (attrib.indexOf("W") != -1) {
+ f.setPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION,
+ true);
+ }
+
+ return (f);
+ }
+ return null;
+
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(FTPClientConfig.SYST_NETWARE,
+ DEFAULT_DATE_FORMAT, DEFAULT_RECENT_DATE_FORMAT, null, null,
+ null);
+ }
+
+}
diff --git a/src/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java b/src/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
new file mode 100644
index 0000000..dc02ffb
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+import java.text.ParseException;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFile;
+
+/**
+ * Implementation of FTPFileEntryParser and FTPFileListParser for OS2 Systems.
+ *
+ * @author Winston Ojeda
+ * @author Steve Cohen
+ * @version $Id: OS2FTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ */
+public class OS2FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
+
+{
+
+ private static final String DEFAULT_DATE_FORMAT
+ = "MM-dd-yy HH:mm"; //11-09-01 12:30
+ /**
+ * this is the regular expression used by this parser.
+ */
+ private static final String REGEX =
+ "\\s*([0-9]+)\\s*"
+ + "(\\s+|[A-Z]+)\\s*"
+ + "(DIR|\\s+)\\s*"
+ + "(\\S+)\\s+(\\S+)\\s+" /* date stuff */
+ + "(\\S.*)";
+
+ /**
+ * The default constructor for a OS2FTPEntryParser object.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ */
+ public OS2FTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of an OS2FTPEntryParser object
+ * with something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public OS2FTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+ /**
+ * Parses a line of an OS2 FTP server file listing and converts it into a
+ * usable format in the form of an FTPFile
instance. If the
+ * file listing line doesn't describe a file, null
is
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ * REGEX
is not a valid regular expression.
+ */
+ public OS400FTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of an OS400FTPEntryParser object
+ * with something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public OS400FTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+
+ public FTPFile parseFTPEntry(String entry)
+ {
+
+ FTPFile file = new FTPFile();
+ file.setRawListing(entry);
+ int type;
+
+ if (matches(entry))
+ {
+ String usr = group(1);
+ String filesize = group(2);
+ String datestr = group(3)+" "+group(4);
+ String typeStr = group(5);
+ String name = group(6);
+
+ try
+ {
+ file.setTimestamp(super.parseTimestamp(datestr));
+ }
+ catch (ParseException e)
+ {
+ // intentionally do nothing
+ }
+
+
+ if (typeStr.equalsIgnoreCase("*STMF"))
+ {
+ type = FTPFile.FILE_TYPE;
+ }
+ else if (typeStr.equalsIgnoreCase("*DIR"))
+ {
+ type = FTPFile.DIRECTORY_TYPE;
+ }
+ else
+ {
+ type = FTPFile.UNKNOWN_TYPE;
+ }
+
+ file.setType(type);
+
+ file.setUser(usr);
+
+ try
+ {
+ file.setSize(Long.parseLong(filesize));
+ }
+ catch (NumberFormatException e)
+ {
+ // intentionally do nothing
+ }
+
+ if (name.endsWith("/"))
+ {
+ name = name.substring(0, name.length() - 1);
+ }
+ int pos = name.lastIndexOf('/');
+ if (pos > -1)
+ {
+ name = name.substring(pos + 1);
+ }
+
+ file.setName(name);
+
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Defines a default configuration to be used when this class is
+ * instantiated without a {@link FTPClientConfig FTPClientConfig}
+ * parameter being specified.
+ * @return the default configuration for this parser.
+ */
+ @Override
+ protected FTPClientConfig getDefaultConfiguration() {
+ return new FTPClientConfig(
+ FTPClientConfig.SYST_OS400,
+ DEFAULT_DATE_FORMAT,
+ null, null, null, null);
+ }
+
+}
diff --git a/src/org/apache/commons/net/ftp/parser/ParserInitializationException.java b/src/org/apache/commons/net/ftp/parser/ParserInitializationException.java
new file mode 100644
index 0000000..8af9261
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/parser/ParserInitializationException.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+
+/**
+ * This class encapsulates all errors that may be thrown by
+ * the process of an FTPFileEntryParserFactory creating and
+ * instantiating an FTPFileEntryParser.
+ */
+public class ParserInitializationException extends RuntimeException {
+
+ /**
+ * Root exception that caused this to be thrown
+ */
+ private final Throwable rootCause;
+
+ /**
+ * Constucts a ParserInitializationException with just a message
+ *
+ * @param message Exception message
+ */
+ public ParserInitializationException(String message) {
+ super(message);
+ this.rootCause = null;
+ }
+
+ /**
+ * Constucts a ParserInitializationException with a message
+ * and a root cause.
+ *
+ * @param message Exception message
+ * @param rootCause root cause throwable that caused
+ * this to be thrown
+ */
+ public ParserInitializationException(String message, Throwable rootCause) {
+ super(message);
+ this.rootCause = rootCause;
+ }
+
+ /**
+ * returns the root cause of this exception or null
+ * if no root cause was specified.
+ *
+ * @return the root cause of this exception being thrown
+ */
+ public Throwable getRootCause() {
+ return this.rootCause;
+ }
+
+}
diff --git a/src/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java b/src/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java
new file mode 100644
index 0000000..5277444
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.commons.net.ftp.parser;
+
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.commons.net.ftp.FTPFileEntryParserImpl;
+
+/**
+ * This abstract class implements both the older FTPFileListParser and
+ * newer FTPFileEntryParser interfaces with default functionality.
+ * All the classes in the parser subpackage inherit from this.
+ *
+ * This is the base for all regular based FTPFileEntryParser
+ *
+ * @author Steve Cohen matchnum'th
group of the internal
+ * match or null if this method is called without a match having
+ * been made.
+ */
+ public String group(int matchnum) {
+ if (this.result == null) {
+ return null;
+ }
+ return this.result.group(matchnum);
+ }
+
+ /**
+ * For debugging purposes - returns a string shows each match group by
+ * number.
+ *
+ * @return a string shows each match group by number.
+ */
+
+ public String getGroupsAsString() {
+ StringBuffer b = new StringBuffer();
+ for (int i = 1; i <= this.result.groupCount(); i++) {
+ b.append(i).append(") ").append(this.result.group(i)).append(
+ System.getProperty("line.separator"));
+ }
+ return b.toString();
+ }
+
+ /**
+ * Alter the current regular expression being utilised for entry parsing
+ * and create a new {@link Pattern} instance.
+ * @param regex The new regular expression
+ * @return
+ * @since 2.0
+ */
+ public boolean setRegex(String regex) {
+ try {
+ pattern = Pattern.compile(regex);
+ } catch (PatternSyntaxException pse) {
+ throw new IllegalArgumentException("Unparseable regex supplied: "
+ + regex);
+ }
+ return (pattern != null);
+ }
+
+}
diff --git a/src/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java b/src/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
new file mode 100644
index 0000000..2a2a909
--- /dev/null
+++ b/src/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
@@ -0,0 +1,295 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.ftp.parser;
+import java.text.ParseException;
+
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPFile;
+
+/**
+ * Implementation FTPFileEntryParser and FTPFileListParser for standard
+ * Unix Systems.
+ *
+ * This class is based on the logic of Daniel Savarese's
+ * DefaultFTPListParser, but adapted to use regular expressions and to fit the
+ * new FTPFileEntryParser interface.
+ * @version $Id: UnixFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
+ * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
+ */
+public class UnixFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
+{
+
+ static final String DEFAULT_DATE_FORMAT
+ = "MMM d yyyy"; //Nov 9 2001
+
+ static final String DEFAULT_RECENT_DATE_FORMAT
+ = "MMM d HH:mm"; //Nov 9 20:06
+
+ static final String NUMERIC_DATE_FORMAT
+ = "yyyy-MM-dd HH:mm"; //2001-11-09 20:06
+
+ /**
+ * Some Linux distributions are now shipping an FTP server which formats
+ * file listing dates in an all-numeric format:
+ *
"yyyy-MM-dd HH:mm
.
+ * This is a very welcome development, and hopefully it will soon become
+ * the standard. However, since it is so new, for now, and possibly
+ * forever, we merely accomodate it, but do not make it the default.
+ * UnixFTPEntryParser(FTPClientConfig)
.
+ * Steve Cohen - 2005-04-17
+ */
+ public static final FTPClientConfig NUMERIC_DATE_CONFIG =
+ new FTPClientConfig(
+ FTPClientConfig.SYST_UNIX,
+ NUMERIC_DATE_FORMAT,
+ null, null, null, null);
+
+ /**
+ * this is the regular expression used by this parser.
+ *
+ * Permissions:
+ * r the file is readable
+ * w the file is writable
+ * x the file is executable
+ * - the indicated permission is not granted
+ * L mandatory locking occurs during access (the set-group-ID bit is
+ * on and the group execution bit is off)
+ * s the set-user-ID or set-group-ID bit is on, and the corresponding
+ * user or group execution bit is also on
+ * S undefined bit-state (the set-user-ID bit is on and the user
+ * execution bit is off)
+ * t the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and
+ * execution is on
+ * T the 1000 bit is turned on, and execution is off (undefined bit-
+ * state)
+ * e z/OS external link bit
+ */
+ private static final String REGEX =
+ "([bcdelfmpSs-])"
+ +"(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))\\+?\\s+"
+ + "(\\d+)\\s+"
+ + "(?:(\\S+(?:\\s\\S+)*?)\\s+)?" // owner name (optional spaces)
+ + "(?:(\\S+(?:\\s\\S+)*)\\s+)?" // group name (optional spaces)
+ + "(\\d+(?:,\\s*\\d+)?)\\s+"
+
+ /*
+ numeric or standard format date
+ */
+ + "((?:\\d+[-/]\\d+[-/]\\d+)|(?:\\S+\\s+\\S+))\\s+"
+
+ /*
+ year (for non-recent standard format)
+ or time (for numeric or recent standard format
+ */
+ + "(\\d+(?::\\d+)?)\\s+"
+
+ + "(\\S*)(\\s*.*)";
+
+
+ /**
+ * The default constructor for a UnixFTPEntryParser object.
+ *
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ */
+ public UnixFTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of a UnixFTPEntryParser object with
+ * something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public UnixFTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+
+ /**
+ * Parses a line of a unix (standard) FTP server file listing and converts
+ * it into a usable format in the form of an FTPFile
+ * instance. If the file listing line doesn't describe a file,
+ * null
is returned, otherwise a FTPFile
+ * instance representing the files in the directory is returned.
+ * REGEX
is not a valid regular expression.
+ */
+ public VMSFTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of a VMSFTPEntryParser object with
+ * something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public VMSFTPEntryParser(FTPClientConfig config)
+ {
+ super(REGEX);
+ configure(config);
+ }
+
+
+
+ /***
+ * Parses an FTP server file listing and converts it into a usable format
+ * in the form of an array of FTPFile
instances. If the
+ * file list contains no files, null
should be
+ * returned, otherwise an array of FTPFile
instances
+ * representing the files in the directory is returned.
+ * FTPFile
instance. If the
+ * file listing line doesn't describe a file, null
is
+ * returned, otherwise a FTPFile
instance representing the
+ * files in the directory is returned.
+ * REGEX
is not a valid regular expression.
+ */
+ public VMSVersioningFTPEntryParser()
+ {
+ this(null);
+ }
+
+ /**
+ * This constructor allows the creation of a VMSVersioningFTPEntryParser
+ * object with something other than the default configuration.
+ *
+ * @param config The {@link FTPClientConfig configuration} object used to
+ * configure this parser.
+ * @exception IllegalArgumentException
+ * Thrown if the regular expression is unparseable. Should not be seen
+ * under normal conditions. It it is seen, this is a sign that
+ * REGEX
is not a valid regular expression.
+ * @since 1.4
+ */
+ public VMSVersioningFTPEntryParser(FTPClientConfig config)
+ {
+ super();
+ configure(config);
+ try
+ {
+ //_preparse_matcher_ = new Perl5Matcher();
+ _preparse_pattern_ = Pattern.compile(PRE_PARSE_REGEX);
+ }
+ catch (PatternSyntaxException pse)
+ {
+ throw new IllegalArgumentException (
+ "Unparseable regex supplied: " + PRE_PARSE_REGEX);
+ }
+
+ }
+
+
+
+ private static class NameVersion {
+ String name;
+ int versionNumber;
+ NameVersion(String name, String vers) {
+ this.name = name;
+ this.versionNumber = Integer.parseInt(vers);
+ }
+ }
+
+ /**
+ * Implement hook provided for those implementers (such as
+ * VMSVersioningFTPEntryParser, and possibly others) which return
+ * multiple files with the same name to remove the duplicates ..
+ *
+ * @param original Original list
+ *
+ * @return Original list purged of duplicates
+ */
+ @Override
+ public ListUNKNOWN_STREAM_SIZE
if the
+ * size is unknown.
+ */
+ public CopyStreamEvent(Object source, long totalBytesTransferred,
+ int bytesTransferred, long streamSize)
+ {
+ super(source);
+ this.bytesTransferred = bytesTransferred;
+ this.totalBytesTransferred = totalBytesTransferred;
+ this.streamSize = streamSize;
+ }
+
+ /**
+ * Returns the number of bytes transferred by the write that triggered
+ * the event.
+ * @return The number of bytes transferred by the write that triggered
+ * the vent.
+ */
+ public int getBytesTransferred()
+ {
+ return bytesTransferred;
+ }
+
+ /**
+ * Returns the total number of bytes transferred so far by the copy
+ * operation.
+ * @return The total number of bytes transferred so far by the copy
+ * operation.
+ */
+ public long getTotalBytesTransferred()
+ {
+ return totalBytesTransferred;
+ }
+
+ /**
+ * Returns the size of the stream being copied.
+ * This may be set to UNKNOWN_STREAM_SIZE
if the
+ * size is unknown.
+ * @return The size of the stream being copied.
+ */
+ public long getStreamSize()
+ {
+ return streamSize;
+ }
+}
diff --git a/src/org/apache/commons/net/io/CopyStreamException.java b/src/org/apache/commons/net/io/CopyStreamException.java
new file mode 100644
index 0000000..8d34145
--- /dev/null
+++ b/src/org/apache/commons/net/io/CopyStreamException.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.io.IOException;
+
+/**
+ * The CopyStreamException class is thrown by the org.apache.commons.io.Util
+ * copyStream() methods. It stores the number of bytes confirmed to
+ * have been transferred before an I/O error as well as the IOException
+ * responsible for the failure of a copy operation.
+ * @see Util
+ * @author Daniel F. Savarese
+ * @version $Id: CopyStreamException.java 489397 2006-12-21 16:28:51Z rwinston $
+ */
+public class CopyStreamException extends IOException
+{
+ private long totalBytesTransferred;
+ private IOException ioException;
+
+ /**
+ * Creates a new CopyStreamException instance.
+ * @param message A message describing the error.
+ * @param bytesTransferred The total number of bytes transferred before
+ * an exception was thrown in a copy operation.
+ * @param exception The IOException thrown during a copy operation.
+ */
+ public CopyStreamException(String message,
+ long bytesTransferred,
+ IOException exception)
+ {
+ super(message);
+ totalBytesTransferred = bytesTransferred;
+ ioException = exception;
+ }
+
+ /**
+ * Returns the total number of bytes confirmed to have
+ * been transferred by a failed copy operation.
+ * @return The total number of bytes confirmed to have
+ * been transferred by a failed copy operation.
+ */
+ public long getTotalBytesTransferred()
+ {
+ return totalBytesTransferred;
+ }
+
+ /**
+ * Returns the IOException responsible for the failure of a copy operation.
+ * @return The IOException responsible for the failure of a copy operation.
+ */
+ public IOException getIOException()
+ {
+ return ioException;
+ }
+}
diff --git a/src/org/apache/commons/net/io/CopyStreamListener.java b/src/org/apache/commons/net/io/CopyStreamListener.java
new file mode 100644
index 0000000..9e97fb9
--- /dev/null
+++ b/src/org/apache/commons/net/io/CopyStreamListener.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.io;
+
+import java.util.EventListener;
+
+/**
+ * The CopyStreamListener class can accept CopyStreamEvents to keep track
+ * of the progress of a stream copying operation. However, it is currently
+ * not used that way within NetComponents for performance reasons. Rather
+ * the bytesTransferred(long, int) method is called directly rather than
+ * passing an event to bytesTransferred(CopyStreamEvent), saving the creation
+ * of a CopyStreamEvent instance. Also, the only place where
+ * CopyStreamListener is currently used within NetComponents is in the
+ * static methods of the uninstantiable org.apache.commons.io.Util class, which
+ * would preclude the use of addCopyStreamListener and
+ * removeCopyStreamListener methods. However, future additions may use the
+ * JavaBean event model, which is why the hooks have been included from the
+ * beginning.
+ * flush()
will
+ * not flush the last byte written if that byte was a carriage
+ * return. A call to {@link #close close() }, however, will
+ * flush the carriage return.
+ * copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE);
+ ***/
+ public static final long copyStream(InputStream source, OutputStream dest)
+ throws CopyStreamException
+ {
+ return copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE);
+ }
+
+
+ /***
+ * Copies the contents of a Reader to a Writer using a
+ * copy buffer of a given size and notifies the provided
+ * CopyStreamListener of the progress of the copy operation by calling
+ * its bytesTransferred(long, int) method after each write to the
+ * destination. If you wish to notify more than one listener you should
+ * use a CopyStreamAdapter as the listener and register the additional
+ * listeners with the CopyStreamAdapter.
+ * copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE);
+ ***/
+ public static final long copyReader(Reader source, Writer dest)
+ throws CopyStreamException
+ {
+ return copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE);
+ }
+
+}
diff --git a/src/org/apache/commons/net/util/ListenerList.java b/src/org/apache/commons/net/util/ListenerList.java
new file mode 100644
index 0000000..796fb78
--- /dev/null
+++ b/src/org/apache/commons/net/util/ListenerList.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.util;
+
+import java.io.Serializable;
+import java.util.EventListener;
+import java.util.Iterator;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * @author Daniel F. Savarese
+ */
+
+public class ListenerList implements Serializable, Iterable super._connectAction_()
first to ensure the
- * initialization of the aforementioned protected variables.
- */
- protected void _connectAction_() throws IOException
- {
- _socket_.setSoTimeout(_timeout_);
- _input_ = _socket_.getInputStream();
- _output_ = _socket_.getOutputStream();
- }
-
-
- /**
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the current host at a system assigned port.
- * Before returning, {@link #_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- * separateErrorStream
- * parameter of {@link #rcommand rcommand() } to true
.
- * The standard input of the remote process can be written to through
- * the output stream returned by
- * {@link org.apache.commons.net.bsd.RExecClient#getOutputStream getOutputStream() }
- * .
- * DEFAULT_PORT
.
- ***/
- public RCommandClient()
- {
- setDefaultPort(DEFAULT_PORT);
- }
-
-
- /***
- * Opens a Socket connected to a remote host at the specified port and
- * originating from the specified local address using a port in a range
- * acceptable to the BSD rshell daemon.
- * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- * MIN_CLIENT_PORT
and
- * MAX_CLIENT_PORT
or an IllegalArgumentException will
- * be thrown.
- * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- * MIN_CLIENT_PORT
and
- * MAX_CLIENT_PORT
or an IllegalArgumentException will
- * be thrown.
- * Before returning, {@link org.apache.commons.net.SocketClient#_connectAction_ _connectAction_() }
- * is called to perform connection initialization actions.
- * rcommand(localUsername, remoteUsername, command, false);
- ***/
- public void rcommand(String localUsername, String remoteUsername,
- String command)
- throws IOException
- {
- rcommand(localUsername, remoteUsername, command, false);
- }
-
-}
-
diff --git a/org/apache/commons/net/bsd/RExecClient.java b/org/apache/commons/net/bsd/RExecClient.java
deleted file mode 100644
index 2924120..0000000
--- a/org/apache/commons/net/bsd/RExecClient.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.bsd;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.ServerSocket;
-import java.net.Socket;
-
-import org.apache.commons.net.SocketClient;
-import org.apache.commons.net.io.SocketInputStream;
-
-/***
- * RExecClient implements the rexec() facility that first appeared in
- * 4.2BSD Unix. This class will probably only be of use for connecting
- * to Unix systems and only when the rexecd daemon is configured to run,
- * which is a rarity these days because of the security risks involved.
- * However, rexec() can be very useful for performing administrative tasks
- * on a network behind a firewall.
- * separateErrorStream
- * parameter of {@link #rexec rexec() } to true
.
- * The standard input of the remote process can be written to through
- * the output stream returned by
- * {@link #getOutputStream getOutputSream() }.
- * _errorStream_
- * will point to an InputStream from which the standard error of the
- * remote process can be read (after a call to rexec()). Otherwise,
- * _errorStream_
will be null.
- ***/
- protected InputStream _errorStream_;
-
- // This can be overridden in local package to implement port range
- // limitations of rcmd and rlogin
- InputStream _createErrorStream() throws IOException
- {
- ServerSocket server;
- Socket socket;
-
- server = _serverSocketFactory_.createServerSocket(0, 1, getLocalAddress());
-
- _output_.write(Integer.toString(server.getLocalPort()).getBytes());
- _output_.write('\0');
- _output_.flush();
-
- socket = server.accept();
- server.close();
-
- if (__remoteVerificationEnabled && !verifyRemote(socket))
- {
- socket.close();
- throw new IOException(
- "Security violation: unexpected connection attempt by " +
- socket.getInetAddress().getHostAddress());
- }
-
- return (new SocketInputStream(socket, socket.getInputStream()));
- }
-
-
- /***
- * The default RExecClient constructor. Initializes the
- * default port to DEFAULT_PORT
.
- ***/
- public RExecClient()
- {
- _errorStream_ = null;
- setDefaultPort(DEFAULT_PORT);
- }
-
-
- /***
- * Returns the InputStream from which the standard outputof the remote
- * process can be read. The input stream will only be set after a
- * successful rexec() invocation.
- * rexec(username, password, command, false);
- ***/
- public void rexec(String username, String password,
- String command)
- throws IOException
- {
- rexec(username, password, command, false);
- }
-
- /***
- * Disconnects from the server, closing all associated open sockets and
- * streams.
- * DEFAULT_PORT
.
- ***/
- public RLoginClient()
- {
- setDefaultPort(DEFAULT_PORT);
- }
-
-
- /***
- * Logins into a remote machine through the rlogind daemon on the server
- * to which the RLoginClient is connected. After calling this method,
- * you may interact with the remote login shell through its standard input
- * and output streams. Standard error is sent over the same stream as
- * standard output. You will typically be able to detect
- * the termination of the remote login shell after reaching end of file
- * on its standard output (accessible through
- * {@link #getInputStream getInputStream() }. Disconnecting
- * from the server or closing the process streams before reaching
- * end of file will terminate the remote login shell in most cases.
- * DEFAULT_PORT
.
- ***/
- public CharGenTCPClient ()
- {
- setDefaultPort(DEFAULT_PORT);
- }
-
- /***
- * Returns an InputStream from which the server generated data can be
- * read. You should NOT close the InputStream when you're finished
- * reading from it. Rather, you should call
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * to clean up properly.
- * send(host, CharGenUDPClient.DEFAULT_PORT);
***/
- public void send(InetAddress host) throws IOException
- {
- send(host, DEFAULT_PORT);
- }
-
- /***
- * Receive the reply data from the server. This will always be 512 bytes
- * or less. Chargen and quote of the day only return one packet. Netstat
- * and systat require multiple calls to receive() with timeout detection.
- * DEFAULT_PORT
.
- ***/
- public DaytimeTCPClient ()
- {
- setDefaultPort(DEFAULT_PORT);
- }
-
- /***
- * Retrieves the time string from the server and returns it. The
- * server will have closed the connection at this point, so you should
- * call
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * after calling this method. To retrieve another time, you must
- * initiate another connection with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * before calling getTime()
again.
- * getTime(host, DaytimeUDPClient.DEFAULT_PORT);
***/
- public String getTime(InetAddress host) throws IOException
- {
- return getTime(host, DEFAULT_PORT);
- }
-
-}
-
diff --git a/org/apache/commons/net/discard/DiscardTCPClient.java b/org/apache/commons/net/discard/DiscardTCPClient.java
deleted file mode 100644
index 7a771c9..0000000
--- a/org/apache/commons/net/discard/DiscardTCPClient.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.discard;
-
-import java.io.OutputStream;
-
-import org.apache.commons.net.SocketClient;
-
-/***
- * The DiscardTCPClient class is a TCP implementation of a client for the
- * Discard protocol described in RFC 863. To use the class, merely
- * establish a connection with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * and call {@link #getOutputStream getOutputStream() } to
- * retrieve the discard output stream. Don't close the output stream
- * when you're done writing to it. Rather, call
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * to clean up properly.
- * DEFAULT_PORT
.
- ***/
- public DiscardTCPClient ()
- {
- setDefaultPort(DEFAULT_PORT);
- }
-
- /***
- * Returns an OutputStream through which you may write data to the server.
- * You should NOT close the OutputStream when you're finished
- * reading from it. Rather, you should call
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * to clean up properly.
- * send(data, length, host. DiscardUDPClient.DEFAULT_PORT)
.
- ***/
- public void send(byte[] data, int length, InetAddress host)
- throws IOException
- {
- send(data, length, host, DEFAULT_PORT);
- }
-
-
- /***
- * Same as
- * send(data, data.length, host. DiscardUDPClient.DEFAULT_PORT)
.
- ***/
- public void send(byte[] data, InetAddress host) throws IOException
- {
- send(data, data.length, host, DEFAULT_PORT);
- }
-
-}
-
diff --git a/org/apache/commons/net/echo/EchoTCPClient.java b/org/apache/commons/net/echo/EchoTCPClient.java
deleted file mode 100644
index b4d43e2..0000000
--- a/org/apache/commons/net/echo/EchoTCPClient.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.echo;
-
-import java.io.InputStream;
-
-import org.apache.commons.net.discard.DiscardTCPClient;
-
-/***
- * The EchoTCPClient class is a TCP implementation of a client for the
- * Echo protocol described in RFC 862. To use the class, merely
- * establish a connection with
- * {@link org.apache.commons.net.SocketClient#connect connect }
- * and call {@link DiscardTCPClient#getOutputStream getOutputStream() } to
- * retrieve the echo output stream and
- * {@link #getInputStream getInputStream() }
- * to get the echo input stream.
- * Don't close either stream when you're done using them. Rather, call
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * to clean up properly.
- * DEFAULT_PORT
.
- ***/
- public EchoTCPClient ()
- {
- setDefaultPort(DEFAULT_PORT);
- }
-
- /***
- * Returns an InputStream from which you may read echoed data from
- * the server. You should NOT close the InputStream when you're finished
- * reading from it. Rather, you should call
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect }
- * to clean up properly.
- * send(data, data.length, host)
***/
- @Override
- public void send(byte[] data, InetAddress host) throws IOException
- {
- send(data, data.length, host, DEFAULT_PORT);
- }
-
-
- /***
- * Receives echoed data and returns its length. The data may be divided
- * up among multiple datagrams, requiring multiple calls to receive.
- * Also, the UDP packets will not necessarily arrive in the same order
- * they were sent.
- * receive(data, data.length)
***/
- public int receive(byte[] data) throws IOException
- {
- return receive(data, data.length);
- }
-
-}
-
diff --git a/org/apache/commons/net/finger/FingerClient.java b/org/apache/commons/net/finger/FingerClient.java
deleted file mode 100644
index d3b6893..0000000
--- a/org/apache/commons/net/finger/FingerClient.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.net.finger;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.BufferedOutputStream;
-import java.io.DataOutputStream;
-
-import org.apache.commons.net.SocketClient;
-
-/***
- * The FingerClient class implements the client side of the Internet Finger
- * Protocol defined in RFC 1288. To finger a host you create a
- * FingerClient instance, connect to the host, query the host, and finally
- * disconnect from the host. If the finger service you want to query is on
- * a non-standard port, connect to the host at that port.
- * Here's a sample use:
- *
- * FingerClient finger;
- *
- * finger = new FingerClient();
- *
- * try {
- * finger.connect("foo.bar.com");
- * System.out.println(finger.query("foobar", false));
- * finger.disconnect();
- * } catch(IOException e) {
- * System.err.println("Error I/O exception: " + e.getMessage());
- * return;
- * }
- *
- * DEFAULT_PORT
.
- ***/
- public FingerClient()
- {
- setDefaultPort(DEFAULT_PORT);
- }
-
-
- /***
- * Fingers a user at the connected host and returns the output
- * as a String. You must first connect to a finger server before
- * calling this method, and you should disconnect afterward.
- * query(longOutput, "")
.
- * config
are somehow inadequate to configure the
- * Configurable object.
- */
- public void configure(FTPClientConfig config);
-}
diff --git a/org/apache/commons/net/ftp/FTP.class b/org/apache/commons/net/ftp/FTP.class
deleted file mode 100644
index a363d55..0000000
Binary files a/org/apache/commons/net/ftp/FTP.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/FTP.java b/org/apache/commons/net/ftp/FTP.java
deleted file mode 100644
index 6e2eff8..0000000
--- a/org/apache/commons/net/ftp/FTP.java
+++ /dev/null
@@ -1,1513 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import org.apache.commons.net.MalformedServerReplyException;
-import org.apache.commons.net.ProtocolCommandListener;
-import org.apache.commons.net.ProtocolCommandSupport;
-import org.apache.commons.net.SocketClient;
-
-/***
- * FTP provides the basic the functionality necessary to implement your
- * own FTP client. It extends org.apache.commons.net.SocketClient since
- * extending TelnetClient was causing unwanted behavior (like connections
- * that did not time out properly).
- * FTPConectionClosedException
- * is a subclass of IOException
and therefore need not be
- * caught separately, but if you are going to catch it separately, its
- * catch block must appear before the more general IOException
- * catch block. When you encounter an
- * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
- * , you must disconnect the connection with
- * {@link #disconnect disconnect() } to properly clean up the
- * system resources used by FTP. Before disconnecting, you may check the
- * last reply code and text with
- * {@link #getReplyCode getReplyCode },
- * {@link #getReplyString getReplyString },
- * and {@link #getReplyStrings getReplyStrings}.
- * You may avoid server disconnections while the client is idle by
- * periodicaly sending NOOP commands to the server.
- * FILE_TYPE
are used to indicate file types.
- ***/
- public static final int ASCII_FILE_TYPE = 0;
-
- /***
- * A constant used to indicate the file(s) being transfered should
- * be treated as EBCDIC. Note however that there are several different
- * EBCDIC formats. All constants ending in FILE_TYPE
- * are used to indicate file types.
- ***/
- public static final int EBCDIC_FILE_TYPE = 1;
-
-
- /***
- * A constant used to indicate the file(s) being transfered should
- * be treated as a binary image, i.e., no translations should be
- * performed. All constants ending in FILE_TYPE
are used to
- * indicate file types.
- ***/
- public static final int BINARY_FILE_TYPE = 2;
-
- /***
- * A constant used to indicate the file(s) being transfered should
- * be treated as a local type. All constants ending in
- * FILE_TYPE
are used to indicate file types.
- ***/
- public static final int LOCAL_FILE_TYPE = 3;
-
- /***
- * A constant used for text files to indicate a non-print text format.
- * This is the default format.
- * All constants ending in TEXT_FORMAT
are used to indicate
- * text formatting for text transfers (both ASCII and EBCDIC).
- ***/
- public static final int NON_PRINT_TEXT_FORMAT = 4;
-
- /***
- * A constant used to indicate a text file contains format vertical format
- * control characters.
- * All constants ending in TEXT_FORMAT
are used to indicate
- * text formatting for text transfers (both ASCII and EBCDIC).
- ***/
- public static final int TELNET_TEXT_FORMAT = 5;
-
- /***
- * A constant used to indicate a text file contains ASA vertical format
- * control characters.
- * All constants ending in TEXT_FORMAT
are used to indicate
- * text formatting for text transfers (both ASCII and EBCDIC).
- ***/
- public static final int CARRIAGE_CONTROL_TEXT_FORMAT = 6;
-
- /***
- * A constant used to indicate a file is to be treated as a continuous
- * sequence of bytes. This is the default structure. All constants ending
- * in _STRUCTURE
are used to indicate file structure for
- * file transfers.
- ***/
- public static final int FILE_STRUCTURE = 7;
-
- /***
- * A constant used to indicate a file is to be treated as a sequence
- * of records. All constants ending in _STRUCTURE
- * are used to indicate file structure for file transfers.
- ***/
- public static final int RECORD_STRUCTURE = 8;
-
- /***
- * A constant used to indicate a file is to be treated as a set of
- * independent indexed pages. All constants ending in
- * _STRUCTURE
are used to indicate file structure for file
- * transfers.
- ***/
- public static final int PAGE_STRUCTURE = 9;
-
- /***
- * A constant used to indicate a file is to be transfered as a stream
- * of bytes. This is the default transfer mode. All constants ending
- * in TRANSFER_MODE
are used to indicate file transfer
- * modes.
- ***/
- public static final int STREAM_TRANSFER_MODE = 10;
-
- /***
- * A constant used to indicate a file is to be transfered as a series
- * of blocks. All constants ending in TRANSFER_MODE
are used
- * to indicate file transfer modes.
- ***/
- public static final int BLOCK_TRANSFER_MODE = 11;
-
- /***
- * A constant used to indicate a file is to be transfered as FTP
- * compressed data. All constants ending in TRANSFER_MODE
- * are used to indicate file transfer modes.
- ***/
- public static final int COMPRESSED_TRANSFER_MODE = 12;
-
- // We have to ensure that the protocol communication is in ASCII
- // but we use ISO-8859-1 just in case 8-bit characters cross
- // the wire.
- /**
- * The default character encoding used for communicating over an
- * FTP control connection. The default encoding is an
- * ASCII-compatible encoding. Some FTP servers expect other
- * encodings. You can change the encoding used by an FTP instance
- * with {@link #setControlEncoding setControlEncoding}.
- */
- public static final String DEFAULT_CONTROL_ENCODING = "ISO-8859-1";
- private static final String __modes = "AEILNTCFRPSBC";
-
- private StringBuilder __commandBuffer = new StringBuilder();
-
- protected int _replyCode;
- protected ArrayListDEFAULT_PORT
and initializes internal data structures
- * for saving FTP reply information.
- ***/
- public FTP()
- {
- super();
- setDefaultPort(DEFAULT_PORT);
- _replyLines = new ArrayList connect
is of type void.
- * FILE_TYPE
- * constants).
- * @param formatOrByteSize The format of the file (one of the
- * _FORMAT
constants. In the case of
- * LOCAL_FILE_TYPE
, the byte size.
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int type(int fileType, int formatOrByteSize) throws IOException
- {
- StringBuffer arg = new StringBuffer();
-
- arg.append(__modes.charAt(fileType));
- arg.append(' ');
- if (fileType == LOCAL_FILE_TYPE)
- arg.append(formatOrByteSize);
- else
- arg.append(__modes.charAt(formatOrByteSize));
-
- return sendCommand(FTPCommand.TYPE, arg.toString());
- }
-
-
- /**
- * A convenience method to send the FTP TYPE command to the server,
- * receive the reply, and return the reply code.
- * FILE_TYPE
- * constants).
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- */
- public int type(int fileType) throws IOException
- {
- return sendCommand(FTPCommand.TYPE,
- __modes.substring(fileType, fileType + 1));
- }
-
- /***
- * A convenience method to send the FTP STRU command to the server,
- * receive the reply, and return the reply code.
- * _STRUCTURE
constants).
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int stru(int structure) throws IOException
- {
- return sendCommand(FTPCommand.STRU,
- __modes.substring(structure, structure + 1));
- }
-
- /***
- * A convenience method to send the FTP MODE command to the server,
- * receive the reply, and return the reply code.
- * TRANSFER_MODE
constants).
- * @return The reply code received from the server.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending the
- * command or receiving the server reply.
- ***/
- public int mode(int mode) throws IOException
- {
- return sendCommand(FTPCommand.MODE,
- __modes.substring(mode, mode + 1));
- }
-
- /***
- * A convenience method to send the FTP RETR command to the server,
- * receive the reply, and return the reply code. Remember, it is up
- * to you to manage the data connection. If you don't need this low
- * level of access, use {@link org.apache.commons.net.ftp.FTPClient}
- * , which will handle all low level details for you.
- *
- * boolean error = false;
- * try {
- * int reply;
- * ftp.connect("ftp.foobar.com");
- * System.out.println("Connected to " + server + ".");
- * System.out.print(ftp.getReplyString());
- *
- * // After connection attempt, you should check the reply code to verify
- * // success.
- * reply = ftp.getReplyCode();
- *
- * if(!FTPReply.isPositiveCompletion(reply)) {
- * ftp.disconnect();
- * System.err.println("FTP server refused connection.");
- * System.exit(1);
- * }
- * ... // transfer files
- * ftp.logout();
- * } catch(IOException e) {
- * error = true;
- * e.printStackTrace();
- * } finally {
- * if(ftp.isConnected()) {
- * try {
- * ftp.disconnect();
- * } catch(IOException ioe) {
- * // do nothing
- * }
- * }
- * System.exit(error ? 1 : 0);
- * }
- *
- * FTP.ASCII_FILE_TYPE
,
- * FTP.NON_PRINT_TEXT_FORMAT
,
- * FTP.STREAM_TRANSFER_MODE
, and
- * FTP.FILE_STRUCTURE
. The only file types directly supported
- * are FTP.ASCII_FILE_TYPE
and
- * FTP.BINARY_FILE_TYPE
. Because there are at least 4
- * different EBCDIC encodings, we have opted not to provide direct support
- * for EBCDIC. To transfer EBCDIC and other unsupported file types you
- * must create your own filter InputStreams and OutputStreams and wrap
- * them around the streams returned or required by the FTPClient methods.
- * FTPClient uses the {@link ToNetASCIIOutputStream NetASCII}
- * filter streams to provide transparent handling of ASCII files. We will
- * consider incorporating EBCDIC support if there is enough demand.
- * FTP.NON_PRINT_TEXT_FORMAT
,
- * FTP.STREAM_TRANSFER_MODE
, and
- * FTP.FILE_STRUCTURE
are the only supported formats,
- * transfer modes, and file structures.
- * FTPConnectionClosedException
- * is a subclass of IOException
and therefore need not be
- * caught separately, but if you are going to catch it separately, its
- * catch block must appear before the more general IOException
- * catch block. When you encounter an
- * {@link org.apache.commons.net.ftp.FTPConnectionClosedException}
- * , you must disconnect the connection with
- * {@link #disconnect disconnect() } to properly clean up the
- * system resources used by FTPClient. Before disconnecting, you may check the
- * last reply code and text with
- * {@link org.apache.commons.net.ftp.FTP#getReplyCode getReplyCode },
- * {@link org.apache.commons.net.ftp.FTP#getReplyString getReplyString },
- * and
- * {@link org.apache.commons.net.ftp.FTP#getReplyStrings getReplyStrings}.
- * You may avoid server disconnections while the client is idle by
- * periodicaly sending NOOP commands to the server.
- *
- * FTPClient f=FTPClient();
- * f.connect(server);
- * f.login(username, password);
- * FTPFile[] files = listFiles(directory);
- *
- *
- * FTPClient f=FTPClient();
- * f.connect(server);
- * f.login(username, password);
- * FTPListParseEngine engine =
- * f.initiateListParsing("com.whatever.YourOwnParser", directory);
- *
- * while (engine.hasNext()) {
- * FTPFile[] files = engine.getNext(25); // "page size" you want
- * //do whatever you want with these files, display them, etc.
- * //expensive FTPFile objects not created until needed.
- * }
- *
- *
- * FTPClient f=FTPClient();
- * f.connect(server);
- * f.login(username, password);
- * FTPListParseEngine engine = f.initiateListParsing(directory);
- *
- * while (engine.hasNext()) {
- * FTPFile[] files = engine.getNext(25); // "page size" you want
- * //do whatever you want with these files, display them, etc.
- * //expensive FTPFile objects not created until needed.
- * }
- *
- *
- *
see {@link FTPClientConfig FTPClientConfig}.
- * MM d yyyy
ACTIVE_LOCAL_DATA_CONNECTION_MODE
, the file type
- * set to FTP.ASCII_FILE_TYPE
, the
- * file format set to FTP.NON_PRINT_TEXT_FORMAT
,
- * the file structure set to FTP.FILE_STRUCTURE
, and
- * the transfer mode set to FTP.STREAM_TRANSFER_MODE
.
- ***/
- public FTPClient()
- {
- __initDefaults();
- __dataTimeout = -1;
- __remoteVerificationEnabled = true;
- __parserFactory = new DefaultFTPFileEntryParserFactory();
- __configuration = null;
- __listHiddenFiles = false;
- }
-
-
- private void __initDefaults()
- {
- __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
- __passiveHost = null;
- __passivePort = -1;
- __fileType = FTP.ASCII_FILE_TYPE;
- __fileStructure = FTP.FILE_STRUCTURE;
- __fileFormat = FTP.NON_PRINT_TEXT_FORMAT;
- __fileTransferMode = FTP.STREAM_TRANSFER_MODE;
- __restartOffset = 0;
- __systemName = null;
- __entryParser = null;
- __bufferSize = Util.DEFAULT_COPY_BUFFER_SIZE;
- }
-
- private String __parsePathname(String reply)
- {
- int begin, end;
-
- begin = reply.indexOf('"') + 1;
- end = reply.indexOf('"', begin);
-
- return reply.substring(begin, end);
- }
-
-
- private void __parsePassiveModeReply(String reply)
- throws MalformedServerReplyException
- {
- java.util.regex.Matcher m = __parms_pat.matcher(reply);
- if (!m.find()) {
- throw new MalformedServerReplyException(
- "Could not parse passive host information.\nServer Reply: " + reply);
- }
- reply = m.group();
- String parts[] = m.group().split(",");
-
- __passiveHost = parts[0] + '.' + parts[1] + '.' + parts[2] + '.' + parts[3];
-
- try
- {
- int oct1 = Integer.parseInt(parts[4]);
- int oct2 = Integer.parseInt(parts[5]);
- __passivePort = (oct1 << 8) | oct2;
- }
- catch (NumberFormatException e)
- {
- throw new MalformedServerReplyException(
- "Could not parse passive host information.\nServer Reply: " + reply);
- }
-
- }
-
- private boolean __storeFile(int command, String remote, InputStream local)
- throws IOException
- {
- OutputStream output;
- Socket socket;
-
- if ((socket = _openDataConnection_(command, remote)) == null)
- return false;
-
- output = new BufferedOutputStream(socket.getOutputStream(),
- getBufferSize()
- );
- if (__fileType == ASCII_FILE_TYPE)
- output = new ToNetASCIIOutputStream(output);
- // Treat everything else as binary for now
- try
- {
- Util.copyStream(local, output, getBufferSize(),
- CopyStreamEvent.UNKNOWN_STREAM_SIZE, null,
- false);
- }
- catch (IOException e)
- {
- try
- {
- socket.close();
- }
- catch (IOException f)
- {}
- throw e;
- }
- output.close();
- socket.close();
- return completePendingCommand();
- }
-
- private OutputStream __storeFileStream(int command, String remote)
- throws IOException
- {
- OutputStream output;
- Socket socket;
-
- if ((socket = _openDataConnection_(command, remote)) == null)
- return null;
-
- output = socket.getOutputStream();
- if (__fileType == ASCII_FILE_TYPE) {
- // We buffer ascii transfers because the buffering has to
- // be interposed between ToNetASCIIOutputSream and the underlying
- // socket output stream. We don't buffer binary transfers
- // because we don't want to impose a buffering policy on the
- // programmer if possible. Programmers can decide on their
- // own if they want to wrap the SocketOutputStream we return
- // for file types other than ASCII.
- output = new BufferedOutputStream(output,
- getBufferSize());
- output = new ToNetASCIIOutputStream(output);
-
- }
- return new org.apache.commons.net.io.SocketOutputStream(socket, output);
- }
-
-
- /**
- * Establishes a data connection with the FTP server, returning
- * a Socket for the connection if successful. If a restart
- * offset has been set with {@link #setRestartOffset(long)},
- * a REST command is issued to the server with the offset as
- * an argument before establishing the data connection. Active
- * mode connections also cause a local PORT command to be issued.
- * ACTIVE_LOCAL_DATA_CONNECTION_MODE
. No communication
- * with the FTP server is conducted, but this causes all future data
- * transfers to require the FTP server to connect to the client's
- * data port. Additionally, to accommodate differences between socket
- * implementations on different platforms, this method causes the
- * client to issue a PORT command before every data transfer.
- ***/
- public void enterLocalActiveMode()
- {
- __dataConnectionMode = ACTIVE_LOCAL_DATA_CONNECTION_MODE;
- __passiveHost = null;
- __passivePort = -1;
- }
-
-
- /***
- * Set the current data connection mode to
- * PASSIVE_LOCAL_DATA_CONNECTION_MODE
. Use this
- * method only for data transfers between the client and server.
- * This method causes a PASV command to be issued to the server
- * before the opening of every data connection, telling the server to
- * open a data port to which the client will connect to conduct
- * data transfers. The FTPClient will stay in
- * PASSIVE_LOCAL_DATA_CONNECTION_MODE
until the
- * mode is changed by calling some other method such as
- * {@link #enterLocalActiveMode enterLocalActiveMode() }
- ***/
- public void enterLocalPassiveMode()
- {
- __dataConnectionMode = PASSIVE_LOCAL_DATA_CONNECTION_MODE;
- // These will be set when just before a data connection is opened
- // in _openDataConnection_()
- __passiveHost = null;
- __passivePort = -1;
- }
-
-
- /***
- * Set the current data connection mode to
- * ACTIVE_REMOTE_DATA_CONNECTION
. Use this method only
- * for server to server data transfers. This method issues a PORT
- * command to the server, indicating the other server and port to which
- * it should connect for data transfers. You must call this method
- * before EVERY server to server transfer attempt. The FTPClient will
- * NOT automatically continue to issue PORT commands. You also
- * must remember to call
- * {@link #enterLocalActiveMode enterLocalActiveMode() } if you
- * wish to return to the normal data connection mode.
- * PASSIVE_REMOTE_DATA_CONNECTION_MODE
. Use this
- * method only for server to server data transfers.
- * This method issues a PASV command to the server, telling it to
- * open a data port to which the active server will connect to conduct
- * data transfers. You must call this method
- * before EVERY server to server transfer attempt. The FTPClient will
- * NOT automatically continue to issue PASV commands. You also
- * must remember to call
- * {@link #enterLocalActiveMode enterLocalActiveMode() } if you
- * wish to return to the normal data connection mode.
- * _DATA_CONNECTION_MODE
constants.
- * _DATA_CONNECTION_MODE
constants.
- ***/
- public int getDataConnectionMode()
- {
- return __dataConnectionMode;
- }
-
-
- /***
- * Sets the file type to be transferred. This should be one of
- * FTP.ASCII_FILE_TYPE
, FTP.BINARY_FILE_TYPE
,
- * etc. The file type only needs to be set when you want to change the
- * type. After changing it, the new type stays in effect until you change
- * it again. The default file type is FTP.ASCII_FILE_TYPE
- * if this method is never called.
- * _FILE_TYPE
constant indcating the
- * type of file.
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean setFileType(int fileType) throws IOException
- {
- if (FTPReply.isPositiveCompletion(type(fileType)))
- {
- __fileType = fileType;
- __fileFormat = FTP.NON_PRINT_TEXT_FORMAT;
- return true;
- }
- return false;
- }
-
-
- /***
- * Sets the file type to be transferred and the format. The type should be
- * one of FTP.ASCII_FILE_TYPE
,
- * FTP.BINARY_FILE_TYPE
, etc. The file type only needs to
- * be set when you want to change the type. After changing it, the new
- * type stays in effect until you change it again. The default file type
- * is FTP.ASCII_FILE_TYPE
if this method is never called.
- * The format should be one of the FTP class TEXT_FORMAT
- * constants, or if the type is FTP.LOCAL_FILE_TYPE
, the
- * format should be the byte size for that type. The default format
- * is FTP.NON_PRINT_TEXT_FORMAT
if this method is never
- * called.
- * _FILE_TYPE
constant indcating the
- * type of file.
- * @param formatOrByteSize The format of the file (one of the
- * _FORMAT
constants. In the case of
- * LOCAL_FILE_TYPE
, the byte size.
- * FTP.FILE_STRUCTURE
if this method is never called.
- * _STRUCTURE
constants).
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean setFileStructure(int structure) throws IOException
- {
- if (FTPReply.isPositiveCompletion(stru(structure)))
- {
- __fileStructure = structure;
- return true;
- }
- return false;
- }
-
-
- /***
- * Sets the transfer mode. The default transfer mode
- * FTP.STREAM_TRANSFER_MODE
if this method is never called.
- * _TRANSFER_MODE
constants).
- * @return True if successfully completed, false if not.
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- ***/
- public boolean setFileTransferMode(int mode) throws IOException
- {
- if (FTPReply.isPositiveCompletion(mode(mode)))
- {
- __fileTransferMode = mode;
- return true;
- }
- return false;
- }
-
-
- /***
- * Initiate a server to server file transfer. This method tells the
- * server to which the client is connected to retrieve a given file from
- * the other server.
- * remoteRetrieve
issued to it by another
- * FTPClient.
- * remoteRetrieve
issued
- * to it by another FTPClient.
- * remoteRetrieve
issued
- * to it by another FTPClient. Many FTP servers require that a base
- * filename be given from which the unique filename can be derived. For
- * those servers use the other version of remoteStoreUnique
- * remoteRetrieve
issued to it by another FTPClient.
- *
- * InputStream input;
- * OutputStream output;
- * input = new FileInputStream("foobaz.txt");
- * output = ftp.storeFileStream("foobar.txt")
- * if(!FTPReply.isPositiveIntermediate(ftp.getReplyCode())) {
- * input.close();
- * output.close();
- * ftp.logout();
- * ftp.disconnect();
- * System.err.println("File transfer failed.");
- * System.exit(1);
- * }
- * Util.copyStream(input, output);
- * input.close();
- * output.close();
- * // Must call completePendingCommand() to finish command.
- * if(!ftp.completePendingCommand()) {
- * ftp.logout();
- * ftp.disconnect();
- * System.err.println("File transfer failed.");
- * System.exit(1);
- * }
- *
- * STREAM_TRANSFER_MODE
file transfer starting
- * from the given offset. This will only work on FTP servers supporting
- * the REST comand for the stream transfer mode. However, most FTP
- * servers support this. Any subsequent file transfer will start
- * reading or writing the remote file from the indicated offset.
- * FTPFileEntryParser
- * used.
- * FTPFileEntryParser
- * used.
- * FTPFileEntryParser
used.
- * parser
parameter. Null will be
- * returned if a data connection cannot be opened. If the current working
- * directory contains no files, an empty array will be the return.
- *
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException
- * If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- * @exception ParserInitializationException
- * Thrown if the autodetect mechanism cannot
- * resolve the type of system we are connected with.
- * @see FTPListParseEngine
- */
- public FTPListParseEngine initiateListParsing()
- throws IOException
- {
- return initiateListParsing((String) null);
- }
-
- /**
- * Using the default autodetect mechanism, initialize an FTPListParseEngine
- * object containing a raw file information for the supplied directory.
- * This information is obtained through the LIST command. This object
- * is then capable of being iterated to return a sequence of FTPFile
- * objects with information filled in by the
- * FTPFileEntryParser
used.
- *
- * FTPClient f=FTPClient();
- * f.connect(server);
- * f.login(username, password);
- * FTPListParseEngine engine = f.initiateListParsing(directory);
- *
- * while (engine.hasNext()) {
- * FTPFile[] files = engine.getNext(25); // "page size" you want
- * //do whatever you want with these files, display them, etc.
- * //expensive FTPFile objects not created until needed.
- * }
- *
- *
- * @return A FTPListParseEngine object that holds the raw information and
- * is capable of providing parsed FTPFile objects, one for each file
- * containing information contained in the given path in the format
- * determined by the parser
parameter. Null will be
- * returned if a data connection cannot be opened. If the current working
- * directory contains no files, an empty array will be the return.
- *
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException
- * If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- * @exception ParserInitializationException
- * Thrown if the autodetect mechanism cannot
- * resolve the type of system we are connected with.
- * @see FTPListParseEngine
- */
- public FTPListParseEngine initiateListParsing(
- String pathname)
- throws IOException
- {
- String key = null;
- return initiateListParsing(key, pathname);
- }
-
- /**
- * Using the supplied parser key, initialize an FTPListParseEngine
- * object containing a raw file information for the supplied directory.
- * This information is obtained through the LIST command. This object
- * is then capable of being iterated to return a sequence of FTPFile
- * objects with information filled in by the
- * FTPFileEntryParser
used.
- * FTPFileEntryParser
that should be
- * used to parse each server file listing.
- *
- * @return A FTPListParseEngine object that holds the raw information and
- * is capable of providing parsed FTPFile objects, one for each file
- * containing information contained in the given path in the format
- * determined by the parser
parameter. Null will be
- * returned if a data connection cannot be opened. If the current working
- * directory contains no files, an empty array will be the return.
- *
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException
- * If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- * @exception ParserInitializationException
- * Thrown if the parserKey parameter cannot be
- * resolved by the selected parser factory.
- * In the DefaultFTPEntryParserFactory, this will
- * happen when parserKey is neither
- * the fully qualified class name of a class
- * implementing the interface
- * org.apache.commons.net.ftp.FTPFileEntryParser
- * nor a string containing one of the recognized keys
- * mapping to such a parser or if class loader
- * security issues prevent its being loaded.
- * @see FTPListParseEngine
- */
- public FTPListParseEngine initiateListParsing(
- String parserKey, String pathname)
- throws IOException
- {
- // We cache the value to avoid creation of a new object every
- // time a file listing is generated.
- if(__entryParser == null) {
- if (null != parserKey) {
- // if a parser key was supplied in the parameters,
- // use that to create the paraser
- __entryParser =
- __parserFactory.createFileEntryParser(parserKey);
-
- } else {
- // if no parserKey was supplied, check for a configuration
- // in the params, and if non-null, use that.
- if (null != __configuration) {
- __entryParser =
- __parserFactory.createFileEntryParser(__configuration);
- } else {
- // if a parserKey hasn't been supplied, and a configuration
- // hasn't been supplied, then autodetect by calling
- // the SYST command and use that to choose the parser.
- __entryParser =
- __parserFactory.createFileEntryParser(getSystemName());
- }
- }
- }
-
- return initiateListParsing(__entryParser, pathname);
-
- }
-
-
- /**
- * private method through which all listFiles() and
- * initiateListParsing methods pass once a parser is determined.
- *
- * @exception FTPConnectionClosedException
- * If the FTP server prematurely closes the connection as a result
- * of the client being idle or some other reason causing the server
- * to send FTP reply code 421. This exception may be caught either
- * as an IOException or independently as itself.
- * @exception IOException
- * If an I/O error occurs while either sending a
- * command to the server or receiving a reply from the server.
- * @see FTPListParseEngine
- */
- private FTPListParseEngine initiateListParsing(
- FTPFileEntryParser parser, String pathname)
- throws IOException
- {
- Socket socket;
-
- FTPListParseEngine engine = new FTPListParseEngine(parser);
-
- if ((socket = _openDataConnection_(FTPCommand.LIST, getListArguments(pathname))) == null)
- {
- return engine;
- }
-
-
- try {
- engine.readServerList(socket.getInputStream(), getControlEncoding());
- }
- finally {
- socket.close();
- }
-
- completePendingCommand();
- return engine;
- }
-
- /**
- * @since 2.0
- */
- protected String getListArguments(String pathname) {
- if (getListHiddenFiles())
- {
- StringBuffer sb = new StringBuffer(pathname.length() + 3);
- sb.append("-a ");
- sb.append(pathname);
- return sb.toString();
- }
-
- return pathname;
- }
-
-
- /***
- * Issue the FTP STAT command to the server.
- * YYYYMMDDhhmmss
format.
- * @throws IOException if an I/O error occurs.
- * @since 2.0
- */
- public String getModificationTime(String pathname) throws IOException {
- if (FTPReply.isPositiveCompletion(mdtm(pathname)))
- return getReplyString();
- return null;
- }
-
-
- /**
- * Set the internal buffer size.
- *
- * @param bufSize The size of the buffer
- */
- public void setBufferSize(int bufSize) {
- __bufferSize = bufSize;
- }
-
- /**
- * Retrieve the current internal buffer size.
- * @return The current buffer size.
- */
- public int getBufferSize() {
- return __bufferSize;
- }
-
-
- /**
- * Implementation of the {@link Configurable Configurable} interface.
- * In the case of this class, configuring merely makes the config object available for the
- * factory methods that construct parsers.
- * @param config {@link FTPClientConfig FTPClientConfig} object used to
- * provide non-standard configurations to the parser.
- * @since 1.4
- */
- public void configure(FTPClientConfig config) {
- this.__configuration = config;
- }
-
- /**
- * You can set this to true if you would like to get hidden files when {@link #listFiles} too.
- * A LIST -a
will be issued to the ftp server.
- * It depends on your ftp server if you need to call this method, also dont expect to get rid
- * of hidden files if you call this method with "false".
- *
- * @param listHiddenFiles true if hidden files should be listed
- * @since 2.0
- */
- public void setListHiddenFiles(boolean listHiddenFiles) {
- this.__listHiddenFiles = listHiddenFiles;
- }
-
- /**
- * @see #setListHiddenFiles(boolean)
- * @return the current state
- * @since 2.0
- */
- public boolean getListHiddenFiles() {
- return this.__listHiddenFiles;
- }
-}
-
-/* Emacs configuration
- * Local variables: **
- * mode: java **
- * c-basic-offset: 4 **
- * indent-tabs-mode: nil **
- * End: **
- */
diff --git a/org/apache/commons/net/ftp/FTPClientConfig.class b/org/apache/commons/net/ftp/FTPClientConfig.class
deleted file mode 100644
index b42c8ee..0000000
Binary files a/org/apache/commons/net/ftp/FTPClientConfig.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/FTPClientConfig.java b/org/apache/commons/net/ftp/FTPClientConfig.java
deleted file mode 100644
index 450eddc..0000000
--- a/org/apache/commons/net/ftp/FTPClientConfig.java
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp;
-
-import java.text.DateFormatSymbols;
-import java.util.Collection;
-import java.util.Locale;
-import java.util.Map;
-import java.util.StringTokenizer;
-import java.util.TreeMap;
-
-/**
- * Examples of use of FTPClientConfig
- * Use cases:
- * You are trying to access a server that
- *
- *
- * MM dd yyyy
MMM d yyyy
date formatting
- *
- * FTPClient f=FTPClient();
- * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
- * conf.setServerLanguageCode("fr");
- * f.configure(conf);
- * f.connect(server);
- * f.login(username, password);
- * FTPFile[] files = listFiles(directory);
- *
- *
- * FTPClient f=FTPClient();
- * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
- * conf.setServerLanguageCode("da");
- * conf.setDefaultDateFormat("d MMM yyyy");
- * conf.setRecentDateFormat("d MMM HH:mm");
- * conf.setTimeZoneId("Europe/Copenhagen");
- * f.configure(conf);
- * f.connect(server);
- * f.login(username, password);
- * FTPListParseEngine engine =
- * f.initiateListParsing("com.whatever.YourOwnParser", directory);
- *
- * while (engine.hasNext()) {
- * FTPFile[] files = engine.getNext(25); // "page size" you want
- * //do whatever you want with these files, display them, etc.
- * //expensive FTPFile objects not created until needed.
- * }
- *
- * MMM d yyyy
date formatting
- *
- * FTPClient f=FTPClient();
- * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_VMS);
- * conf.setShortMonthNames(
- * "jan|feb|mar|apr|ma\u00ED|j\u00FAn|j\u00FAl|\u00e1g\u00FA|sep|okt|n\u00F3v|des");
- * f.configure(conf);
- * f.connect(server);
- * f.login(username, password);
- * FTPFile[] files = listFiles(directory);
- *
- *
- * FTPClient f=FTPClient();
- * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
- * conf.setTimeZoneId("America/Denver");
- * f.configure(conf);
- * f.connect(server);
- * f.login(username, password);
- * FTPFile[] files = listFiles(directory);
- *
- *
- * FTPClient f=FTPClient();
- * FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
- * conf.setTimeZoneId("America/Denver");
- * f.configure(conf);
- * f.connect(server);
- * f.login(username, password);
- * FTPFile[] files = listFiles(directory);
- *
- * FTPClientConfig.SYST_*
codes
- * or else the fully qualified class name of a parser implementing both
- * the FTPFileEntryParser
and Configurable
- * interfaces.
- * @return Returns the serverSystemKey property.
- */
- public String getServerSystemKey() {
- return serverSystemKey;
- }
-
- /**
- * getter for the {@link #setDefaultDateFormatStr(String) defaultDateFormatStr}
- * property.
- * @return Returns the defaultDateFormatStr property.
- */
- public String getDefaultDateFormatStr() {
- return defaultDateFormatStr;
- }
-
- /**
- * getter for the {@link #setRecentDateFormatStr(String) recentDateFormatStr} property.
- * @return Returns the recentDateFormatStr property.
- */
-
- public String getRecentDateFormatStr() {
- return recentDateFormatStr;
- }
-
- /**
- * getter for the {@link #setServerTimeZoneId(String) serverTimeZoneId} property.
- * @return Returns the serverTimeZoneId property.
- */
- public String getServerTimeZoneId() {
- return serverTimeZoneId;
- }
-
- /**
- * en_US
locales.
- * java.text.SimpleDateFormat
.
- * property.
- * java.text.SimpleDateFormat
.
- * java.util.TimeZone
to refer to time zones, for example,
- * America/Chicago
or Asia/Rangoon
.
- * "jan|feb|mar|apr|maí|jún|júl|ágú|sep|okt|nóv|des"
.
- * en_US
- * month names will be used. We are supporting here those language
- * codes which, when a java.util.Locale
is constucted
- * using it, and a java.text.SimpleDateFormat
is
- * constructed using that Locale, the array returned by the
- * SimpleDateFormat's getShortMonths()
method consists
- * solely of three 8-bit ASCII character strings. Additionally,
- * languages which do not meet this requirement are included if a
- * common alternative set of short month names is known to be used.
- * This means that users who can tell us of additional such encodings
- * may get them added to the list of supported languages by contacting
- * the jakarta-commons-net team.
- * en_US
date format
- * orderings of MMM d yyyy
and MMM d HH:mm
- * and attempting to deduce this automatically here would cause more
- * problems than it would solve. The date format must be changed
- * via the {@link #setDefaultDateFormatStr(String) defaultDateFormatStr} and/or
- * {@link #setRecentDateFormatStr(String) recentDateFormatStr} parameters.
- * Locale.US
- * @param languageCode See {@link #setServerLanguageCode(String) serverLanguageCode}
- * @return a DateFormatSymbols object configured with short month names
- * corresponding to the supplied code, or with month names for
- * Locale.US
if there is no corresponding entry in the internal
- * table.
- */
- public static DateFormatSymbols lookupDateFormatSymbols(String languageCode)
- {
- Object lang = LANGUAGE_CODE_MAP.get(languageCode);
- if (lang != null) {
- if (lang instanceof Locale) {
- return new DateFormatSymbols((Locale) lang);
- } else if (lang instanceof String){
- return getDateFormatSymbols((String) lang);
- }
- }
- return new DateFormatSymbols(Locale.US);
- }
-
- /**
- * Returns a DateFormatSymbols object configured with short month names
- * as in the supplied string
- * @param shortmonths This should be as described in
- * {@link #setShortMonthNames(String) shortMonthNames}
- * @return a DateFormatSymbols object configured with short month names
- * as in the supplied string
- */
- public static DateFormatSymbols getDateFormatSymbols(String shortmonths)
- {
- String[] months = splitShortMonthString(shortmonths);
- DateFormatSymbols dfs = new DateFormatSymbols(Locale.US);
- dfs.setShortMonths(months);
- return dfs;
- }
-
- private static String[] splitShortMonthString(String shortmonths) {
- StringTokenizer st = new StringTokenizer(shortmonths, "|");
- int monthcnt = st.countTokens();
- if (12 != monthcnt) {
- throw new IllegalArgumentException(
- "expecting a pipe-delimited string containing 12 tokens");
- }
- String[] months = new String[13];
- int pos = 0;
- while(st.hasMoreTokens()) {
- months[pos++] = st.nextToken();
- }
- months[pos]="";
- return months;
- }
-
- /**
- * Returns a Collection of all the language codes currently supported
- * by this class. See {@link #setServerLanguageCode(String) serverLanguageCode}
- * for a functional descrption of language codes within this system.
- *
- * @return a Collection of all the language codes currently supported
- * by this class
- */
- public static CollectionDIRECTORY_TYPE
, false if
- * not.
- ***/
- public boolean isDirectory()
- {
- return (_type == DIRECTORY_TYPE);
- }
-
- /***
- * Determine if the file is a regular file.
- * FILE_TYPE
, false if
- * not.
- ***/
- public boolean isFile()
- {
- return (_type == FILE_TYPE);
- }
-
- /***
- * Determine if the file is a symbolic link.
- * UNKNOWN_TYPE
, false if
- * not.
- ***/
- public boolean isSymbolicLink()
- {
- return (_type == SYMBOLIC_LINK_TYPE);
- }
-
- /***
- * Determine if the type of the file is unknown.
- * UNKNOWN_TYPE
, false if
- * not.
- ***/
- public boolean isUnknown()
- {
- return (_type == UNKNOWN_TYPE);
- }
-
-
- /***
- * Set the type of the file (DIRECTORY_TYPE
,
- * FILE_TYPE
, etc.).
- * _TYPE
constants),
- * e.g., if it is a directory, a regular file, or a symbolic link.
- * _ACCESS
- * constants) has the given access permission (one of the
- * _PERMISSION
constants) to the file.
- * _ACCESS
- * constants)
- * @param permission The access permission (one of the
- * _PERMISSION
constants)
- * @param value True if permission is allowed, false if not.
- ***/
- public void setPermission(int access, int permission, boolean value)
- {
- _permissions[access][permission] = value;
- }
-
-
- /***
- * Determines if the given access group (one of the _ACCESS
- * constants) has the given access permission (one of the
- * _PERMISSION
constants) to the file.
- * _ACCESS
- * constants)
- * @param permission The access permission (one of the
- * _PERMISSION
constants)
- ***/
- public boolean hasPermission(int access, int permission)
- {
- return _permissions[access][permission];
- }
-
-
- /***
- * Returns a string representation of the FTPFile information. This
- * will be the raw FTP server listing that was used to initialize the
- * FTPFile instance.
- * FTPFile
objects are not created until needed. This
- * is suitable for paged displays. It requires that a parser object be created
- * beforehand: parser
is an object (in the package
- * org.apache.commons.net.ftp.parser
)
- * implementing this inteface.
- *
- *
- * FTPClient f=FTPClient();
- * f.connect(server);
- * f.login(username, password);
- * FTPFileList list = f.createFileList(directory, parser);
- * FTPFileIterator iter = list.iterator();
- *
- * while (iter.hasNext()) {
- * FTPFile[] files = iter.getNext(25); // "page size" you want
- * //do whatever you want with these files, display them, etc.
- * //expensive FTPFile objects not created until needed.
- * }
- *
- *
- * The second example uses the revised FTPClient.listFiles()
- * API to pull the whole list from the subfolder subfolder
in
- * one call, attempting to automatically detect the parser type. This
- * method, without a parserKey parameter, indicates that autodection should
- * be used.
- *
- *
- * FTPClient f=FTPClient();
- * f.connect(server);
- * f.login(username, password);
- * FTPFile[] files = f.listFiles("subfolder");
- *
- *
- * The third example uses the revised FTPClient.listFiles()
>
- * API to pull the whole list from the current working directory in one call,
- * but specifying by classname the parser to be used. For this particular
- * parser class, this approach is necessary since there is no way to
- * autodetect this server type.
- *
- *
- * FTPClient f=FTPClient();
- * f.connect(server);
- * f.login(username, password);
- * FTPFile[] files = f.listFiles(
- * "org.apache.commons.net.ftp.parser.EnterpriseUnixFTPFileEntryParser",
- * ".");
- *
- *
- * The fourth example uses the revised FTPClient.listFiles()
- * API to pull a single file listing in an arbitrary directory in one call,
- * specifying by KEY the parser to be used, in this case, VMS.
- *
- *
- * FTPClient f=FTPClient();
- * f.connect(server);
- * f.login(username, password);
- * FTPFile[] files = f.listFiles("VMS", "subfolder/foo.java");
- *
- *
- * @author Steve Cohen
- * @version $Id: FTPFileEntryParser.java 636854 2008-03-13 19:55:01Z sebb $
- * @see org.apache.commons.net.ftp.FTPFile
- * @see org.apache.commons.net.ftp.FTPClient#createFileList
- */
-public interface FTPFileEntryParser
-{
- /**
- * Parses a line of an FTP server file listing and converts it into a usable
- * format in the form of an FTPFile
instance. If the
- * file listing line doesn't describe a file, null
should be
- * returned, otherwise a FTPFile
instance representing the
- * files in the directory is returned.
- * original
unmodified.
- */
- public ListreadNextEntry()
- which handles the issue of
- * what delimits one entry from another, usually but not always a line
- * feed and preParse()
- which handles removal of
- * extraneous matter such as the preliminary lines of a listing, removal
- * of duplicates on versioning systems, etc.
- * getNext()
and
- * getPrevious()
methods to provide "paged" output of less
- * than the whole list at one time, or by calling the
- * getFiles()
method to return the entire list.
- *
- * FTPClient f=FTPClient();
- * f.connect(server);
- * f.login(username, password);
- * FTPListParseEngine engine = f.initiateListParsing(directory);
- *
- * while (engine.hasNext()) {
- * FTPFile[] files = engine.getNext(25); // "page size" you want
- * //do whatever you want with these files, display them, etc.
- * //expensive FTPFile objects not created until needed.
- * }
- *
- * entries
list.
- * After this method has completed, entries
will contain a
- * collection of entries (as defined by
- * FTPFileEntryParser.readNextEntry()
), but this may contain
- * various non-entry preliminary lines from the server output, duplicates,
- * and other data that will not be part of the final listing.
- *
- * @param stream The socket stream on which the input will be read.
- * @param encoding The encoding to use.
- *
- * @exception IOException
- * thrown on any failure to read the stream
- */
- private void readStream(InputStream stream, String encoding) throws IOException
- {
- BufferedReader reader;
- if (encoding == null)
- {
- reader = new BufferedReader(new InputStreamReader(stream));
- }
- else
- {
- reader = new BufferedReader(new InputStreamReader(stream, encoding));
- }
-
- String line = this.parser.readNextEntry(reader);
-
- while (line != null)
- {
- this.entries.add(line);
- line = this.parser.readNextEntry(reader);
- }
- reader.close();
- }
-
- /**
- * Returns an array of at most quantityRequested
FTPFile
- * objects starting at this object's internal iterator's current position.
- * If fewer than quantityRequested
such
- * elements are available, the returned array will have a length equal
- * to the number of entries at and after after the current position.
- * If no such entries are found, this array will have a length of 0.
- *
- * After this method is called this object's internal iterator is advanced
- * by a number of positions equal to the size of the array returned.
- *
- * @param quantityRequested
- * the maximum number of entries we want to get.
- *
- * @return an array of at most quantityRequested
FTPFile
- * objects starting at the current position of this iterator within its
- * list and at least the number of elements which exist in the list at
- * and after its current position.
- * quantityRequested
FTPFile
- * objects starting at this object's internal iterator's current position,
- * and working back toward the beginning.
- *
- * If fewer than quantityRequested
such
- * elements are available, the returned array will have a length equal
- * to the number of entries at and after after the current position.
- * If no such entries are found, this array will have a length of 0.
- *
- * After this method is called this object's internal iterator is moved
- * back by a number of positions equal to the size of the array returned.
- *
- * @param quantityRequested
- * the maximum number of entries we want to get.
- *
- * @return an array of at most quantityRequested
FTPFile
- * objects starting at the current position of this iterator within its
- * list and at least the number of elements which exist in the list at
- * and after its current position. This array will be in the same order
- * as the underlying list (not reversed).
- * timestampParser
for extracting the timestamp.
- * @return a java.util.Calendar
containing results of the
- * timestamp parse.
- */
- public Calendar parseTimestamp(String timestampStr) throws ParseException {
- return this.timestampParser.parseTimestamp(timestampStr);
- }
-
-
- /**
- * Implementation of the {@link Configurable Configurable}
- * interface. Configures this parser by delegating to the
- * underlying Configurable FTPTimestampParser implementation, '
- * passing it the supplied {@link FTPClientConfig FTPClientConfig}
- * if that is non-null or a default configuration defined by
- * each concrete subclass.
- * key
is not recognized as a fully qualified
- * classname known to the system, this method will then attempt
- * to see whether it contains a string identifying one of
- * the known parsers. This comparison is case-insensitive.
- * The intent here is where possible, to select as keys strings
- * which are returned by the SYST command on the systems which
- * the corresponding parser successfully parses. This enables
- * this factory to be used in the auto-detection system.
- *
- *
- * @param key should be a fully qualified classname corresponding to
- * a class implementing the FTPFileEntryParser interface
- * OR
- * a string containing (case-insensitively) one of the
- * following keywords:
- *
- *
- * @return the FTPFileEntryParser corresponding to the supplied key.
- * @throws ParserInitializationException thrown if for any reason the factory cannot resolve
- * the supplied key into an FTPFileEntryParser.
- * @see FTPFileEntryParser
- */
- public FTPFileEntryParser createFileEntryParser(String key)
- {
- if (key == null)
- throw new ParserInitializationException("Parser key cannot be null");
-
- Class> parserClass = null;
- FTPFileEntryParser parser = null;
- try
- {
- parserClass = Class.forName(key);
- parser = (FTPFileEntryParser) parserClass.newInstance();
- }
- catch (ClassNotFoundException e)
- {
- try
- {
- String ukey = null;
- if (null != key)
- {
- ukey = key.toUpperCase(java.util.Locale.ENGLISH);
- }
- if ((ukey.indexOf(FTPClientConfig.SYST_UNIX) >= 0)
- || (ukey.indexOf(FTPClientConfig.SYST_L8) >= 0))
- {
- parser = createUnixFTPEntryParser();
- }
- else if (ukey.indexOf(FTPClientConfig.SYST_VMS) >= 0)
- {
- parser = createVMSVersioningFTPEntryParser();
- }
- else if (ukey.indexOf(FTPClientConfig.SYST_NT) >= 0)
- {
- parser = createNTFTPEntryParser();
- }
- else if (ukey.indexOf(FTPClientConfig.SYST_OS2) >= 0)
- {
- parser = createOS2FTPEntryParser();
- }
- else if (ukey.indexOf(FTPClientConfig.SYST_OS400) >= 0 ||
- ukey.indexOf(FTPClientConfig.SYST_AS400) >= 0)
- {
- parser = createOS400FTPEntryParser();
- }
- else if (ukey.indexOf(FTPClientConfig.SYST_MVS) >= 0)
- {
- parser = createMVSEntryParser();
- }
- else if (ukey.indexOf(FTPClientConfig.SYST_NETWARE) >= 0)
- {
- parser = createNetwareFTPEntryParser();
- }
- else
- {
- throw new ParserInitializationException("Unknown parser type: " + key);
- }
- }
- catch (NoClassDefFoundError nf) {
- throw new ParserInitializationException("Error initializing parser", nf);
- }
-
- }
- catch (NoClassDefFoundError e)
- {
- throw new ParserInitializationException("Error initializing parser", e);
- }
- catch (ClassCastException e)
- {
- throw new ParserInitializationException(parserClass.getName()
- + " does not implement the interface "
- + "org.apache.commons.net.ftp.FTPFileEntryParser.", e);
- }
- catch (Throwable e)
- {
- throw new ParserInitializationException("Error initializing parser", e);
- }
-
- if (parser instanceof Configurable) {
- ((Configurable)parser).configure(this.config);
- }
- return parser;
- }
-
- /**
- * FTPFile
instance. If
- * the file listing line doesn't describe a file, null
is
- * returned, otherwise a FTPFile
instance representing the
- * files in the directory is returned.
- *
- * @param entry A line of text from the file listing
- * @return An FTPFile instance corresponding to the supplied entry
- */
- public FTPFile parseFTPEntry(String entry)
- {
-
- FTPFile file = new FTPFile();
- file.setRawListing(entry);
-
- if (matches(entry))
- {
- String usr = group(14);
- String grp = group(15);
- String filesize = group(16);
- String mo = group(17);
- String da = group(18);
- String yr = group(20);
- String hr = group(21);
- String min = group(22);
- String name = group(23);
-
- file.setType(FTPFile.FILE_TYPE);
- file.setUser(usr);
- file.setGroup(grp);
- try
- {
- file.setSize(Long.parseLong(filesize));
- }
- catch (NumberFormatException e)
- {
- // intentionally do nothing
- }
-
- Calendar cal = Calendar.getInstance();
- cal.set(Calendar.MILLISECOND, 0);
- cal.set(Calendar.SECOND,
- 0);
- cal.set(Calendar.MINUTE,
- 0);
- cal.set(Calendar.HOUR_OF_DAY,
- 0);
- try
- {
-
- int pos = MONTHS.indexOf(mo);
- int month = pos / 4;
- if (yr != null)
- {
- // it's a year
- cal.set(Calendar.YEAR,
- Integer.parseInt(yr));
- }
- else
- {
- // it must be hour/minute or we wouldn't have matched
- int year = cal.get(Calendar.YEAR);
-
- // if the month we're reading is greater than now, it must
- // be last year
- if (cal.get(Calendar.MONTH) < month)
- {
- year--;
- }
- cal.set(Calendar.YEAR,
- year);
- cal.set(Calendar.HOUR_OF_DAY,
- Integer.parseInt(hr));
- cal.set(Calendar.MINUTE,
- Integer.parseInt(min));
- }
- cal.set(Calendar.MONTH,
- month);
- cal.set(Calendar.DATE,
- Integer.parseInt(da));
- file.setTimestamp(cal);
- }
- catch (NumberFormatException e)
- {
- // do nothing, date will be uninitialized
- }
- file.setName(name);
-
- return file;
- }
- return null;
- }
-}
diff --git a/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.class b/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.class
deleted file mode 100644
index f1bdf1b..0000000
Binary files a/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java b/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
deleted file mode 100644
index e80ec0d..0000000
--- a/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp.parser;
-import org.apache.commons.net.ftp.FTPClientConfig;
-import org.apache.commons.net.ftp.FTPFileEntryParser;
-
-/**
- * The interface describes a factory for creating FTPFileEntryParsers.
- * @since 1.2
- */
-public interface FTPFileEntryParserFactory
-{
- /**
- * Implementation should be a method that decodes the
- * supplied key and creates an object implementing the
- * interface FTPFileEntryParser.
- *
- * @param key A string that somehow identifies an
- * FTPFileEntryParser to be created.
- *
- * @return the FTPFileEntryParser created.
- * @exception ParserInitializationException
- * Thrown on any exception in instantiation
- */
- public FTPFileEntryParser createFileEntryParser(String key)
- throws ParserInitializationException;
-
- /**
- *java.util.Calendar
object initialized to the date
- * parsed by the parser
- * @throws ParseException if none of the parser mechanisms belonging to
- * the implementor can parse the input.
- */
- public Calendar parseTimestamp(String timestampStr) throws ParseException;
-
-}
diff --git a/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.class b/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.class
deleted file mode 100644
index 0ae3067..0000000
Binary files a/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java b/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
deleted file mode 100644
index 02a0cc8..0000000
--- a/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp.parser;
-
-import java.text.DateFormatSymbols;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.TimeZone;
-
-import org.apache.commons.net.ftp.Configurable;
-import org.apache.commons.net.ftp.FTPClientConfig;
-
-/**
- * Default implementation of the {@link FTPTimestampParser FTPTimestampParser}
- * interface also implements the {@link org.apache.commons.net.ftp.Configurable Configurable}
- * interface to allow the parsing to be configured from the outside.
- *
- * @see ConfigurableFTPFileEntryParserImpl
- * @since 1.4
- */
-public class FTPTimestampParserImpl implements
- FTPTimestampParser, Configurable
-{
-
-
- private SimpleDateFormat defaultDateFormat;
- private SimpleDateFormat recentDateFormat;
- private boolean lenientFutureDates = false;
-
-
- /**
- * The only constructor for this class.
- */
- public FTPTimestampParserImpl() {
- setDefaultDateFormat(DEFAULT_SDF);
- setRecentDateFormat(DEFAULT_RECENT_SDF);
- }
-
- /**
- * Implements the one {@link FTPTimestampParser#parseTimestamp(String) method}
- * in the {@link FTPTimestampParser FTPTimestampParser} interface
- * according to this algorithm:
- *
- * If the recentDateFormat member has been defined, try to parse the
- * supplied string with that. If that parse fails, or if the recentDateFormat
- * member has not been defined, attempt to parse with the defaultDateFormat
- * member. If that fails, throw a ParseException.
- *
- * This method allows a {@link Calendar} instance to be passed in which represents the
- * current (system) time.
- *
- * @see org.apache.commons.net.ftp.parser.FTPTimestampParser#parseTimestamp(java.lang.String)
- *
- * @param timestampStr The timestamp to be parsed
- */
- public Calendar parseTimestamp(String timestampStr) throws ParseException {
- Calendar now = Calendar.getInstance();
- return parseTimestamp(timestampStr, now);
- }
-
- /**
- * Implements the one {@link FTPTimestampParser#parseTimestamp(String) method}
- * in the {@link FTPTimestampParser FTPTimestampParser} interface
- * according to this algorithm:
- *
- * If the recentDateFormat member has been defined, try to parse the
- * supplied string with that. If that parse fails, or if the recentDateFormat
- * member has not been defined, attempt to parse with the defaultDateFormat
- * member. If that fails, throw a ParseException.
- *
- * @see org.apache.commons.net.ftp.parser.FTPTimestampParser#parseTimestamp(java.lang.String)
- * @param timestampStr The timestamp to be parsed
- * @param serverTime The current time for the server
- * @since 1.5
- */
- public Calendar parseTimestamp(String timestampStr, Calendar serverTime) throws ParseException {
- Calendar now = (Calendar) serverTime.clone();// Copy this, because we may change it
- now.setTimeZone(this.getServerTimeZone());
- Calendar working = (Calendar) now.clone();
- working.setTimeZone(getServerTimeZone());
- ParsePosition pp = new ParsePosition(0);
-
- Date parsed = null;
- if (recentDateFormat != null) {
- if (lenientFutureDates) {
- // add a day to "now" so that "slop" doesn't cause a date
- // slightly in the future to roll back a full year. (Bug 35181)
- now.add(Calendar.DATE, 1);
- }
- parsed = recentDateFormat.parse(timestampStr, pp);
- }
- if (parsed != null && pp.getIndex() == timestampStr.length())
- {
- working.setTime(parsed);
- working.set(Calendar.YEAR, now.get(Calendar.YEAR));
-
- if (working.after(now)) {
- working.add(Calendar.YEAR, -1);
- }
- } else {
- // Temporarily add the current year to the short date time
- // to cope with short-date leap year strings.
- // e.g. Java's DateFormatter will assume that "Feb 29 12:00" refers to
- // Feb 29 1970 (an invalid date) rather than a potentially valid leap year date.
- // This is pretty bad hack to work around the deficiencies of the JDK date/time classes.
- if (recentDateFormat != null) {
- pp = new ParsePosition(0);
- int year = now.get(Calendar.YEAR);
- String timeStampStrPlusYear = timestampStr + " " + year;
- SimpleDateFormat hackFormatter = new SimpleDateFormat(recentDateFormat.toPattern() + " yyyy",
- recentDateFormat.getDateFormatSymbols());
- hackFormatter.setLenient(false);
- hackFormatter.setTimeZone(recentDateFormat.getTimeZone());
- parsed = hackFormatter.parse(timeStampStrPlusYear, pp);
- }
- if (parsed != null && pp.getIndex() == timestampStr.length() + 5) {
- working.setTime(parsed);
- }
- else {
- pp = new ParsePosition(0);
- parsed = defaultDateFormat.parse(timestampStr, pp);
- // note, length checks are mandatory for us since
- // SimpleDateFormat methods will succeed if less than
- // full string is matched. They will also accept,
- // despite "leniency" setting, a two-digit number as
- // a valid year (e.g. 22:04 will parse as 22 A.D.)
- // so could mistakenly confuse an hour with a year,
- // if we don't insist on full length parsing.
- if (parsed != null && pp.getIndex() == timestampStr.length()) {
- working.setTime(parsed);
- } else {
- throw new ParseException(
- "Timestamp could not be parsed with older or recent DateFormat",
- pp.getIndex());
- }
- }
- }
- return working;
- }
-
- /**
- * @return Returns the defaultDateFormat.
- */
- public SimpleDateFormat getDefaultDateFormat() {
- return defaultDateFormat;
- }
- /**
- * @return Returns the defaultDateFormat pattern string.
- */
- public String getDefaultDateFormatString() {
- return defaultDateFormat.toPattern();
- }
- /**
- * @param defaultDateFormat The defaultDateFormat to be set.
- */
- private void setDefaultDateFormat(String format) {
- if (format != null) {
- this.defaultDateFormat = new SimpleDateFormat(format);
- this.defaultDateFormat.setLenient(false);
- }
- }
- /**
- * @return Returns the recentDateFormat.
- */
- public SimpleDateFormat getRecentDateFormat() {
- return recentDateFormat;
- }
- /**
- * @return Returns the recentDateFormat.
- */
- public String getRecentDateFormatString() {
- return recentDateFormat.toPattern();
- }
- /**
- * @param recentDateFormat The recentDateFormat to set.
- */
- private void setRecentDateFormat(String format) {
- if (format != null) {
- this.recentDateFormat = new SimpleDateFormat(format);
- this.recentDateFormat.setLenient(false);
- }
- }
-
- /**
- * @return returns an array of 12 strings representing the short
- * month names used by this parse.
- */
- public String[] getShortMonths() {
- return defaultDateFormat.getDateFormatSymbols().getShortMonths();
- }
-
-
- /**
- * @return Returns the serverTimeZone used by this parser.
- */
- public TimeZone getServerTimeZone() {
- return this.defaultDateFormat.getTimeZone();
- }
- /**
- * sets a TimeZone represented by the supplied ID string into all
- * of the parsers used by this server.
- * @param serverTimeZone Time Id java.util.TimeZone id used by
- * the ftp server. If null the client's local time zone is assumed.
- */
- private void setServerTimeZone(String serverTimeZoneId) {
- TimeZone serverTimeZone = TimeZone.getDefault();
- if (serverTimeZoneId != null) {
- serverTimeZone = TimeZone.getTimeZone(serverTimeZoneId);
- }
- this.defaultDateFormat.setTimeZone(serverTimeZone);
- if (this.recentDateFormat != null) {
- this.recentDateFormat.setTimeZone(serverTimeZone);
- }
- }
-
- /**
- * Implementation of the {@link Configurable Configurable}
- * interface. Configures this FTPTimestampParser
according
- * to the following logic:
- *
- *
config
, use that to parse parse timestamps.config
, use the month names represented
- * by that {@link FTPClientConfig#lookupDateFormatSymbols(String) language}
- * to parse timestamps. FTPFile
instance.
- * If the file listing line doesn't describe a file, then
- * null
is returned. Otherwise a FTPFile
- * instance representing the file is returned.
- *
- * @param entry
- * A line of text from the file listing
- * @return An FTPFile instance corresponding to the supplied entry
- */
- public FTPFile parseFTPEntry(String entry) {
- boolean isParsed = false;
- FTPFile f = new FTPFile();
-
- if (isType == FILE_LIST_TYPE)
- isParsed = parseFileList(f, entry);
- else if (isType == MEMBER_LIST_TYPE) {
- isParsed = parseMemberList(f, entry);
- if (!isParsed)
- isParsed = parseSimpleEntry(f, entry);
- } else if (isType == UNIX_LIST_TYPE) {
- isParsed = parseUnixList(f, entry);
- } else if (isType == JES_LEVEL_1_LIST_TYPE) {
- isParsed = parseJeslevel1List(f, entry);
- } else if (isType == JES_LEVEL_2_LIST_TYPE) {
- isParsed = parseJeslevel2List(f, entry);
- }
-
- if (!isParsed)
- f = null;
-
- return f;
- }
-
- /**
- * Parse entries representing a dataset list. Only datasets with DSORG PS or
- * PO or PO-E and with RECFM F* or V* will be parsed.
- *
- * Format of ZOS/MVS file list: 1 2 3 4 5 6 7 8 9 10 Volume Unit Referred
- * Ext Used Recfm Lrecl BlkSz Dsorg Dsname B10142 3390 2006/03/20 2 31 F 80
- * 80 PS MDI.OKL.WORK ARCIVE Not Direct Access Device
- * KJ.IOP998.ERROR.PL.UNITTEST B1N231 3390 2006/03/20 1 15 VB 256 27998 PO
- * PLU B1N231 3390 2006/03/20 1 15 VB 256 27998 PO-E PLB
- *
- * ----------------------------------- Group within Regex [1] Volume [2]
- * Unit [3] Referred [4] Ext: number of extents [5] Used [6] Recfm: Record
- * format [7] Lrecl: Logical record length [8] BlkSz: Block size [9] Dsorg:
- * Dataset organisation. Many exists but only support: PS, PO, PO-E [10]
- * Dsname: Dataset name
- *
- * Note: When volume is ARCIVE, it means the dataset is stored somewhere in
- * a tape archive. These entries is currently not supported by this parser.
- * A null value is returned.
- *
- * @param file
- * will be updated with Name, Type, Timestamp if parsed.
- * @param entry zosDirectoryEntry
- * @return true: entry was parsed, false: entry was not parsed.
- */
- private boolean parseFileList(FTPFile file, String entry) {
- if (matches(entry)) {
- file.setRawListing(entry);
- String name = group(2);
- String dsorg = group(1);
- file.setName(name);
-
- // DSORG
- if ("PS".equals(dsorg)) {
- file.setType(FTPFile.FILE_TYPE);
- }
- else if ("PO".equals(dsorg) || "PO-E".equals(dsorg)) {
- // regex already ruled out anything other than PO or PO-E
- file.setType(FTPFile.DIRECTORY_TYPE);
- }
- else {
- return false;
- }
-
- return true;
- }
-
- return false;
- }
-
- /**
- * Parse entries within a partitioned dataset.
- *
- * Format of a memberlist within a PDS: 1 2 3 4 5 6 7 8 9 Name VV.MM Created
- * Changed Size Init Mod Id TBSHELF 01.03 2002/09/12 2002/10/11 09:37 11 11
- * 0 KIL001 TBTOOL 01.12 2002/09/12 2004/11/26 19:54 51 28 0 KIL001
- *
- * ------------------------------------------- [1] Name [2] VV.MM: Version .
- * modification [3] Created: yyyy / MM / dd [4,5] Changed: yyyy / MM / dd
- * HH:mm [6] Size: number of lines [7] Init: number of lines when first
- * created [8] Mod: number of modified lines a last save [9] Id: User id for
- * last update
- *
- *
- * @param file
- * will be updated with Name, Type and Timestamp if parsed.
- * @param entry zosDirectoryEntry
- * @return true: entry was parsed, false: entry was not parsed.
- */
- private boolean parseMemberList(FTPFile file, String entry) {
- if (matches(entry)) {
- file.setRawListing(entry);
- String name = group(1);
- String datestr = group(2) + " " + group(3);
- file.setName(name);
- file.setType(FTPFile.FILE_TYPE);
- try {
- file.setTimestamp(super.parseTimestamp(datestr));
- } catch (ParseException e) {
- e.printStackTrace();
- // just ignore parsing errors.
- // TODO check this is ok
- return false; // this is a parsing failure too.
- }
- return true;
- }
-
- return false;
- }
-
- /**
- * Assigns the name to the first word of the entry. Only to be used from a
- * safe context, for example from a memberlist, where the regex for some
- * reason fails. Then just assign the name field of FTPFile.
- *
- * @param file
- * @param entry
- * @return
- */
- private boolean parseSimpleEntry(FTPFile file, String entry) {
- if (entry != null && entry.length() > 0) {
- file.setRawListing(entry);
- String name = entry.split(" ")[0];
- file.setName(name);
- file.setType(FTPFile.FILE_TYPE);
- return true;
- }
- return false;
- }
-
- /**
- * Parse the entry as a standard unix file. Using the UnixFTPEntryParser.
- *
- * @param file
- * @param entry
- * @return true: entry is parsed, false: entry could not be parsed.
- */
- private boolean parseUnixList(FTPFile file, String entry) {
- file = unixFTPEntryParser.parseFTPEntry(entry);
- if (file == null)
- return false;
- return true;
- }
-
- /**
- * Matches these entries, note: no header: [1] [2] [3] [4] [5] IBMUSER1
- * JOB01906 OUTPUT 3 Spool Files
- * 012345678901234567890123456789012345678901234 1 2 3 4
- * ------------------------------------------- Group in regex [1] Job name
- * [2] Job number [3] Job status (INPUT,ACTIVE,OUTPUT) [4] Number of sysout
- * files [5] The string "Spool Files"
- *
- *
- * @param file
- * will be updated with Name, Type and Timestamp if parsed.
- * @param entry zosDirectoryEntry
- * @return true: entry was parsed, false: entry was not parsed.
- */
- private boolean parseJeslevel1List(FTPFile file, String entry) {
- if (matches(entry)) {
- if (group(3).equalsIgnoreCase("OUTPUT")) {
- file.setRawListing(entry);
- String name = group(2); /* Job Number, used by GET */
- file.setName(name);
- file.setType(FTPFile.FILE_TYPE);
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Matches these entries, note: no header: [1] [2] [3] [4] [5] JOBNAME JOBID
- * OWNER STATUS CLASS IBMUSER1 JOB01906 IBMUSER OUTPUT A RC=0000 3 spool
- * files IBMUSER TSU01830 IBMUSER OUTPUT TSU ABEND=522 3 spool files
- * 012345678901234567890123456789012345678901234 1 2 3 4
- * ------------------------------------------- Group in regex [1] Job name
- * [2] Job number [3] Owner [4] Job status (INPUT,ACTIVE,OUTPUT) [5] Job
- * Class [6] The rest
- *
- *
- * @param file
- * will be updated with Name, Type and Timestamp if parsed.
- * @param entry zosDirectoryEntry
- * @return true: entry was parsed, false: entry was not parsed.
- */
- private boolean parseJeslevel2List(FTPFile file, String entry) {
- if (matches(entry)) {
- if (group(4).equalsIgnoreCase("OUTPUT")) {
- file.setRawListing(entry);
- String name = group(2); /* Job Number, used by GET */
- file.setName(name);
- file.setType(FTPFile.FILE_TYPE);
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * preParse is called as part of the interface. Per definition is is called
- * before the parsing takes place. Three kind of lists is recognize:
- * z/OS-MVS File lists z/OS-MVS Member lists unix file lists
- * @since 2.0
- */
- @Override
- public ListREGEX
is not a valid regular expression.
- */
- public NTFTPEntryParser()
- {
- this(null);
- }
-
- /**
- * This constructor allows the creation of an NTFTPEntryParser object
- * with something other than the default configuration.
- *
- * @param config The {@link FTPClientConfig configuration} object used to
- * configure this parser.
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- * REGEX
is not a valid regular expression.
- * @since 1.4
- */
- public NTFTPEntryParser(FTPClientConfig config)
- {
- super(REGEX);
- configure(config);
- }
-
- /**
- * Parses a line of an NT FTP server file listing and converts it into a
- * usable format in the form of an FTPFile
instance. If the
- * file listing line doesn't describe a file, null
is
- * returned, otherwise a FTPFile
instance representing the
- * files in the directory is returned.
- * REGEX
is not a valid regular expression.
- */
- public NetwareFTPEntryParser() {
- this(null);
- }
-
- /**
- * This constructor allows the creation of an NetwareFTPEntryParser object
- * with something other than the default configuration.
- *
- * @param config The {@link FTPClientConfig configuration} object used to
- * configure this parser.
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- * REGEX
is not a valid regular expression.
- * @since 1.4
- */
- public NetwareFTPEntryParser(FTPClientConfig config) {
- super(REGEX);
- configure(config);
- }
-
- /**
- * Parses a line of an NetwareFTP server file listing and converts it into a
- * usable format in the form of an FTPFile
instance. If the
- * file listing line doesn't describe a file, null
is
- * returned, otherwise a FTPFile
instance representing the
- * files in the directory is returned.
- *
- *
- *
- * See here
- * for more details
- *
- * @param entry A line of text from the file listing
- * @return An FTPFile instance corresponding to the supplied entry
- */
- public FTPFile parseFTPEntry(String entry) {
-
- FTPFile f = new FTPFile();
- if (matches(entry)) {
- String dirString = group(1);
- String attrib = group(2);
- String user = group(3);
- String size = group(4);
- String datestr = group(5);
- String name = group(9);
-
- try {
- f.setTimestamp(super.parseTimestamp(datestr));
- } catch (ParseException e) {
- // intentionally do nothing
- }
-
- //is it a DIR or a file
- if (dirString.trim().equals("d")) {
- f.setType(FTPFile.DIRECTORY_TYPE);
- } else // Should be "-"
- {
- f.setType(FTPFile.FILE_TYPE);
- }
-
- f.setUser(user);
-
- //set the name
- f.setName(name.trim());
-
- //set the size
- f.setSize(Long.parseLong(size.trim()));
-
- // Now set the permissions (or at least a subset thereof - full permissions would probably require
- // subclassing FTPFile and adding extra metainformation there)
- if (attrib.indexOf("R") != -1) {
- f.setPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION,
- true);
- }
- if (attrib.indexOf("W") != -1) {
- f.setPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION,
- true);
- }
-
- return (f);
- }
- return null;
-
- }
-
- /**
- * Defines a default configuration to be used when this class is
- * instantiated without a {@link FTPClientConfig FTPClientConfig}
- * parameter being specified.
- * @return the default configuration for this parser.
- */
- @Override
- protected FTPClientConfig getDefaultConfiguration() {
- return new FTPClientConfig(FTPClientConfig.SYST_NETWARE,
- DEFAULT_DATE_FORMAT, DEFAULT_RECENT_DATE_FORMAT, null, null,
- null);
- }
-
-}
diff --git a/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.class b/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.class
deleted file mode 100644
index 332ae30..0000000
Binary files a/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java b/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
deleted file mode 100644
index dc02ffb..0000000
--- a/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp.parser;
-import java.text.ParseException;
-
-import org.apache.commons.net.ftp.FTPClientConfig;
-import org.apache.commons.net.ftp.FTPFile;
-
-/**
- * Implementation of FTPFileEntryParser and FTPFileListParser for OS2 Systems.
- *
- * @author Winston Ojeda
- * @author Steve Cohen
- * @version $Id: OS2FTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
- * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
- */
-public class OS2FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
-
-{
-
- private static final String DEFAULT_DATE_FORMAT
- = "MM-dd-yy HH:mm"; //11-09-01 12:30
- /**
- * this is the regular expression used by this parser.
- */
- private static final String REGEX =
- "\\s*([0-9]+)\\s*"
- + "(\\s+|[A-Z]+)\\s*"
- + "(DIR|\\s+)\\s*"
- + "(\\S+)\\s+(\\S+)\\s+" /* date stuff */
- + "(\\S.*)";
-
- /**
- * The default constructor for a OS2FTPEntryParser object.
- *
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- * REGEX
is not a valid regular expression.
- */
- public OS2FTPEntryParser()
- {
- this(null);
- }
-
- /**
- * This constructor allows the creation of an OS2FTPEntryParser object
- * with something other than the default configuration.
- *
- * @param config The {@link FTPClientConfig configuration} object used to
- * configure this parser.
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- * REGEX
is not a valid regular expression.
- * @since 1.4
- */
- public OS2FTPEntryParser(FTPClientConfig config)
- {
- super(REGEX);
- configure(config);
- }
-
- /**
- * Parses a line of an OS2 FTP server file listing and converts it into a
- * usable format in the form of an FTPFile
instance. If the
- * file listing line doesn't describe a file, null
is
- * returned, otherwise a FTPFile
instance representing the
- * files in the directory is returned.
- * REGEX
is not a valid regular expression.
- */
- public OS400FTPEntryParser()
- {
- this(null);
- }
-
- /**
- * This constructor allows the creation of an OS400FTPEntryParser object
- * with something other than the default configuration.
- *
- * @param config The {@link FTPClientConfig configuration} object used to
- * configure this parser.
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- * REGEX
is not a valid regular expression.
- * @since 1.4
- */
- public OS400FTPEntryParser(FTPClientConfig config)
- {
- super(REGEX);
- configure(config);
- }
-
-
- public FTPFile parseFTPEntry(String entry)
- {
-
- FTPFile file = new FTPFile();
- file.setRawListing(entry);
- int type;
-
- if (matches(entry))
- {
- String usr = group(1);
- String filesize = group(2);
- String datestr = group(3)+" "+group(4);
- String typeStr = group(5);
- String name = group(6);
-
- try
- {
- file.setTimestamp(super.parseTimestamp(datestr));
- }
- catch (ParseException e)
- {
- // intentionally do nothing
- }
-
-
- if (typeStr.equalsIgnoreCase("*STMF"))
- {
- type = FTPFile.FILE_TYPE;
- }
- else if (typeStr.equalsIgnoreCase("*DIR"))
- {
- type = FTPFile.DIRECTORY_TYPE;
- }
- else
- {
- type = FTPFile.UNKNOWN_TYPE;
- }
-
- file.setType(type);
-
- file.setUser(usr);
-
- try
- {
- file.setSize(Long.parseLong(filesize));
- }
- catch (NumberFormatException e)
- {
- // intentionally do nothing
- }
-
- if (name.endsWith("/"))
- {
- name = name.substring(0, name.length() - 1);
- }
- int pos = name.lastIndexOf('/');
- if (pos > -1)
- {
- name = name.substring(pos + 1);
- }
-
- file.setName(name);
-
- return file;
- }
- return null;
- }
-
- /**
- * Defines a default configuration to be used when this class is
- * instantiated without a {@link FTPClientConfig FTPClientConfig}
- * parameter being specified.
- * @return the default configuration for this parser.
- */
- @Override
- protected FTPClientConfig getDefaultConfiguration() {
- return new FTPClientConfig(
- FTPClientConfig.SYST_OS400,
- DEFAULT_DATE_FORMAT,
- null, null, null, null);
- }
-
-}
diff --git a/org/apache/commons/net/ftp/parser/ParserInitializationException.class b/org/apache/commons/net/ftp/parser/ParserInitializationException.class
deleted file mode 100644
index 4f7fb6f..0000000
Binary files a/org/apache/commons/net/ftp/parser/ParserInitializationException.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/ParserInitializationException.java b/org/apache/commons/net/ftp/parser/ParserInitializationException.java
deleted file mode 100644
index 8af9261..0000000
--- a/org/apache/commons/net/ftp/parser/ParserInitializationException.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp.parser;
-
-/**
- * This class encapsulates all errors that may be thrown by
- * the process of an FTPFileEntryParserFactory creating and
- * instantiating an FTPFileEntryParser.
- */
-public class ParserInitializationException extends RuntimeException {
-
- /**
- * Root exception that caused this to be thrown
- */
- private final Throwable rootCause;
-
- /**
- * Constucts a ParserInitializationException with just a message
- *
- * @param message Exception message
- */
- public ParserInitializationException(String message) {
- super(message);
- this.rootCause = null;
- }
-
- /**
- * Constucts a ParserInitializationException with a message
- * and a root cause.
- *
- * @param message Exception message
- * @param rootCause root cause throwable that caused
- * this to be thrown
- */
- public ParserInitializationException(String message, Throwable rootCause) {
- super(message);
- this.rootCause = rootCause;
- }
-
- /**
- * returns the root cause of this exception or null
- * if no root cause was specified.
- *
- * @return the root cause of this exception being thrown
- */
- public Throwable getRootCause() {
- return this.rootCause;
- }
-
-}
diff --git a/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.class b/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.class
deleted file mode 100644
index 3cd32f0..0000000
Binary files a/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java b/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java
deleted file mode 100644
index 5277444..0000000
--- a/org/apache/commons/net/ftp/parser/RegexFTPFileEntryParserImpl.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.apache.commons.net.ftp.parser;
-
-import java.util.regex.MatchResult;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import org.apache.commons.net.ftp.FTPFileEntryParserImpl;
-
-/**
- * This abstract class implements both the older FTPFileListParser and
- * newer FTPFileEntryParser interfaces with default functionality.
- * All the classes in the parser subpackage inherit from this.
- *
- * This is the base for all regular based FTPFileEntryParser
- *
- * @author Steve Cohen matchnum'th
group of the internal
- * match or null if this method is called without a match having
- * been made.
- */
- public String group(int matchnum) {
- if (this.result == null) {
- return null;
- }
- return this.result.group(matchnum);
- }
-
- /**
- * For debugging purposes - returns a string shows each match group by
- * number.
- *
- * @return a string shows each match group by number.
- */
-
- public String getGroupsAsString() {
- StringBuffer b = new StringBuffer();
- for (int i = 1; i <= this.result.groupCount(); i++) {
- b.append(i).append(") ").append(this.result.group(i)).append(
- System.getProperty("line.separator"));
- }
- return b.toString();
- }
-
- /**
- * Alter the current regular expression being utilised for entry parsing
- * and create a new {@link Pattern} instance.
- * @param regex The new regular expression
- * @return
- * @since 2.0
- */
- public boolean setRegex(String regex) {
- try {
- pattern = Pattern.compile(regex);
- } catch (PatternSyntaxException pse) {
- throw new IllegalArgumentException("Unparseable regex supplied: "
- + regex);
- }
- return (pattern != null);
- }
-
-}
diff --git a/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.class b/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.class
deleted file mode 100644
index 27a082b..0000000
Binary files a/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.class and /dev/null differ
diff --git a/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java b/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
deleted file mode 100644
index 2a2a909..0000000
--- a/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.ftp.parser;
-import java.text.ParseException;
-
-import org.apache.commons.net.ftp.FTPClientConfig;
-import org.apache.commons.net.ftp.FTPFile;
-
-/**
- * Implementation FTPFileEntryParser and FTPFileListParser for standard
- * Unix Systems.
- *
- * This class is based on the logic of Daniel Savarese's
- * DefaultFTPListParser, but adapted to use regular expressions and to fit the
- * new FTPFileEntryParser interface.
- * @version $Id: UnixFTPEntryParser.java 658518 2008-05-21 01:04:30Z sebb $
- * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
- */
-public class UnixFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
-{
-
- static final String DEFAULT_DATE_FORMAT
- = "MMM d yyyy"; //Nov 9 2001
-
- static final String DEFAULT_RECENT_DATE_FORMAT
- = "MMM d HH:mm"; //Nov 9 20:06
-
- static final String NUMERIC_DATE_FORMAT
- = "yyyy-MM-dd HH:mm"; //2001-11-09 20:06
-
- /**
- * Some Linux distributions are now shipping an FTP server which formats
- * file listing dates in an all-numeric format:
- *
"yyyy-MM-dd HH:mm
.
- * This is a very welcome development, and hopefully it will soon become
- * the standard. However, since it is so new, for now, and possibly
- * forever, we merely accomodate it, but do not make it the default.
- * UnixFTPEntryParser(FTPClientConfig)
.
- * Steve Cohen - 2005-04-17
- */
- public static final FTPClientConfig NUMERIC_DATE_CONFIG =
- new FTPClientConfig(
- FTPClientConfig.SYST_UNIX,
- NUMERIC_DATE_FORMAT,
- null, null, null, null);
-
- /**
- * this is the regular expression used by this parser.
- *
- * Permissions:
- * r the file is readable
- * w the file is writable
- * x the file is executable
- * - the indicated permission is not granted
- * L mandatory locking occurs during access (the set-group-ID bit is
- * on and the group execution bit is off)
- * s the set-user-ID or set-group-ID bit is on, and the corresponding
- * user or group execution bit is also on
- * S undefined bit-state (the set-user-ID bit is on and the user
- * execution bit is off)
- * t the 1000 (octal) bit, or sticky bit, is on [see chmod(1)], and
- * execution is on
- * T the 1000 bit is turned on, and execution is off (undefined bit-
- * state)
- * e z/OS external link bit
- */
- private static final String REGEX =
- "([bcdelfmpSs-])"
- +"(((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-]))((r|-)(w|-)([xsStTL-])))\\+?\\s+"
- + "(\\d+)\\s+"
- + "(?:(\\S+(?:\\s\\S+)*?)\\s+)?" // owner name (optional spaces)
- + "(?:(\\S+(?:\\s\\S+)*)\\s+)?" // group name (optional spaces)
- + "(\\d+(?:,\\s*\\d+)?)\\s+"
-
- /*
- numeric or standard format date
- */
- + "((?:\\d+[-/]\\d+[-/]\\d+)|(?:\\S+\\s+\\S+))\\s+"
-
- /*
- year (for non-recent standard format)
- or time (for numeric or recent standard format
- */
- + "(\\d+(?::\\d+)?)\\s+"
-
- + "(\\S*)(\\s*.*)";
-
-
- /**
- * The default constructor for a UnixFTPEntryParser object.
- *
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- * REGEX
is not a valid regular expression.
- */
- public UnixFTPEntryParser()
- {
- this(null);
- }
-
- /**
- * This constructor allows the creation of a UnixFTPEntryParser object with
- * something other than the default configuration.
- *
- * @param config The {@link FTPClientConfig configuration} object used to
- * configure this parser.
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- * REGEX
is not a valid regular expression.
- * @since 1.4
- */
- public UnixFTPEntryParser(FTPClientConfig config)
- {
- super(REGEX);
- configure(config);
- }
-
-
- /**
- * Parses a line of a unix (standard) FTP server file listing and converts
- * it into a usable format in the form of an FTPFile
- * instance. If the file listing line doesn't describe a file,
- * null
is returned, otherwise a FTPFile
- * instance representing the files in the directory is returned.
- * REGEX
is not a valid regular expression.
- */
- public VMSFTPEntryParser()
- {
- this(null);
- }
-
- /**
- * This constructor allows the creation of a VMSFTPEntryParser object with
- * something other than the default configuration.
- *
- * @param config The {@link FTPClientConfig configuration} object used to
- * configure this parser.
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- * REGEX
is not a valid regular expression.
- * @since 1.4
- */
- public VMSFTPEntryParser(FTPClientConfig config)
- {
- super(REGEX);
- configure(config);
- }
-
-
-
- /***
- * Parses an FTP server file listing and converts it into a usable format
- * in the form of an array of FTPFile
instances. If the
- * file list contains no files, null
should be
- * returned, otherwise an array of FTPFile
instances
- * representing the files in the directory is returned.
- * FTPFile
instance. If the
- * file listing line doesn't describe a file, null
is
- * returned, otherwise a FTPFile
instance representing the
- * files in the directory is returned.
- * REGEX
is not a valid regular expression.
- */
- public VMSVersioningFTPEntryParser()
- {
- this(null);
- }
-
- /**
- * This constructor allows the creation of a VMSVersioningFTPEntryParser
- * object with something other than the default configuration.
- *
- * @param config The {@link FTPClientConfig configuration} object used to
- * configure this parser.
- * @exception IllegalArgumentException
- * Thrown if the regular expression is unparseable. Should not be seen
- * under normal conditions. It it is seen, this is a sign that
- * REGEX
is not a valid regular expression.
- * @since 1.4
- */
- public VMSVersioningFTPEntryParser(FTPClientConfig config)
- {
- super();
- configure(config);
- try
- {
- //_preparse_matcher_ = new Perl5Matcher();
- _preparse_pattern_ = Pattern.compile(PRE_PARSE_REGEX);
- }
- catch (PatternSyntaxException pse)
- {
- throw new IllegalArgumentException (
- "Unparseable regex supplied: " + PRE_PARSE_REGEX);
- }
-
- }
-
-
-
- private static class NameVersion {
- String name;
- int versionNumber;
- NameVersion(String name, String vers) {
- this.name = name;
- this.versionNumber = Integer.parseInt(vers);
- }
- }
-
- /**
- * Implement hook provided for those implementers (such as
- * VMSVersioningFTPEntryParser, and possibly others) which return
- * multiple files with the same name to remove the duplicates ..
- *
- * @param original Original list
- *
- * @return Original list purged of duplicates
- */
- @Override
- public ListUNKNOWN_STREAM_SIZE
if the
- * size is unknown.
- */
- public CopyStreamEvent(Object source, long totalBytesTransferred,
- int bytesTransferred, long streamSize)
- {
- super(source);
- this.bytesTransferred = bytesTransferred;
- this.totalBytesTransferred = totalBytesTransferred;
- this.streamSize = streamSize;
- }
-
- /**
- * Returns the number of bytes transferred by the write that triggered
- * the event.
- * @return The number of bytes transferred by the write that triggered
- * the vent.
- */
- public int getBytesTransferred()
- {
- return bytesTransferred;
- }
-
- /**
- * Returns the total number of bytes transferred so far by the copy
- * operation.
- * @return The total number of bytes transferred so far by the copy
- * operation.
- */
- public long getTotalBytesTransferred()
- {
- return totalBytesTransferred;
- }
-
- /**
- * Returns the size of the stream being copied.
- * This may be set to UNKNOWN_STREAM_SIZE
if the
- * size is unknown.
- * @return The size of the stream being copied.
- */
- public long getStreamSize()
- {
- return streamSize;
- }
-}
diff --git a/org/apache/commons/net/io/CopyStreamException.class b/org/apache/commons/net/io/CopyStreamException.class
deleted file mode 100644
index adf2ebb..0000000
Binary files a/org/apache/commons/net/io/CopyStreamException.class and /dev/null differ
diff --git a/org/apache/commons/net/io/CopyStreamException.java b/org/apache/commons/net/io/CopyStreamException.java
deleted file mode 100644
index 8d34145..0000000
--- a/org/apache/commons/net/io/CopyStreamException.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.io.IOException;
-
-/**
- * The CopyStreamException class is thrown by the org.apache.commons.io.Util
- * copyStream() methods. It stores the number of bytes confirmed to
- * have been transferred before an I/O error as well as the IOException
- * responsible for the failure of a copy operation.
- * @see Util
- * @author Daniel F. Savarese
- * @version $Id: CopyStreamException.java 489397 2006-12-21 16:28:51Z rwinston $
- */
-public class CopyStreamException extends IOException
-{
- private long totalBytesTransferred;
- private IOException ioException;
-
- /**
- * Creates a new CopyStreamException instance.
- * @param message A message describing the error.
- * @param bytesTransferred The total number of bytes transferred before
- * an exception was thrown in a copy operation.
- * @param exception The IOException thrown during a copy operation.
- */
- public CopyStreamException(String message,
- long bytesTransferred,
- IOException exception)
- {
- super(message);
- totalBytesTransferred = bytesTransferred;
- ioException = exception;
- }
-
- /**
- * Returns the total number of bytes confirmed to have
- * been transferred by a failed copy operation.
- * @return The total number of bytes confirmed to have
- * been transferred by a failed copy operation.
- */
- public long getTotalBytesTransferred()
- {
- return totalBytesTransferred;
- }
-
- /**
- * Returns the IOException responsible for the failure of a copy operation.
- * @return The IOException responsible for the failure of a copy operation.
- */
- public IOException getIOException()
- {
- return ioException;
- }
-}
diff --git a/org/apache/commons/net/io/CopyStreamListener.class b/org/apache/commons/net/io/CopyStreamListener.class
deleted file mode 100644
index 3d5bb08..0000000
Binary files a/org/apache/commons/net/io/CopyStreamListener.class and /dev/null differ
diff --git a/org/apache/commons/net/io/CopyStreamListener.java b/org/apache/commons/net/io/CopyStreamListener.java
deleted file mode 100644
index 9e97fb9..0000000
--- a/org/apache/commons/net/io/CopyStreamListener.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.io;
-
-import java.util.EventListener;
-
-/**
- * The CopyStreamListener class can accept CopyStreamEvents to keep track
- * of the progress of a stream copying operation. However, it is currently
- * not used that way within NetComponents for performance reasons. Rather
- * the bytesTransferred(long, int) method is called directly rather than
- * passing an event to bytesTransferred(CopyStreamEvent), saving the creation
- * of a CopyStreamEvent instance. Also, the only place where
- * CopyStreamListener is currently used within NetComponents is in the
- * static methods of the uninstantiable org.apache.commons.io.Util class, which
- * would preclude the use of addCopyStreamListener and
- * removeCopyStreamListener methods. However, future additions may use the
- * JavaBean event model, which is why the hooks have been included from the
- * beginning.
- * flush()
will
- * not flush the last byte written if that byte was a carriage
- * return. A call to {@link #close close() }, however, will
- * flush the carriage return.
- * copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE);
- ***/
- public static final long copyStream(InputStream source, OutputStream dest)
- throws CopyStreamException
- {
- return copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE);
- }
-
-
- /***
- * Copies the contents of a Reader to a Writer using a
- * copy buffer of a given size and notifies the provided
- * CopyStreamListener of the progress of the copy operation by calling
- * its bytesTransferred(long, int) method after each write to the
- * destination. If you wish to notify more than one listener you should
- * use a CopyStreamAdapter as the listener and register the additional
- * listeners with the CopyStreamAdapter.
- * copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE);
- ***/
- public static final long copyReader(Reader source, Writer dest)
- throws CopyStreamException
- {
- return copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE);
- }
-
-}
diff --git a/org/apache/commons/net/nntp/Article.java b/org/apache/commons/net/nntp/Article.java
deleted file mode 100644
index cccba3b..0000000
--- a/org/apache/commons/net/nntp/Article.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.nntp;
-
-import java.util.ArrayList;
-import java.util.StringTokenizer;
-
-/**
- * This is a class that contains the basic state needed for message retrieval and threading.
- * With thanks to Jamie Zawinski NNTPConectionClosedException
- * is a subclass of IOException
and therefore need not be
- * caught separately, but if you are going to catch it separately, its
- * catch block must appear before the more general IOException
- * catch block. When you encounter an
- * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
- * , you must disconnect the connection with
- * {@link #disconnect disconnect() } to properly clean up the
- * system resources used by NNTP. Before disconnecting, you may check the
- * last reply code and text with
- * {@link #getReplyCode getReplyCode } and
- * {@link #getReplyString getReplyString }.
- * DEFAULT_PORT
and initializes internal data structures
- * for saving NNTP reply information.
- ***/
- public NNTP()
- {
- setDefaultPort(DEFAULT_PORT);
- __commandBuffer = new StringBuffer();
- _replyString = null;
- _reader_ = null;
- _writer_ = null;
- _isAllowedToPost = false;
- _commandSupport_ = new ProtocolCommandSupport(this);
- }
-
- private void __getReply() throws IOException
- {
- _replyString = _reader_.readLine();
-
- if (_replyString == null)
- throw new NNTPConnectionClosedException(
- "Connection closed without indication.");
-
- // In case we run into an anomaly we don't want fatal index exceptions
- // to be thrown.
- if (_replyString.length() < 3)
- throw new MalformedServerReplyException(
- "Truncated server reply: " + _replyString);
- try
- {
- _replyCode = Integer.parseInt(_replyString.substring(0, 3));
- }
- catch (NumberFormatException e)
- {
- throw new MalformedServerReplyException(
- "Could not parse response code.\nServer Reply: " + _replyString);
- }
-
- if (_commandSupport_.getListenerCount() > 0)
- _commandSupport_.fireReplyReceived(_replyCode, _replyString +
- SocketClient.NETASCII_EOL);
-
- if (_replyCode == NNTPReply.SERVICE_DISCONTINUED)
- throw new NNTPConnectionClosedException(
- "NNTP response 400 received. Server closed connection.");
- }
-
- /***
- * Initiates control connections and gets initial reply, determining
- * if the client is allowed to post to the server. Initializes
- * {@link #_reader_} and {@link #_writer_} to wrap
- * {@link SocketClient#_input_} and {@link SocketClient#_output_}.
- ***/
- @Override
- protected void _connectAction_() throws IOException
- {
- super._connectAction_();
- _reader_ =
- new BufferedReader(new InputStreamReader(_input_,
- __DEFAULT_ENCODING));
- _writer_ =
- new BufferedWriter(new OutputStreamWriter(_output_,
- __DEFAULT_ENCODING));
- __getReply();
-
- _isAllowedToPost = (_replyCode == NNTPReply.SERVER_READY_POSTING_ALLOWED);
- }
-
- /***
- * Adds a ProtocolCommandListener. Delegates this task to
- * {@link #_commandSupport_ _commandSupport_ }.
- * connect
is of type void.
- * NNTPConectionClosedException
- * is a subclass of IOException
and therefore need not be
- * caught separately, but if you are going to catch it separately, its
- * catch block must appear before the more general IOException
- * catch block. When you encounter an
- * {@link org.apache.commons.net.nntp.NNTPConnectionClosedException}
- * , you must disconnect the connection with
- * {@link org.apache.commons.net.nntp.NNTP#disconnect disconnect() }
- * to properly clean up the
- * system resources used by NNTP. Before disconnecting, you may check the
- * last reply code and text with
- * {@link org.apache.commons.net.nntp.NNTP#getReplyCode getReplyCode } and
- * {@link org.apache.commons.net.nntp.NNTP#getReplyString getReplyString }.
- * articleId
- * field of the ArticlePointer cannot always be trusted because some
- * NNTP servers do not correctly follow the RFC 977 reply format.
- * retrieveArticle(articleId, null)
***/
- public Reader retrieveArticle(String articleId) throws IOException
- {
- return retrieveArticle(articleId, null);
- }
-
- /*** Same as retrieveArticle(null)
***/
- public Reader retrieveArticle() throws IOException
- {
- return retrieveArticle(null);
- }
-
-
- /***
- * Retrieves an article from the currently selected newsgroup. The
- * article is referenced by its article number.
- * The article number and identifier contained in the server reply
- * are returned through an ArticlePointer. The articleId
- * field of the ArticlePointer cannot always be trusted because some
- * NNTP servers do not correctly follow the RFC 977 reply format.
- * retrieveArticle(articleNumber, null)
***/
- public Reader retrieveArticle(int articleNumber) throws IOException
- {
- return retrieveArticle(articleNumber, null);
- }
-
-
-
- /***
- * Retrieves an article header from the NNTP server. The article is
- * referenced
- * by its unique article identifier (including the enclosing < and >).
- * The article number and identifier contained in the server reply
- * are returned through an ArticlePointer. The articleId
- * field of the ArticlePointer cannot always be trusted because some
- * NNTP servers do not correctly follow the RFC 977 reply format.
- * retrieveArticleHeader(articleId, null)
***/
- public Reader retrieveArticleHeader(String articleId) throws IOException
- {
- return retrieveArticleHeader(articleId, null);
- }
-
- /*** Same as retrieveArticleHeader(null)
***/
- public Reader retrieveArticleHeader() throws IOException
- {
- return retrieveArticleHeader(null);
- }
-
-
- /***
- * Retrieves an article header from the currently selected newsgroup. The
- * article is referenced by its article number.
- * The article number and identifier contained in the server reply
- * are returned through an ArticlePointer. The articleId
- * field of the ArticlePointer cannot always be trusted because some
- * NNTP servers do not correctly follow the RFC 977 reply format.
- * retrieveArticleHeader(articleNumber, null)
***/
- public Reader retrieveArticleHeader(int articleNumber) throws IOException
- {
- return retrieveArticleHeader(articleNumber, null);
- }
-
-
-
- /***
- * Retrieves an article body from the NNTP server. The article is
- * referenced
- * by its unique article identifier (including the enclosing < and >).
- * The article number and identifier contained in the server reply
- * are returned through an ArticlePointer. The articleId
- * field of the ArticlePointer cannot always be trusted because some
- * NNTP servers do not correctly follow the RFC 977 reply format.
- * retrieveArticleBody(articleId, null)
***/
- public Reader retrieveArticleBody(String articleId) throws IOException
- {
- return retrieveArticleBody(articleId, null);
- }
-
- /*** Same as retrieveArticleBody(null)
***/
- public Reader retrieveArticleBody() throws IOException
- {
- return retrieveArticleBody(null);
- }
-
-
- /***
- * Retrieves an article body from the currently selected newsgroup. The
- * article is referenced by its article number.
- * The article number and identifier contained in the server reply
- * are returned through an ArticlePointer. The articleId
- * field of the ArticlePointer cannot always be trusted because some
- * NNTP servers do not correctly follow the RFC 977 reply format.
- * retrieveArticleBody(articleNumber, null)
***/
- public Reader retrieveArticleBody(int articleNumber) throws IOException
- {
- return retrieveArticleBody(articleNumber, null);
- }
-
-
- /***
- * Select the specified newsgroup to be the target of for future article
- * retrieval and posting operations. Also return the newsgroup
- * information contained in the server reply through the info parameter.
- * selectNewsgroup(newsgroup, null)
***/
- public boolean selectNewsgroup(String newsgroup) throws IOException
- {
- return selectNewsgroup(newsgroup, null);
- }
-
- /***
- * List the command help from the server.
- * selectArticle(articleId, null)
***/
- public boolean selectArticle(String articleId) throws IOException
- {
- return selectArticle(articleId, null);
- }
-
- /****
- * Same as selectArticle(null, articleId)
. Useful
- * for retrieving the current article number.
- ***/
- public boolean selectArticle(ArticlePointer pointer) throws IOException
- {
- return selectArticle(null, pointer);
- }
-
-
- /***
- * Select an article in the currently selected newsgroup by its number.
- * and return its article number and id through the
- * pointer parameter. This is achieved through the STAT command.
- * According to RFC 977, this WILL set the current article pointer
- * on the server. Use this command to select an article before retrieving
- * it, or to obtain an article's unique identifier given its number.
- * selectArticle(articleNumber, null)
***/
- public boolean selectArticle(int articleNumber) throws IOException
- {
- return selectArticle(articleNumber, null);
- }
-
-
- /***
- * Select the article preceeding the currently selected article in the
- * currently selected newsgroup and return its number and unique id
- * through the pointer parameter. Because of deviating server
- * implementations, the articleId information cannot be trusted. To
- * obtain the article identifier, issue a
- * selectArticle(pointer.articleNumber, pointer)
immediately
- * afterward.
- * selectPreviousArticle(null)
***/
- public boolean selectPreviousArticle() throws IOException
- {
- return selectPreviousArticle(null);
- }
-
-
- /***
- * Select the article following the currently selected article in the
- * currently selected newsgroup and return its number and unique id
- * through the pointer parameter. Because of deviating server
- * implementations, the articleId information cannot be trusted. To
- * obtain the article identifier, issue a
- * selectArticle(pointer.articleNumber, pointer)
immediately
- * afterward.
- * selectNextArticle(null)
***/
- public boolean selectNextArticle() throws IOException
- {
- return selectNextArticle(null);
- }
-
-
- /***
- * List all newsgroups served by the NNTP server. If no newsgroups
- * are served, a zero length array will be returned. If the command
- * fails, null will be returned.
- *
- * writer = client.postArticle();
- * if(writer == null) // failure
- * return false;
- * header = new SimpleNNTPHeader("foobar@foo.com", "Just testing");
- * header.addNewsgroup("alt.test");
- * writer.write(header.toString());
- * writer.write("This is just a test");
- * writer.close();
- * if(!client.completePendingCommand()) // failure
- * return false;
- *
- *
- * query = new NewsGroupsOrNewsQuery(new GregorianCalendar(97, 11, 15), false);
- * query.addDistribution("comp");
- * NewsgroupInfo[] newsgroups = client.listNewgroups(query);
- *
- * This will retrieve the list of newsgroups starting with the comp.
- * distribution prefix created since midnight 11/15/97.
- * *
wildcard, as in
- * comp.lang.*
or comp.lang.java.*
. Adding
- * at least one newsgroup is mandatory for the NEWNEWS command.
- * *
wildcard, as in
- * comp.lang.*
or comp.lang.java.*
.
- *
- * query.addNewsgroup("comp.lang.java.*");
- * query.omitNewsgroup("comp.lang.java.advocacy");
- *
- * POSTING_PERMISSION
constants.
- *
- * writer = client.postArticle();
- * if(writer == null) // failure
- * return false;
- * header = new SimpleNNTPHeader("foobar@foo.com", "Just testing");
- * header.addNewsgroup("alt.test");
- * header.addHeaderField("Organization", "Foobar, Inc.");
- * writer.write(header.toString());
- * writer.write("This is just a test");
- * writer.close();
- * if(!client.completePendingCommand()) // failure
- * return false;
- *
- * From:
header field. This
- * should be the article poster's email address.
- * @param subject The value of the Subject:
header field.
- * This should be the subject of the article.
- ***/
- public SimpleNNTPHeader(String from, String subject)
- {
- __from = from;
- __subject = subject;
- __newsgroups = new StringBuilder();
- __headerFields = new StringBuilder();
- __newsgroupCount = 0;
- }
-
- /***
- * Adds a newsgroup to the article Newsgroups:
field.
- *
- * header.addHeaderField("Organization", "Foobar, Inc.");
- *
- * From:
header field.
- * Subject:
header field.
- * Newsgroups:
header field.
- * ts
is null then zero time is used.
- *
- * @param ts NTP timestamp
- */
- public void setTransmitTime(TimeStamp ts)
- {
- setTimestamp(TRANSMIT_TIMESTAMP_INDEX, ts);
- }
-
- /***
- * Set originate timestamp given NTP TimeStamp object.
- * If ts
is null then zero time is used.
- *
- * @param ts NTP timestamp
- */
- public void setOriginateTimeStamp(TimeStamp ts)
- {
- setTimestamp(ORIGINATE_TIMESTAMP_INDEX, ts);
- }
-
- /***
- * Returns the originate time as defined in RFC-1305.
- *
- * @return the originate time.
- * Never returns null.
- */
- public TimeStamp getOriginateTimeStamp()
- {
- return getTimestamp(ORIGINATE_TIMESTAMP_INDEX);
- }
-
- /***
- * Returns the reference time as defined in RFC-1305.
- *
- * @return the reference time as TimeStamp
object.
- * Never returns null.
- */
- public TimeStamp getReferenceTimeStamp()
- {
- return getTimestamp(REFERENCE_TIMESTAMP_INDEX);
- }
-
- /***
- * Set Reference time with NTP timestamp. If ts
is null
- * then zero time is used.
- *
- * @param ts NTP timestamp
- */
- public void setReferenceTime(TimeStamp ts)
- {
- setTimestamp(REFERENCE_TIMESTAMP_INDEX, ts);
- }
-
- /***
- * Returns receive timestamp as defined in RFC-1305.
- *
- * @return the receive time.
- * Never returns null.
- */
- public TimeStamp getReceiveTimeStamp()
- {
- return getTimestamp(RECEIVE_TIMESTAMP_INDEX);
- }
-
- /***
- * Set receive timestamp given NTP TimeStamp object.
- * If ts
is null then zero time is used.
- *
- * @param ts timestamp
- */
- public void setReceiveTimeStamp(TimeStamp ts)
- {
- setTimestamp(RECEIVE_TIMESTAMP_INDEX, ts);
- }
-
- /***
- * Return type of time packet. The values (e.g. NTP, TIME, ICMP, ...)
- * correspond to the protocol used to obtain the timing information.
- *
- * @return packet type string identifier which in this case is "NTP".
- */
- public String getType()
- {
- return "NTP";
- }
-
- /***
- * @return 4 bytes as 32-bit int
- */
- private int getInt(int index)
- {
- int i = ui(buf[index]) << 24 |
- ui(buf[index + 1]) << 16 |
- ui(buf[index + 2]) << 8 |
- ui(buf[index + 3]);
-
- return i;
- }
-
- /***
- * Get NTP Timestamp at specified starting index.
- *
- * @param index index into data array
- * @return TimeStamp object for 64 bits starting at index
- */
- private TimeStamp getTimestamp(int index)
- {
- return new TimeStamp(getLong(index));
- }
-
- /***
- * Get Long value represented by bits starting at specified index.
- *
- * @return 8 bytes as 64-bit long
- */
- private long getLong(int index)
- {
- long i = ul(buf[index]) << 56 |
- ul(buf[index + 1]) << 48 |
- ul(buf[index + 2]) << 40 |
- ul(buf[index + 3]) << 32 |
- ul(buf[index + 4]) << 24 |
- ul(buf[index + 5]) << 16 |
- ul(buf[index + 6]) << 8 |
- ul(buf[index + 7]);
- return i;
- }
-
- /***
- * Sets the NTP timestamp at the given array index.
- *
- * @param index index into the byte array.
- * @param t TimeStamp.
- */
- private void setTimestamp(int index, TimeStamp t)
- {
- long ntpTime = (t == null) ? 0 : t.ntpValue();
- // copy 64-bits from Long value into 8 x 8-bit bytes of array
- // one byte at a time shifting 8-bits for each position.
- for (int i = 7; i >= 0; i--) {
- buf[index + i] = (byte) (ntpTime & 0xFF);
- ntpTime >>>= 8; // shift to next byte
- }
- // buf[index] |= 0x80; // only set if 1900 baseline....
- }
-
- /***
- * Returns the datagram packet with the NTP details already filled in.
- *
- * @return a datagram packet.
- */
- public synchronized DatagramPacket getDatagramPacket()
- {
- if (dp == null) {
- dp = new DatagramPacket(buf, buf.length);
- dp.setPort(NTP_PORT);
- }
- return dp;
- }
-
- /***
- * Set the contents of this object from source datagram packet.
- *
- * @param srcDp source DatagramPacket to copy contents from.
- */
- public void setDatagramPacket(DatagramPacket srcDp)
- {
- byte[] incomingBuf = srcDp.getData();
- int len = srcDp.getLength();
- if (len > buf.length)
- len = buf.length;
-
- System.arraycopy(incomingBuf, 0, buf, 0, len);
- }
-
- /***
- * Convert byte to unsigned integer.
- * Java only has signed types so we have to do
- * more work to get unsigned ops.
- *
- * @param b
- * @return unsigned int value of byte
- */
- protected final static int ui(byte b)
- {
- int i = b & 0xFF;
- return i;
- }
-
- /***
- * Convert byte to unsigned long.
- * Java only has signed types so we have to do
- * more work to get unsigned ops
- *
- * @param b
- * @return unsigned long value of byte
- */
- protected final static long ul(byte b)
- {
- long i = b & 0xFF;
- return i;
- }
-
- /***
- * Returns details of NTP packet as a string.
- *
- * @return details of NTP packet as a string.
- */
- @Override
- public String toString()
- {
- return "[" +
- "version:" + getVersion() +
- ", mode:" + getMode() +
- ", poll:" + getPoll() +
- ", precision:" + getPrecision() +
- ", delay:" + getRootDelay() +
- ", dispersion(ms):" + getRootDispersionInMillisDouble() +
- ", id:" + getReferenceIdString() +
- ", xmitTime:" + getTransmitTimeStamp().toDateString() +
- " ]";
- }
-
-}
diff --git a/org/apache/commons/net/ntp/NtpV3Packet.java b/org/apache/commons/net/ntp/NtpV3Packet.java
deleted file mode 100644
index 52c828b..0000000
--- a/org/apache/commons/net/ntp/NtpV3Packet.java
+++ /dev/null
@@ -1,236 +0,0 @@
-package org.apache.commons.net.ntp;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-import java.net.DatagramPacket;
-
-/**
- * Interface for a NtpV3Packet with get/set methods corresponding to the fields
- * in the NTP Data Message Header described in RFC 1305.
- *
- * @author Naz Irizarry, MITRE Corp
- * @author Jason Mathews, MITRE Corp
- * @version $Revision: 489397 $ $Date: 2006-12-21 16:28:51 +0000 (Thu, 21 Dec 2006) $
- */
-public interface NtpV3Packet
-{
-
- /**
- * Standard NTP UDP port
- */
- public static final int NTP_PORT = 123;
-
- public static final int LI_NO_WARNING = 0;
- public static final int LI_LAST_MINUTE_HAS_61_SECONDS = 1;
- public static final int LI_LAST_MINUTE_HAS_59_SECONDS = 2;
- public static final int LI_ALARM_CONDITION = 3;
-
- /* mode options */
- public static final int MODE_RESERVED = 0;
- public static final int MODE_SYMMETRIC_ACTIVE = 1;
- public static final int MODE_SYMMETRIC_PASSIVE = 2;
- public static final int MODE_CLIENT = 3;
- public static final int MODE_SERVER = 4;
- public static final int MODE_BROADCAST = 5;
- public static final int MODE_CONTROL_MESSAGE = 6;
- public static final int MODE_PRIVATE = 7;
-
- public static final int NTP_MINPOLL = 4; // 16 seconds
- public static final int NTP_MAXPOLL = 14; // 16284 seconds
-
- public static final int NTP_MINCLOCK = 1;
- public static final int NTP_MAXCLOCK = 10;
-
- public static final int VERSION_3 = 3;
- public static final int VERSION_4 = 4;
-
- /* possible getType values such that other time-related protocols can
- * have its information represented as NTP packets
- */
- public static final String TYPE_NTP = "NTP"; // RFC-1305/2030
- public static final String TYPE_ICMP = "ICMP"; // RFC-792
- public static final String TYPE_TIME = "TIME"; // RFC-868
- public static final String TYPE_DAYTIME = "DAYTIME"; // RFC-867
-
- /**
- * @return a datagram packet with the NTP parts already filled in
- */
- public DatagramPacket getDatagramPacket();
-
- /**
- * Set the contents of this object from the datagram packet
- */
- public void setDatagramPacket(DatagramPacket dp);
-
- /**
- * @return leap indicator as defined in RFC-1305
- */
- public int getLeapIndicator();
-
- /**
- * Set leap indicator.
- * @param li - leap indicator code
- */
- public void setLeapIndicator(int li);
-
- /**
- * @return mode as defined in RFC-1305
- */
- public int getMode();
-
- /**
- * @return mode as human readable string; e.g. 3=Client
- */
- public String getModeName();
-
- /**
- * Set mode as defined in RFC-1305
- */
- public void setMode(int mode);
-
- /**
- * @return poll interval as defined in RFC-1305.
- * Field range between NTP_MINPOLL and NTP_MAXPOLL.
- */
- public int getPoll();
-
- /**
- * Set poll interval as defined in RFC-1305.
- * Field range between NTP_MINPOLL and NTP_MAXPOLL.
- */
- public void setPoll(int poll);
-
- /**
- * @return precision as defined in RFC-1305
- */
- public int getPrecision();
-
- /**
- * @return root delay as defined in RFC-1305
- */
- public int getRootDelay();
-
- /**
- * @return root delay in milliseconds
- */
- public double getRootDelayInMillisDouble();
-
- /**
- * @return root dispersion as defined in RFC-1305
- */
- public int getRootDispersion();
-
- /**
- * @return root dispersion in milliseconds
- */
- public long getRootDispersionInMillis();
-
- /**
- * @return root dispersion in milliseconds
- */
- public double getRootDispersionInMillisDouble();
-
- /**
- * @return version as defined in RFC-1305
- */
- public int getVersion();
-
- /**
- * Set version as defined in RFC-1305
- */
- public void setVersion(int mode);
-
- /**
- * @return stratum as defined in RFC-1305
- */
- public int getStratum();
-
- /**
- * Set stratum as defined in RFC-1305
- */
- public void setStratum(int stratum);
-
- /**
- * @return the reference id string
- */
- public String getReferenceIdString();
-
- /**
- * @return the reference id (32-bit code) as defined in RFC-1305
- */
- public int getReferenceId();
-
- /**
- * Set reference clock identifier field.
- * @param refId
- */
- public void setReferenceId(int refId);
-
- /**
- * @return the transmit timestamp as defined in RFC-1305
- */
- public TimeStamp getTransmitTimeStamp();
-
- /**
- * @return the reference time as defined in RFC-1305
- */
- public TimeStamp getReferenceTimeStamp();
-
- /**
- * @return the originate time as defined in RFC-1305
- */
- public TimeStamp getOriginateTimeStamp();
-
- /**
- * @return the receive time as defined in RFC-1305
- */
- public TimeStamp getReceiveTimeStamp();
-
- /**
- * Set the transmit timestamp given NTP TimeStamp object.
- * @param ts - timestamp
- */
- public void setTransmitTime(TimeStamp ts);
-
- /**
- * Set the reference timestamp given NTP TimeStamp object.
- * @param ts - timestamp
- */
- public void setReferenceTime(TimeStamp ts);
-
- /**
- * Set originate timestamp given NTP TimeStamp object.
- * @param ts - timestamp
- */
- public void setOriginateTimeStamp(TimeStamp ts);
-
- /**
- * Set receive timestamp given NTP TimeStamp object.
- * @param ts - timestamp
- */
- public void setReceiveTimeStamp(TimeStamp ts);
-
- /**
- * Return type of time packet. The values (e.g. NTP, TIME, ICMP, ...)
- * correspond to the protocol used to obtain the timing information.
- *
- * @return packet type string identifier
- */
- public String getType();
-
-}
diff --git a/org/apache/commons/net/ntp/TimeInfo.java b/org/apache/commons/net/ntp/TimeInfo.java
deleted file mode 100644
index 4ef17fd..0000000
--- a/org/apache/commons/net/ntp/TimeInfo.java
+++ /dev/null
@@ -1,295 +0,0 @@
-package org.apache.commons.net.ntp;
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Wrapper class to network time packet messages (NTP, etc) that computes
- * related timing info and stats.
- *
- * @author Jason Mathews, MITRE Corp
- *
- * @version $Revision: 658518 $ $Date: 2008-05-21 02:04:30 +0100 (Wed, 21 May 2008) $
- */
-public class TimeInfo {
-
- private NtpV3Packet _message;
- private Listjava.text.SimpleDateFormat
for code descriptions.
- */
- public final static String NTP_DATE_FORMAT = "EEE, MMM dd yyyy HH:mm:ss.SSS";
-
- /*
- * Caches for the DateFormatters used by various toString methods.
- */
- private static SoftReferencelong
value
- * represented by this TimeStamp
object. That is, the hashcode
- * is the value of the expression:
- *
- *
- * @return a hash code value for this object.
- */
- @Override
- public int hashCode()
- {
- return (int) (ntpTime ^ (ntpTime >>> 32));
- }
-
- /***
- * Compares this object against the specified object.
- * The result is
- * (int)(this.ntpValue()^(this.ntpValue() >>> 32))
- *
true
if and only if the argument is
- * not null
and is a Long
object that
- * contains the same long
value as this object.
- *
- * @param obj the object to compare with.
- * @return true
if the objects are the same;
- * false
otherwise.
- */
- @Override
- public boolean equals(Object obj)
- {
- if (obj instanceof TimeStamp) {
- return ntpTime == ((TimeStamp) obj).ntpValue();
- }
- return false;
- }
-
- /***
- * Converts this TimeStamp
object to a String
.
- * The NTP timestamp 64-bit long value is represented as hex string with
- * seconds separated by fractional seconds by a decimal point;
- * e.g. c1a089bd.fc904f6d <=> Tue, Dec 10 2002 10:41:49.986
- *
- * @return NTP timestamp 64-bit long value as hex string with seconds
- * separated by fractional seconds.
- */
- @Override
- public String toString()
- {
- return toString(ntpTime);
- }
-
- /***
- * Left-pad 8-character hex string with 0's
- *
- * @param buf - StringBuffer which is appended with leading 0's.
- * @param l - a long.
- */
- private static void appendHexString(StringBuffer buf, long l)
- {
- String s = Long.toHexString(l);
- for (int i = s.length(); i < 8; i++)
- buf.append('0');
- buf.append(s);
- }
-
- /***
- * Converts 64-bit NTP timestamp value to a String
.
- * The NTP timestamp value is represented as hex string with
- * seconds separated by fractional seconds by a decimal point;
- * e.g. c1a089bd.fc904f6d <=> Tue, Dec 10 2002 10:41:49.986
- *
- * @return NTP timestamp 64-bit long value as hex string with seconds
- * separated by fractional seconds.
- */
- public static String toString(long ntpTime)
- {
- StringBuffer buf = new StringBuffer();
- // high-order second bits (32..63) as hexstring
- appendHexString(buf, (ntpTime >>> 32) & 0xffffffffL);
-
- // low-order fractional seconds bits (0..31) as hexstring
- buf.append('.');
- appendHexString(buf, ntpTime & 0xffffffffL);
-
- return buf.toString();
- }
-
- /***
- * Converts this TimeStamp
object to a String
- * of the form:
- *
- * See java.text.SimpleDataFormat for code descriptions.
- *
- * @return a string representation of this date.
- */
- public String toDateString()
- {
- DateFormat formatter = null;
- if (simpleFormatter != null) {
- formatter = simpleFormatter.get();
- }
- if (formatter == null) {
- // No cache yet, or cached formatter GC'd
- formatter = new SimpleDateFormat(NTP_DATE_FORMAT, Locale.US);
- formatter.setTimeZone(TimeZone.getDefault());
- simpleFormatter = new SoftReference
- * EEE, MMM dd yyyy HH:mm:ss.SSS
TimeStamp
object to a String
- * of the form:
- *
- * See java.text.SimpleDataFormat for code descriptions.
- *
- * @return a string representation of this date in UTC.
- */
- public String toUTCString()
- {
- DateFormat formatter = null;
- if (utcFormatter != null)
- formatter = utcFormatter.get();
- if (formatter == null) {
- // No cache yet, or cached formatter GC'd
- formatter = new SimpleDateFormat(NTP_DATE_FORMAT + " 'UTC'",
- Locale.US);
- formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
- utcFormatter = new SoftReference
- * EEE, MMM dd yyyy HH:mm:ss.SSS UTC
TimeStamp
to be compared.
- * @return the value 0
if the argument TimeStamp is equal to
- * this TimeStamp; a value less than 0
if this TimeStamp
- * is numerically less than the TimeStamp argument; and a
- * value greater than 0
if this TimeStamp is
- * numerically greater than the TimeStamp argument
- * (signed comparison).
- */
- public int compareTo(TimeStamp anotherTimeStamp)
- {
- long thisVal = this.ntpTime;
- long anotherVal = anotherTimeStamp.ntpTime;
- return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
- }
-
- /***
- * Compares this TimeStamp to another Object. If the Object is a TimeStamp,
- * this function behaves like compareTo(TimeStamp)
. Otherwise,
- * it throws a ClassCastException
(as TimeStamps are comparable
- * only to other TimeStamps).
- *
- * @param o the Object
to be compared.
- * @return the value 0
if the argument is a TimeStamp
- * numerically equal to this TimeStamp; a value less than
- * 0
if the argument is a TimeStamp numerically
- * greater than this TimeStamp; and a value greater than
- * 0
if the argument is a TimeStamp numerically
- * less than this TimeStamp.
- * @exception ClassCastException if the argument is not a
- * TimeStamp
.
- * @see java.lang.Comparable
- */
- public int compareTo(Object o)
- {
- return compareTo((TimeStamp) o);
- }
-
-}
diff --git a/org/apache/commons/net/pop3/POP3.java b/org/apache/commons/net/pop3/POP3.java
deleted file mode 100644
index 80033ab..0000000
--- a/org/apache/commons/net/pop3/POP3.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.pop3;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.util.Enumeration;
-import java.util.Vector;
-
-import org.apache.commons.net.MalformedServerReplyException;
-import org.apache.commons.net.ProtocolCommandListener;
-import org.apache.commons.net.ProtocolCommandSupport;
-import org.apache.commons.net.SocketClient;
-
-/***
- * The POP3 class is not meant to be used by itself and is provided
- * only so that you may easily implement your own POP3 client if
- * you so desire. If you have no need to perform your own implementation,
- * you should use {@link org.apache.commons.net.pop3.POP3Client}.
- * DISCONNECTED_STATE
.
- ***/
- public POP3()
- {
- setDefaultPort(DEFAULT_PORT);
- __commandBuffer = new StringBuffer();
- __popState = DISCONNECTED_STATE;
- _reader = null;
- __writer = null;
- _replyLines = new Vector AUTHORIZATION_STATE
.
- ***/
- @Override
- protected void _connectAction_() throws IOException
- {
- super._connectAction_();
- _reader =
- new BufferedReader(new InputStreamReader(_input_,
- __DEFAULT_ENCODING));
- __writer =
- new BufferedWriter(new OutputStreamWriter(_output_,
- __DEFAULT_ENCODING));
- __getReply();
- setState(AUTHORIZATION_STATE);
- }
-
-
- /***
- * Adds a ProtocolCommandListener. Delegates this task to
- * {@link #_commandSupport_ _commandSupport_ }.
- * _STATE
constants.
- * DISCONNECTED_STATE
. The reply text information
- * from the last issued command is voided to allow garbage collection
- * of the memory used to store that information.
- * getReplyStrings
- * again. You only have to worry about this if you are implementing
- * your own client using the {@link #sendCommand sendCommand } methods.
- * getReplyString
- * again. You only have to worry about this if you are implementing
- * your own client using the {@link #sendCommand sendCommand } methods.
- * number
- * contains the number of messages in the mailbox, size
- * contains the size of the mailbox in bytes, and identifier
- * is null.
- * number
- * contains the message number, size
contains the
- * size of the message in bytes, and identifier
is null.
- * number
contains
- * the message number, size
is undefined, and
- * identifier
contains the message's unique identifier.
- * number
and
- * size
set to 0, and identifier
set to
- * null.
- ***/
- public POP3MessageInfo()
- {
- number = size = 0;
- identifier = null;
- }
-
- /***
- * Creates a POP3MessageInfo instance with number
set
- * to num
, size
set to octets
,
- * and identifier
set to null.
- ***/
- public POP3MessageInfo(int num, int octets)
- {
- number = num;
- size = octets;
- identifier = null;
- }
-
- /***
- * Creates a POP3MessageInfo instance with number
set
- * to num
, size
undefined,
- * and identifier
set to uid
.
- ***/
- public POP3MessageInfo(int num, String uid)
- {
- number = num;
- size = -1;
- identifier = uid;
- }
-}
diff --git a/org/apache/commons/net/pop3/POP3Reply.java b/org/apache/commons/net/pop3/POP3Reply.java
deleted file mode 100644
index 08e4246..0000000
--- a/org/apache/commons/net/pop3/POP3Reply.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.pop3;
-
-/***
- * POP3Reply stores POP3 reply code constants.
- * < @bar.com,@foo.com:foobar@foo.com >
- *
- * path = new RelayPath("foobar@foo.com");
- * path.addRelay("bar.com");
- * path.addRelay("foo.com");
- *
- * SMTPConectionClosedException
- * is a subclass of IOException
and therefore need not be
- * caught separately, but if you are going to catch it separately, its
- * catch block must appear before the more general IOException
- * catch block. When you encounter an
- * {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
- * , you must disconnect the connection with
- * {@link org.apache.commons.net.SocketClient#disconnect disconnect() }
- * to properly clean up the system resources used by SMTP. Before
- * disconnecting, you may check the
- * last reply code and text with
- * {@link #getReplyCode getReplyCode },
- * {@link #getReplyString getReplyString },
- * and {@link #getReplyStrings getReplyStrings}.
- * DEFAULT_PORT
and initializes internal data structures
- * for saving SMTP reply information.
- ***/
- public SMTP()
- {
- setDefaultPort(DEFAULT_PORT);
- __commandBuffer = new StringBuffer();
- _replyLines = new ArrayList connect
is of type void.
- *
- * try {
- * int reply;
- * client.connect("mail.foobar.com");
- * System.out.print(client.getReplyString());
- *
- * // After connection attempt, you should check the reply code to verify
- * // success.
- * reply = client.getReplyCode();
- *
- * if(!SMTPReply.isPositiveCompletion(reply)) {
- * client.disconnect();
- * System.err.println("SMTP server refused connection.");
- * System.exit(1);
- * }
- *
- * // Do useful stuff here.
- * ...
- * } catch(IOException e) {
- * if(client.isConnected()) {
- * try {
- * client.disconnect();
- * } catch(IOException f) {
- * // do nothing
- * }
- * }
- * System.err.println("Could not connect to server.");
- * e.printStackTrace();
- * System.exit(1);
- * }
- *
- * SMTPConectionClosedException
- * is a subclass of IOException
and therefore need not be
- * caught separately, but if you are going to catch it separately, its
- * catch block must appear before the more general IOException
- * catch block. When you encounter an
- * {@link org.apache.commons.net.smtp.SMTPConnectionClosedException}
- * , you must disconnect the connection with
- * {@link #disconnect disconnect() } to properly clean up the
- * system resources used by SMTPClient. Before disconnecting, you may check
- * the last reply code and text with
- * {@link org.apache.commons.net.smtp.SMTP#getReplyCode getReplyCode },
- * {@link org.apache.commons.net.smtp.SMTP#getReplyString getReplyString },
- * and
- * {@link org.apache.commons.net.smtp.SMTP#getReplyStrings getReplyStrings}.
- *
- * writer = client.sendMessage();
- * if(writer == null) // failure
- * return false;
- * header =
- * new SimpleSMTPHeader("foobar@foo.com", "foo@foobar.com", "Re: Foo");
- * writer.write(header.toString());
- * writer.write("This is just a test");
- * writer.close();
- * if(!client.completePendingCommand()) // failure
- * return false;
- *
- *
- * writer = client.sendMessageData();
- * if(writer == null) // failure
- * return false;
- * header =
- * new SimpleSMTPHeader("foobar@foo.com", "foo@bar.com" "Just testing");
- * header.addCC("bar@foo.com");
- * header.addHeaderField("Organization", "Foobar, Inc.");
- * writer.write(header.toString());
- * writer.write("This is just a test");
- * writer.close();
- * if(!client.completePendingCommand()) // failure
- * return false;
- *
- * From:
header field. This
- * should be the sender's email address.
- * @param to The value of the To:
header field. This
- * should be the recipient's email address.
- * @param subject The value of the Subject:
header field.
- * This should be the subject of the message.
- ***/
- public SimpleSMTPHeader(String from, String to, String subject)
- {
- __to = to;
- __from = from;
- __subject = subject;
- __headerFields = new StringBuffer();
- __cc = null;
- }
-
- /***
- * Adds an arbitrary header field with the given value to the article
- * header. These headers will be written before the From, To, Subject, and
- * Cc fields when the SimpleSMTPHeader is convertered to a string.
- * An example use would be:
- *
- * header.addHeaderField("Organization", "Foobar, Inc.");
- *
- * DEFAULT_PORT
.
- ***/
- public TimeTCPClient ()
- {
- setDefaultPort(DEFAULT_PORT);
- }
-
- /***
- * Retrieves the time from the server and returns it. The time
- * is the number of seconds since 00:00 (midnight) 1 January 1900 GMT,
- * as specified by RFC 868. This method reads the raw 32-bit big-endian
- * unsigned integer from the server, converts it to a Java long, and
- * returns the value.
- * getTime()
again.
- * getDate()
again.
- * getTime(host, DEFAULT_PORT);
***/
- public long getTime(InetAddress host) throws IOException
- {
- return getTime(host, DEFAULT_PORT);
- }
-
-
- /***
- * Retrieves the time from the server and returns a Java Date
- * containing the time converted to the local timezone.
- * getTime(host, DEFAULT_PORT);
***/
- public Date getDate(InetAddress host) throws IOException
- {
- return new Date((getTime(host, DEFAULT_PORT) -
- SECONDS_1900_TO_1970)*1000L);
- }
-
-}
-
diff --git a/org/apache/commons/net/util/ListenerList.class b/org/apache/commons/net/util/ListenerList.class
deleted file mode 100644
index f05ebb5..0000000
Binary files a/org/apache/commons/net/util/ListenerList.class and /dev/null differ
diff --git a/org/apache/commons/net/util/ListenerList.java b/org/apache/commons/net/util/ListenerList.java
deleted file mode 100644
index 796fb78..0000000
--- a/org/apache/commons/net/util/ListenerList.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.commons.net.util;
-
-import java.io.Serializable;
-import java.util.EventListener;
-import java.util.Iterator;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * @author Daniel F. Savarese
- */
-
-public class ListenerList implements Serializable, Iterable
- * WhoisClient whois;
- *
- * whois = new WhoisClient();
- *
- * try {
- * whois.connect(WhoisClient.DEFAULT_HOST);
- * System.out.println(whois.query("foobar"));
- * whois.disconnect();
- * } catch(IOException e) {
- * System.err.println("Error I/O exception: " + e.getMessage());
- * return;
- * }
- *
- *
- * DEFAULT_PORT
.
- ***/
- public WhoisClient()
- {
- setDefaultPort(DEFAULT_PORT);
- }
-
- /***
- * Queries the connected whois server for information regarding
- * the given handle. It is up to the programmer to be familiar with the
- * handle syntax of the whois server. You must first connect to a whois
- * server before calling this method, and you should disconnect afterward.
- *