Make a copy


git-svn-id: https://svn.apache.org/repos/asf/commons/proper/net/tags/NET_1_5_0_RC3@796050 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/build.xml b/build.xml
index f40f51f..95ad64c 100644
--- a/build.xml
+++ b/build.xml
@@ -4,6 +4,14 @@
   on date September 8 2004, time 2216-->
 
 <project default="jar" name="commons-net" basedir=".">
+
+  <available property="jre.dom.available" classname="java.lang.CharSequence" />
+
+  <fileset id="xmlLibs" dir="${ant.home}/lib">
+    <include name="xml-apis.jar" unless="jre.dom.available" />
+    <include name="xercesImpl.jar" unless="jre.dom.available" />
+  </fileset>
+
   <property name="defaulttargetdir" value="target">
   </property>
   <property name="libdir" value="target/lib">
@@ -104,6 +112,7 @@
         </pathelement>
         <pathelement path="${classesdir}">
         </pathelement>
+        <fileset refid="xmlLibs" />
       </classpath>
       <batchtest todir="${testreportdir}">
         <fileset dir="src/test">
diff --git a/doap_net.rdf b/doap_net.rdf
index ad2d70f..9e4b043 100644
--- a/doap_net.rdf
+++ b/doap_net.rdf
@@ -34,11 +34,11 @@
       </SVNRepository>
     </repository>
     <release>
-      <revision>
+      <Version>
         <name>commons-net</name>
         <created>2005-12-03</created>
-        <version>1.4.1</version>
-      </revision>
+        <revision>1.4.1</revision>
+      </Version>
     </release>
     <mailing-list rdf:resource="http://commons.apache.org/mail-lists.html"/>
   </Project>
diff --git a/pom.xml b/pom.xml
index c76f3d9..136a8f0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,191 +1,216 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
- 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
+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
+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.
+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.
 -->
 
 <project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-    <parent>
-        <groupId>org.apache.commons</groupId>
-        <artifactId>commons-parent</artifactId>
-        <version>9</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>commons-net</groupId>
-    <artifactId>commons-net</artifactId>
-    <version>1.5.0-SNAPSHOT</version>
-    <name>Commons Net</name>
-    <description>
-        A collection of network utilities and protocol implementations.
-    </description>
-    <url>http://commons.apache.org/net/</url>
-    <issueManagement>
-        <system>jira</system>
-        <url>http://issues.apache.org/jira/browse/NET</url>
-    </issueManagement>
-    <inceptionYear>1997</inceptionYear>
-    <scm>
-        <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/net/trunk/</connection>
-        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/net/trunk/</developerConnection>
-        <url>http://svn.apache.org/viewvc/commons/proper/net/trunk/</url>
-    </scm>
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<parent>
+		<groupId>org.apache.commons</groupId>
+		<artifactId>commons-parent</artifactId>
+		<version>11</version>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>commons-net</groupId>
+	<artifactId>commons-net</artifactId>
+	<version>1.5.0</version>
+	<name>Commons Net</name>
+	<description>
+		A collection of network utilities and protocol implementations.
+	</description>
+	<url>http://commons.apache.org/net/</url>
+	<issueManagement>
+		<system>jira</system>
+		<url>http://issues.apache.org/jira/browse/NET</url>
+	</issueManagement>
+	<inceptionYear>1997</inceptionYear>
+	<scm>
+		<connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/net/trunk/</connection>
+		<developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/net/trunk/</developerConnection>
+		<url>http://svn.apache.org/viewvc/commons/proper/net/trunk/</url>
+	</scm>
 
-    <developers>
-        <developer>
-            <name>Jeffrey D. Brekke</name>
-            <id>brekke</id>
-            <email>Jeff.Brekke@qg.com</email>
-            <organization>Quad/Graphics, Inc.</organization>
-        </developer>
-        <developer>
-            <name>Steve Cohen</name>
-            <id>scohen</id>
-            <email>scohen@apache.org</email>
-            <organization>javactivity.org</organization>
-        </developer>
-        <developer>
-            <name>Bruno D'Avanzo</name>
-            <id>brudav</id>
-            <email>bruno.davanzo@hp.com</email>
-            <organization>Hewlett-Packard</organization>
-        </developer>
-        <developer>
-            <name>Daniel F. Savarese</name>
-            <id>dfs</id>
-            <email>dfs -> apache.org</email>
-            <organization>
-            &lt;a href="http://www.savarese.com/"&gt;Savarese Software Research&lt;/a&gt;
-            </organization>
-        </developer>
-        <developer>
-            <name>Rory Winston</name>
-            <id>rwinston</id>
-            <email>rwinston@apache.org</email>
-            <organization></organization>
-        </developer>
-    </developers>
+	<developers>
+		<developer>
+			<name>Jeffrey D. Brekke</name>
+			<id>brekke</id>
+			<email>Jeff.Brekke@qg.com</email>
+			<organization>Quad/Graphics, Inc.</organization>
+		</developer>
+		<developer>
+			<name>Steve Cohen</name>
+			<id>scohen</id>
+			<email>scohen@apache.org</email>
+			<organization>javactivity.org</organization>
+		</developer>
+		<developer>
+			<name>Bruno D'Avanzo</name>
+			<id>brudav</id>
+			<email>bruno.davanzo@hp.com</email>
+			<organization>Hewlett-Packard</organization>
+		</developer>
+		<developer>
+			<name>Daniel F. Savarese</name>
+			<id>dfs</id>
+			<email>dfs -> apache.org</email>
+			<organization>
+				&lt;a href="http://www.savarese.com/"&gt;Savarese Software Research&lt;/a&gt;
+			</organization>
+		</developer>
+		<developer>
+			<name>Rory Winston</name>
+			<id>rwinston</id>
+			<email>rwinston@apache.org</email>
+			<organization></organization>
+		</developer>
+	</developers>
 
-    <contributors>
-        <contributor>
-            <name>Rob Hasselbaum</name>
-            <email>rhasselbaum -> alumni.ithaca.edu</email>
-        </contributor>
-        <contributor>
-            <name>Mario Ivankovits</name>
-            <email>mario@ops.co.at</email>
-        </contributor>
-        <contributor>
-            <name>Tapan Karecha</name>
-            <email>tapan@india.hp.com</email>
-        </contributor>
-        <contributor>
-            <name>Winston Ojeda</name>
-            <email>Winston.Ojeda@qg.com</email>
-            <organization>Quad/Graphics, Inc.</organization>
-        </contributor>
-        <contributor>
-            <name>Ted Wise</name>
-            <email>ctwise@bellsouth.net</email>
-        </contributor>
-    </contributors>
+	<contributors>
+		<contributor>
+			<name>Rob Hasselbaum</name>
+			<email>rhasselbaum -> alumni.ithaca.edu</email>
+		</contributor>
+		<contributor>
+			<name>Mario Ivankovits</name>
+			<email>mario@ops.co.at</email>
+		</contributor>
+		<contributor>
+			<name>Tapan Karecha</name>
+			<email>tapan@india.hp.com</email>
+		</contributor>
+		<contributor>
+			<name>Winston Ojeda</name>
+			<email>Winston.Ojeda@qg.com</email>
+			<organization>Quad/Graphics, Inc.</organization>
+		</contributor>
+		<contributor>
+			<name>Ted Wise</name>
+			<email>ctwise@bellsouth.net</email>
+		</contributor>
+	</contributors>
 
-    <dependencies>
-        <dependency>
-            <groupId>oro</groupId>
-            <artifactId>oro</artifactId>
-            <version>2.0.8</version>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>3.8.1</version>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
+	<dependencies>
+		<dependency>
+			<groupId>oro</groupId>
+			<artifactId>oro</artifactId>
+			<version>2.0.8</version>
+		</dependency>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.1</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
 
-    <properties>
-        <commons.componentid>net</commons.componentid>
-        <commons.release.version>1.4.1</commons.release.version>
-        <commons.binary.suffix></commons.binary.suffix>
-        <commons.jira.id>NET</commons.jira.id>
-        <commons.jira.pid>12310487</commons.jira.pid>
-    </properties> 
+	<properties>
+		<commons.componentid>net</commons.componentid>
+		<commons.release.version>1.4.1</commons.release.version>
+		<commons.binary.suffix></commons.binary.suffix>
+		<commons.jira.id>NET</commons.jira.id>
+		<commons.jira.pid>12310487</commons.jira.pid>
+	</properties> 
 
-    <build>
-        <sourceDirectory>src/java</sourceDirectory>
-        <testSourceDirectory>src/test</testSourceDirectory>
-        <plugins>
+	<build>
+		<sourceDirectory>src/java</sourceDirectory>
+		<testSourceDirectory>src/test</testSourceDirectory>
+		<plugins>
 
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <configuration>
-                    <includes>
-                        <include>**/*Test.java</include>
-                    </includes>
-                    <excludes>
-                        <exclude>**/*FunctionalTest.java</exclude>
-                        <exclude>**/*POP3*.java</exclude>
-                    </excludes>
-                </configuration>
-            </plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<excludes>
+						<exclude>**/examples/**/*.java</exclude>
+					</excludes>
+				</configuration>
+			</plugin>
 
-            <plugin>
-                <artifactId>maven-assembly-plugin</artifactId>
-                <configuration>
-                    <descriptors>
-                        <descriptor>src/assembly/bin.xml</descriptor>
-                        <descriptor>src/assembly/src.xml</descriptor>
-                    </descriptors>
-                    <tarLongFileMode>gnu</tarLongFileMode>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
 
-    <reporting>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-changes-plugin</artifactId>
-                <configuration>
-                    <xmlPath>xdocs/changes.xml</xmlPath>
-                    <issueLinkTemplate>%URL%/%ISSUE%</issueLinkTemplate>
-                </configuration>
-                <reportSets>
-                    <reportSet>
-                        <reports>
-                            <report>changes-report</report>
-                            <report>jira-report</report>
-                        </reports>
-                    </reportSet>
-                </reportSets>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>clirr-maven-plugin</artifactId>
-                <version>2.1</version>
-                <configuration>
-                    <comparisonVersion>1.4.1</comparisonVersion>
-                    <minSeverity>info</minSeverity>
-                </configuration>
-            </plugin>
 
-        </plugins>
-    </reporting>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-surefire-plugin</artifactId>
+				<configuration>
+					<includes>
+						<include>**/*Test.java</include>
+					</includes>
+					<excludes>
+						<exclude>**/*FunctionalTest.java</exclude>
+						<exclude>**/*POP3*.java</exclude>
+					</excludes>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<configuration>
+					<descriptors>
+						<descriptor>src/assembly/bin.xml</descriptor>
+						<descriptor>src/assembly/src.xml</descriptor>
+					</descriptors>
+					<tarLongFileMode>gnu</tarLongFileMode>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<reporting>
+		<plugins>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-changes-plugin</artifactId>
+				<version>2.0</version>
+				<configuration>
+					<xmlPath>xdocs/changes.xml</xmlPath>
+					<issueLinkTemplate>%URL%/%ISSUE%</issueLinkTemplate>
+				</configuration>
+				<reportSets>
+					<reportSet>
+						<reports>
+							<report>changes-report</report>
+							<report>jira-report</report>
+						</reports>
+					</reportSet>
+				</reportSets>
+			</plugin>
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>clirr-maven-plugin</artifactId>
+				<version>2.2.2</version>
+				<configuration>
+					<comparisonVersion>1.4.1</comparisonVersion>
+					<minSeverity>info</minSeverity>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-javadoc-plugin</artifactId>
+				<version>2.4</version>
+				<configuration>
+					<linksource>true</linksource>
+					<links>
+						<link>http://java.sun.com/j2se/1.5.0/docs/api/</link>
+					</links>
+				</configuration>
+			</plugin>
+
+		</plugins>
+	</reporting>
 
 </project>
diff --git a/src/java/examples/nntp/ExtendedNNTPOps.java b/src/java/examples/nntp/ExtendedNNTPOps.java
index b48cfa7..4fe311d 100644
--- a/src/java/examples/nntp/ExtendedNNTPOps.java
+++ b/src/java/examples/nntp/ExtendedNNTPOps.java
@@ -32,60 +32,60 @@
  */
 public class ExtendedNNTPOps {
 
-	
-	NNTPClient client;
+    
+    NNTPClient client;
 
-	public ExtendedNNTPOps() {
-		client = new NNTPClient();
-		client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
-	}
+    public ExtendedNNTPOps() {
+        client = new NNTPClient();
+        client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
+    }
 
 
-	public void demo(String host, String user, String password) {
-		try {
-			client.connect(host);
+    public void demo(String host, String user, String password) {
+        try {
+            client.connect(host);
 
-			// AUTHINFO USER/AUTHINFO PASS
-			boolean success = client.authenticate(user, password);
-			if (success) {
-				System.out.println("Authentication succeeded");
-			} else {
-				System.out.println("Authentication failed, error =" + client.getReplyString());
-			}
+            // AUTHINFO USER/AUTHINFO PASS
+            boolean success = client.authenticate(user, password);
+            if (success) {
+                System.out.println("Authentication succeeded");
+            } else {
+                System.out.println("Authentication failed, error =" + client.getReplyString());
+            }
 
-			// XOVER
-			NewsgroupInfo testGroup = new NewsgroupInfo();
-			client.selectNewsgroup("alt.test", testGroup);
-			int lowArticleNumber = testGroup.getFirstArticle();
-			int highArticleNumber = lowArticleNumber + 100;
-			Article[] articles = NNTPUtils.getArticleInfo(client, lowArticleNumber, highArticleNumber);
+            // XOVER
+            NewsgroupInfo testGroup = new NewsgroupInfo();
+            client.selectNewsgroup("alt.test", testGroup);
+            int lowArticleNumber = testGroup.getFirstArticle();
+            int highArticleNumber = lowArticleNumber + 100;
+            Article[] articles = NNTPUtils.getArticleInfo(client, lowArticleNumber, highArticleNumber);
 
-			for (int i = 0; i < articles.length; ++i) {
-				System.out.println(articles[i].getSubject());
-			}
+            for (int i = 0; i < articles.length; ++i) {
+                System.out.println(articles[i].getSubject());
+            }
 
-			// LIST ACTIVE
-			NewsgroupInfo[] fanGroups = client.listNewsgroups("alt.fan.*");
-			for (int i = 0; i < fanGroups.length; ++i) {
-				System.out.println(fanGroups[i].getNewsgroup());
-			}
+            // LIST ACTIVE
+            NewsgroupInfo[] fanGroups = client.listNewsgroups("alt.fan.*");
+            for (int i = 0; i < fanGroups.length; ++i) {
+                System.out.println(fanGroups[i].getNewsgroup());
+            }
 
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-	}
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
 
-	public static void main(String[] args) {
-		ExtendedNNTPOps ops;
+    public static void main(String[] args) {
+        ExtendedNNTPOps ops;
 
-		if (args.length != 3) {
-			System.err.println("usage: ExtendedNNTPOps nntpserver username password");
-			System.exit(1);
-		}
+        if (args.length != 3) {
+            System.err.println("usage: ExtendedNNTPOps nntpserver username password");
+            System.exit(1);
+        }
 
-		ops = new ExtendedNNTPOps();
-		ops.demo(args[0], args[1], args[2]);
-	}
+        ops = new ExtendedNNTPOps();
+        ops.demo(args[0], args[1], args[2]);
+    }
 
 }
 
diff --git a/src/java/examples/nntp/MessageThreading.java b/src/java/examples/nntp/MessageThreading.java
index d8d27e2..5c04c09 100644
--- a/src/java/examples/nntp/MessageThreading.java
+++ b/src/java/examples/nntp/MessageThreading.java
@@ -29,47 +29,47 @@
 import examples.PrintCommandListener;
 
 public class MessageThreading {
-	public MessageThreading() {
-	}
-	
-	public static void main(String[] args) throws SocketException, IOException {
-		
-		if (args.length != 3)
-			usage();
-		
-		String hostname = args[0];
-		String user = args[1];
-		String password = args[2];
-		
-		NNTPClient client = new NNTPClient();
-		client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
-		client.connect(hostname);
-		
-		if(!client.authenticate(user, password)) {
-			System.out.println("Authentication failed for user " + user + "!");
-			System.exit(1);
-		}
-		
-		NewsgroupInfo group = new NewsgroupInfo();
-		client.selectNewsgroup("comp.lang.lisp", group);
-		
-		int lowArticleNumber = group.getFirstArticle();
-		int highArticleNumber = lowArticleNumber + 100;
-		
-		System.out.println("Retrieving articles between [" + lowArticleNumber + "] and [" + highArticleNumber + "]");
-		Article[] articles = NNTPUtils.getArticleInfo(client, lowArticleNumber, highArticleNumber);
-		
-		System.out.println("Building message thread tree...");
-		Threader threader = new Threader();
-		Article root = (Article)threader.thread(articles);
-		
-		Article.printThread(root, 0);	
-		
-	}
-	
-	
-	public static void usage() {
-		System.out.println("Usage: MessageThreading <hostname> <user> <password>");
-		System.exit(0);
-	}
+    public MessageThreading() {
+    }
+    
+    public static void main(String[] args) throws SocketException, IOException {
+        
+        if (args.length != 3)
+            usage();
+        
+        String hostname = args[0];
+        String user = args[1];
+        String password = args[2];
+        
+        NNTPClient client = new NNTPClient();
+        client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
+        client.connect(hostname);
+        
+        if(!client.authenticate(user, password)) {
+            System.out.println("Authentication failed for user " + user + "!");
+            System.exit(1);
+        }
+        
+        NewsgroupInfo group = new NewsgroupInfo();
+        client.selectNewsgroup("comp.lang.lisp", group);
+        
+        int lowArticleNumber = group.getFirstArticle();
+        int highArticleNumber = lowArticleNumber + 100;
+        
+        System.out.println("Retrieving articles between [" + lowArticleNumber + "] and [" + highArticleNumber + "]");
+        Article[] articles = NNTPUtils.getArticleInfo(client, lowArticleNumber, highArticleNumber);
+        
+        System.out.println("Building message thread tree...");
+        Threader threader = new Threader();
+        Article root = (Article)threader.thread(articles);
+        
+        Article.printThread(root, 0);
+        
+    }
+    
+    
+    public static void usage() {
+        System.out.println("Usage: MessageThreading <hostname> <user> <password>");
+        System.exit(0);
+    }
 }
diff --git a/src/java/examples/nntp/NNTPUtils.java b/src/java/examples/nntp/NNTPUtils.java
index 8b66eba..60222c6 100644
--- a/src/java/examples/nntp/NNTPUtils.java
+++ b/src/java/examples/nntp/NNTPUtils.java
@@ -33,77 +33,77 @@
  */
 public class NNTPUtils {
 
-	/**
-	 * Given an {@link NNTPClient} instance, and an integer range of messages, return 
-	 * an array of {@link Article} instances.
-	 * @param client 
-	 * @param lowArticleNumber
-	 * @param highArticleNumber
-	 * @return Article[] An array of Article
-	 * @throws IOException
-	 */
-	public  static Article[] getArticleInfo(NNTPClient client, int lowArticleNumber, int highArticleNumber)
-			throws IOException {
-			Reader reader = null;
-			Article[] articles = null;
-			reader =
-				(DotTerminatedMessageReader) client.retrieveArticleInfo(
-					lowArticleNumber,
-					highArticleNumber);
+    /**
+     * Given an {@link NNTPClient} instance, and an integer range of messages, return 
+     * an array of {@link Article} instances.
+     * @param client 
+     * @param lowArticleNumber
+     * @param highArticleNumber
+     * @return Article[] An array of Article
+     * @throws IOException
+     */
+    public  static Article[] getArticleInfo(NNTPClient client, int lowArticleNumber, int highArticleNumber)
+            throws IOException {
+            Reader reader = null;
+            Article[] articles = null;
+            reader =
+                (DotTerminatedMessageReader) client.retrieveArticleInfo(
+                    lowArticleNumber,
+                    highArticleNumber);
 
-			if (reader != null) {
-				String theInfo = readerToString(reader);
-				StringTokenizer st = new StringTokenizer(theInfo, "\n");
+            if (reader != null) {
+                String theInfo = readerToString(reader);
+                StringTokenizer st = new StringTokenizer(theInfo, "\n");
 
-				// Extract the article information
-				// Mandatory format (from NNTP RFC 2980) is :
-				// Subject\tAuthor\tDate\tID\tReference(s)\tByte Count\tLine Count
+                // Extract the article information
+                // Mandatory format (from NNTP RFC 2980) is :
+                // Subject\tAuthor\tDate\tID\tReference(s)\tByte Count\tLine Count
 
-				int count = st.countTokens();
-				articles = new Article[count];
-				int index = 0;
+                int count = st.countTokens();
+                articles = new Article[count];
+                int index = 0;
 
-				while (st.hasMoreTokens()) {
-					StringTokenizer stt = new StringTokenizer(st.nextToken(), "\t");
-					Article article = new Article();
-					article.setArticleNumber(Integer.parseInt(stt.nextToken()));
-					article.setSubject(stt.nextToken());
-					article.setFrom(stt.nextToken());
-					article.setDate(stt.nextToken());
-					article.setArticleId(stt.nextToken());
-					article.addHeaderField("References", stt.nextToken());
-					articles[index++] = article;
-				}
-			} else {
-				return null;
-			}
+                while (st.hasMoreTokens()) {
+                    StringTokenizer stt = new StringTokenizer(st.nextToken(), "\t");
+                    Article article = new Article();
+                    article.setArticleNumber(Integer.parseInt(stt.nextToken()));
+                    article.setSubject(stt.nextToken());
+                    article.setFrom(stt.nextToken());
+                    article.setDate(stt.nextToken());
+                    article.setArticleId(stt.nextToken());
+                    article.addHeaderField("References", stt.nextToken());
+                    articles[index++] = article;
+                }
+            } else {
+                return null;
+            }
 
-			return articles;
-		}
-		
-	
-	/**
-	 * Convert a {@link Reader} instance to a String
-	 * @param reader The Reader instance
-	 * @return String
-	 */		
-	public static String readerToString(Reader reader) {
-		String temp = null;
-		StringBuffer sb = null;
-		BufferedReader bufReader = new BufferedReader(reader);
+            return articles;
+        }
+        
+    
+    /**
+     * Convert a {@link Reader} instance to a String
+     * @param reader The Reader instance
+     * @return String
+     */
+    public static String readerToString(Reader reader) {
+        String temp = null;
+        StringBuffer sb = null;
+        BufferedReader bufReader = new BufferedReader(reader);
 
-		sb = new StringBuffer();
-		try {
-			temp = bufReader.readLine();
-			while (temp != null) {
-				sb.append(temp);
-				sb.append("\n");
-				temp = bufReader.readLine();
-			}
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
+        sb = new StringBuffer();
+        try {
+            temp = bufReader.readLine();
+            while (temp != null) {
+                sb.append(temp);
+                sb.append("\n");
+                temp = bufReader.readLine();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
 
-		return sb.toString();
-	}
+        return sb.toString();
+    }
 }
diff --git a/src/java/examples/ntp/TimeClient.java b/src/java/examples/ntp/TimeClient.java
index 61238db..a4cda26 100644
--- a/src/java/examples/ntp/TimeClient.java
+++ b/src/java/examples/ntp/TimeClient.java
@@ -40,14 +40,14 @@
     public static final void timeTCP(String host) throws IOException
     {
         TimeTCPClient client = new TimeTCPClient();
-	try {
+    try {
           // We want to timeout if a response takes longer than 60 seconds
           client.setDefaultTimeout(60000);
-	  client.connect(host);
+      client.connect(host);
           System.out.println(client.getDate());
-	} finally {
+    } finally {
           client.disconnect();
-	}
+    }
     }
 
     public static final void timeUDP(String host) throws IOException
diff --git a/src/java/org/apache/commons/net/SocketClient.java b/src/java/org/apache/commons/net/SocketClient.java
index fc98573..fa68894 100644
--- a/src/java/org/apache/commons/net/SocketClient.java
+++ b/src/java/org/apache/commons/net/SocketClient.java
@@ -22,6 +22,7 @@
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.SocketException;
+import java.net.UnknownHostException;
 
 /**
  * The SocketClient provides the basic operations that are required of
@@ -158,7 +159,7 @@
      * @exception UnknownHostException If the hostname cannot be resolved.
      */
     public void connect(String hostname, int port)
-    throws SocketException, IOException
+    throws SocketException, IOException, UnknownHostException
     {
         _socket_ = _socketFactory_.createSocket(hostname, port);
         _connectAction_();
@@ -264,9 +265,9 @@
      */
     public void disconnect() throws IOException
     {
-        _socket_.close();
-        _input_.close();
-        _output_.close();
+        if(_socket_ != null) _socket_.close();
+        if(_input_ != null) _input_.close();
+        if(_output_ != null) _output_.close();
         _socket_ = null;
         _input_ = null;
         _output_ = null;
diff --git a/src/java/org/apache/commons/net/bsd/RCommandClient.java b/src/java/org/apache/commons/net/bsd/RCommandClient.java
index f2f89c8..c42e621 100644
--- a/src/java/org/apache/commons/net/bsd/RCommandClient.java
+++ b/src/java/org/apache/commons/net/bsd/RCommandClient.java
@@ -23,6 +23,7 @@
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketException;
+import java.net.UnknownHostException;
 
 import org.apache.commons.net.io.SocketInputStream;
 
@@ -244,7 +245,7 @@
      * @exception UnknownHostException If the hostname cannot be resolved.
      ***/
     public void connect(String hostname, int port)
-    throws SocketException, IOException
+    throws SocketException, IOException, UnknownHostException, BindException
     {
         connect(InetAddress.getByName(hostname), port, InetAddress.getLocalHost());
     }
diff --git a/src/java/org/apache/commons/net/ftp/Configurable.java b/src/java/org/apache/commons/net/ftp/Configurable.java
index 597ddbe..0442d36 100644
--- a/src/java/org/apache/commons/net/ftp/Configurable.java
+++ b/src/java/org/apache/commons/net/ftp/Configurable.java
@@ -24,13 +24,12 @@
  */
 public interface Configurable {
 
-	/**
-	 * @param config the object containing the configuration data
-	 * @return the object being configured after the configuration
-	 * @throws IllegalArgumentException if the elements of the 
-	 * <code>config</code> are somehow inadequate to configure the
-	 * Configurable object.
-	 */
-	public void configure(
-			FTPClientConfig config);	
+    /**
+     * @param config the object containing the configuration data
+     * @throws IllegalArgumentException if the elements of the 
+     * <code>config</code> are somehow inadequate to configure the
+     * Configurable object.
+     */
+    public void configure(
+            FTPClientConfig config);
 }
\ No newline at end of file
diff --git a/src/java/org/apache/commons/net/ftp/FTP.java b/src/java/org/apache/commons/net/ftp/FTP.java
index 704435d..864f629 100644
--- a/src/java/org/apache/commons/net/ftp/FTP.java
+++ b/src/java/org/apache/commons/net/ftp/FTP.java
@@ -459,7 +459,7 @@
         __commandBuffer.append(SocketClient.NETASCII_EOL);
 
         try{
-	    _controlOutput_.write(message = __commandBuffer.toString());
+        _controlOutput_.write(message = __commandBuffer.toString());
             _controlOutput_.flush();
         }
         catch (SocketException e)
@@ -473,7 +473,7 @@
                 throw e;
             }
         }
-	
+    
 
         if (_commandSupport_.getListenerCount() > 0)
             _commandSupport_.fireCommandSent(command, message);
diff --git a/src/java/org/apache/commons/net/ftp/FTPClient.java b/src/java/org/apache/commons/net/ftp/FTPClient.java
index 95313fc..2d41573 100644
--- a/src/java/org/apache/commons/net/ftp/FTPClient.java
+++ b/src/java/org/apache/commons/net/ftp/FTPClient.java
@@ -318,7 +318,7 @@
         __restartOffset      = 0;
         __systemName         = null;
         __entryParser        = null;
-        __bufferSize 		 = Util.DEFAULT_COPY_BUFFER_SIZE;
+        __bufferSize         = Util.DEFAULT_COPY_BUFFER_SIZE;
     }
     
     private String __parsePathname(String reply)
@@ -2057,7 +2057,7 @@
      *         the format determined by the parser represented by the
      *         <code> parserKey </code> parameter.
      *         <p><b> 
-     * 		   NOTE:</b> This array may contain null members if any of the 
+     *         NOTE:</b> 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
@@ -2086,7 +2086,7 @@
      * @see org.apache.commons.net.ftp.FTPFileEntryParser
      * @deprecated use {@link  #listFiles()  listFiles()} or 
      * {@link  #listFiles(String)  listFiles(String)} instead and specify the
-     * parser Key in an {@link  #FTPClientConfig  FTPClientConfig} object instead.
+     * parser Key in an {@link  FTPClientConfig} object instead.
      */
     public FTPFile[] listFiles(String parserKey, String pathname)
     throws IOException
@@ -2158,7 +2158,7 @@
      * @return The list of file information contained in the current directory
      *         in the format determined by the autodetection mechanism.  
      *         <p><b> 
-     * 		   NOTE:</b> This array may contain null members if any of the 
+     *         NOTE:</b> 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
@@ -2346,22 +2346,22 @@
             if (null != parserKey) {
                 // if a parser key was supplied in the parameters, 
                 // use that to create the paraser
-        	    __entryParser = 
-        	        __parserFactory.createFileEntryParser(parserKey);
+                __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 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
+                    // hasn't been supplied, then autodetect by calling
                     // the SYST command and use that to choose the parser.
-            	    __entryParser = 
-            	        __parserFactory.createFileEntryParser(getSystemName());
-             	}
+                    __entryParser = 
+                        __parserFactory.createFileEntryParser(getSystemName());
+                }
             }
         }
 
@@ -2397,9 +2397,12 @@
         }
 
 
-        engine.readServerList(socket.getInputStream(), getControlEncoding());
-
-        socket.close();
+        try {
+            engine.readServerList(socket.getInputStream(), getControlEncoding());
+        }
+        finally {
+            socket.close();
+        }
 
         completePendingCommand();
         return engine;
@@ -2461,7 +2464,7 @@
      * @return The list of file information contained in the given path in
      *         the format determined by the <code> parser </code> parameter.
      *         <p><b> 
-     * 		   NOTE:</b> This array may contain null members if any of the 
+     *         NOTE:</b> 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
@@ -2472,13 +2475,6 @@
      * @exception IOException  If an I/O error occurs while either sending a
      *      command to the server or receiving a reply from the server.
      *
-     * @return The list of file information contained in the given path in
-     *         the format determined by<code> parserKey </code>parameter.
-     *         <p><b> 
-     * 		   NOTE:</b> 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
      * @since 5 Jan 2004
      * @deprecated use listFiles(String parserKey, String pathname) instead
@@ -2516,7 +2512,7 @@
      * @return The list of file information contained in the given path in
      *         the format determined by the <code> parser </code> parameter.
      *         <p><b> 
-     * 		   NOTE:</b> This array may contain null members if any of the 
+     *         NOTE:</b> 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
@@ -2648,7 +2644,7 @@
      * @param bufSize The size of the buffer
      */
     public void setBufferSize(int bufSize) {
-    	__bufferSize = bufSize;
+        __bufferSize = bufSize;
     }
     
     /**
@@ -2656,7 +2652,7 @@
      * @return The current buffer size.
      */
     public int getBufferSize() {
-    	return __bufferSize;
+        return __bufferSize;
     }
 
 
@@ -2669,7 +2665,7 @@
      * @since 1.4
      */
     public void configure(FTPClientConfig config) {
-    	this.__configuration = config;
+        this.__configuration = config;
     }
     
 }
diff --git a/src/java/org/apache/commons/net/ftp/FTPClientConfig.java b/src/java/org/apache/commons/net/ftp/FTPClientConfig.java
index 0d7ffe6..1239bcb 100644
--- a/src/java/org/apache/commons/net/ftp/FTPClientConfig.java
+++ b/src/java/org/apache/commons/net/ftp/FTPClientConfig.java
@@ -140,7 +140,7 @@
  */
 public class FTPClientConfig
 {
-	
+    
     /**
      * Identifier by which a unix-based ftp server is known throughout
      * the commons-net ftp system.
@@ -171,6 +171,12 @@
      */
     public static final String SYST_OS400 = "OS/400";
     
+
+    /**
+     * Alternate SYST value for an AS/400 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.
@@ -182,384 +188,389 @@
      * 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.
+     *
+     * @since 1.5
      */
-    public static final String SYST_L8 = "Type: L8";
+    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";
+    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;
-	}
+    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);
-	}
+    /**
+     * 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 LANGUAGE_CODE_MAP = new TreeMap();
-	static {
-		
-		// if there are other commonly used month name encodings which
-		// correspond to particular locales, please add them here.
-		
-		
-		
-		// many locales code short names for months as all three letters
-		// these we handle simply.
-		LANGUAGE_CODE_MAP.put("en", Locale.ENGLISH);
-		LANGUAGE_CODE_MAP.put("de",Locale.GERMAN);
-		LANGUAGE_CODE_MAP.put("it",Locale.ITALIAN);
-		LANGUAGE_CODE_MAP.put("es", new Locale("es", "", "")); // spanish
-		LANGUAGE_CODE_MAP.put("pt", new Locale("pt", "", "")); // portuguese
-		LANGUAGE_CODE_MAP.put("da", new Locale("da", "", "")); // danish
-		LANGUAGE_CODE_MAP.put("sv", new Locale("sv", "", "")); // swedish
-		LANGUAGE_CODE_MAP.put("no", new Locale("no", "", "")); // norwegian
-		LANGUAGE_CODE_MAP.put("nl", new Locale("nl", "", "")); // dutch
-		LANGUAGE_CODE_MAP.put("ro", new Locale("ro", "", "")); // romanian
-		LANGUAGE_CODE_MAP.put("sq", new Locale("sq", "", "")); // albanian
-		LANGUAGE_CODE_MAP.put("sh", new Locale("sh", "", "")); // serbo-croatian
-		LANGUAGE_CODE_MAP.put("sk", new Locale("sk", "", "")); // slovak		
-		LANGUAGE_CODE_MAP.put("sl", new Locale("sl", "", "")); // slovenian
+    /**
+     * 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 LANGUAGE_CODE_MAP = new TreeMap();
+    static {
+        
+        // if there are other commonly used month name encodings which
+        // correspond to particular locales, please add them here.
+        
+        
+        
+        // many locales code short names for months as all three letters
+        // these we handle simply.
+        LANGUAGE_CODE_MAP.put("en", Locale.ENGLISH);
+        LANGUAGE_CODE_MAP.put("de",Locale.GERMAN);
+        LANGUAGE_CODE_MAP.put("it",Locale.ITALIAN);
+        LANGUAGE_CODE_MAP.put("es", new Locale("es", "", "")); // spanish
+        LANGUAGE_CODE_MAP.put("pt", new Locale("pt", "", "")); // portuguese
+        LANGUAGE_CODE_MAP.put("da", new Locale("da", "", "")); // danish
+        LANGUAGE_CODE_MAP.put("sv", new Locale("sv", "", "")); // swedish
+        LANGUAGE_CODE_MAP.put("no", new Locale("no", "", "")); // norwegian
+        LANGUAGE_CODE_MAP.put("nl", new Locale("nl", "", "")); // dutch
+        LANGUAGE_CODE_MAP.put("ro", new Locale("ro", "", "")); // romanian
+        LANGUAGE_CODE_MAP.put("sq", new Locale("sq", "", "")); // albanian
+        LANGUAGE_CODE_MAP.put("sh", new Locale("sh", "", "")); // serbo-croatian
+        LANGUAGE_CODE_MAP.put("sk", new Locale("sk", "", "")); // slovak
+        LANGUAGE_CODE_MAP.put("sl", new Locale("sl", "", "")); // slovenian
 
 
-		// some don't
-		LANGUAGE_CODE_MAP.put("fr",	
-		        "jan|f\u00e9v|mar|avr|mai|jun|jui|ao\u00fb|sep|oct|nov|d\u00e9c");  //french
-			
-	}
-	
-	/**
-	 * Getter for the serverSystemKey property.  This property
+        // some don't
+        LANGUAGE_CODE_MAP.put("fr",
+                "jan|f\u00e9v|mar|avr|mai|jun|jui|ao\u00fb|sep|oct|nov|d\u00e9c");  //french
+            
+    }
+    
+    /**
+     * Getter for the serverSystemKey property.  This property
      * specifies the general type of server to which the client connects.
      * Should be either one of the <code>FTPClientConfig.SYST_*</code> codes
      * or else the fully qualified class name of a parser implementing both
      * the <code>FTPFileEntryParser</code> and <code>Configurable</code>
      * 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;
-	}
-	
-	/**
-	 * <p>
-	 * getter for the {@link  #setShortMonthNames(String)  shortMonthNames} 
-	 * property.  
-	 * </p>
-	 * @return Returns the shortMonthNames.
-	 */
-	public String getShortMonthNames() {
-		return shortMonthNames;
-	}
-	
-	/**
-	 * <p>
-	 * getter for the {@link  #setServerLanguageCode(String)  serverLanguageCode} property.
-	 * </p>  
-* 	 * @return Returns the serverLanguageCode property.
-	 */
-	public String getServerLanguageCode() {
-		return serverLanguageCode;
-	}
-	
+     * @return Returns the serverSystemKey property.
+     */
+    public String getServerSystemKey() {
+        return serverSystemKey;
+    }
+    
     /**
-	 * <p>
-	 * getter for the {@link  #setLenientFutureDates(boolean)  lenientFutureDates} property.
-	 * </p>  
+     * 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;
+    }
+    
+    /**
+     * <p>
+     * getter for the {@link  #setShortMonthNames(String)  shortMonthNames} 
+     * property.  
+     * </p>
+     * @return Returns the shortMonthNames.
+     */
+    public String getShortMonthNames() {
+        return shortMonthNames;
+    }
+    
+    /**
+     * <p>
+     * getter for the {@link  #setServerLanguageCode(String)  serverLanguageCode} property.
+     * </p>  
+     * @return Returns the serverLanguageCode property.
+     */
+    public String getServerLanguageCode() {
+        return serverLanguageCode;
+    }
+    
+    /**
+     * <p>
+     * getter for the {@link  #setLenientFutureDates(boolean)  lenientFutureDates} property.
+     * </p>  
      * @return Returns the lenientFutureDates.
+     * @since 1.5
      */
     public boolean isLenientFutureDates() {
         return lenientFutureDates;
     }
-	/**
-	 * <p>
-	 * 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 <code>en_US</code> locales.
-	 * </p><p>
-	 * This should be in the format described for 
-	 * <code>java.text.SimpleDateFormat</code>. 
-	 * property.
-	 * </p>
-	 * @param defaultDateFormatStr The defaultDateFormatStr to set.
-	 */
-	public void setDefaultDateFormatStr(String defaultDateFormatStr) {
-		this.defaultDateFormatStr = defaultDateFormatStr;
-	}
-	
-	/**
-	 * <p>
-	 * 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.
-	 * </p>
-	 * This is used primarily in unix-based systems.
-	 * </p>
-	 * This should be in the format described for 
-	 * <code>java.text.SimpleDateFormat</code>.
-	 * </p>
-	 * @param recentDateFormatStr The recentDateFormatStr to set.
-	 */
-	public void setRecentDateFormatStr(String recentDateFormatStr) {
-		this.recentDateFormatStr = recentDateFormatStr;
-	}
-	
-	/**
-	 * <p>
-	 * 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.
-	 * </p><p>
-	 * This is used primarily in unix-based systems.
-	 * </p>
-	 * @param lenientFutureDates set true to compensate for out-of-synch 
-	 * conditions.
-	 */
+    /**
+     * <p>
+     * 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 <code>en_US</code> locales.
+     * </p><p>
+     * This should be in the format described for 
+     * <code>java.text.SimpleDateFormat</code>. 
+     * property.
+     * </p>
+     * @param defaultDateFormatStr The defaultDateFormatStr to set.
+     */
+    public void setDefaultDateFormatStr(String defaultDateFormatStr) {
+        this.defaultDateFormatStr = defaultDateFormatStr;
+    }
+    
+    /**
+     * <p>
+     * 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.
+     * </p>
+     * This is used primarily in unix-based systems.
+     * </p>
+     * This should be in the format described for 
+     * <code>java.text.SimpleDateFormat</code>.
+     * </p>
+     * @param recentDateFormatStr The recentDateFormatStr to set.
+     */
+    public void setRecentDateFormatStr(String recentDateFormatStr) {
+        this.recentDateFormatStr = recentDateFormatStr;
+    }
+    
+    /**
+     * <p>
+     * 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.
+     * </p><p>
+     * This is used primarily in unix-based systems.
+     * </p>
+     * @param lenientFutureDates set true to compensate for out-of-synch 
+     * conditions.
+     */
     public void setLenientFutureDates(boolean lenientFutureDates) {
         this.lenientFutureDates = lenientFutureDates;
     }
-	/**
-	 * <p>
-	 * 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.
-	 * </p><p>
-	 * This should be one of the identifiers used by 
-	 * <code>java.util.TimeZone</code> to refer to time zones, for example, 
-	 * <code>America/Chicago</code> or <code>Asia/Rangoon</code>.
-	 * </p>
-	 * @param serverTimeZoneId The serverTimeZoneId to set.
-	 */
-	public void setServerTimeZoneId(String serverTimeZoneId) {
-		this.serverTimeZoneId = serverTimeZoneId;
-	}
-	
-	/**
-	 * <p>
-	 * 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.
-	 * </p><p>
-	 * 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 
-	 * <code>"jan|feb|mar|apr|ma&#xED;|j&#xFA;n|j&#xFA;l|&#xE1;g&#xFA;|sep|okt|n&#xF3;v|des"</code>.  
-	 * </p>
-	 * @param shortMonthNames The value to set to the shortMonthNames property.
-	 */
-	public void setShortMonthNames(String shortMonthNames) {
-		this.shortMonthNames = shortMonthNames;
-	}
-	
-	/**
-	 * <p>
-	 * setter for the serverLanguageCode property.  This property allows
-	 * user to specify a 
-	 * <a href="http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt">
-	 * two-letter ISO-639 language code</a> 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.
-	 * </p>
-	 * <p>If the code supplied is not supported here, <code>en_US</code>
-	 * month names will be used.  We are supporting here those language 
-	 * codes which, when a <code> java.util.Locale</code> is constucted
-	 * using it, and a <code>java.text.SimpleDateFormat</code> is 
-	 * constructed using that Locale, the array returned by the 
-	 * SimpleDateFormat's <code>getShortMonths()</code> 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.
-	 * </p>
-	 * <p><strong>
-	 * Please note that this attribute will NOT be used to determine a 
-	 * locale-based date format for the language.  </strong>  
-	 * Experience has shown that many if not most FTP servers outside the
-	 * United States employ the standard <code>en_US</code> date format 
-	 * orderings of <code>MMM d yyyy</code> and <code>MMM d HH:mm</code> 
-	 * 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.
-	 * </p>	  
-	 * @param serverLanguageCode The value to set to the serverLanguageCode property.  
-	 */
-	public void setServerLanguageCode(String serverLanguageCode) {
-		this.serverLanguageCode = serverLanguageCode;
-	}
-	
-	/**
-	 * Looks up the supplied language code in the internally maintained table of 
-	 * language codes.  Returns a DateFormatSymbols object configured with 
-	 * short month names corresponding to the code.  If there is no corresponding
-	 * entry in the table, the object returned will be that for 
-	 * <code>Locale.US</code> 
-	 * @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  
-	 * <code>Locale.US</code> 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;
-	}
+    /**
+     * <p>
+     * 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.
+     * </p><p>
+     * This should be one of the identifiers used by 
+     * <code>java.util.TimeZone</code> to refer to time zones, for example, 
+     * <code>America/Chicago</code> or <code>Asia/Rangoon</code>.
+     * </p>
+     * @param serverTimeZoneId The serverTimeZoneId to set.
+     */
+    public void setServerTimeZoneId(String serverTimeZoneId) {
+        this.serverTimeZoneId = serverTimeZoneId;
+    }
+    
+    /**
+     * <p>
+     * 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.
+     * </p><p>
+     * 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 
+     * <code>"jan|feb|mar|apr|ma&#xED;|j&#xFA;n|j&#xFA;l|&#xE1;g&#xFA;|sep|okt|n&#xF3;v|des"</code>.  
+     * </p>
+     * @param shortMonthNames The value to set to the shortMonthNames property.
+     */
+    public void setShortMonthNames(String shortMonthNames) {
+        this.shortMonthNames = shortMonthNames;
+    }
+    
+    /**
+     * <p>
+     * setter for the serverLanguageCode property.  This property allows
+     * user to specify a 
+     * <a href="http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt">
+     * two-letter ISO-639 language code</a> 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.
+     * </p>
+     * <p>If the code supplied is not supported here, <code>en_US</code>
+     * month names will be used.  We are supporting here those language 
+     * codes which, when a <code> java.util.Locale</code> is constucted
+     * using it, and a <code>java.text.SimpleDateFormat</code> is 
+     * constructed using that Locale, the array returned by the 
+     * SimpleDateFormat's <code>getShortMonths()</code> 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.
+     * </p>
+     * <p><strong>
+     * Please note that this attribute will NOT be used to determine a 
+     * locale-based date format for the language.  </strong>  
+     * Experience has shown that many if not most FTP servers outside the
+     * United States employ the standard <code>en_US</code> date format 
+     * orderings of <code>MMM d yyyy</code> and <code>MMM d HH:mm</code> 
+     * 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.
+     * </p>
+     * @param serverLanguageCode The value to set to the serverLanguageCode property.  
+     */
+    public void setServerLanguageCode(String serverLanguageCode) {
+        this.serverLanguageCode = serverLanguageCode;
+    }
+    
+    /**
+     * Looks up the supplied language code in the internally maintained table of 
+     * language codes.  Returns a DateFormatSymbols object configured with 
+     * short month names corresponding to the code.  If there is no corresponding
+     * entry in the table, the object returned will be that for 
+     * <code>Locale.US</code> 
+     * @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  
+     * <code>Locale.US</code> 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 getSupportedLanguageCodes() {
-	    return LANGUAGE_CODE_MAP.keySet();
-	}
-	
-	
+    /**
+     * 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 getSupportedLanguageCodes() {
+        return LANGUAGE_CODE_MAP.keySet();
+    }
+    
+    
 }
diff --git a/src/java/org/apache/commons/net/ftp/FTPFileEntryParserImpl.java b/src/java/org/apache/commons/net/ftp/FTPFileEntryParserImpl.java
index 4584cc2..16cede8 100644
--- a/src/java/org/apache/commons/net/ftp/FTPFileEntryParserImpl.java
+++ b/src/java/org/apache/commons/net/ftp/FTPFileEntryParserImpl.java
@@ -77,7 +77,7 @@
     ***/
     public FTPFile[] parseFileList(InputStream listStream) throws IOException
     {
-    	return parseFileList(listStream, null);
+        return parseFileList(listStream, null);
     }
 
     /**
@@ -101,7 +101,7 @@
      * perform some action upon the FTPFileList after it has been created
      * from the server stream, but before any clients see the list.
      *
-     * This default implementation is a no-op.
+     * This default implementation removes entries that do not parse as files.
      *
      * @param original Original list after it has been created from the server stream
      *
@@ -113,8 +113,6 @@
             String entry = (String) it.next();
             if (null == parseFTPEntry(entry)) {
                 it.remove();
-            } else {
-                break;
             }
          }
          return original;
diff --git a/src/java/org/apache/commons/net/ftp/FTPFileList.java b/src/java/org/apache/commons/net/ftp/FTPFileList.java
index 38c5193..c507529 100644
--- a/src/java/org/apache/commons/net/ftp/FTPFileList.java
+++ b/src/java/org/apache/commons/net/ftp/FTPFileList.java
@@ -94,7 +94,7 @@
      */
     public static FTPFileList create(InputStream stream,
                                       FTPFileEntryParser parser,
-									  String encoding)
+                                      String encoding)
             throws IOException
     {
         FTPFileList list = new FTPFileList(parser, encoding);
@@ -122,11 +122,10 @@
      *
      * @deprecated The version of this method which takes an encoding should be used.
     */
-    public static FTPFileList create(InputStream stream, 
-    								  FTPFileEntryParser parser)
-    	throws IOException
+    public static FTPFileList create(InputStream stream, FTPFileEntryParser parser)
+        throws IOException
     {
-    	return create(stream, parser, null);
+        return create(stream, parser, null);
     }
     
     
@@ -154,19 +153,19 @@
     }
     
     /**
-	 * internal method for reading the input into the <code>lines</code> vector.
-	 *
-	 * @param stream The socket stream on which the input will be read.
-	 *
-	 * @exception IOException thrown on any failure to read the stream
-	 *
-	 * @deprecated The version of this method which takes an encoding should be used.
-	*/
-	public void readStream(InputStream stream) throws IOException
-	{
-	 readStream(stream, null);
-	}
-	 
+     * internal method for reading the input into the <code>lines</code> vector.
+     *
+     * @param stream The socket stream on which the input will be read.
+     *
+     * @exception IOException thrown on any failure to read the stream
+     *
+     * @deprecated The version of this method which takes an encoding should be used.
+    */
+    public void readStream(InputStream stream) throws IOException
+    {
+     readStream(stream, null);
+    }
+     
 
     /**
      * Accessor for this object's default parser.
diff --git a/src/java/org/apache/commons/net/ftp/FTPListParseEngine.java b/src/java/org/apache/commons/net/ftp/FTPListParseEngine.java
index 19b93c7..4f7f05c 100644
--- a/src/java/org/apache/commons/net/ftp/FTPListParseEngine.java
+++ b/src/java/org/apache/commons/net/ftp/FTPListParseEngine.java
@@ -102,24 +102,24 @@
     }
     
     /**
-	 * handle the iniitial reading and preparsing of the list returned by
-	 * the server.  After this method has completed, this object will contain
-	 * a list of unparsed entries (Strings) each referring to a unique file
-	 * on the server.
-	 *
-	 * @param stream input stream provided by the server socket.
-	 *
-	 * @exception IOException
-	 *                   thrown on any failure to read from the sever.
-	 *
-	 * @deprecated The version of this method which takes an encoding should be used.
-	*/
-	public void readServerList(InputStream stream)
-	throws IOException
-	{
-		readServerList(stream, null);
-	}
-	
+     * handle the iniitial reading and preparsing of the list returned by
+     * the server.  After this method has completed, this object will contain
+     * a list of unparsed entries (Strings) each referring to a unique file
+     * on the server.
+     *
+     * @param stream input stream provided by the server socket.
+     *
+     * @exception IOException
+     *                   thrown on any failure to read from the sever.
+     *
+     * @deprecated The version of this method which takes an encoding should be used.
+    */
+    public void readServerList(InputStream stream)
+    throws IOException
+    {
+        readServerList(stream, null);
+    }
+    
 
 
     /**
@@ -138,16 +138,16 @@
      */
     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));
-    	}
-    	
+        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)
diff --git a/src/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.java b/src/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.java
index eb26d8b..b0ae19f 100644
--- a/src/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.java
+++ b/src/java/org/apache/commons/net/ftp/parser/ConfigurableFTPFileEntryParserImpl.java
@@ -46,61 +46,61 @@
 implements Configurable 
 {
 
-	private FTPTimestampParser timestampParser;
-	
-	/**
-	 * Only constructor for this absract class.
-	 * @param regex  Regular expression used main parsing of the 
-	 * file listing.
-	 */
-	public ConfigurableFTPFileEntryParserImpl(String regex)
-	{
-		super(regex);
-		this.timestampParser = new FTPTimestampParserImpl();
-	}
+    private FTPTimestampParser timestampParser;
+    
+    /**
+     * Only constructor for this absract class.
+     * @param regex  Regular expression used main parsing of the 
+     * file listing.
+     */
+    public ConfigurableFTPFileEntryParserImpl(String regex)
+    {
+        super(regex);
+        this.timestampParser = new FTPTimestampParserImpl();
+    }
 
-	/**
-	 * This method is called by the concrete parsers to delegate
-	 * timestamp parsing to the timestamp parser.
-	 * <p>
-	 * @param timestampStr the timestamp string pulled from the 
-	 * file listing by the regular expression parser, to be submitted
-	 * to the <code>timestampParser</code> for extracting the timestamp.
-	 * @return a <code>java.util.Calendar</code> containing results of the 
-	 * timestamp parse. 
-	 */
-	public Calendar parseTimestamp(String timestampStr) throws ParseException {
-		return this.timestampParser.parseTimestamp(timestampStr);
-	}
+    /**
+     * This method is called by the concrete parsers to delegate
+     * timestamp parsing to the timestamp parser.
+     * <p>
+     * @param timestampStr the timestamp string pulled from the 
+     * file listing by the regular expression parser, to be submitted
+     * to the <code>timestampParser</code> for extracting the timestamp.
+     * @return a <code>java.util.Calendar</code> 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.
-	 * </p> 
-	 * @param config the configuration to be used to configure this parser.
-	 * If it is null, a default configuration defined by
-	 * each concrete subclass is used instead.
-	 */
+    /**
+     * 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.
+     * </p> 
+     * @param config the configuration to be used to configure this parser.
+     * If it is null, a default configuration defined by
+     * each concrete subclass is used instead.
+     */
     public void configure(FTPClientConfig config)
     {
         if (this.timestampParser instanceof Configurable) {
             FTPClientConfig defaultCfg = getDefaultConfiguration();
-	        if (config != null) {
-	            if (null == config.getDefaultDateFormatStr()) {
-	                config.setDefaultDateFormatStr(defaultCfg.getDefaultDateFormatStr());
-	            }
-	            if (null == config.getRecentDateFormatStr()) {
-	                config.setRecentDateFormatStr(defaultCfg.getRecentDateFormatStr());
-	            }
-	            ((Configurable)this.timestampParser).configure(config);
-	        } else {
-	            ((Configurable)this.timestampParser).configure(defaultCfg);
-	        }
+            if (config != null) {
+                if (null == config.getDefaultDateFormatStr()) {
+                    config.setDefaultDateFormatStr(defaultCfg.getDefaultDateFormatStr());
+                }
+                if (null == config.getRecentDateFormatStr()) {
+                    config.setRecentDateFormatStr(defaultCfg.getRecentDateFormatStr());
+                }
+                ((Configurable)this.timestampParser).configure(config);
+            } else {
+                ((Configurable)this.timestampParser).configure(defaultCfg);
+            }
         }
     }
     
diff --git a/src/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java b/src/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java
index 1ada092..5a5ad1e 100644
--- a/src/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java
+++ b/src/java/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactory.java
@@ -28,15 +28,15 @@
  * org.apache.commons.net.ftp.FTPClient.listFiles()
  * if no other implementation has been specified.
  *
- * @see org.apache.commons.net.ftp.FTPClient#listFiles
+ * @see org.apache.commons.net.ftp.FTPClient#listFiles()
  * @see org.apache.commons.net.ftp.FTPClient#setParserFactory
  */
 public class DefaultFTPFileEntryParserFactory
     implements FTPFileEntryParserFactory
 {
-	private FTPClientConfig config = null;
+    private FTPClientConfig config = null;
 
-	/**
+    /**
      * This default implementation of the FTPFileEntryParserFactory
      * interface works according to the following logic:
      * First it attempts to interpret the supplied key as a fully
@@ -87,50 +87,51 @@
         {
             try 
             {
-	            String ukey = null;
-	            if (null != key)
-	            {
-	                ukey = key.toUpperCase();
-	            }
-	            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)
-	            {
-	                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);
-	            }
+                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)
-            { 	
+            {
                 if (nf.getMessage().startsWith("org/apache/oro")) {
-    	            throw new ParserInitializationException(
-    	                " jakarta-oro-2.x.jar required on the runtime classpath. ", nf);
+                    throw new ParserInitializationException(
+                        " jakarta-oro-2.x.jar required on the runtime classpath. ", nf);
                 } else {
                     throw new ParserInitializationException("Error initializing parser", nf);
                 }
@@ -138,10 +139,10 @@
 
         }
         catch (NoClassDefFoundError e)
-        { 	
+        {
             if (e.getMessage().startsWith("org/apache/oro")) {
-	            throw new ParserInitializationException(
-	                " jakarta-oro-2.x.jar required on the runtime classpath. ", e);
+                throw new ParserInitializationException(
+                    " jakarta-oro-2.x.jar required on the runtime classpath. ", e);
             } else {
                 throw new ParserInitializationException("Error initializing parser", e);
             }
@@ -183,13 +184,13 @@
      *                   Thrown on any exception in instantiation
      * @since 1.4
      */
-	public FTPFileEntryParser createFileEntryParser(FTPClientConfig config) 
-	throws ParserInitializationException 
-	{
-	    this.config = config;
-		String key = config.getServerSystemKey();
-		return createFileEntryParser(key);
-	}
+    public FTPFileEntryParser createFileEntryParser(FTPClientConfig config) 
+    throws ParserInitializationException 
+    {
+        this.config = config;
+        String key = config.getServerSystemKey();
+        return createFileEntryParser(key);
+    }
 
 
     public FTPFileEntryParser createUnixFTPEntryParser()
@@ -202,23 +203,26 @@
         return new VMSVersioningFTPEntryParser();
     }
     
+    /**
+     * @since 1.5
+     */
     public FTPFileEntryParser createNetwareFTPEntryParser() {
-    	return new NetwareFTPEntryParser();
+        return new NetwareFTPEntryParser();
     }
 
     public FTPFileEntryParser createNTFTPEntryParser()
     {
-    	if (config != null && FTPClientConfig.SYST_NT.equals(
-    	        config.getServerSystemKey())) 
-    	{
+        if (config != null && FTPClientConfig.SYST_NT.equals(
+                config.getServerSystemKey())) 
+        {
             return new NTFTPEntryParser();
-    	} else {
+        } else {
             return new CompositeFileEntryParser(new FTPFileEntryParser[]
-	   	        {
-	   	            new NTFTPEntryParser(),
-	   	            new UnixFTPEntryParser()
-	   	        });
-    	}
+                {
+                    new NTFTPEntryParser(),
+                    new UnixFTPEntryParser()
+                });
+        }
     }
     
      public FTPFileEntryParser createOS2FTPEntryParser()
@@ -228,17 +232,17 @@
 
     public FTPFileEntryParser createOS400FTPEntryParser()
     {
-    	if (config != null && 
-    	        FTPClientConfig.SYST_OS400.equals(config.getServerSystemKey())) 
-    	{
+        if (config != null && 
+                FTPClientConfig.SYST_OS400.equals(config.getServerSystemKey())) 
+        {
             return new OS400FTPEntryParser();
-    	} else {
-	        return new CompositeFileEntryParser(new FTPFileEntryParser[]
-	            {
-	                new OS400FTPEntryParser(),
-	                new UnixFTPEntryParser()
-	            });
-    	}
+        } else {
+            return new CompositeFileEntryParser(new FTPFileEntryParser[]
+                {
+                    new OS400FTPEntryParser(),
+                    new UnixFTPEntryParser()
+                });
+        }
     }
 
     public FTPFileEntryParser createMVSEntryParser()
@@ -247,6 +251,5 @@
     }
 
 
-	
+    
 }
-
diff --git a/src/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParser.java b/src/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParser.java
index 307bc36..1c52ba1 100644
--- a/src/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParser.java
+++ b/src/java/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParser.java
@@ -110,7 +110,7 @@
             }
 
             Calendar cal = Calendar.getInstance();
-	    cal.set(Calendar.MILLISECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
             cal.set(Calendar.SECOND,
                     0);
             cal.set(Calendar.MINUTE,
diff --git a/src/java/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java b/src/java/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
index 3153558..b9f48ba 100644
--- a/src/java/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
+++ b/src/java/org/apache/commons/net/ftp/parser/FTPFileEntryParserFactory.java
@@ -62,6 +62,6 @@
      * @since 1.4
      */
     public FTPFileEntryParser createFileEntryParser(FTPClientConfig config)
-    	throws ParserInitializationException;
+        throws ParserInitializationException;
 
 }
diff --git a/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParser.java b/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParser.java
index 86f6b0b..8e6f5c3 100644
--- a/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParser.java
+++ b/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParser.java
@@ -26,26 +26,26 @@
  */
 public interface FTPTimestampParser {
     
-	/**
-	 * the default default date format. 
-	 */
-	public static final String DEFAULT_SDF = UnixFTPEntryParser.DEFAULT_DATE_FORMAT;
-	/**
-	 * the default recent date format. 
-	 */
-	public static final String DEFAULT_RECENT_SDF = UnixFTPEntryParser.DEFAULT_RECENT_DATE_FORMAT;
-	
-	/**
-	 * Parses the supplied datestamp parameter.  This parameter typically would 
-	 * have been pulled from a longer FTP listing via the regular expression 
-	 * mechanism
-	 * @param timestampStr - the timestamp portion of the FTP directory listing
-	 * to be parsed
-	 * @return a <code>java.util.Calendar</code> 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;
-	
+    /**
+     * the default default date format. 
+     */
+    public static final String DEFAULT_SDF = UnixFTPEntryParser.DEFAULT_DATE_FORMAT;
+    /**
+     * the default recent date format. 
+     */
+    public static final String DEFAULT_RECENT_SDF = UnixFTPEntryParser.DEFAULT_RECENT_DATE_FORMAT;
+    
+    /**
+     * Parses the supplied datestamp parameter.  This parameter typically would 
+     * have been pulled from a longer FTP listing via the regular expression 
+     * mechanism
+     * @param timestampStr - the timestamp portion of the FTP directory listing
+     * to be parsed
+     * @return a <code>java.util.Calendar</code> 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/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java b/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
index 4a1304f..fc8c564 100644
--- a/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
+++ b/src/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java
@@ -23,7 +23,6 @@
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
-import java.util.GregorianCalendar;
 import java.util.TimeZone;
 
 import org.apache.commons.net.ftp.Configurable;
@@ -38,253 +37,246 @@
  * @since 1.4
  */
 public class FTPTimestampParserImpl implements
-		FTPTimestampParser, Configurable 
+        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 now The current time 	 
-	 */
-	public Calendar parseTimestamp(String timestampStr, Calendar now) throws ParseException {
-		now.setTimeZone(this.getServerTimeZone());
-		Calendar working = (Calendar) now.clone();;
-		working.setTimeZone(getServerTimeZone());
-		ParsePosition pp = new ParsePosition(0);
+    
+    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) {
-			parsed = recentDateFormat.parse(timestampStr, pp);
-		}
-		if (parsed != null && pp.getIndex() == timestampStr.length()) 
-		{
-			working.setTime(parsed);
-			working.set(Calendar.YEAR, now.get(Calendar.YEAR));
+        Date parsed = null;
+        String timeStampStrPlusYear="";
+        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);
+            }    
+            // 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.
+            int year = now.get(Calendar.YEAR);
+            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() == timeStampStrPlusYear.length()) 
+        {
+            working.setTime(parsed);
 
-			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);
-			}    
-			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;
-	}
+            if (working.after(now)) {
+                working.add(Calendar.YEAR, -1);
+            }
+        } 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 <code>FTPTimestampParser</code> according
-	 * to the following logic:
-	 * <p>
-	 * 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:
-	 * </p><p><ul>
-	 * <li>If a {@link  FTPClientConfig#setShortMonthNames(String) shortMonthString}
-	 * has been supplied in the <code>config</code>, use that to parse  parse timestamps.</li> 
-	 * <li>Otherwise, if a {@link  FTPClientConfig#setServerLanguageCode(String) serverLanguageCode}
-	 * has been supplied in the <code>config</code>, use the month names represented 
-	 * by that {@link  FTPClientConfig#lookupDateFormatSymbols(String) language}
-	 * to parse timestamps.</li>
-	 * <li>otherwise use default English month names</li>
-	 * </ul></p><p>
-	 * 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.  
-	 * </p> 
-	 */
-	public void configure(FTPClientConfig config) {
-		DateFormatSymbols dfs = null;
-		
-		String languageCode = config.getServerLanguageCode();
-		String shortmonths = config.getShortMonthNames();
-		if (shortmonths != null) {
-			dfs = FTPClientConfig.getDateFormatSymbols(shortmonths);
-		} else if (languageCode != null) {
-			dfs = FTPClientConfig.lookupDateFormatSymbols(languageCode);
-		} else {
-			dfs = FTPClientConfig.lookupDateFormatSymbols("en");
-		}
-		
-		
-		String recentFormatString = config.getRecentDateFormatStr();
-		if (recentFormatString == null) {
-		    this.recentDateFormat = null;
-		} else {
-			this.recentDateFormat = new SimpleDateFormat(recentFormatString, dfs);
-			this.recentDateFormat.setLenient(false);
-		}
-			
-		String defaultFormatString = config.getDefaultDateFormatStr();
-		if (defaultFormatString == null) {
-			throw new IllegalArgumentException("defaultFormatString cannot be null");
-		}
-		this.defaultDateFormat = new SimpleDateFormat(defaultFormatString, dfs);
-		this.defaultDateFormat.setLenient(false);
-		
-		setServerTimeZone(config.getServerTimeZoneId());
-		
-		this.lenientFutureDates = config.isLenientFutureDates();
-	}
+    /**
+     * @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 <code>FTPTimestampParser</code> according
+     * to the following logic:
+     * <p>
+     * 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:
+     * </p><p><ul>
+     * <li>If a {@link  FTPClientConfig#setShortMonthNames(String) shortMonthString}
+     * has been supplied in the <code>config</code>, use that to parse  parse timestamps.</li> 
+     * <li>Otherwise, if a {@link  FTPClientConfig#setServerLanguageCode(String) serverLanguageCode}
+     * has been supplied in the <code>config</code>, use the month names represented 
+     * by that {@link  FTPClientConfig#lookupDateFormatSymbols(String) language}
+     * to parse timestamps.</li>
+     * <li>otherwise use default English month names</li>
+     * </ul></p><p>
+     * 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.  
+     * </p> 
+     */
+    public void configure(FTPClientConfig config) {
+        DateFormatSymbols dfs = null;
+        
+        String languageCode = config.getServerLanguageCode();
+        String shortmonths = config.getShortMonthNames();
+        if (shortmonths != null) {
+            dfs = FTPClientConfig.getDateFormatSymbols(shortmonths);
+        } else if (languageCode != null) {
+            dfs = FTPClientConfig.lookupDateFormatSymbols(languageCode);
+        } else {
+            dfs = FTPClientConfig.lookupDateFormatSymbols("en");
+        }
+        
+        
+        String recentFormatString = config.getRecentDateFormatStr();
+        if (recentFormatString == null) {
+            this.recentDateFormat = null;
+        } else {
+            this.recentDateFormat = new SimpleDateFormat(recentFormatString, dfs);
+            this.recentDateFormat.setLenient(false);
+        }
+            
+        String defaultFormatString = config.getDefaultDateFormatStr();
+        if (defaultFormatString == null) {
+            throw new IllegalArgumentException("defaultFormatString cannot be null");
+        }
+        this.defaultDateFormat = new SimpleDateFormat(defaultFormatString, dfs);
+        this.defaultDateFormat.setLenient(false);
+        
+        setServerTimeZone(config.getServerTimeZoneId());
+        
+        this.lenientFutureDates = config.isLenientFutureDates();
+    }
     /**
      * @return Returns the lenientFutureDates.
      */
diff --git a/src/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java b/src/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java
index d1d107c..a43715d 100644
--- a/src/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java
+++ b/src/java/org/apache/commons/net/ftp/parser/MVSFTPEntryParser.java
@@ -32,8 +32,8 @@
     /**
      * This is the regular expression used by this parser.
      */
-	private static final String REGEX = "(.*)\\s+([^\\s]+)\\s*";
-	
+    private static final String REGEX = "(.*)\\s+([^\\s]+)\\s*";
+    
     /**
      * Although this parser is now ignoring dates, someone may someday
      * figure out a way to accomodate this and this appears to be the 
@@ -41,32 +41,32 @@
      * SMC 2005/04/08
      */
     static final String DEFAULT_DATE_FORMAT 
-		= "yyyy/MM/dd"; // 2001/11/09
+        = "yyyy/MM/dd"; // 2001/11/09
 
         
- 	// This is not at all the tightest possible regexp for MVS LIST
-	// output, but I'm not a mainframe guru so I have little idea what the
-	// range of valid values are.  I just needed to get the filename (Dsname);
-	// note that no other FTPFile fields can be filled in with the results of
-	// a LIST on MVS.  The 'Referred' date seems to be 'last accessed date'
-	// and not 'last modified date' so I didn't bother parsing it.
-	//
-	// Of course it works perfectly as-is and it distinguishes header lines from
-	// file results so that's the important thing.  
-	//
-	// This parser should be used when SYST returns:
-	// 'MVS is the operating system of this server. FTP Server is running on z/OS.'
-	//
-	// Also note that there is no concept of directories in MVS, just datasets,
-	// which have names composed of four dot separated names of up to 8 chars.
-	// As a result, FTPFile.FILE_TYPE is always used. -JN 6/2004 jnadler<at>srcginc<dotcom>
+    // This is not at all the tightest possible regexp for MVS LIST
+    // output, but I'm not a mainframe guru so I have little idea what the
+    // range of valid values are.  I just needed to get the filename (Dsname);
+    // note that no other FTPFile fields can be filled in with the results of
+    // a LIST on MVS.  The 'Referred' date seems to be 'last accessed date'
+    // and not 'last modified date' so I didn't bother parsing it.
+    //
+    // Of course it works perfectly as-is and it distinguishes header lines from
+    // file results so that's the important thing.  
+    //
+    // This parser should be used when SYST returns:
+    // 'MVS is the operating system of this server. FTP Server is running on z/OS.'
+    //
+    // Also note that there is no concept of directories in MVS, just datasets,
+    // which have names composed of four dot separated names of up to 8 chars.
+    // As a result, FTPFile.FILE_TYPE is always used. -JN 6/2004 jnadler<at>srcginc<dotcom>
 
-	// Sample LIST results from MVS:
-	//
-	//Volume Unit    Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname
-	//FPFS42 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.RPTBM023.D061704
-	//FPFS41 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.RPTBM056.D061704
-	//FPFS25 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.WTM204.D061704
+    // Sample LIST results from MVS:
+    //
+    //Volume Unit    Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname
+    //FPFS42 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.RPTBM023.D061704
+    //FPFS41 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.RPTBM056.D061704
+    //FPFS25 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.WTM204.D061704
 
     /**
      * The sole constructor for a MVSFTPEntryParser object.
@@ -99,9 +99,9 @@
             f = new FTPFile();
             String dataSetName = group(2);
             f.setType(FTPFile.FILE_TYPE);
-			f.setName(dataSetName);
+            f.setName(dataSetName);
 
-			return (f);
+            return (f);
         }
         return null;
     }
diff --git a/src/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java b/src/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java
index 1f3802a..2b2ab5b 100644
--- a/src/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java
+++ b/src/java/org/apache/commons/net/ftp/parser/NTFTPEntryParser.java
@@ -30,9 +30,9 @@
  */
 public class NTFTPEntryParser extends ConfigurableFTPFileEntryParserImpl
 {
-	
+    
     private static final String DEFAULT_DATE_FORMAT 
-		= "MM-dd-yy hh:mma"; //11-09-01 12:30PM
+        = "MM-dd-yy hh:mma"; //11-09-01 12:30PM
 
 
     /**
@@ -91,7 +91,7 @@
 
         if (matches(entry))
         {
-        	String datestr = group(1)+" "+group(2);
+            String datestr = group(1)+" "+group(2);
             String dirString = group(3);
             String size = group(4);
             String name = group(5);
diff --git a/src/java/org/apache/commons/net/ftp/parser/NetwareFTPEntryParser.java b/src/java/org/apache/commons/net/ftp/parser/NetwareFTPEntryParser.java
index 27b5362..12f5827 100644
--- a/src/java/org/apache/commons/net/ftp/parser/NetwareFTPEntryParser.java
+++ b/src/java/org/apache/commons/net/ftp/parser/NetwareFTPEntryParser.java
@@ -30,144 +30,145 @@
  * @author <a href="rwinston@apache.org">Rory Winston</a>
  * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
  * @version $Id$
+ * @since 1.5
  */
 public class NetwareFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
 
-	/**
-	 * Default date format is e.g. Feb 22 2006
-	 */
-	private static final String DEFAULT_DATE_FORMAT = "MMM dd yyyy";
+    /**
+     * Default date format is e.g. Feb 22 2006
+     */
+    private static final String DEFAULT_DATE_FORMAT = "MMM dd yyyy";
 
-	/**
-	 * Default recent date format is e.g. Feb 22 17:32
-	 */
-	private static final String DEFAULT_RECENT_DATE_FORMAT = "MMM dd HH:mm";
+    /**
+     * Default recent date format is e.g. Feb 22 17:32
+     */
+    private static final String DEFAULT_RECENT_DATE_FORMAT = "MMM dd HH:mm";
 
-	/**
-	 * this is the regular expression used by this parser.
-	 * Example: d [-W---F--] SCION_VOL2                        512 Apr 13 23:12 VOL2
-	 */
-	private static final String REGEX = "(d|-){1}\\s+"	// Directory/file flag 
-			+ "\\[(.*)\\]\\s+"			// Attributes
-			+ "(\\S+)\\s+" + "(\\d+)\\s+"		// Owner and size
-			+ "(\\S+\\s+\\S+\\s+((\\d+:\\d+)|(\\d{4})))" // Long/short date format
-			+ "\\s+(.*)";				// Filename (incl. spaces)
+    /**
+     * this is the regular expression used by this parser.
+     * Example: d [-W---F--] SCION_VOL2                        512 Apr 13 23:12 VOL2
+     */
+    private static final String REGEX = "(d|-){1}\\s+"      // Directory/file flag 
+            + "\\[(.*)\\]\\s+"                              // Attributes
+            + "(\\S+)\\s+" + "(\\d+)\\s+"                   // Owner and size
+            + "(\\S+\\s+\\S+\\s+((\\d+:\\d+)|(\\d{4})))"    // Long/short date format
+            + "\\s+(.*)";                                   // Filename (incl. spaces)
 
-	/**
-	 * The default constructor for a NetwareFTPEntryParser 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
-	 * <code>REGEX</code> is  not a valid regular expression.
-	 */
-	public NetwareFTPEntryParser() {
-		this(null);
-	}
+    /**
+     * The default constructor for a NetwareFTPEntryParser 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
+     * <code>REGEX</code> 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
-	 * <code>REGEX</code> is  not a valid regular expression.
-	 * @since 1.4
-	 */
-	public NetwareFTPEntryParser(FTPClientConfig config) {
-		super(REGEX);
-		configure(config);
-	}
+    /**
+     * 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
+     * <code>REGEX</code> 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 <code> FTPFile </code> instance.  If the
-	 * file listing line doesn't describe a file, <code> null </code> is
-	 * returned, otherwise a <code> FTPFile </code> instance representing the
-	 * files in the directory is returned.
-	 * <p>
-	 * <p>
-	 * Netware file permissions are in the following format:  RWCEAFMS, and are explained as follows:
-	 * <ul>
-	 * <li><b>S</b> - Supervisor; All rights.
-	 * <li><b>R</b> - Read; Right to open and read or execute.
-	 * <li><b>W</b> - Write; Right to open and modify.
-	 * <li><b>C</b> - Create; Right to create; when assigned to a file, allows a deleted file to be recovered.
-	 * <li><b>E</b> - Erase; Right to delete.
-	 * <li><b>M</b> - Modify; Right to rename a file and to change attributes.
-	 * <li><b>F</b> - File Scan; Right to see directory or file listings.
-	 * <li><b>A</b> - Access Control; Right to modify trustee assignments and the Inherited Rights Mask.
-	 * </ul>
-	 * 
-	 * See <a href="http://www.novell.com/documentation/nfap10/index.html?page=/documentation/nfap10/nfaubook/data/abxraws.html">here</a> 
-	 * 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) {
+    /**
+     * Parses a line of an NetwareFTP server file listing and converts it into a
+     * usable format in the form of an <code> FTPFile </code> instance.  If the
+     * file listing line doesn't describe a file, <code> null </code> is
+     * returned, otherwise a <code> FTPFile </code> instance representing the
+     * files in the directory is returned.
+     * <p>
+     * <p>
+     * Netware file permissions are in the following format:  RWCEAFMS, and are explained as follows:
+     * <ul>
+     * <li><b>S</b> - Supervisor; All rights.
+     * <li><b>R</b> - Read; Right to open and read or execute.
+     * <li><b>W</b> - Write; Right to open and modify.
+     * <li><b>C</b> - Create; Right to create; when assigned to a file, allows a deleted file to be recovered.
+     * <li><b>E</b> - Erase; Right to delete.
+     * <li><b>M</b> - Modify; Right to rename a file and to change attributes.
+     * <li><b>F</b> - File Scan; Right to see directory or file listings.
+     * <li><b>A</b> - Access Control; Right to modify trustee assignments and the Inherited Rights Mask.
+     * </ul>
+     * 
+     * See <a href="http://www.novell.com/documentation/nfap10/index.html?page=/documentation/nfap10/nfaubook/data/abxraws.html">here</a> 
+     * 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);
+        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
-			}
+            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);
-			}
+            //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);
+            f.setUser(user);
 
-			//set the name
-			f.setName(name.trim());
+            //set the name
+            f.setName(name.trim());
 
-			//set the size
-			f.setSize(Long.parseLong(size.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);
-			}
+            // 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;
+            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.
-	 */
-	protected FTPClientConfig getDefaultConfiguration() {
-		return new FTPClientConfig(FTPClientConfig.SYST_NETWARE,
-				DEFAULT_DATE_FORMAT, DEFAULT_RECENT_DATE_FORMAT, null, null,
-				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.
+     */
+    protected FTPClientConfig getDefaultConfiguration() {
+        return new FTPClientConfig(FTPClientConfig.SYST_NETWARE,
+                DEFAULT_DATE_FORMAT, DEFAULT_RECENT_DATE_FORMAT, null, null,
+                null);
+    }
 
 }
diff --git a/src/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java b/src/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
index 336b0fc..32fe70b 100644
--- a/src/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
+++ b/src/java/org/apache/commons/net/ftp/parser/OS2FTPEntryParser.java
@@ -31,9 +31,9 @@
 public class OS2FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
 
 {
-	
+    
     private static final String DEFAULT_DATE_FORMAT 
-		= "MM-dd-yy HH:mm"; //11-09-01 12:30
+        = "MM-dd-yy HH:mm"; //11-09-01 12:30
     /**
      * this is the regular expression used by this parser.
      */
@@ -94,7 +94,7 @@
             String size = group(1);
             String attrib = group(2);
             String dirString = group(3);
-        	String datestr = group(4)+" "+group(5);
+            String datestr = group(4)+" "+group(5);
             String name = group(6);
             try
             {
diff --git a/src/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java b/src/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
index 8685f53..f9e2640 100644
--- a/src/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
+++ b/src/java/org/apache/commons/net/ftp/parser/OS400FTPEntryParser.java
@@ -28,11 +28,11 @@
 public class OS400FTPEntryParser extends ConfigurableFTPFileEntryParserImpl
 {
     private static final String DEFAULT_DATE_FORMAT 
-		= "yy/MM/dd HH:mm:ss"; //01/11/09 12:30:24
+        = "yy/MM/dd HH:mm:ss"; //01/11/09 12:30:24
     
 
 
-	private static final String REGEX =
+    private static final String REGEX =
         "(\\S+)\\s+"                // user
         + "(\\d+)\\s+"              // size
         + "(\\S+)\\s+(\\S+)\\s+"    // date stuff 
@@ -83,7 +83,7 @@
         {
             String usr = group(1);
             String filesize = group(2);
-        	String datestr = group(3)+" "+group(4);
+            String datestr = group(3)+" "+group(4);
             String typeStr = group(5);
             String name = group(6);
             
@@ -93,7 +93,7 @@
             }
             catch (ParseException e)
             {
-            	// intentionally do nothing
+                // intentionally do nothing
             }
 
 
diff --git a/src/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java b/src/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
index 4b42dfe..3ef4dc6 100644
--- a/src/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
+++ b/src/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java
@@ -40,13 +40,13 @@
         "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)";
     
     static final String DEFAULT_DATE_FORMAT 
-		= "MMM d yyyy"; //Nov 9 2001
+        = "MMM d yyyy"; //Nov 9 2001
     
     static final String DEFAULT_RECENT_DATE_FORMAT 
-		= "MMM d HH:mm"; //Nov 9 20:06
+        = "MMM d HH:mm"; //Nov 9 20:06
 
     static final String NUMERIC_DATE_FORMAT 
-		= "yyyy-MM-dd HH:mm"; //2001-11-09 20:06
+        = "yyyy-MM-dd HH:mm"; //2001-11-09 20:06
 
     /**
      * Some Linux distributions are now shipping an FTP server which formats
@@ -97,14 +97,14 @@
           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+"
+           or time (for numeric or recent standard format  
+        */
+        + "(\\d+(?::\\d+)?)\\s+"
         
-		+ "(\\S*)(\\s*.*)";
+        + "(\\S*)(\\s*.*)";
 
 
     /**
@@ -149,7 +149,7 @@
      * @param entry A line of text from the file listing
      * @return An FTPFile instance corresponding to the supplied entry
      */
-	public FTPFile parseFTPEntry(String entry) {
+    public FTPFile parseFTPEntry(String entry) {
         FTPFile file = new FTPFile();
         file.setRawListing(entry);
         int type;
@@ -191,8 +191,8 @@
                 // break; - fall through
             case 'f':
             case '-':
-            	type = FTPFile.FILE_TYPE;
-            	break;
+                type = FTPFile.FILE_TYPE;
+                break;
             default:
                 type = FTPFile.UNKNOWN_TYPE;
             }
@@ -276,7 +276,7 @@
             return file;
         }
         return null;
-	}
+    }
 
     /**
      * Defines a default configuration to be used when this class is
diff --git a/src/java/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java b/src/java/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java
index fd27e88..4c408a1 100644
--- a/src/java/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java
+++ b/src/java/org/apache/commons/net/ftp/parser/VMSFTPEntryParser.java
@@ -51,17 +51,18 @@
 {
 
     private static final String DEFAULT_DATE_FORMAT 
-		= "d-MMM-yyyy HH:mm:ss"; //9-NOV-2001 12:30:24
+        = "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*"
-        + "(\\d+)/\\d+\\s*"
-        +"(\\S+)\\s+(\\S+)\\s+"
-        + "\\[(([0-9$A-Za-z_]+)|([0-9$A-Za-z_]+),([0-9$a-zA-Z_]+))\\]?\\s*"
-        + "\\([a-zA-Z]*,[a-zA-Z]*,[a-zA-Z]*,[a-zA-Z]*\\)";
+        "(.*;[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]* ?
 
 
 
@@ -141,8 +142,12 @@
             f.setRawListing(entry);
             String name = group(1);
             String size = group(2);
-        	String datestr = group(3)+" "+group(4);
+            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));
@@ -197,9 +202,21 @@
             f.setGroup(grp);
             f.setUser(user);
             //set group and owner
-            //Since I don't need the persmissions on this file (RWED), I'll
-            //leave that for further development. 'Cause it will be a bit
-            //elaborate to do it right with VMSes World, Global and so forth.
+
+            //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;
diff --git a/src/java/org/apache/commons/net/nntp/Article.java b/src/java/org/apache/commons/net/nntp/Article.java
index 9c0b09a..e65865a 100644
--- a/src/java/org/apache/commons/net/nntp/Article.java
+++ b/src/java/org/apache/commons/net/nntp/Article.java
@@ -27,227 +27,227 @@
  *
  */
 public class Article implements Threadable {
-	private int articleNumber;
-	private String subject;
-	private String date;
-	private String articleId;
-	private String simplifiedSubject;
-	private String from;
-	private StringBuffer header;
-	private StringBuffer references;
-	private boolean isReply = false;
-	
-	public Article kid, next;
+    private int articleNumber;
+    private String subject;
+    private String date;
+    private String articleId;
+    private String simplifiedSubject;
+    private String from;
+    private StringBuffer header;
+    private StringBuffer references;
+    private boolean isReply = false;
+    
+    public Article kid, next;
 
-	public Article() {
-		header = new StringBuffer();
-	}
+    public Article() {
+        header = new StringBuffer();
+    }
 
-	/**
-	 * Adds an arbitrary header key and value to this message's header.
-	 * @param name the header name
-	 * @param val the header value
-	 */
-	public void addHeaderField(String name, String val) {
-		header.append(name);
-		header.append(": ");
-		header.append(val);
-		header.append('\n');
-	}
-	
-	/**
-	 * Adds a message-id to the list of messages that this message references (i.e. replies to)
-	 * @param msgId
-	 */
-	public void addReference(String msgId) {
-		if (references == null) {
-			references = new StringBuffer();
-			references.append("References: ");
-		}
-		references.append(msgId);
-		references.append("\t");
-	}
+    /**
+     * Adds an arbitrary header key and value to this message's header.
+     * @param name the header name
+     * @param val the header value
+     */
+    public void addHeaderField(String name, String val) {
+        header.append(name);
+        header.append(": ");
+        header.append(val);
+        header.append('\n');
+    }
+    
+    /**
+     * Adds a message-id to the list of messages that this message references (i.e. replies to)
+     * @param msgId
+     */
+    public void addReference(String msgId) {
+        if (references == null) {
+            references = new StringBuffer();
+            references.append("References: ");
+        }
+        references.append(msgId);
+        references.append("\t");
+    }
 
-	/**
-	 * Returns the MessageId references as an array of Strings
-	 * @return an array of message-ids
-	 */
-	public String[] getReferences() {
-		if (references == null)
-			return new String[0];
-		ArrayList list = new ArrayList();
-		int terminator = references.toString().indexOf(':');
-		StringTokenizer st =
-			new StringTokenizer(references.substring(terminator), "\t");
-		while (st.hasMoreTokens()) {
-			list.add(st.nextToken());
-		}
-		return (String[]) list.toArray(new String[list.size()]);
-	}
-	
-	/**
-	 * Attempts to parse the subject line for some typical reply signatures, and strip them out
-	 *
-	 */
-	private void simplifySubject() {
-			int start = 0;
-			String subject = getSubject();
-			int len = subject.length();
+    /**
+     * Returns the MessageId references as an array of Strings
+     * @return an array of message-ids
+     */
+    public String[] getReferences() {
+        if (references == null)
+            return new String[0];
+        ArrayList list = new ArrayList();
+        int terminator = references.toString().indexOf(':');
+        StringTokenizer st =
+            new StringTokenizer(references.substring(terminator), "\t");
+        while (st.hasMoreTokens()) {
+            list.add(st.nextToken());
+        }
+        return (String[]) list.toArray(new String[list.size()]);
+    }
+    
+    /**
+     * Attempts to parse the subject line for some typical reply signatures, and strip them out
+     *
+     */
+    private void simplifySubject() {
+            int start = 0;
+            String subject = getSubject();
+            int len = subject.length();
 
-			boolean done = false;
+            boolean done = false;
 
-			while (!done) {
-				done = true;
+            while (!done) {
+                done = true;
 
-				// skip whitespace
-				// "Re: " breaks this
-				while (start < len && subject.charAt(start) == ' ') {
-					start++;
-				}
+                // skip whitespace
+                // "Re: " breaks this
+                while (start < len && subject.charAt(start) == ' ') {
+                    start++;
+                }
 
-				if (start < (len - 2)
-					&& (subject.charAt(start) == 'r' || subject.charAt(start) == 'R')
-					&& (subject.charAt(start + 1) == 'e' || subject.charAt(start + 1) == 'E')) {
+                if (start < (len - 2)
+                    && (subject.charAt(start) == 'r' || subject.charAt(start) == 'R')
+                    && (subject.charAt(start + 1) == 'e' || subject.charAt(start + 1) == 'E')) {
 
-					if (subject.charAt(start + 2) == ':') {
-						start += 3; // Skip "Re:"
-						isReply = true;
-						done = false;
-					} else if (
-						start < (len - 2) 
-						&& 
-						(subject.charAt(start + 2) == '[' || subject.charAt(start + 2) == '(')) {
-                    	
-						int i = start + 3;
+                    if (subject.charAt(start + 2) == ':') {
+                        start += 3; // Skip "Re:"
+                        isReply = true;
+                        done = false;
+                    } else if (
+                        start < (len - 2) 
+                        && 
+                        (subject.charAt(start + 2) == '[' || subject.charAt(start + 2) == '(')) {
 
-						while (i < len && subject.charAt(i) >= '0' && subject.charAt(i) <= '9')
-							i++;
+                        int i = start + 3;
 
-						if (i < (len - 1)
-							&& (subject.charAt(i) == ']' || subject.charAt(i) == ')')
-							&& subject.charAt(i + 1) == ':') {
-							start = i + 2;
-							isReply = true;
-							done = false;
-						}
-					}
-				}
+                        while (i < len && subject.charAt(i) >= '0' && subject.charAt(i) <= '9')
+                            i++;
 
-				if (simplifiedSubject == "(no subject)")
-					simplifiedSubject = "";
+                        if (i < (len - 1)
+                            && (subject.charAt(i) == ']' || subject.charAt(i) == ')')
+                            && subject.charAt(i + 1) == ':') {
+                            start = i + 2;
+                            isReply = true;
+                            done = false;
+                        }
+                    }
+                }
 
-				int end = len;
+                if (simplifiedSubject == "(no subject)")
+                    simplifiedSubject = "";
 
-				while (end > start && subject.charAt(end - 1) < ' ')
-					end--;
+                int end = len;
 
-				if (start == 0 && end == len)
-					simplifiedSubject = subject;
-				else
-					simplifiedSubject = subject.substring(start, end);
-			}
-		}
-		
-	/**
-	 * Recursive method that traverses a pre-threaded graph (or tree) 
-	 * of connected Article objects and prints them out.  
-	 * @param article the root of the article 'tree'
-	 * @param depth the current tree depth
-	 */
-	public static void printThread(Article article, int depth) {
-			for (int i = 0; i < depth; ++i)
-				System.out.print("==>");
-			System.out.println(article.getSubject() + "\t" + article.getFrom());
-			if (article.kid != null)
-				printThread(article.kid, depth + 1);
-			if (article.next != null)
-				printThread(article.next, depth);
-	}
+                while (end > start && subject.charAt(end - 1) < ' ')
+                    end--;
 
-	public String getArticleId() {
-		return articleId;
-	}
+                if (start == 0 && end == len)
+                    simplifiedSubject = subject;
+                else
+                    simplifiedSubject = subject.substring(start, end);
+            }
+        }
+        
+    /**
+     * Recursive method that traverses a pre-threaded graph (or tree) 
+     * of connected Article objects and prints them out.  
+     * @param article the root of the article 'tree'
+     * @param depth the current tree depth
+     */
+    public static void printThread(Article article, int depth) {
+            for (int i = 0; i < depth; ++i)
+                System.out.print("==>");
+            System.out.println(article.getSubject() + "\t" + article.getFrom());
+            if (article.kid != null)
+                printThread(article.kid, depth + 1);
+            if (article.next != null)
+                printThread(article.next, depth);
+    }
 
-	public int getArticleNumber() {
-		return articleNumber;
-	}
+    public String getArticleId() {
+        return articleId;
+    }
 
-	public String getDate() {
-		return date;
-	}
+    public int getArticleNumber() {
+        return articleNumber;
+    }
 
-	public String getFrom() {
-		return from;
-	}
+    public String getDate() {
+        return date;
+    }
 
-	public String getSubject() {
-		return subject;
-	}
+    public String getFrom() {
+        return from;
+    }
 
-	public void setArticleId(String string) {
-		articleId = string;
-	}
+    public String getSubject() {
+        return subject;
+    }
 
-	public void setArticleNumber(int i) {
-		articleNumber = i;
-	}
+    public void setArticleId(String string) {
+        articleId = string;
+    }
 
-	public void setDate(String string) {
-		date = string;
-	}
+    public void setArticleNumber(int i) {
+        articleNumber = i;
+    }
 
-	public void setFrom(String string) {
-		from = string;
-	}
+    public void setDate(String string) {
+        date = string;
+    }
 
-	public void setSubject(String string) {
-		subject = string;
-	}
+    public void setFrom(String string) {
+        from = string;
+    }
 
-	
-	public boolean isDummy() {
-		return (getSubject() == null);
-	}
+    public void setSubject(String string) {
+        subject = string;
+    }
 
-	public String messageThreadId() {
-		return articleId;
-	}
-	
-	public String[] messageThreadReferences() {
-		return getReferences();
-	}
-	
-	public String simplifiedSubject() {
-		if(simplifiedSubject == null)
-			simplifySubject();
-		return simplifiedSubject;
-	}
+    
+    public boolean isDummy() {
+        return (getSubject() == null);
+    }
 
-	
-	public boolean subjectIsReply() {
-		if(simplifiedSubject == null)
-			simplifySubject();
-		return isReply;
-	}
+    public String messageThreadId() {
+        return articleId;
+    }
+    
+    public String[] messageThreadReferences() {
+        return getReferences();
+    }
+    
+    public String simplifiedSubject() {
+        if(simplifiedSubject == null)
+            simplifySubject();
+        return simplifiedSubject;
+    }
 
-	
-	public void setChild(Threadable child) {
-		this.kid = (Article) child;
-		flushSubjectCache();
-	}
+    
+    public boolean subjectIsReply() {
+        if(simplifiedSubject == null)
+            simplifySubject();
+        return isReply;
+    }
 
-	private void flushSubjectCache() {
-		simplifiedSubject = null;
-	}
+    
+    public void setChild(Threadable child) {
+        this.kid = (Article) child;
+        flushSubjectCache();
+    }
 
-	
-	public void setNext(Threadable next) {
-		this.next = (Article)next;
-		flushSubjectCache();
-	}
+    private void flushSubjectCache() {
+        simplifiedSubject = null;
+    }
 
-	
-	public Threadable makeDummy() {
-		return new Article();
-	}
+    
+    public void setNext(Threadable next) {
+        this.next = (Article)next;
+        flushSubjectCache();
+    }
+
+    
+    public Threadable makeDummy() {
+        return new Article();
+    }
 }
diff --git a/src/java/org/apache/commons/net/nntp/NNTPClient.java b/src/java/org/apache/commons/net/nntp/NNTPClient.java
index 7f25b18..b1e2f21 100644
--- a/src/java/org/apache/commons/net/nntp/NNTPClient.java
+++ b/src/java/org/apache/commons/net/nntp/NNTPClient.java
@@ -195,10 +195,10 @@
             result._setFirstArticle(firstNum);
             result._setLastArticle(lastNum);
 
-	    if((firstNum == 0) && (lastNum == 0))
-		    result._setArticleCount(0);
-	    else
-		    result._setArticleCount(lastNum - firstNum + 1);
+        if((firstNum == 0) && (lastNum == 0))
+            result._setArticleCount(0);
+        else
+            result._setArticleCount(lastNum - firstNum + 1);
         }
         catch (NumberFormatException e)
         {
diff --git a/src/java/org/apache/commons/net/nntp/Threadable.java b/src/java/org/apache/commons/net/nntp/Threadable.java
index acdfe0c..b8e3b6b 100644
--- a/src/java/org/apache/commons/net/nntp/Threadable.java
+++ b/src/java/org/apache/commons/net/nntp/Threadable.java
@@ -22,12 +22,12 @@
  *
  */
 public interface Threadable {
-	public boolean isDummy();
-	public String messageThreadId();
-	public String[] messageThreadReferences();
-	public String simplifiedSubject();
-	public boolean subjectIsReply();
-	public void setChild(Threadable child); 
-	public void setNext(Threadable next);
-	public Threadable makeDummy();
+    public boolean isDummy();
+    public String messageThreadId();
+    public String[] messageThreadReferences();
+    public String simplifiedSubject();
+    public boolean subjectIsReply();
+    public void setChild(Threadable child); 
+    public void setNext(Threadable next);
+    public Threadable makeDummy();
 }
\ No newline at end of file
diff --git a/src/java/org/apache/commons/net/nntp/Threader.java b/src/java/org/apache/commons/net/nntp/Threader.java
index 233118c..0787b0e 100644
--- a/src/java/org/apache/commons/net/nntp/Threader.java
+++ b/src/java/org/apache/commons/net/nntp/Threader.java
@@ -30,374 +30,374 @@
 import java.util.Iterator;
 
 public class Threader {
-	private ThreadContainer root;
-	private HashMap idTable;
-	private int bogusIdCount = 0;
+    private ThreadContainer root;
+    private HashMap idTable;
+    private int bogusIdCount = 0;
 
-	/**
-	 * The main threader entry point - The client passes in an array of Threadable objects, and 
-	 * the Threader constructs a connected 'graph' of messages
-	 * @param messages
-	 * @return
-	 */
-	public Threadable thread(Threadable[] messages) {
-		if (messages == null)
-			return null;
+    /**
+     * The main threader entry point - The client passes in an array of Threadable objects, and 
+     * the Threader constructs a connected 'graph' of messages
+     * @param messages
+     * @return null if messages == null or root.child == null
+     */
+    public Threadable thread(Threadable[] messages) {
+        if (messages == null)
+            return null;
 
-		idTable = new HashMap();
+        idTable = new HashMap();
 
-		// walk through each Threadable element
-		for (int i = 0; i < messages.length; ++i) {
-			if (!messages[i].isDummy())
-				buildContainer(messages[i]);
-		}
+        // walk through each Threadable element
+        for (int i = 0; i < messages.length; ++i) {
+            if (!messages[i].isDummy())
+                buildContainer(messages[i]);
+        }
 
-		root = findRootSet();
-		idTable.clear();
-		idTable = null;
+        root = findRootSet();
+        idTable.clear();
+        idTable = null;
 
-		pruneEmptyContainers(root);
+        pruneEmptyContainers(root);
 
-		root.reverseChildren();
-		gatherSubjects();
+        root.reverseChildren();
+        gatherSubjects();
 
-		if (root.next != null)
-			throw new RuntimeException("root node has a next:" + root);
+        if (root.next != null)
+            throw new RuntimeException("root node has a next:" + root);
 
-		for (ThreadContainer r = root.child; r != null; r = r.next) {
-			if (r.threadable == null)
-				r.threadable = r.child.threadable.makeDummy();
-		}
+        for (ThreadContainer r = root.child; r != null; r = r.next) {
+            if (r.threadable == null)
+                r.threadable = r.child.threadable.makeDummy();
+        }
 
-		Threadable result = (root.child == null ? null : root.child.threadable);
-		root.flush();
-		root = null;
+        Threadable result = (root.child == null ? null : root.child.threadable);
+        root.flush();
+        root = null;
 
-		return result;
-	}
+        return result;
+    }
 
-	/**
-	 * 
-	 * @param threadable
-	 */
-	private void buildContainer(Threadable threadable) {
-		String id = threadable.messageThreadId();
-		ThreadContainer container = (ThreadContainer) idTable.get(id);
+    /**
+     * 
+     * @param threadable
+     */
+    private void buildContainer(Threadable threadable) {
+        String id = threadable.messageThreadId();
+        ThreadContainer container = (ThreadContainer) idTable.get(id);
 
-		// A ThreadContainer exists for this id already. This should be a forward reference, but may 
-		// be a duplicate id, in which case we will need to generate a bogus placeholder id
-		if (container != null) {
-			if (container.threadable != null) { // oops! duplicate ids...
-				id = "<Bogus-id:" + (bogusIdCount++) + ">";
-				container = null;
-			} else {
-				// The container just contained a forward reference to this message, so let's
-				// fill in the threadable field of the container with this message
-				container.threadable = threadable;
-			}
-		}
+        // A ThreadContainer exists for this id already. This should be a forward reference, but may 
+        // be a duplicate id, in which case we will need to generate a bogus placeholder id
+        if (container != null) {
+            if (container.threadable != null) { // oops! duplicate ids...
+                id = "<Bogus-id:" + (bogusIdCount++) + ">";
+                container = null;
+            } else {
+                // The container just contained a forward reference to this message, so let's
+                // fill in the threadable field of the container with this message
+                container.threadable = threadable;
+            }
+        }
 
-		// No container exists for that message Id. Create one and insert it into the hash table.
-		if (container == null) {
-			container = new ThreadContainer();
-			container.threadable = threadable;
-			idTable.put(id, container);
-		}
+        // No container exists for that message Id. Create one and insert it into the hash table.
+        if (container == null) {
+            container = new ThreadContainer();
+            container.threadable = threadable;
+            idTable.put(id, container);
+        }
 
-		// Iterate through all of the references and create ThreadContainers for any references that
-		// don't have them.
-		ThreadContainer parentRef = null;
-		{
-			String[] references = threadable.messageThreadReferences();
-			for (int i = 0; i < references.length; ++i) {
-				String refString = references[i];
-				ThreadContainer ref = (ThreadContainer) idTable.get(refString);
+        // Iterate through all of the references and create ThreadContainers for any references that
+        // don't have them.
+        ThreadContainer parentRef = null;
+        {
+            String[] references = threadable.messageThreadReferences();
+            for (int i = 0; i < references.length; ++i) {
+                String refString = references[i];
+                ThreadContainer ref = (ThreadContainer) idTable.get(refString);
 
-				// if this id doesnt have a container, create one
-				if (ref == null) {
-					ref = new ThreadContainer();
-					idTable.put(refString, ref);
-				}
+                // if this id doesnt have a container, create one
+                if (ref == null) {
+                    ref = new ThreadContainer();
+                    idTable.put(refString, ref);
+                }
 
-				// Link references together in the order they appear in the References: header,
-				// IF they dont have a have a parent already &&
-				// IF it will not cause a circular reference
-				if ((parentRef != null)
-					&& (ref.parent == null)
-					&& (parentRef != ref)
-					&& !(parentRef.findChild(ref))) {
-					// Link ref into the parent's child list
-					ref.parent = parentRef;
-					ref.next = parentRef.child;
-					parentRef.child = ref;
-				}
-				parentRef = ref;
-			}
-		}
+                // Link references together in the order they appear in the References: header,
+                // IF they dont have a have a parent already &&
+                // IF it will not cause a circular reference
+                if ((parentRef != null)
+                    && (ref.parent == null)
+                    && (parentRef != ref)
+                    && !(parentRef.findChild(ref))) {
+                    // Link ref into the parent's child list
+                    ref.parent = parentRef;
+                    ref.next = parentRef.child;
+                    parentRef.child = ref;
+                }
+                parentRef = ref;
+            }
+        }
 
-		// parentRef is now set to the container of the last element in the references field. make that 
-		// be the parent of this container, unless doing so causes a circular reference
-		if (parentRef != null
-			&& (parentRef == container || container.findChild(parentRef)))
-			parentRef = null;
+        // parentRef is now set to the container of the last element in the references field. make that 
+        // be the parent of this container, unless doing so causes a circular reference
+        if (parentRef != null
+            && (parentRef == container || container.findChild(parentRef)))
+            parentRef = null;
 
-		// if it has a parent already, its because we saw this message in a References: field, and presumed
-		// a parent based on the other entries in that field. Now that we have the actual message, we can
-		// throw away the old parent and use this new one
-		if (container.parent != null) {
-			ThreadContainer rest, prev;
+        // if it has a parent already, its because we saw this message in a References: field, and presumed
+        // a parent based on the other entries in that field. Now that we have the actual message, we can
+        // throw away the old parent and use this new one
+        if (container.parent != null) {
+            ThreadContainer rest, prev;
 
-			for (prev = null, rest = container.parent.child;
-				rest != null;
-				prev = rest, rest = rest.next) {
-				if (rest == container)
-					break;
-			}
+            for (prev = null, rest = container.parent.child;
+                rest != null;
+                prev = rest, rest = rest.next) {
+                if (rest == container)
+                    break;
+            }
 
-			if (rest == null) {
-				throw new RuntimeException(
-					"Didnt find "
-						+ container
-						+ " in parent"
-						+ container.parent);
-			}
+            if (rest == null) {
+                throw new RuntimeException(
+                    "Didnt find "
+                        + container
+                        + " in parent"
+                        + container.parent);
+            }
 
-			// Unlink this container from the parent's child list
-			if (prev == null)
-				container.parent.child = container.next;
-			else
-				prev.next = container.next;
+            // Unlink this container from the parent's child list
+            if (prev == null)
+                container.parent.child = container.next;
+            else
+                prev.next = container.next;
 
-			container.next = null;
-			container.parent = null;
-		}
+            container.next = null;
+            container.parent = null;
+        }
 
-		// If we have a parent, link container into the parents child list
-		if (parentRef != null) {
-			container.parent = parentRef;
-			container.next = parentRef.child;
-			parentRef.child = container;
-		}
-	}
+        // If we have a parent, link container into the parents child list
+        if (parentRef != null) {
+            container.parent = parentRef;
+            container.next = parentRef.child;
+            parentRef.child = container;
+        }
+    }
 
-	/**
-	 * Find the root set of all existing ThreadContainers
-	 * @return root the ThreadContainer representing the root node
-	 */
-	private ThreadContainer findRootSet() {
-		ThreadContainer root = new ThreadContainer();
-		Iterator iter = idTable.keySet().iterator();
+    /**
+     * Find the root set of all existing ThreadContainers
+     * @return root the ThreadContainer representing the root node
+     */
+    private ThreadContainer findRootSet() {
+        ThreadContainer root = new ThreadContainer();
+        Iterator iter = idTable.keySet().iterator();
 
-		while (iter.hasNext()) {
-			Object key = iter.next();
-			ThreadContainer c = (ThreadContainer) idTable.get(key);
-			if (c.parent == null) {
-				if (c.next != null)
-					throw new RuntimeException(
-						"c.next is " + c.next.toString());
-				c.next = root.child;
-				root.child = c;
-			}
-		}
-		return root;
-	}
+        while (iter.hasNext()) {
+            Object key = iter.next();
+            ThreadContainer c = (ThreadContainer) idTable.get(key);
+            if (c.parent == null) {
+                if (c.next != null)
+                    throw new RuntimeException(
+                        "c.next is " + c.next.toString());
+                c.next = root.child;
+                root.child = c;
+            }
+        }
+        return root;
+    }
 
-	/**
-	 * Delete any empty or dummy ThreadContainers
-	 * @param parent
-	 */
-	private void pruneEmptyContainers(ThreadContainer parent) {
-		ThreadContainer container, prev, next;
-		for (prev = null, container = parent.child, next = container.next;
-			container != null;
-			prev = container,
-				container = next,
-				next = (container == null ? null : container.next)) {
+    /**
+     * Delete any empty or dummy ThreadContainers
+     * @param parent
+     */
+    private void pruneEmptyContainers(ThreadContainer parent) {
+        ThreadContainer container, prev, next;
+        for (prev = null, container = parent.child, next = container.next;
+            container != null;
+            prev = container,
+                container = next,
+                next = (container == null ? null : container.next)) {
 
-			// Is it empty and without any children? If so,delete it 
-			if (container.threadable == null && container.child == null) {
-				if (prev == null)
-					parent.child = container.next;
-				else
-					prev.next = container.next;
+            // Is it empty and without any children? If so,delete it 
+            if (container.threadable == null && container.child == null) {
+                if (prev == null)
+                    parent.child = container.next;
+                else
+                    prev.next = container.next;
 
-				// Set container to prev so that prev keeps its same value the next time through the loop	
-				container = prev;
-			}
+                // Set container to prev so that prev keeps its same value the next time through the loop
+                container = prev;
+            }
 
-			// Else if empty, with kids, and (not at root or only one kid)
-			else if (
-				container.threadable == null
-					&& container.child != null
-					&& (container.parent != null
-						|| container.child.next == null)) {
-				// We have an invalid/expired message with kids. Promote the kids to this level. 
-				ThreadContainer tail;
-				ThreadContainer kids = container.child;
+            // Else if empty, with kids, and (not at root or only one kid)
+            else if (
+                container.threadable == null
+                    && container.child != null
+                    && (container.parent != null
+                        || container.child.next == null)) {
+                // We have an invalid/expired message with kids. Promote the kids to this level. 
+                ThreadContainer tail;
+                ThreadContainer kids = container.child;
 
-				// Remove this container and replace with 'kids'.
-				if (prev == null)
-					parent.child = kids;
-				else
-					prev.next = kids;
+                // Remove this container and replace with 'kids'.
+                if (prev == null)
+                    parent.child = kids;
+                else
+                    prev.next = kids;
 
-				// Make each child's parent be this level's parent -> i.e. promote the children. Make the last child's next point to this container's next
-				// i.e. splice kids into the list in place of container
-				for (tail = kids; tail.next != null; tail = tail.next)
-					tail.parent = container.parent;
+                // Make each child's parent be this level's parent -> i.e. promote the children. Make the last child's next point to this container's next
+                // i.e. splice kids into the list in place of container
+                for (tail = kids; tail.next != null; tail = tail.next)
+                    tail.parent = container.parent;
 
-				tail.parent = container.parent;
-				tail.next = container.next;
+                tail.parent = container.parent;
+                tail.next = container.next;
 
-				// next currently points to the item after the inserted items in the chain - reset that so we process the newly
-				// promoted items next time round
-				next = kids;
+                // next currently points to the item after the inserted items in the chain - reset that so we process the newly
+                // promoted items next time round
+                next = kids;
 
-				// Set container to prev so that prev keeps its same value the next time through the loop
-				container = prev;
-			} else if (container.child != null) {
-				// A real message , with kids
-				// Iterate over the children
-				pruneEmptyContainers(container);
-			}
-		}
-	}
+                // Set container to prev so that prev keeps its same value the next time through the loop
+                container = prev;
+            } else if (container.child != null) {
+                // A real message , with kids
+                // Iterate over the children
+                pruneEmptyContainers(container);
+            }
+        }
+    }
 
-	/**
-	 *  If any two members of the root set have the same subject, merge them. This is to attempt to accomodate messages without References: headers. 
-	 */
-	private void gatherSubjects() {
+    /**
+     *  If any two members of the root set have the same subject, merge them. This is to attempt to accomodate messages without References: headers. 
+     */
+    private void gatherSubjects() {
 
-		int count = 0;
+        int count = 0;
 
-		for (ThreadContainer c = root.child; c != null; c = c.next)
-			count++;
+        for (ThreadContainer c = root.child; c != null; c = c.next)
+            count++;
 
-		// TODO verify this will avoid rehashing
-		HashMap subjectTable = new HashMap((int) (count * 1.2), (float) 0.9);
-		count = 0;
+        // TODO verify this will avoid rehashing
+        HashMap subjectTable = new HashMap((int) (count * 1.2), (float) 0.9);
+        count = 0;
 
-		for (ThreadContainer c = root.child; c != null; c = c.next) {
-			Threadable threadable = c.threadable;
+        for (ThreadContainer c = root.child; c != null; c = c.next) {
+            Threadable threadable = c.threadable;
 
-			// No threadable? If so, it is a dummy node in the root set.
-			// Only root set members may be dummies, and they alway have at least 2 kids
-			// Take the first kid as representative of the subject
-			if (threadable == null)
-				threadable = c.child.threadable;
+            // No threadable? If so, it is a dummy node in the root set.
+            // Only root set members may be dummies, and they alway have at least 2 kids
+            // Take the first kid as representative of the subject
+            if (threadable == null)
+                threadable = c.child.threadable;
 
-			String subj = threadable.simplifiedSubject();
+            String subj = threadable.simplifiedSubject();
 
-			if (subj == null || subj == "")
-				continue;
+            if (subj == null || subj == "")
+                continue;
 
-			ThreadContainer old = (ThreadContainer) subjectTable.get(subj);
+            ThreadContainer old = (ThreadContainer) subjectTable.get(subj);
 
-			// Add this container to the table iff:
-			// - There exists no container with this subject
-			// - or this is a dummy container and the old one is not - the dummy one is
-			// more interesting as a root, so put it in the table instead
-			// - The container in the table has a "Re:" version of this subject, and 
-			// this container has a non-"Re:" version of this subject. The non-"Re:" version
-			// is the more interesting of the two.
-			if (old == null
-				|| (c.threadable == null && old.threadable != null)
-				|| (old.threadable != null
-					&& old.threadable.subjectIsReply()
-					&& c.threadable != null
-					&& !c.threadable.subjectIsReply())) {
-				subjectTable.put(subj, c);
-				count++;
-			}
-		}
+            // Add this container to the table iff:
+            // - There exists no container with this subject
+            // - or this is a dummy container and the old one is not - the dummy one is
+            // more interesting as a root, so put it in the table instead
+            // - The container in the table has a "Re:" version of this subject, and 
+            // this container has a non-"Re:" version of this subject. The non-"Re:" version
+            // is the more interesting of the two.
+            if (old == null
+                || (c.threadable == null && old.threadable != null)
+                || (old.threadable != null
+                    && old.threadable.subjectIsReply()
+                    && c.threadable != null
+                    && !c.threadable.subjectIsReply())) {
+                subjectTable.put(subj, c);
+                count++;
+            }
+        }
 
-		// If the table is empty, we're done
-		if (count == 0)
-			return;
+        // If the table is empty, we're done
+        if (count == 0)
+            return;
 
-		// subjectTable is now populated with one entry for each subject which occurs in the 
-		// root set. Iterate over the root set, and gather together the difference.
-		ThreadContainer prev, c, rest;
-		for (prev = null, c = root.child, rest = c.next;
-			c != null;
-			prev = c, c = rest, rest = (rest == null ? null : rest.next)) {
-			Threadable threadable = c.threadable;
+        // subjectTable is now populated with one entry for each subject which occurs in the 
+        // root set. Iterate over the root set, and gather together the difference.
+        ThreadContainer prev, c, rest;
+        for (prev = null, c = root.child, rest = c.next;
+            c != null;
+            prev = c, c = rest, rest = (rest == null ? null : rest.next)) {
+            Threadable threadable = c.threadable;
 
-			// is it a dummy node?
-			if (threadable == null)
-				threadable = c.child.threadable;
+            // is it a dummy node?
+            if (threadable == null)
+                threadable = c.child.threadable;
 
-			String subj = threadable.simplifiedSubject();
+            String subj = threadable.simplifiedSubject();
 
-			// Dont thread together all subjectless messages
-			if (subj == null || subj == "")
-				continue;
+            // Dont thread together all subjectless messages
+            if (subj == null || subj == "")
+                continue;
 
-			ThreadContainer old = (ThreadContainer) subjectTable.get(subj);
+            ThreadContainer old = (ThreadContainer) subjectTable.get(subj);
 
-			if (old == c) // That's us
-				continue;
+            if (old == c) // That's us
+                continue;
 
-			// We have now found another container in the root set with the same subject
-			// Remove the "second" message from the root set
-			if (prev == null)
-				root.child = c.next;
-			else
-				prev.next = c.next;
-			c.next = null;
+            // We have now found another container in the root set with the same subject
+            // Remove the "second" message from the root set
+            if (prev == null)
+                root.child = c.next;
+            else
+                prev.next = c.next;
+            c.next = null;
 
-			if (old.threadable == null && c.threadable == null) {
-				// both dummies - merge them
-				ThreadContainer tail;
-				for (tail = old.child;
-					tail != null && tail.next != null;
-					tail = tail.next);
+            if (old.threadable == null && c.threadable == null) {
+                // both dummies - merge them
+                ThreadContainer tail;
+                for (tail = old.child;
+                    tail != null && tail.next != null;
+                    tail = tail.next);
 
-				tail.next = c.child;
+                tail.next = c.child;
 
-				for (tail = c.child; tail != null; tail = tail.next)
-					tail.parent = old;
+                for (tail = c.child; tail != null; tail = tail.next)
+                    tail.parent = old;
 
-				c.child = null;
-			} else if (
-				old.threadable == null
-					|| (c.threadable != null
-						&& c.threadable.subjectIsReply()
-						&& !old.threadable.subjectIsReply())) {
-				// Else if old is empty, or c has "Re:" and old does not  ==> make this message a child of old
-				c.parent = old;
-				c.next = old.child;
-				old.child = c;
-			} else {
-				//	else make the old and new messages be children of a new dummy container.
-				// We create a new container object for old.msg and empty the old container
-				ThreadContainer newc = new ThreadContainer();
-				newc.threadable = old.threadable;
-				newc.child = old.child;
+                c.child = null;
+            } else if (
+                old.threadable == null
+                    || (c.threadable != null
+                        && c.threadable.subjectIsReply()
+                        && !old.threadable.subjectIsReply())) {
+                // Else if old is empty, or c has "Re:" and old does not  ==> make this message a child of old
+                c.parent = old;
+                c.next = old.child;
+                old.child = c;
+            } else {
+                // else make the old and new messages be children of a new dummy container.
+                // We create a new container object for old.msg and empty the old container
+                ThreadContainer newc = new ThreadContainer();
+                newc.threadable = old.threadable;
+                newc.child = old.child;
 
-				for (ThreadContainer tail = newc.child;
-					tail != null;
-					tail = tail.next)
-					tail.parent = newc;
+                for (ThreadContainer tail = newc.child;
+                    tail != null;
+                    tail = tail.next)
+                    tail.parent = newc;
 
-				old.threadable = null;
-				old.child = null;
+                old.threadable = null;
+                old.child = null;
 
-				c.parent = old;
-				newc.parent = old;
+                c.parent = old;
+                newc.parent = old;
 
-				// Old is now a dummy- give it 2 kids , c and newc
-				old.child = c;
-				c.next = newc;
-			}
-			// We've done a merge, so keep the same prev
-			c = prev;
-		}
+                // Old is now a dummy- give it 2 kids , c and newc
+                old.child = c;
+                c.next = newc;
+            }
+            // We've done a merge, so keep the same prev
+            c = prev;
+        }
 
-		subjectTable.clear();
-		subjectTable = null;
+        subjectTable.clear();
+        subjectTable = null;
 
-	}
+    }
 }
 
 /**
@@ -408,73 +408,73 @@
  * @author Rory Winston <rwinston@checkfree.com>
  */
 class ThreadContainer {
-	Threadable threadable;
-	ThreadContainer parent;
-	ThreadContainer prev;
-	ThreadContainer next;
-	ThreadContainer child;
+    Threadable threadable;
+    ThreadContainer parent;
+    ThreadContainer prev;
+    ThreadContainer next;
+    ThreadContainer child;
 
-	/**
-	 * 
-	 * @param container
-	 * @return true if child is under self's tree. Detects circular references
-	 */
-	boolean findChild(ThreadContainer target) {
-		if (child == null)
-			return false;
+    /**
+     * 
+     * @param container
+     * @return true if child is under self's tree. Detects circular references
+     */
+    boolean findChild(ThreadContainer target) {
+        if (child == null)
+            return false;
 
-		else if (child == target)
-			return true;
-		else
-			return child.findChild(target);
-	}
+        else if (child == target)
+            return true;
+        else
+            return child.findChild(target);
+    }
 
-	// Copy the ThreadContainer tree structure down into the underlying Threadable objects
-	// (Make the Threadable tree look like the ThreadContainer tree)
-	void flush() {
-		if (parent != null && threadable == null)
-			throw new RuntimeException("no threadable in " + this.toString());
+    // Copy the ThreadContainer tree structure down into the underlying Threadable objects
+    // (Make the Threadable tree look like the ThreadContainer tree)
+    void flush() {
+        if (parent != null && threadable == null)
+            throw new RuntimeException("no threadable in " + this.toString());
 
-		parent = null;
+        parent = null;
 
-		if (threadable != null)
-			threadable.setChild(child == null ? null : child.threadable);
+        if (threadable != null)
+            threadable.setChild(child == null ? null : child.threadable);
 
-		if (child != null) {
-			child.flush();
-			child = null;
-		}
+        if (child != null) {
+            child.flush();
+            child = null;
+        }
 
-		if (threadable != null)
-			threadable.setNext(next == null ? null : next.threadable);
+        if (threadable != null)
+            threadable.setNext(next == null ? null : next.threadable);
 
-		if (next != null) {
-			next.flush();
-			next = null;
-		}
+        if (next != null) {
+            next.flush();
+            next = null;
+        }
 
-		threadable = null;
-	}
+        threadable = null;
+    }
 
-	/**
-	 * Reverse the entire set of children
-	 *
-	 */
-	void reverseChildren() {
-		if (child != null) {
-			ThreadContainer kid, prev, rest;
-			for (prev = null, kid = child, rest = kid.next;
-				kid != null;
-				prev = kid,
-					kid = rest,
-					rest = (rest == null ? null : rest.next))
-				kid.next = prev;
+    /**
+     * Reverse the entire set of children
+     *
+     */
+    void reverseChildren() {
+        if (child != null) {
+            ThreadContainer kid, prev, rest;
+            for (prev = null, kid = child, rest = kid.next;
+                kid != null;
+                prev = kid,
+                    kid = rest,
+                    rest = (rest == null ? null : rest.next))
+                kid.next = prev;
 
-			child = prev;
+            child = prev;
 
-			// Do it for the kids 
-			for (kid = child; kid != null; kid = kid.next)
-				kid.reverseChildren();
-		}
-	}
+            // Do it for the kids 
+            for (kid = child; kid != null; kid = kid.next)
+                kid.reverseChildren();
+        }
+    }
 }
diff --git a/src/java/org/apache/commons/net/ntp/NtpV3Impl.java b/src/java/org/apache/commons/net/ntp/NtpV3Impl.java
index c59e495..b89dd6a 100644
--- a/src/java/org/apache/commons/net/ntp/NtpV3Impl.java
+++ b/src/java/org/apache/commons/net/ntp/NtpV3Impl.java
@@ -95,10 +95,10 @@
 
     /***
      * 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)
+     *  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.
      */
@@ -507,15 +507,12 @@
      *
      * @return a datagram packet.
      */
-    public DatagramPacket getDatagramPacket()
+    public synchronized DatagramPacket getDatagramPacket()
     {
-        if (dp == null)
-            synchronized(this) {
-                if (dp == null) {
-                    dp = new DatagramPacket(buf, buf.length);
-                    dp.setPort(NTP_PORT);
-                }
-            }
+        if (dp == null) {
+            dp = new DatagramPacket(buf, buf.length);
+            dp.setPort(NTP_PORT);
+        }
         return dp;
     }
 
diff --git a/src/java/org/apache/commons/net/ntp/TimeInfo.java b/src/java/org/apache/commons/net/ntp/TimeInfo.java
index c77ac7f..fd9285f 100644
--- a/src/java/org/apache/commons/net/ntp/TimeInfo.java
+++ b/src/java/org/apache/commons/net/ntp/TimeInfo.java
@@ -153,7 +153,7 @@
          * according to this standard NTP equation:
          *
          * LocalClockOffset = ((ReceiveTimestamp - OriginateTimestamp) +
-         *		        (TransmitTimestamp - DestinationTimestamp)) / 2
+         *                     (TransmitTimestamp - DestinationTimestamp)) / 2
          *
          * equations from RFC-1305 (NTPv3)
          *      roundtrip delay = (t4 - t1) - (t3 - t2)
diff --git a/src/java/org/apache/commons/net/ntp/TimeStamp.java b/src/java/org/apache/commons/net/ntp/TimeStamp.java
index 53581bc..831e0f9 100644
--- a/src/java/org/apache/commons/net/ntp/TimeStamp.java
+++ b/src/java/org/apache/commons/net/ntp/TimeStamp.java
@@ -188,8 +188,8 @@
      */
     public static long getTime(long ntpTimeValue)
     {
-        long seconds = (ntpTimeValue >>> 32) & 0xffffffffL;	// high-order 32-bits
-        long fraction = ntpTimeValue & 0xffffffffL;		// low-order 32-bits
+        long seconds = (ntpTimeValue >>> 32) & 0xffffffffL;     // high-order 32-bits
+        long fraction = ntpTimeValue & 0xffffffffL;             // low-order 32-bits
 
         // Use round-off on fractional part to preserve going to lower precision
         fraction = Math.round(1000D * fraction / 0x100000000L);
@@ -285,7 +285,7 @@
      */
     protected static long toNtpTime(long t)
     {
-        boolean useBase1 = t < msb0baseTime;	// time < Feb-2036
+        boolean useBase1 = t < msb0baseTime;    // time < Feb-2036
         long baseTime;
         if (useBase1) {
             baseTime = t - msb1baseTime; // dates <= Feb-2036
@@ -452,7 +452,7 @@
      *          is numerically less than the TimeStamp argument; and a
      *          value greater than <code>0</code> if this TimeStamp is
      *          numerically greater than the TimeStamp argument
-     *		(signed comparison).
+     *          (signed comparison).
      */
     public int compareTo(TimeStamp anotherTimeStamp)
     {
@@ -469,13 +469,13 @@
      *
      * @param   o the <code>Object</code> to be compared.
      * @return  the value <code>0</code> if the argument is a TimeStamp
-     *		numerically equal to this TimeStamp; a value less than
-     *		<code>0</code> if the argument is a TimeStamp numerically
-     *		greater than this TimeStamp; and a value greater than
-     *		<code>0</code> if the argument is a TimeStamp numerically
-     *		less than this TimeStamp.
+     *      numerically equal to this TimeStamp; a value less than
+     *      <code>0</code> if the argument is a TimeStamp numerically
+     *      greater than this TimeStamp; and a value greater than
+     *      <code>0</code> if the argument is a TimeStamp numerically
+     *      less than this TimeStamp.
      * @exception ClassCastException if the argument is not a
-     *		  <code>TimeStamp</code>.
+     *        <code>TimeStamp</code>.
      * @see     java.lang.Comparable
      */
     public int compareTo(Object o)
diff --git a/src/java/org/apache/commons/net/telnet/Telnet.java b/src/java/org/apache/commons/net/telnet/Telnet.java
index a07b8e7..dfa010c 100644
--- a/src/java/org/apache/commons/net/telnet/Telnet.java
+++ b/src/java/org/apache/commons/net/telnet/Telnet.java
@@ -282,7 +282,7 @@
                     {
                         _sendSubnegotiation(subneg);
                     }
-                    catch (Exception e)
+                    catch (IOException e)
                     {
                         System.err.println(
                             "Exception in option subnegotiation"
@@ -319,7 +319,7 @@
                     {
                         _sendSubnegotiation(subneg);
                     }
-                    catch (Exception e)
+                    catch (IOException e)
                     {
                         System.err.println("Exception in option subnegotiation"
                             + e.getMessage());
@@ -404,13 +404,12 @@
         _options[option] &= ~_REQUESTED_DO_MASK;
     }
 
-    /***
+    /**
      * Processes a DO request.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     * 
      * @param option - option code to be set.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     void _processDo(int option) throws IOException
     {
         if (debugoptions)
@@ -502,13 +501,12 @@
         _setWill(option);
     }
 
-    /***
+    /**
      * Processes a DONT request.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     * 
      * @param option - option code to be set.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     void _processDont(int option) throws IOException
     {
         if (debugoptions)
@@ -556,13 +554,12 @@
     }
 
 
-    /***
+    /**
      * Processes a WILL request.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     * 
      * @param option - option code to be set.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     void _processWill(int option) throws IOException
     {
         if (debugoptions)
@@ -623,13 +620,12 @@
         _setDo(option);
     }
 
-    /***
+    /**
      * Processes a WONT request.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     * 
      * @param option - option code to be set.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     void _processWont(int option) throws IOException
     {
         if (debugoptions)
@@ -679,14 +675,13 @@
     }
 
     /* TERMINAL-TYPE option (start)*/
-    /***
+    /**
      * Processes a suboption negotiation.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     * 
      * @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
     {
@@ -753,13 +748,12 @@
     /* TERMINAL-TYPE option (end)*/
 
     /* open TelnetOptionHandler functionality (start)*/
-    /***
+    /**
      * Manages subnegotiation for Terminal Type.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     *
      * @param subn - subnegotiation data to be sent
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     final synchronized void _sendSubnegotiation(int subn[])
     throws IOException
     {
@@ -808,7 +802,7 @@
                 {
                     aytMonitor.notifyAll();
                 }
-                catch (Exception e)
+                catch (IllegalMonitorStateException e)
                 {
                     System.err.println("Exception notifying:" + e.getMessage());
                 }
@@ -879,13 +873,12 @@
         /* open TelnetOptionHandler functionality (end)*/
     }
 
-    /***
+    /**
      * Sends a DO.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     *
      * @param option - Option code.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     final synchronized void _sendDo(int option)
     throws IOException
     {
@@ -901,13 +894,12 @@
         /* Code Section added for sending the negotiation ASAP (end)*/
     }
 
-    /***
+    /**
      * Requests a DO.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     *
      * @param option - Option code.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     final synchronized void _requestDo(int option)
     throws IOException
     {
@@ -921,13 +913,12 @@
         _sendDo(option);
     }
 
-    /***
+    /**
      * Sends a DONT.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     *
      * @param option - Option code.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     final synchronized void _sendDont(int option)
     throws IOException
     {
@@ -943,13 +934,12 @@
         /* Code Section added for sending the negotiation ASAP (end)*/
     }
 
-    /***
+    /**
      * Requests a DONT.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     *
      * @param option - Option code.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     final synchronized void _requestDont(int option)
     throws IOException
     {
@@ -964,13 +954,12 @@
     }
 
 
-    /***
+    /**
      * Sends a WILL.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     *
      * @param option - Option code.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     final synchronized void _sendWill(int option)
     throws IOException
     {
@@ -986,13 +975,12 @@
         /* Code Section added for sending the negotiation ASAP (end)*/
     }
 
-    /***
+    /**
      * Requests a WILL.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     *
      * @param option - Option code.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     final synchronized void _requestWill(int option)
     throws IOException
     {
@@ -1006,13 +994,12 @@
         _sendWill(option);
     }
 
-    /***
+    /**
      * Sends a WONT.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     *
      * @param option - Option code.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     final synchronized void _sendWont(int option)
     throws IOException
     {
@@ -1028,13 +1015,12 @@
         /* Code Section added for sending the negotiation ASAP (end)*/
     }
 
-    /***
+    /**
      * Requests a WONT.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     *
      * @param option - Option code.
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     final synchronized void _requestWont(int option)
     throws IOException
     {
@@ -1048,13 +1034,12 @@
         _sendWont(option);
     }
 
-    /***
+    /**
      * Sends a byte.
-     * <p>
-     * @throws IOException - Exception in I/O.
-     * <p>
+     *
      * @param b - byte to send
-     ***/
+     * @throws IOException - Exception in I/O.
+     **/
     final synchronized void _sendByte(int b)
     throws IOException
     {
@@ -1067,17 +1052,15 @@
     }
 
     /* Code Section added for supporting AYT (start)*/
-    /***
+    /**
      * Sends an Are You There sequence and waits for the result.
-     * <p>
+     *
+     * @param timeout - Time to wait for a response (millis.)
      * @throws IOException - Exception in I/O.
      * @throws IllegalArgumentException - Illegal argument
      * @throws InterruptedException - Interrupted during wait.
-     * <p>
-     * @param timeout - Time to wait for a response (millis.)
-     * <p>
      * @return true if AYT received a response, false otherwise
-     ***/
+     **/
     final boolean _sendAYT(long timeout)
     throws IOException, IllegalArgumentException, InterruptedException
     {
@@ -1117,13 +1100,12 @@
 
     /* open TelnetOptionHandler functionality (start)*/
 
-    /***
+    /**
      * Registers a new TelnetOptionHandler for this telnet  to use.
-     * <p>
-     * @throws InvalidTelnetOptionException - The option code is invalid.
-     * <p>
+     *
      * @param opthand - option handler to be registered.
-     ***/
+     * @throws InvalidTelnetOptionException - The option code is invalid.
+     **/
     void addOptionHandler(TelnetOptionHandler opthand)
     throws InvalidTelnetOptionException
     {
@@ -1177,13 +1159,12 @@
         }
     }
 
-    /***
+    /**
      * Unregisters a  TelnetOptionHandler.
-     * <p>
-     * @throws InvalidTelnetOptionException - The option code is invalid.
-     * <p>
+     *
      * @param optcode - Code of the option to be unregistered.
-     ***/
+     * @throws InvalidTelnetOptionException - The option code is invalid.
+     **/
     void deleteOptionHandler(int optcode)
     throws InvalidTelnetOptionException
     {
@@ -1269,17 +1250,17 @@
         {
             try
             {
-                if (ch != (int) '\r')
+                if (ch != '\r')
                 {
                     spyStream.write(ch);
-                    if (ch == (int) '\n')
+                    if (ch == '\n')
                     {
-                        spyStream.write((int) '\r');
+                        spyStream.write('\r');
                     }
                     spyStream.flush();
                 }
             }
-            catch (Exception e)
+            catch (IOException e)
             {
                 spyStream = null;
             }
@@ -1303,7 +1284,7 @@
                     spyStream.write(ch);
                     spyStream.flush();
                 }
-                catch (Exception e)
+                catch (IOException e)
                 {
                     spyStream = null;
                 }
diff --git a/src/java/org/apache/commons/net/telnet/TelnetClient.java b/src/java/org/apache/commons/net/telnet/TelnetClient.java
index e0015df..dc3a61a 100644
--- a/src/java/org/apache/commons/net/telnet/TelnetClient.java
+++ b/src/java/org/apache/commons/net/telnet/TelnetClient.java
@@ -75,11 +75,11 @@
 
     void _flushOutputStream() throws IOException
     {
-        _output_.flush();
+        if(_output_ != null) _output_.flush();
     }
     void _closeOutputStream() throws IOException
     {
-        _output_.close();
+    	if(_output_ != null) _output_.close();
     }
 
     /***
@@ -123,8 +123,8 @@
      ***/
     public void disconnect() throws IOException
     {
-        __input.close();
-        __output.close();
+        if(__input != null) __input.close();
+        if(__output != null) __output.close();
         super.disconnect();
     }
 
@@ -186,13 +186,13 @@
     /***
      * Sends an Are You There sequence and waits for the result.
      * <p>
-     * @throws InterruptedException
-     * @throws IllegalArgumentException
-     * @throws IOException
-     * <p>
      * @param timeout - Time to wait for a response (millis.)
      * <p>
      * @return true if AYT received a response, false otherwise
+     * <p>
+     * @throws InterruptedException
+     * @throws IllegalArgumentException
+     * @throws IOException
      ***/
     public boolean sendAYT(long timeout)
     throws IOException, IllegalArgumentException, InterruptedException
@@ -206,9 +206,9 @@
     /***
      * Registers a new TelnetOptionHandler for this telnet client to use.
      * <p>
-     * @throws InvalidTelnetOptionException
-     * <p>
      * @param opthand - option handler to be registered.
+     * <p>
+     * @throws InvalidTelnetOptionException
      ***/
     public void addOptionHandler(TelnetOptionHandler opthand)
     throws InvalidTelnetOptionException
@@ -220,9 +220,9 @@
     /***
      * Unregisters a  TelnetOptionHandler.
      * <p>
-     * @throws InvalidTelnetOptionException
-     * <p>
      * @param optcode - Code of the option to be unregistered.
+     * <p>
+     * @throws InvalidTelnetOptionException
      ***/
     public void deleteOptionHandler(int optcode)
     throws InvalidTelnetOptionException
diff --git a/src/java/org/apache/commons/net/telnet/TelnetInputStream.java b/src/java/org/apache/commons/net/telnet/TelnetInputStream.java
index 522c94d..562d93e 100644
--- a/src/java/org/apache/commons/net/telnet/TelnetInputStream.java
+++ b/src/java/org/apache/commons/net/telnet/TelnetInputStream.java
@@ -115,7 +115,7 @@
             // 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;
@@ -355,7 +355,7 @@
                         }
                         catch (InterruptedException e)
                         {
-                            throw new IOException("Fatal thread interruption during read.");
+                            throw new InterruptedIOException("Fatal thread interruption during read.");
                         }
                     }
                     else
@@ -363,7 +363,7 @@
                         //__alreadyread = false;
                         __readIsWaiting = true;
                         int ch;
-                        boolean mayBlock = true;	// block on the first read only
+                        boolean mayBlock = true;    // block on the first read only
                         
                         do
                         {
@@ -427,11 +427,11 @@
 
                     --__bytesAvailable;
 
-		    // Need to explicitly notify() so available() works properly
-		    if(__bytesAvailable == 0 && __threaded) {
-			    __queue.notify();
-		    }
-		    
+            // Need to explicitly notify() so available() works properly
+            if(__bytesAvailable == 0 && __threaded) {
+                __queue.notify();
+            }
+            
                     return ch;
                 }
             }
diff --git a/src/java/org/apache/commons/net/tftp/TFTPClient.java b/src/java/org/apache/commons/net/tftp/TFTPClient.java
index edd8c0a..c036805 100644
--- a/src/java/org/apache/commons/net/tftp/TFTPClient.java
+++ b/src/java/org/apache/commons/net/tftp/TFTPClient.java
@@ -233,10 +233,10 @@
                             }
                             ++block;
                             if (block > 65535)
-							{
-								// wrap the block number
-								block = 0;
-							}
+                            {
+                                // wrap the block number
+                                block = 0;
+                            }
                             
                             break _receivePacket;
                         }
@@ -372,7 +372,6 @@
         TFTPErrorPacket error;
         TFTPDataPacket data =
             new TFTPDataPacket(host, port, 0, _sendBuffer, 4, 0);
-        ;
         TFTPAckPacket ack;
 
         boolean justStarted = true;
@@ -472,10 +471,10 @@
                         {
                             ++block;
                             if (block > 65535)
-							{
-								// wrap the block number
-								block = 0;
-							}
+                            {
+                                // wrap the block number
+                                block = 0;
+                            }
                             if (lastAckWait) {
                                 
                               break _sendPacket;
diff --git a/src/java/org/apache/commons/net/tftp/TFTPRequestPacket.java b/src/java/org/apache/commons/net/tftp/TFTPRequestPacket.java
index 84e88b0..551d045 100644
--- a/src/java/org/apache/commons/net/tftp/TFTPRequestPacket.java
+++ b/src/java/org/apache/commons/net/tftp/TFTPRequestPacket.java
@@ -143,7 +143,7 @@
             ++index;
         }
 
-        mode = buffer.toString().toLowerCase();
+        mode = buffer.toString().toLowerCase(java.util.Locale.ENGLISH);
         length = _modeStrings.length;
 
         for (index = 0; index < length; index++)
diff --git a/src/test/org/apache/commons/net/ftp/FTPClientConfigFunctionalTest.java b/src/test/org/apache/commons/net/ftp/FTPClientConfigFunctionalTest.java
index 207d6c7..2281740 100644
--- a/src/test/org/apache/commons/net/ftp/FTPClientConfigFunctionalTest.java
+++ b/src/test/org/apache/commons/net/ftp/FTPClientConfigFunctionalTest.java
@@ -60,16 +60,16 @@
     public FTPClientConfigFunctionalTest() {
         super();
 
-	}
+    }
 
     /* 
      * @throws java.lang.Exception
      */
     protected void setUp() throws Exception {
         super.setUp();
-	    FTPConf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
-	    FTPConf.setServerTimeZoneId("GMT"); 
-	    FTP.configure(FTPConf); 
+        FTPConf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
+        FTPConf.setServerTimeZoneId("GMT"); 
+        FTP.configure(FTPConf); 
         try {
             FTP.connect("tgftp.nws.noaa.gov");
             FTP.login("anonymous","testing@apache.org");
@@ -95,7 +95,7 @@
         super(arg0);
     }
 
-	
+    
     private TreeSet getSortedList(FTPFile[] files) {
         // create a TreeSet which will sort each element
         // as it is added.
@@ -111,10 +111,10 @@
         
          
         for (int i=0; i < files.length; i++) {
-			// The directory contains a few additional files at the beginning
-			// which aren't in the series we want. The series we want consists
-			// of files named sn.dddd. This adjusts the file list to get rid 
-			// of the uninteresting ones. 
+            // The directory contains a few additional files at the beginning
+            // which aren't in the series we want. The series we want consists
+            // of files named sn.dddd. This adjusts the file list to get rid 
+            // of the uninteresting ones. 
             if (files[i].getName().startsWith("sn")) {
                 sorted.add(files[i]);
             }    
@@ -122,7 +122,7 @@
         return sorted;
     }
 
-	
+    
     public static void main(String[] args) {
         FTPClientConfigFunctionalTest F = new FTPClientConfigFunctionalTest();
     }
diff --git a/src/test/org/apache/commons/net/ftp/FTPClientConfigTest.java b/src/test/org/apache/commons/net/ftp/FTPClientConfigTest.java
index 7de9721..351d7c0 100644
--- a/src/test/org/apache/commons/net/ftp/FTPClientConfigTest.java
+++ b/src/test/org/apache/commons/net/ftp/FTPClientConfigTest.java
@@ -111,17 +111,17 @@
         Date d2 = null;
         Date d3 = null;
         try {
-	        d1 = sdf1.parse("31 d\u00e9c 2004");
+            d1 = sdf1.parse("31 d\u00e9c 2004");
         } catch (ParseException px) {
             fail("failed.to.parse.french");
         }
         try {
-	        d2 = sdf2.parse("dhj 31, 2004");
+            d2 = sdf2.parse("dhj 31, 2004");
         } catch (ParseException px) {
             fail("failed.to.parse.albanian");
         }
         try {
-	        d3 = sdf3.parse("DEC 31, 2004");
+            d3 = sdf3.parse("DEC 31, 2004");
         } catch (ParseException px) {
             fail("failed.to.parse.'russian'");
         }
@@ -163,12 +163,12 @@
         Date d1 = null;
         Date d2 = null;
         try {
-	        d1 = sdf1.parse("dec 31, 2004");
+            d1 = sdf1.parse("dec 31, 2004");
         } catch (ParseException px) {
             fail("failed.to.parse.std");
         }
         try {
-	        d2 = sdf2.parse("hij 31, 2004");
+            d2 = sdf2.parse("hij 31, 2004");
         } catch (ParseException px) {
             fail("failed.to.parse.weird");
         }
@@ -176,12 +176,12 @@
         assertEquals("different.parser.same.date",d1, d2);
         
         try {
-	        d2 = sdf1.parse("hij 31, 2004");
+            d2 = sdf1.parse("hij 31, 2004");
             fail("should.have.failed.to.parse.weird");
         } catch (ParseException px) {
         }
         try {
-	        d2 = sdf2.parse("dec 31, 2004");
+            d2 = sdf2.parse("dec 31, 2004");
             fail("should.have.failed.to.parse.standard");
         } catch (ParseException px) {
         }
diff --git a/src/test/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.java b/src/test/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.java
index 6a9aa64..98b626c 100644
--- a/src/test/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.java
+++ b/src/test/org/apache/commons/net/ftp/parser/DefaultFTPFileEntryParserFactoryTest.java
@@ -62,6 +62,15 @@
         parser = factory.createFileEntryParser("OS/400");
         assertTrue(parser instanceof CompositeFileEntryParser);
 
+        parser = factory.createFileEntryParser("AS/400");
+        assertTrue(parser instanceof CompositeFileEntryParser);
+
+        // Added test to make sure it handles the Unix systems that were
+        // compiled with OS as "UNKNOWN". This test validates that the
+        // check is case-insensitive.
+        parser = factory.createFileEntryParser("UNKNOWN Type: L8");
+
+
         try {
             parser = factory.createFileEntryParser("OS2FTPFileEntryParser");
             fail("Exception should have been thrown. \"OS2FTPFileEntryParser\" is not a recognized key");
diff --git a/src/test/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java b/src/test/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java
index c679c95..7e11c64 100644
--- a/src/test/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java
+++ b/src/test/org/apache/commons/net/ftp/parser/EnterpriseUnixFTPEntryParserTest.java
@@ -60,7 +60,7 @@
     private static final String[] GOODSAMPLES =
     {
         "-C--E-----FTP B QUA1I1      18128       41 Aug 12 13:56 QUADTEST",
-		"-C--E-----FTP A QUA1I1      18128       41 Aug 12 13:56 QUADTEST2"
+        "-C--E-----FTP A QUA1I1      18128       41 Aug 12 13:56 QUADTEST2"
     };
 
     /**
@@ -106,7 +106,7 @@
         assertEquals("QUADTEST",
                      file.getName());
         assertEquals(5000000000L, 
-        			 file.getSize());
+                    file.getSize());
         assertEquals("QUA1I1",
                      file.getUser());
         assertEquals("18128",
diff --git a/src/test/org/apache/commons/net/ftp/parser/FTPConfigEntryParserTest.java b/src/test/org/apache/commons/net/ftp/parser/FTPConfigEntryParserTest.java
index 600183a..8bd2896 100644
--- a/src/test/org/apache/commons/net/ftp/parser/FTPConfigEntryParserTest.java
+++ b/src/test/org/apache/commons/net/ftp/parser/FTPConfigEntryParserTest.java
@@ -35,130 +35,130 @@
  *  @version $Id$
  */
 public class FTPConfigEntryParserTest extends TestCase {
-	
-	private SimpleDateFormat df = new SimpleDateFormat();
+    
+    private SimpleDateFormat df = new SimpleDateFormat();
 
-	public void testParseFieldsOnAIX() {
-		
-		// Set a date format for this server type
-		FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
-		config.setDefaultDateFormatStr("dd MMM HH:mm");
+    public void testParseFieldsOnAIX() {
+        
+        // Set a date format for this server type
+        FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
+        config.setDefaultDateFormatStr("dd MMM HH:mm");
 
-		UnixFTPEntryParser parser = new UnixFTPEntryParser();
-		parser.configure(config);
+        UnixFTPEntryParser parser = new UnixFTPEntryParser();
+        parser.configure(config);
 
-		FTPFile f = parser.parseFTPEntry("-rw-r-----   1 ravensm  sca          814 02 Mar 16:27 ZMIR2.m");
+        FTPFile f = parser.parseFTPEntry("-rw-r-----   1 ravensm  sca          814 02 Mar 16:27 ZMIR2.m");
 
-		assertNotNull("Could not parse entry.", f);
-		assertFalse("Is not a directory.", f.isDirectory());
+        assertNotNull("Could not parse entry.", f);
+        assertFalse("Is not a directory.", f.isDirectory());
 
-		assertTrue("Should have user read permission.", f.hasPermission(
-				FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION));
-		assertTrue("Should have user write permission.", f.hasPermission(
-				FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION));
-		assertFalse("Should NOT have user execute permission.", f
-				.hasPermission(FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION));
-		assertTrue("Should have group read permission.", f.hasPermission(
-				FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION));
-		assertFalse("Should NOT have group write permission.", f
-				.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION));
-		assertFalse("Should NOT have group execute permission.",
-				f.hasPermission(FTPFile.GROUP_ACCESS,
-						FTPFile.EXECUTE_PERMISSION));
-		assertFalse("Should NOT have world read permission.", f.hasPermission(
-				FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION));
-		assertFalse("Should NOT have world write permission.", f
-				.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION));
-		assertFalse("Should NOT have world execute permission.",
-				f.hasPermission(FTPFile.WORLD_ACCESS,
-						FTPFile.EXECUTE_PERMISSION));
+        assertTrue("Should have user read permission.", f.hasPermission(
+                FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION));
+        assertTrue("Should have user write permission.", f.hasPermission(
+                FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION));
+        assertFalse("Should NOT have user execute permission.", f
+                .hasPermission(FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION));
+        assertTrue("Should have group read permission.", f.hasPermission(
+                FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION));
+        assertFalse("Should NOT have group write permission.", f
+                .hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION));
+        assertFalse("Should NOT have group execute permission.",
+                f.hasPermission(FTPFile.GROUP_ACCESS,
+                        FTPFile.EXECUTE_PERMISSION));
+        assertFalse("Should NOT have world read permission.", f.hasPermission(
+                FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION));
+        assertFalse("Should NOT have world write permission.", f
+                .hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION));
+        assertFalse("Should NOT have world execute permission.",
+                f.hasPermission(FTPFile.WORLD_ACCESS,
+                        FTPFile.EXECUTE_PERMISSION));
 
-		assertEquals(1, f.getHardLinkCount());
+        assertEquals(1, f.getHardLinkCount());
 
-		assertEquals("ravensm", f.getUser());
-		assertEquals("sca", f.getGroup());
+        assertEquals("ravensm", f.getUser());
+        assertEquals("sca", f.getGroup());
 
-		assertEquals("ZMIR2.m", f.getName());
-		assertEquals(814, f.getSize());
+        assertEquals("ZMIR2.m", f.getName());
+        assertEquals(814, f.getSize());
 
-		Calendar cal = Calendar.getInstance();
-		
-		Date refDate = new Date();
-		
-		cal.set(Calendar.MONTH, Calendar.MARCH);
-		cal.set(Calendar.DATE, 2);
-		cal.set(Calendar.HOUR_OF_DAY, 16);
-		cal.set(Calendar.MINUTE, 27);
-		cal.set(Calendar.SECOND, 0);
-		
-		// With no year specified, it defaults to 1970
-		// TODO this is probably a bug - it should default to the current year
-		cal.set(Calendar.YEAR, 1970);
-		
-		assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp()
-				.getTime()));
-	}
-	
-	/**
-	 * This is a new format reported on the mailing lists. Parsing this kind of 
-	 * entry necessitated changing the regex in the parser.
-	 *
-	 */
-	public void testParseEntryWithSymlink() {
-		
-		FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
-		config.setDefaultDateFormatStr("yyyy-MM-dd HH:mm");
+        Calendar cal = Calendar.getInstance();
+        
+        Date refDate = new Date();
+        
+        cal.set(Calendar.MONTH, Calendar.MARCH);
+        cal.set(Calendar.DATE, 2);
+        cal.set(Calendar.HOUR_OF_DAY, 16);
+        cal.set(Calendar.MINUTE, 27);
+        cal.set(Calendar.SECOND, 0);
+        
+        // With no year specified, it defaults to 1970
+        // TODO this is probably a bug - it should default to the current year
+        cal.set(Calendar.YEAR, 1970);
+        
+        assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp()
+                .getTime()));
+    }
+    
+    /**
+     * This is a new format reported on the mailing lists. Parsing this kind of 
+     * entry necessitated changing the regex in the parser.
+     *
+     */
+    public void testParseEntryWithSymlink() {
+        
+        FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
+        config.setDefaultDateFormatStr("yyyy-MM-dd HH:mm");
 
-		UnixFTPEntryParser parser = new UnixFTPEntryParser();
-		parser.configure(config);
+        UnixFTPEntryParser parser = new UnixFTPEntryParser();
+        parser.configure(config);
 
-		FTPFile f = parser.parseFTPEntry("lrwxrwxrwx   1 neeme neeme    23 2005-03-02 18:06 macros");
+        FTPFile f = parser.parseFTPEntry("lrwxrwxrwx   1 neeme neeme    23 2005-03-02 18:06 macros");
 
-		assertNotNull("Could not parse entry.", f);
-		assertFalse("Is not a directory.", f.isDirectory());
-		assertTrue("Is a symbolic link", f.isSymbolicLink());
+        assertNotNull("Could not parse entry.", f);
+        assertFalse("Is not a directory.", f.isDirectory());
+        assertTrue("Is a symbolic link", f.isSymbolicLink());
 
-		assertTrue("Should have user read permission.", f.hasPermission(
-				FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION));
-		assertTrue("Should have user write permission.", f.hasPermission(
-				FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION));
-		assertTrue("Should have user execute permission.", f
-				.hasPermission(FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION));
-		assertTrue("Should have group read permission.", f.hasPermission(
-				FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION));
-		assertTrue("Should have group write permission.", f
-				.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION));
-		assertTrue("Should have group execute permission.",
-				f.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION));
-		assertTrue("Should have world read permission.", f.hasPermission(
-				FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION));
-		assertTrue("Should have world write permission.", f
-				.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION));
-		assertTrue("Should have world execute permission.",
-				f.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION));
+        assertTrue("Should have user read permission.", f.hasPermission(
+                FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION));
+        assertTrue("Should have user write permission.", f.hasPermission(
+                FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION));
+        assertTrue("Should have user execute permission.", f
+                .hasPermission(FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION));
+        assertTrue("Should have group read permission.", f.hasPermission(
+                FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION));
+        assertTrue("Should have group write permission.", f
+                .hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION));
+        assertTrue("Should have group execute permission.",
+                f.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION));
+        assertTrue("Should have world read permission.", f.hasPermission(
+                FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION));
+        assertTrue("Should have world write permission.", f
+                .hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION));
+        assertTrue("Should have world execute permission.",
+                f.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION));
 
-		assertEquals(1, f.getHardLinkCount());
+        assertEquals(1, f.getHardLinkCount());
 
-		assertEquals("neeme", f.getUser());
-		assertEquals("neeme", f.getGroup());
+        assertEquals("neeme", f.getUser());
+        assertEquals("neeme", f.getGroup());
 
-		assertEquals("macros", f.getName());
-		assertEquals(23, f.getSize());
+        assertEquals("macros", f.getName());
+        assertEquals(23, f.getSize());
 
-		Calendar cal = Calendar.getInstance();
-		
-		Date refDate = new Date();
-		
-		cal.set(Calendar.MONTH, Calendar.MARCH);
-		cal.set(Calendar.DATE, 2);
-		cal.set(Calendar.HOUR_OF_DAY, 18);
-		cal.set(Calendar.MINUTE, 06);
-		cal.set(Calendar.SECOND, 0);
-		cal.set(Calendar.YEAR, 2005);
-			
-		assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp()
-				.getTime()));
-		
-	}
+        Calendar cal = Calendar.getInstance();
+        
+        Date refDate = new Date();
+        
+        cal.set(Calendar.MONTH, Calendar.MARCH);
+        cal.set(Calendar.DATE, 2);
+        cal.set(Calendar.HOUR_OF_DAY, 18);
+        cal.set(Calendar.MINUTE, 06);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.YEAR, 2005);
+            
+        assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp()
+                .getTime()));
+        
+    }
 
 }
diff --git a/src/test/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java b/src/test/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java
index ce0ad05..779f591 100644
--- a/src/test/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java
+++ b/src/test/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java
@@ -36,198 +36,209 @@
  *
  */
 public class FTPTimestampParserImplTest extends TestCase {
-	
-	private static final int TWO_HOURS_OF_MILLISECONDS = 2 * 60 * 60 * 1000;
+    
+    private static final int TWO_HOURS_OF_MILLISECONDS = 2 * 60 * 60 * 1000;
 
-	public void testParseTimestamp() {
-		Calendar cal = Calendar.getInstance();
-		cal.add(Calendar.HOUR_OF_DAY, 1);
-		cal.set(Calendar.SECOND,0);
-		cal.set(Calendar.MILLISECOND,0);
-		Date anHourFromNow = cal.getTime();
-		FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
-		SimpleDateFormat sdf = 
-			new SimpleDateFormat(parser.getRecentDateFormatString());
-		String fmtTime = sdf.format(anHourFromNow);
-		try {
-			Calendar parsed = parser.parseTimestamp(fmtTime);
-			// since the timestamp is ahead of now (by one hour),
-			// this must mean the file's date refers to a year ago.
-			assertEquals("test.roll.back.year", 1, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR));
-		} catch (ParseException e) {
-			fail("Unable to parse");
-		}
-	}
-		
-	public void testParseTimestampWithSlop() {
-		Calendar cal = Calendar.getInstance();
-		cal.add(Calendar.HOUR_OF_DAY, 1);
-		cal.set(Calendar.SECOND,0);
-		cal.set(Calendar.MILLISECOND,0);
-		Date anHourFromNow = cal.getTime();
-		cal.add(Calendar.DATE, 1);
-		Date anHourFromNowTomorrow = cal.getTime();
-		cal.add(Calendar.DATE, -1);
+    public void testParseTimestamp() {
+        Calendar cal = Calendar.getInstance();
+        cal.add(Calendar.HOUR_OF_DAY, 1);
+        cal.set(Calendar.SECOND,0);
+        cal.set(Calendar.MILLISECOND,0);
+        Date anHourFromNow = cal.getTime();
+        FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
+        SimpleDateFormat sdf = 
+            new SimpleDateFormat(parser.getRecentDateFormatString());
+        String fmtTime = sdf.format(anHourFromNow);
+        try {
+            Calendar parsed = parser.parseTimestamp(fmtTime);
+            // since the timestamp is ahead of now (by one hour),
+            // this must mean the file's date refers to a year ago.
+            assertEquals("test.roll.back.year", 1, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR));
+        } catch (ParseException e) {
+            fail("Unable to parse");
+        }
+    }
+        
+    public void testParseTimestampWithSlop() {
+        Calendar cal = Calendar.getInstance();
+        cal.add(Calendar.HOUR_OF_DAY, 1);
+        cal.set(Calendar.SECOND,0);
+        cal.set(Calendar.MILLISECOND,0);
+        Date anHourFromNow = cal.getTime();
+        cal.add(Calendar.DATE, 1);
+        Date anHourFromNowTomorrow = cal.getTime();
+        cal.add(Calendar.DATE, -1);
 
-		FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
-		
-		// set the "slop" factor on
-		parser.setLenientFutureDates(true);
-		
-		SimpleDateFormat sdf = 
-			new SimpleDateFormat(parser.getRecentDateFormatString());
-		try {
-			String fmtTime = sdf.format(anHourFromNow);
-			Calendar parsed = parser.parseTimestamp(fmtTime);
-			// the timestamp is ahead of now (by one hour), but
-			// that's within range of the "slop" factor.
-			// so the date is still considered this year.
-			assertEquals("test.slop.no.roll.back.year", 0, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR));
+        FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
+        
+        // set the "slop" factor on
+        parser.setLenientFutureDates(true);
+        
+        SimpleDateFormat sdf = 
+            new SimpleDateFormat(parser.getRecentDateFormatString());
+        try {
+            String fmtTime = sdf.format(anHourFromNow);
+            Calendar parsed = parser.parseTimestamp(fmtTime);
+            // the timestamp is ahead of now (by one hour), but
+            // that's within range of the "slop" factor.
+            // so the date is still considered this year.
+            assertEquals("test.slop.no.roll.back.year", 0, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR));
 
-			// add a day to get beyond the range of the slop factor. 
-			// this must mean the file's date refers to a year ago.
-			fmtTime = sdf.format(anHourFromNowTomorrow);
-			parsed = parser.parseTimestamp(fmtTime);
-			assertEquals("test.slop.roll.back.year", 1, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR));
-			
-		} catch (ParseException e) {
-			fail("Unable to parse");
-		}
-	}
+            // add a day to get beyond the range of the slop factor. 
+            // this must mean the file's date refers to a year ago.
+            fmtTime = sdf.format(anHourFromNowTomorrow);
+            parsed = parser.parseTimestamp(fmtTime);
+            assertEquals("test.slop.roll.back.year", 1, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR));
+            
+        } catch (ParseException e) {
+            fail("Unable to parse");
+        }
+    }
 
-	public void testParseTimestampAcrossTimeZones() {
-	    
-	    
-	    Calendar cal = Calendar.getInstance();
-		cal.set(Calendar.SECOND,0);
-		cal.set(Calendar.MILLISECOND,0);
+    public void testParseTimestampAcrossTimeZones() {
+        
+        
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.SECOND,0);
+        cal.set(Calendar.MILLISECOND,0);
 
-		cal.add(Calendar.HOUR_OF_DAY, 1);
-		Date anHourFromNow = cal.getTime();
-		
-		cal.add(Calendar.HOUR_OF_DAY, 2);
-		Date threeHoursFromNow = cal.getTime();
-		cal.add(Calendar.HOUR_OF_DAY, -2);
-		
-		FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
+        cal.add(Calendar.HOUR_OF_DAY, 1);
+        Date anHourFromNow = cal.getTime();
+        
+        cal.add(Calendar.HOUR_OF_DAY, 2);
+        Date threeHoursFromNow = cal.getTime();
+        cal.add(Calendar.HOUR_OF_DAY, -2);
+        
+        FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
 
-		// assume we are FTPing a server in Chicago, two hours ahead of 
-		// L. A.
-		FTPClientConfig config = 
-		    new FTPClientConfig(FTPClientConfig.SYST_UNIX);
-		config.setDefaultDateFormatStr(FTPTimestampParser.DEFAULT_SDF);
-		config.setRecentDateFormatStr(FTPTimestampParser.DEFAULT_RECENT_SDF);
-	    // 2 hours difference
-		config.setServerTimeZoneId("America/Chicago");
-		parser.configure(config);
-		
-		SimpleDateFormat sdf = (SimpleDateFormat)
-			parser.getRecentDateFormat().clone();
-		
-	    // assume we're in the US Pacific Time Zone
-	    TimeZone tzla = TimeZone.getTimeZone("America/Los_Angeles");
-		sdf.setTimeZone(tzla);
-		
-		// get formatted versions of time in L.A. 
-		String fmtTimePlusOneHour = sdf.format(anHourFromNow);
-		String fmtTimePlusThreeHours = sdf.format(threeHoursFromNow);
-		
-		
-		try {
-			Calendar parsed = parser.parseTimestamp(fmtTimePlusOneHour);
-			// the only difference should be the two hours
-			// difference, no rolling back a year should occur.
-			assertEquals("no.rollback.because.of.time.zones",
-				(long)TWO_HOURS_OF_MILLISECONDS, 
-				cal.getTime().getTime() - parsed.getTime().getTime());
-		} catch (ParseException e){
-			fail("Unable to parse " + fmtTimePlusOneHour);
-		}
-		
-		//but if the file's timestamp is THREE hours ahead of now, that should 
-		//cause a rollover even taking the time zone difference into account.
-		//Since that time is still later than ours, it is parsed as occurring
-		//on this date last year.
-		try {
-			Calendar parsed = parser.parseTimestamp(fmtTimePlusThreeHours);
-			// rollback should occur here.
-			assertEquals("rollback.even.with.time.zones", 
-					1, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR));
-		} catch (ParseException e){
-			fail("Unable to parse" + fmtTimePlusThreeHours);
-		}
-	}
+        // assume we are FTPing a server in Chicago, two hours ahead of 
+        // L. A.
+        FTPClientConfig config = 
+            new FTPClientConfig(FTPClientConfig.SYST_UNIX);
+        config.setDefaultDateFormatStr(FTPTimestampParser.DEFAULT_SDF);
+        config.setRecentDateFormatStr(FTPTimestampParser.DEFAULT_RECENT_SDF);
+        // 2 hours difference
+        config.setServerTimeZoneId("America/Chicago");
+        parser.configure(config);
+        
+        SimpleDateFormat sdf = (SimpleDateFormat)
+            parser.getRecentDateFormat().clone();
+        
+        // assume we're in the US Pacific Time Zone
+        TimeZone tzla = TimeZone.getTimeZone("America/Los_Angeles");
+        sdf.setTimeZone(tzla);
+        
+        // get formatted versions of time in L.A. 
+        String fmtTimePlusOneHour = sdf.format(anHourFromNow);
+        String fmtTimePlusThreeHours = sdf.format(threeHoursFromNow);
+        
+        
+        try {
+            Calendar parsed = parser.parseTimestamp(fmtTimePlusOneHour);
+            // the only difference should be the two hours
+            // difference, no rolling back a year should occur.
+            assertEquals("no.rollback.because.of.time.zones",
+                TWO_HOURS_OF_MILLISECONDS, 
+                cal.getTime().getTime() - parsed.getTime().getTime());
+        } catch (ParseException e){
+            fail("Unable to parse " + fmtTimePlusOneHour);
+        }
+        
+        //but if the file's timestamp is THREE hours ahead of now, that should 
+        //cause a rollover even taking the time zone difference into account.
+        //Since that time is still later than ours, it is parsed as occurring
+        //on this date last year.
+        try {
+            Calendar parsed = parser.parseTimestamp(fmtTimePlusThreeHours);
+            // rollback should occur here.
+            assertEquals("rollback.even.with.time.zones", 
+                    1, cal.get(Calendar.YEAR) - parsed.get(Calendar.YEAR));
+        } catch (ParseException e){
+            fail("Unable to parse" + fmtTimePlusThreeHours);
+        }
+    }
 
 
-	public void testParser() {
-		FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
-		try {
-			parser.parseTimestamp("feb 22 2002");
-		} catch (ParseException e) {
-			fail("failed.to.parse.default");
-		}
-		try {
-			parser.parseTimestamp("f\u00e9v 22 2002");
-			fail("should.have.failed.to.parse.default");
-		} catch (ParseException e) {
-			// this is the success case
-		}
+    public void testParser() {
+        FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
+        try {
+            parser.parseTimestamp("feb 22 2002");
+        } catch (ParseException e) {
+            fail("failed.to.parse.default");
+        }
+        try {
+            parser.parseTimestamp("f\u00e9v 22 2002");
+            fail("should.have.failed.to.parse.default");
+        } catch (ParseException e) {
+            // this is the success case
+        }
 
-		FTPClientConfig config = new FTPClientConfig();
-		config.setDefaultDateFormatStr("d MMM yyyy");
-		config.setRecentDateFormatStr("d MMM HH:mm");
-		config.setServerLanguageCode("fr");
-		parser.configure(config);
-		try {
-			parser.parseTimestamp("d\u00e9c 22 2002");
-			fail("incorrect.field.order");
-		} catch (ParseException e) {
-			// this is the success case
-		}
-		try {
-			parser.parseTimestamp("22 d\u00e9c 2002");
-		} catch (ParseException e) {
-			fail("failed.to.parse.french");
-		}
-		
-		try {
-			parser.parseTimestamp("22 dec 2002");
-			fail("incorrect.language");
-		} catch (ParseException e) {
-			// this is the success case
-		}
-		try {
-			parser.parseTimestamp("29 f\u00e9v 2002");
-			fail("nonexistent.date");
-		} catch (ParseException e) {
-			// this is the success case
-		}
+        FTPClientConfig config = new FTPClientConfig();
+        config.setDefaultDateFormatStr("d MMM yyyy");
+        config.setRecentDateFormatStr("d MMM HH:mm");
+        config.setServerLanguageCode("fr");
+        parser.configure(config);
+        try {
+            parser.parseTimestamp("d\u00e9c 22 2002");
+            fail("incorrect.field.order");
+        } catch (ParseException e) {
+            // this is the success case
+        }
+        try {
+            parser.parseTimestamp("22 d\u00e9c 2002");
+        } catch (ParseException e) {
+            fail("failed.to.parse.french");
+        }
+        
+        try {
+            parser.parseTimestamp("22 dec 2002");
+            fail("incorrect.language");
+        } catch (ParseException e) {
+            // this is the success case
+        }
+        try {
+            parser.parseTimestamp("29 f\u00e9v 2002");
+            fail("nonexistent.date");
+        } catch (ParseException e) {
+            // this is the success case
+        }
 
-		try {
-			parser.parseTimestamp("22 ao\u00fb 30:02");
-			fail("bad.hour");
-		} catch (ParseException e) {
-			// this is the success case
-		}
-		
-		try {
-			parser.parseTimestamp("22 ao\u00fb 20:74");
-			fail("bad.minute");
-		} catch (ParseException e) {
-			// this is the success case
-		}
-		try {
-			parser.parseTimestamp("28 ao\u00fb 20:02");
-		} catch (ParseException e) {
-			fail("failed.to.parse.french.recent");
-		}
-	}
-	
+        try {
+            parser.parseTimestamp("22 ao\u00fb 30:02");
+            fail("bad.hour");
+        } catch (ParseException e) {
+            // this is the success case
+        }
+        
+        try {
+            parser.parseTimestamp("22 ao\u00fb 20:74");
+            fail("bad.minute");
+        } catch (ParseException e) {
+            // this is the success case
+        }
+        try {
+            parser.parseTimestamp("28 ao\u00fb 20:02");
+        } catch (ParseException e) {
+            fail("failed.to.parse.french.recent");
+        }
+    }
+    
     /*
-     * Check how short date is interpreted at a given time
+     * Check how short date is interpreted at a given time.
+     * Check both with and without lenient future dates
      */
     private void checkShortParse(String msg, Calendar now, Calendar input) throws ParseException {
+        checkShortParse(msg, now, input, false);
+        checkShortParse(msg, now, input, true);
+    }
+
+    /*
+     * Check how short date is interpreted at a given time
+     * Check only using specified lenient future dates setting
+     */
+    private void checkShortParse(String msg, Calendar now, Calendar input, boolean lenient) throws ParseException {
         FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
+        parser.setLenientFutureDates(lenient);
         Format shortFormat = parser.getRecentDateFormat(); // It's expecting this format
         Format longFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm");
         
@@ -327,6 +338,30 @@
         }
     }
 
+    public void testParseDec31Lenient() throws Exception {
+        GregorianCalendar now = new GregorianCalendar(2007, Calendar.DECEMBER, 30, 12, 0);
+        checkShortParse("2007-12-30",now,now); // should always work
+        GregorianCalendar target = (GregorianCalendar) now.clone();
+        target.add(Calendar.DAY_OF_YEAR, +1); // tomorrow
+        checkShortParse("2007-12-31",now,target, true);
+    }
+
+    public void testParseJan01Lenient() throws Exception {
+        GregorianCalendar now = new GregorianCalendar(2007, Calendar.DECEMBER, 31, 12, 0);
+        checkShortParse("2007-12-31",now,now); // should always work
+        GregorianCalendar target = (GregorianCalendar) now.clone();
+        target.add(Calendar.DAY_OF_YEAR, +1); // tomorrow
+        checkShortParse("2008-1-1",now,target, true);
+    }
+
+    public void testParseJan01() throws Exception {
+        GregorianCalendar now = new GregorianCalendar(2007, Calendar.JANUARY, 1, 12, 0);
+        checkShortParse("2007-01-01",now,now); // should always work
+        GregorianCalendar target = new GregorianCalendar(2006, Calendar.DECEMBER, 31, 12, 0);
+        checkShortParse("2006-12-31",now,target, true);
+        checkShortParse("2006-12-31",now,target, false);
+    }
+
     /**
      * Method suite.
      *
diff --git a/src/test/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java b/src/test/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java
index 1bc8446..5e35b06 100644
--- a/src/test/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java
+++ b/src/test/org/apache/commons/net/ftp/parser/MVSFTPEntryParserTest.java
@@ -40,9 +40,9 @@
         "Migrated                                                file6.O",
         "PSMLB7 3390   2005/04/04  1    1  VB   27994 27998  PS  file7.O",
         "PSMLC6 3390   2005/04/05  1    1  VB   27994 27998  PS  file7.O.BU",
-    	"FPFS42 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.RPTBM023.D061704",
-    	"FPFS41 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.RPTBM056.D061704",
-    	"FPFS25 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.WTM204.D061704",                
+        "FPFS42 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.RPTBM023.D061704",
+        "FPFS41 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.RPTBM056.D061704",
+        "FPFS25 3390   2004/06/23  1    1  FB     128  6144  PS  INCOMING.WTM204.D061704",                
     };
     
     private static final String [] badsamples = 
diff --git a/src/test/org/apache/commons/net/ftp/parser/NetwareFTPEntryParserTest.java b/src/test/org/apache/commons/net/ftp/parser/NetwareFTPEntryParserTest.java
index 9ff756c..1704788 100644
--- a/src/test/org/apache/commons/net/ftp/parser/NetwareFTPEntryParserTest.java
+++ b/src/test/org/apache/commons/net/ftp/parser/NetwareFTPEntryParserTest.java
@@ -29,103 +29,103 @@
  */
 public class NetwareFTPEntryParserTest extends FTPParseTestFramework {
 
-	private static final String[] badsamples = {
-		"a [-----F--] SCION_SYS                         512 Apr 13 23:52 SYS",
-    		"d [----AF--]          0                        512 10-04-2001 _ADMIN"
-	};
-
-	private static final String [] goodsamples = {
-    	"d [-----F--] SCION_SYS                         512 Apr 13 23:52 SYS",
-    	"d [----AF--]          0                        512 Feb 22 17:32 _ADMIN",
-    	"d [-W---F--] SCION_VOL2                        512 Apr 13 23:12 VOL2",
-    	"- [RWCEAFMS] rwinston                        19968 Mar 12 15:20 Executive Summary.doc",
-    	"d [RWCEAFMS] rwinston                          512 Nov 24  2005 Favorites"
+    private static final String[] badsamples = {
+        "a [-----F--] SCION_SYS                         512 Apr 13 23:52 SYS",
+        "d [----AF--]          0                        512 10-04-2001 _ADMIN"
     };
-	
-	/**
-	 * @see junit.framework.TestCase#TestCase(String)
-	 */
-	public NetwareFTPEntryParserTest(String name) {
-		super(name);
-	}
 
-	/**
-	 * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing()
-	 */
-	protected String[] getBadListing() {
-		return (badsamples);
-	}
+    private static final String [] goodsamples = {
+        "d [-----F--] SCION_SYS                         512 Apr 13 23:52 SYS",
+        "d [----AF--]          0                        512 Feb 22 17:32 _ADMIN",
+        "d [-W---F--] SCION_VOL2                        512 Apr 13 23:12 VOL2",
+        "- [RWCEAFMS] rwinston                        19968 Mar 12 15:20 Executive Summary.doc",
+        "d [RWCEAFMS] rwinston                          512 Nov 24  2005 Favorites"
+    };
+    
+    /**
+     * @see junit.framework.TestCase#TestCase(String)
+     */
+    public NetwareFTPEntryParserTest(String name) {
+        super(name);
+    }
 
-	/**
-	 * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing()
-	 */
-	protected String[] getGoodListing() {
-		return (goodsamples);
-	}
+    /**
+     * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing()
+     */
+    protected String[] getBadListing() {
+        return (badsamples);
+    }
 
-	/**
-	 * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser()
-	 */
-	protected FTPFileEntryParser getParser() {
-		return (new NetwareFTPEntryParser());
-	}
+    /**
+     * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing()
+     */
+    protected String[] getGoodListing() {
+        return (goodsamples);
+    }
 
-	/**
-	 * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory()
-	 */
-	
-	public void testParseFieldsOnDirectory() throws Exception {
-		String reply = "d [-W---F--] testUser                        512 Apr 13 23:12 testFile";
-		FTPFile f = getParser().parseFTPEntry(reply);
-		
-		assertNotNull("Could not parse file", f);
-		assertEquals("testFile", f.getName());
-		assertEquals(512L, f.getSize());
-		assertEquals("testUser", f.getUser());
-		assertTrue("Directory flag is not set!", f.isDirectory());
-		
-		Calendar cal = Calendar.getInstance();
-		cal.set(Calendar.MONTH, 3);
-		cal.set(Calendar.DAY_OF_MONTH, 13);
-		cal.set(Calendar.HOUR_OF_DAY, 23);
-		cal.set(Calendar.MINUTE, 12);
-		cal.set(Calendar.SECOND, 0);
-		cal.set(Calendar.MILLISECOND, 0);
-		cal.set(Calendar.YEAR, f.getTimestamp().get(Calendar.YEAR));
-		
-		assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp()
-				.getTime()));
+    /**
+     * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser()
+     */
+    protected FTPFileEntryParser getParser() {
+        return (new NetwareFTPEntryParser());
+    }
 
-	}
-	
-	
-	/**
-	 * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile()
-	 */
-	public void testParseFieldsOnFile() throws Exception {
-		String reply = "- [R-CEAFMS] rwinston                        19968 Mar 12 15:20 Document name with spaces.doc";
-		
-		FTPFile f = getParser().parseFTPEntry(reply);
-		
-		assertNotNull("Could not parse file", f);
-		assertEquals("Document name with spaces.doc", f.getName());
-		assertEquals(19968L, f.getSize());
-		assertEquals("rwinston", f.getUser());
-		assertTrue("File flag is not set!", f.isFile());
-		
-		assertTrue(f.hasPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION));
-		assertFalse(f.hasPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION));
-	}
-	
+    /**
+     * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory()
+     */
+    
+    public void testParseFieldsOnDirectory() throws Exception {
+        String reply = "d [-W---F--] testUser                        512 Apr 13 23:12 testFile";
+        FTPFile f = getParser().parseFTPEntry(reply);
+        
+        assertNotNull("Could not parse file", f);
+        assertEquals("testFile", f.getName());
+        assertEquals(512L, f.getSize());
+        assertEquals("testUser", f.getUser());
+        assertTrue("Directory flag is not set!", f.isDirectory());
+        
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.MONTH, 3);
+        cal.set(Calendar.DAY_OF_MONTH, 13);
+        cal.set(Calendar.HOUR_OF_DAY, 23);
+        cal.set(Calendar.MINUTE, 12);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        cal.set(Calendar.YEAR, f.getTimestamp().get(Calendar.YEAR));
+        
+        assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp()
+                .getTime()));
 
-	/**
-	 * Method suite.
-	 * @return TestSuite
-	 */
-	public static TestSuite suite() {
-		return (new TestSuite(NetwareFTPEntryParserTest.class));
-	}
-	
-	
+    }
+    
+    
+    /**
+     * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile()
+     */
+    public void testParseFieldsOnFile() throws Exception {
+        String reply = "- [R-CEAFMS] rwinston                        19968 Mar 12 15:20 Document name with spaces.doc";
+        
+        FTPFile f = getParser().parseFTPEntry(reply);
+        
+        assertNotNull("Could not parse file", f);
+        assertEquals("Document name with spaces.doc", f.getName());
+        assertEquals(19968L, f.getSize());
+        assertEquals("rwinston", f.getUser());
+        assertTrue("File flag is not set!", f.isFile());
+        
+        assertTrue(f.hasPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION));
+        assertFalse(f.hasPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION));
+    }
+    
+
+    /**
+     * Method suite.
+     * @return TestSuite
+     */
+    public static TestSuite suite() {
+        return (new TestSuite(NetwareFTPEntryParserTest.class));
+    }
+    
+    
 }
 
diff --git a/src/test/org/apache/commons/net/ftp/parser/UnixFTPEntryParserTest.java b/src/test/org/apache/commons/net/ftp/parser/UnixFTPEntryParserTest.java
index aad5421..6d386de 100644
--- a/src/test/org/apache/commons/net/ftp/parser/UnixFTPEntryParserTest.java
+++ b/src/test/org/apache/commons/net/ftp/parser/UnixFTPEntryParserTest.java
@@ -29,83 +29,83 @@
  */
 public class UnixFTPEntryParserTest extends FTPParseTestFramework {
 
-	private static final String[] badsamples = {
-			"zrwxr-xr-x   2 root     root         4096 Mar  2 15:13 zxbox",
-			"dxrwr-xr-x   2 root     root         4096 Aug 24  2001 zxjdbc",
-			"drwxr-xr-x   2 root     root         4096 Jam  4 00:03 zziplib",
-			"drwxr-xr-x   2 root     99           4096 Feb 23 30:01 zzplayer",
-			"drwxr-xr-x   2 root     root         4096 Aug 36  2001 zztpp",
-			"-rw-r--r--   1 14       staff       80284 Aug 22  zxJDBC-1.2.3.tar.gz",
-			"-rw-r--r--   1 14       staff      119:26 Aug 22  2000 zxJDBC-1.2.3.zip",
-			/*"-rw-r--r--   1 ftp      no group    83853 Jan 22  2001 zxJDBC-1.2.4.tar.gz",*/
-			"-rw-r--r--   1ftp       nogroup    126552 Jan 22  2001 zxJDBC-1.2.4.zip",
-			"-rw-r--r--   1 root     root       190144 2001-04-27 zxJDBC-2.0.1b1.zip",
-			"-rw-r--r--   1 root     root       111325 Apr -7 18:79 zxJDBC-2.0.1b1.tar.gz" };
+    private static final String[] badsamples = {
+            "zrwxr-xr-x   2 root     root         4096 Mar  2 15:13 zxbox",
+            "dxrwr-xr-x   2 root     root         4096 Aug 24  2001 zxjdbc",
+            "drwxr-xr-x   2 root     root         4096 Jam  4 00:03 zziplib",
+            "drwxr-xr-x   2 root     99           4096 Feb 23 30:01 zzplayer",
+            "drwxr-xr-x   2 root     root         4096 Aug 36  2001 zztpp",
+            "-rw-r--r--   1 14       staff       80284 Aug 22  zxJDBC-1.2.3.tar.gz",
+            "-rw-r--r--   1 14       staff      119:26 Aug 22  2000 zxJDBC-1.2.3.zip",
+            /*"-rw-r--r--   1 ftp      no group    83853 Jan 22  2001 zxJDBC-1.2.4.tar.gz",*/
+            "-rw-r--r--   1ftp       nogroup    126552 Jan 22  2001 zxJDBC-1.2.4.zip",
+            "-rw-r--r--   1 root     root       190144 2001-04-27 zxJDBC-2.0.1b1.zip",
+            "-rw-r--r--   1 root     root       111325 Apr -7 18:79 zxJDBC-2.0.1b1.tar.gz" };
 
-	private static final String[] goodsamples = 
-	{
-			"-rw-r--r--   1 500      500            21 Aug  8 14:14 JB3-TES1.gz",
-			"-rwxr-xr-x   2 root     root         4096 Mar  2 15:13 zxbox",
-			"drwxr-xr-x   2 root     root         4096 Aug 24  2001 zxjdbc",
-			"drwxr-xr-x   2 root     root         4096 Jan  4 00:03 zziplib",
-			"drwxr-xr-x   2 root     99           4096 Feb 23  2001 zzplayer",
-			"drwxr-xr-x   2 root     root         4096 Aug  6  2001 zztpp",
-			"drwxr-xr-x 1 usernameftp 512 Jan 29 23:32 prog",
-			"lrw-r--r--   1 14       14          80284 Aug 22  2000 zxJDBC-1.2.3.tar.gz",
-			"frw-r--r--   1 14       staff      119926 Aug 22  2000 zxJDBC-1.2.3.zip",
-			"crw-r--r--   1 ftp      nogroup     83853 Jan 22  2001 zxJDBC-1.2.4.tar.gz",
-			"brw-r--r--   1 ftp      nogroup    126552 Jan 22  2001 zxJDBC-1.2.4.zip",
-			"-rw-r--r--   1 root     root       111325 Apr 27  2001 zxJDBC-2.0.1b1.tar.gz",
-			"-rw-r--r--   1 root     root       190144 Apr 27  2001 zxJDBC-2.0.1b1.zip",
-			"-rwxr-xr-x   2 500      500           166 Nov  2  2001 73131-testtes1.afp",
-			"-rw-r--r--   1 500      500           166 Nov  9  2001 73131-testtes1.AFP",
-			"-rw-r--r--   1 500      500           166 Nov 12  2001 73131-testtes2.afp",
-			"-rw-r--r--   1 500      500           166 Nov 12  2001 73131-testtes2.AFP",
-			"-rw-r--r--   1 500      500       2040000 Aug  5 07:35 testRemoteUPCopyNIX",
-			"-rw-r--r--   1 500      500       2040000 Aug  5 07:31 testRemoteUPDCopyNIX",
-			"-rw-r--r--   1 500      500       2040000 Aug  5 07:31 testRemoteUPVCopyNIX",
-			"-rw-r--r-T   1 500      500             0 Mar 25 08:20 testSticky",
-			"-rwxr-xr-t   1 500      500             0 Mar 25 08:21 testStickyExec",
-			"-rwSr-Sr--   1 500      500             0 Mar 25 08:22 testSuid",
-			"-rwsr-sr--   1 500      500             0 Mar 25 08:23 testSuidExec",
-			"-rwsr-sr--   1 500      500             0 Mar 25 0:23 testSuidExec2",
-			"drwxrwx---+ 23 500     500    0 Jan 10 13:09 testACL",
-			"-rw-r--r--   1 1        3518644 May 25 12:12 std",
+    private static final String[] goodsamples = 
+    {
+            "-rw-r--r--   1 500      500            21 Aug  8 14:14 JB3-TES1.gz",
+            "-rwxr-xr-x   2 root     root         4096 Mar  2 15:13 zxbox",
+            "drwxr-xr-x   2 root     root         4096 Aug 24  2001 zxjdbc",
+            "drwxr-xr-x   2 root     root         4096 Jan  4 00:03 zziplib",
+            "drwxr-xr-x   2 root     99           4096 Feb 23  2001 zzplayer",
+            "drwxr-xr-x   2 root     root         4096 Aug  6  2001 zztpp",
+            "drwxr-xr-x 1 usernameftp 512 Jan 29 23:32 prog",
+            "lrw-r--r--   1 14       14          80284 Aug 22  2000 zxJDBC-1.2.3.tar.gz",
+            "frw-r--r--   1 14       staff      119926 Aug 22  2000 zxJDBC-1.2.3.zip",
+            "crw-r--r--   1 ftp      nogroup     83853 Jan 22  2001 zxJDBC-1.2.4.tar.gz",
+            "brw-r--r--   1 ftp      nogroup    126552 Jan 22  2001 zxJDBC-1.2.4.zip",
+            "-rw-r--r--   1 root     root       111325 Apr 27  2001 zxJDBC-2.0.1b1.tar.gz",
+            "-rw-r--r--   1 root     root       190144 Apr 27  2001 zxJDBC-2.0.1b1.zip",
+            "-rwxr-xr-x   2 500      500           166 Nov  2  2001 73131-testtes1.afp",
+            "-rw-r--r--   1 500      500           166 Nov  9  2001 73131-testtes1.AFP",
+            "-rw-r--r--   1 500      500           166 Nov 12  2001 73131-testtes2.afp",
+            "-rw-r--r--   1 500      500           166 Nov 12  2001 73131-testtes2.AFP",
+            "-rw-r--r--   1 500      500       2040000 Aug  5 07:35 testRemoteUPCopyNIX",
+            "-rw-r--r--   1 500      500       2040000 Aug  5 07:31 testRemoteUPDCopyNIX",
+            "-rw-r--r--   1 500      500       2040000 Aug  5 07:31 testRemoteUPVCopyNIX",
+            "-rw-r--r-T   1 500      500             0 Mar 25 08:20 testSticky",
+            "-rwxr-xr-t   1 500      500             0 Mar 25 08:21 testStickyExec",
+            "-rwSr-Sr--   1 500      500             0 Mar 25 08:22 testSuid",
+            "-rwsr-sr--   1 500      500             0 Mar 25 08:23 testSuidExec",
+            "-rwsr-sr--   1 500      500             0 Mar 25 0:23 testSuidExec2",
+            "drwxrwx---+ 23 500     500    0 Jan 10 13:09 testACL",
+            "-rw-r--r--   1 1        3518644 May 25 12:12 std",
             "lrwxrwxrwx   1 neeme neeme             23 Mar  2 18:06 macros -> ./../../global/macros/.",
-			"-rw-r--r--   1 ftp      group with spaces in it as allowed in cygwin see bug 38634   83853 Jan 22  2001 zxJDBC-1.2.4.tar.gz",
-			"crw-r----- 1 root kmem 0, 27 Jan 30 11:42 kmem",  //FreeBSD device
-			"crw-------   1 root     sys      109,767 Jul  2  2004 pci@1c,600000:devctl" //Solaris device
+            "-rw-r--r--   1 ftp      group with spaces in it as allowed in cygwin see bug 38634   83853 Jan 22  2001 zxJDBC-1.2.4.tar.gz",
+            "crw-r----- 1 root kmem 0, 27 Jan 30 11:42 kmem",  //FreeBSD device
+            "crw-------   1 root     sys      109,767 Jul  2  2004 pci@1c,600000:devctl" //Solaris device
 
 
-		};
+        };
 
-	/**
-	 * @see junit.framework.TestCase#TestCase(String)
-	 */
-	public UnixFTPEntryParserTest(String name) {
-		super(name);
-	}
+    /**
+     * @see junit.framework.TestCase#TestCase(String)
+     */
+    public UnixFTPEntryParserTest(String name) {
+        super(name);
+    }
 
-	/**
-	 * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing()
-	 */
-	protected String[] getBadListing() {
-		return (badsamples);
-	}
+    /**
+     * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing()
+     */
+    protected String[] getBadListing() {
+        return (badsamples);
+    }
 
-	/**
-	 * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing()
-	 */
-	protected String[] getGoodListing() {
-		return (goodsamples);
-	}
-	
+    /**
+     * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing()
+     */
+    protected String[] getGoodListing() {
+        return (goodsamples);
+    }
+    
     /**
      */
     public void testNumericDateFormat()
     {
         String testNumericDF = 
-			"-rw-r-----   1 neeme neeme   346 2005-04-08 11:22 services.vsp";
+            "-rw-r-----   1 neeme neeme   346 2005-04-08 11:22 services.vsp";
         String testNumericDF2 = 
             "lrwxrwxrwx   1 neeme neeme    23 2005-03-02 18:06 macros -> ./../../global/macros/.";
 
@@ -117,15 +117,15 @@
                       f);
         
         
-		Calendar cal = Calendar.getInstance();
-		cal.clear();
-		cal.set(Calendar.YEAR, 2005);
-		cal.set(Calendar.MONTH, Calendar.APRIL);
+        Calendar cal = Calendar.getInstance();
+        cal.clear();
+        cal.set(Calendar.YEAR, 2005);
+        cal.set(Calendar.MONTH, Calendar.APRIL);
 
-		cal.set(Calendar.DATE, 8);
-		cal.set(Calendar.HOUR_OF_DAY, 11);
-		cal.set(Calendar.MINUTE, 22);
-		assertEquals(cal.getTime(), f.getTimestamp().getTime());
+        cal.set(Calendar.DATE, 8);
+        cal.set(Calendar.HOUR_OF_DAY, 11);
+        cal.set(Calendar.MINUTE, 22);
+        assertEquals(cal.getTime(), f.getTimestamp().getTime());
 
         FTPFile f2 = parser.parseFTPEntry(testNumericDF2);
         assertNotNull("Failed to parse " + testNumericDF2,
@@ -135,114 +135,114 @@
     }
 
 
-	/**
-	 * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser()
-	 */
-	protected FTPFileEntryParser getParser() {
-		return (new UnixFTPEntryParser());
-	}
+    /**
+     * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser()
+     */
+    protected FTPFileEntryParser getParser() {
+        return (new UnixFTPEntryParser());
+    }
 
-	/**
-	 * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory()
-	 */
-	public void testParseFieldsOnDirectory() throws Exception {
-		FTPFile f = getParser().parseFTPEntry("drwxr-xr-x   2 user     group         4096 Mar  2 15:13 zxbox");
-		assertNotNull("Could not parse entry.", f);
-		assertTrue("Should have been a directory.", f.isDirectory());
-		checkPermissions(f);
-		assertEquals(2, f.getHardLinkCount());
-		assertEquals("user", f.getUser());
-		assertEquals("group", f.getGroup());
-		assertEquals("zxbox", f.getName());
-		assertEquals(4096, f.getSize());
+    /**
+     * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory()
+     */
+    public void testParseFieldsOnDirectory() throws Exception {
+        FTPFile f = getParser().parseFTPEntry("drwxr-xr-x   2 user     group         4096 Mar  2 15:13 zxbox");
+        assertNotNull("Could not parse entry.", f);
+        assertTrue("Should have been a directory.", f.isDirectory());
+        checkPermissions(f);
+        assertEquals(2, f.getHardLinkCount());
+        assertEquals("user", f.getUser());
+        assertEquals("group", f.getGroup());
+        assertEquals("zxbox", f.getName());
+        assertEquals(4096, f.getSize());
 
-		Calendar cal = Calendar.getInstance();
-		cal.set(Calendar.MONTH, Calendar.MARCH);
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.MONTH, Calendar.MARCH);
 
-		cal.set(Calendar.DATE, 1);
-		cal.set(Calendar.HOUR_OF_DAY, 0);
-		cal.set(Calendar.MINUTE, 0);
-		cal.set(Calendar.SECOND, 0);
-		if (f.getTimestamp().getTime().before(cal.getTime())) {
-			cal.add(Calendar.YEAR, -1);
-		}
-		cal.set(Calendar.DATE, 2);
-		cal.set(Calendar.HOUR_OF_DAY, 15);
-		cal.set(Calendar.MINUTE, 13);
+        cal.set(Calendar.DATE, 1);
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        if (f.getTimestamp().getTime().before(cal.getTime())) {
+            cal.add(Calendar.YEAR, -1);
+        }
+        cal.set(Calendar.DATE, 2);
+        cal.set(Calendar.HOUR_OF_DAY, 15);
+        cal.set(Calendar.MINUTE, 13);
 
-		assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp()
-				.getTime()));
-	}
+        assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp()
+                .getTime()));
+    }
 
-	
-	/**
-	 * Method checkPermissions.
-	 * Verify that the persmissions were properly set.
-	 * @param f
-	 */
-	private void checkPermissions(FTPFile f) {
-		assertTrue("Should have user read permission.", f.hasPermission(
-				FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION));
-		assertTrue("Should have user write permission.", f.hasPermission(
-				FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION));
-		assertTrue("Should have user execute permission.", f.hasPermission(
-				FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION));
-		assertTrue("Should have group read permission.", f.hasPermission(
-				FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION));
-		assertTrue("Should NOT have group write permission.", !f.hasPermission(
-				FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION));
-		assertTrue("Should have group execute permission.", f.hasPermission(
-				FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION));
-		assertTrue("Should have world read permission.", f.hasPermission(
-				FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION));
-		assertTrue("Should NOT have world write permission.", !f.hasPermission(
-				FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION));
-		assertTrue("Should have world execute permission.", f.hasPermission(
-				FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION));
-	}
+    
+    /**
+     * Method checkPermissions.
+     * Verify that the persmissions were properly set.
+     * @param f
+     */
+    private void checkPermissions(FTPFile f) {
+        assertTrue("Should have user read permission.", f.hasPermission(
+                FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION));
+        assertTrue("Should have user write permission.", f.hasPermission(
+                FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION));
+        assertTrue("Should have user execute permission.", f.hasPermission(
+                FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION));
+        assertTrue("Should have group read permission.", f.hasPermission(
+                FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION));
+        assertTrue("Should NOT have group write permission.", !f.hasPermission(
+                FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION));
+        assertTrue("Should have group execute permission.", f.hasPermission(
+                FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION));
+        assertTrue("Should have world read permission.", f.hasPermission(
+                FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION));
+        assertTrue("Should NOT have world write permission.", !f.hasPermission(
+                FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION));
+        assertTrue("Should have world execute permission.", f.hasPermission(
+                FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION));
+    }
 
-	/**
-	 * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile()
-	 */
-	public void testParseFieldsOnFile() throws Exception {
-		FTPFile f = getParser()
-				.parseFTPEntry(
-						"-rwxr-xr-x   2 user     my group 500        5000000000 Mar  2 15:13 zxbox");
-		assertNotNull("Could not parse entry.", f);
-		assertTrue("Should have been a file.", f.isFile());
-		checkPermissions(f);
-		assertEquals(2, f.getHardLinkCount());
-		assertEquals("user", f.getUser());
-		assertEquals("my group 500", f.getGroup());
-		assertEquals("zxbox", f.getName());
-		assertEquals(5000000000L, f.getSize());
+    /**
+     * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile()
+     */
+    public void testParseFieldsOnFile() throws Exception {
+        FTPFile f = getParser()
+                .parseFTPEntry(
+                        "-rwxr-xr-x   2 user     my group 500        5000000000 Mar  2 15:13 zxbox");
+        assertNotNull("Could not parse entry.", f);
+        assertTrue("Should have been a file.", f.isFile());
+        checkPermissions(f);
+        assertEquals(2, f.getHardLinkCount());
+        assertEquals("user", f.getUser());
+        assertEquals("my group 500", f.getGroup());
+        assertEquals("zxbox", f.getName());
+        assertEquals(5000000000L, f.getSize());
 
-		Calendar cal = Calendar.getInstance();
-		cal.set(Calendar.MONTH, Calendar.MARCH);
+        Calendar cal = Calendar.getInstance();
+        cal.set(Calendar.MONTH, Calendar.MARCH);
 
-		cal.set(Calendar.DATE, 1);
-		cal.set(Calendar.HOUR_OF_DAY, 0);
-		cal.set(Calendar.MINUTE, 0);
-		cal.set(Calendar.SECOND, 0);
-		if (f.getTimestamp().getTime().before(cal.getTime())) {
-			cal.add(Calendar.YEAR, -1);
-		}
-		cal.set(Calendar.DATE, 2);
-		cal.set(Calendar.HOUR_OF_DAY, 15);
-		cal.set(Calendar.MINUTE, 13);
-		assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime()));
-	}
-	
+        cal.set(Calendar.DATE, 1);
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        if (f.getTimestamp().getTime().before(cal.getTime())) {
+            cal.add(Calendar.YEAR, -1);
+        }
+        cal.set(Calendar.DATE, 2);
+        cal.set(Calendar.HOUR_OF_DAY, 15);
+        cal.set(Calendar.MINUTE, 13);
+        assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime()));
+    }
+    
 
-	/**
-	 * Method suite.
-	 * @return TestSuite
-	 */
-	public static TestSuite suite() {
-		return (new TestSuite(UnixFTPEntryParserTest.class));
-	}
-	
-	
+    /**
+     * Method suite.
+     * @return TestSuite
+     */
+    public static TestSuite suite() {
+        return (new TestSuite(UnixFTPEntryParserTest.class));
+    }
+    
+    
     /* 
      * @param test
      * @param f
@@ -277,10 +277,10 @@
         }
         
         for (int access = FTPFile.USER_ACCESS; 
-        	access <= FTPFile.WORLD_ACCESS; access++) 
+            access <= FTPFile.WORLD_ACCESS; access++) 
         {
             for (int perm = FTPFile.READ_PERMISSION; 
-            	perm <= FTPFile.EXECUTE_PERMISSION; perm++)
+                perm <= FTPFile.EXECUTE_PERMISSION; perm++)
             {
                 int pos = 3*access + perm + 1;
                 char permchar = test.charAt(pos);
diff --git a/src/test/org/apache/commons/net/ftp/parser/VMSFTPEntryParserTest.java b/src/test/org/apache/commons/net/ftp/parser/VMSFTPEntryParserTest.java
index b622497..30eb5ed 100644
--- a/src/test/org/apache/commons/net/ftp/parser/VMSFTPEntryParserTest.java
+++ b/src/test/org/apache/commons/net/ftp/parser/VMSFTPEntryParserTest.java
@@ -160,10 +160,10 @@
                      dir.getGroup());
         assertEquals("OWNER",
                      dir.getUser());
-        checkPermisions(dir);
+        checkPermisions(dir, 0775);
 
 
-        dir = getParser().parseFTPEntry("DATA.DIR;1               1/9           2-JUN-1998 07:32:04  [TRANSLATED]    (RWED,RWED,RWED,RE)");
+        dir = getParser().parseFTPEntry("DATA.DIR;1               1/9           2-JUN-1998 07:32:04  [TRANSLATED]    (RWED,RWED,,RE)");
         assertTrue("Should be a directory.",
                            dir.isDirectory());
         assertEquals("DATA.DIR",
@@ -176,7 +176,7 @@
                      dir.getGroup());
         assertEquals("TRANSLATED",
                      dir.getUser());
-        checkPermisions(dir);
+        checkPermisions(dir, 0705);
     }
 
     /**
@@ -184,7 +184,7 @@
      */
     public void testParseFieldsOnFile() throws Exception
     {
-        FTPFile file = getParser().parseFTPEntry("1-JUN.LIS;1              9/9           2-JUN-1998 07:32:04  [GROUP,OWNER]    (RWED,RWED,RWED,RE)");
+        FTPFile file = getParser().parseFTPEntry("1-JUN.LIS;1              9/9           2-JUN-1998 07:32:04  [GROUP,OWNER]    (RWED,RWED,RW,R)");
         assertTrue("Should be a file.",
                    file.isFile());
         assertEquals("1-JUN.LIS",
@@ -197,10 +197,10 @@
                      file.getGroup());
         assertEquals("OWNER",
                      file.getUser());
-        checkPermisions(file);
+        checkPermisions(file, 0764);
 
 
-        file = getParser().parseFTPEntry("1-JUN.LIS;1              9/9           2-JUN-1998 07:32:04  [TRANSLATED]    (RWED,RWED,RWED,RE)");
+        file = getParser().parseFTPEntry("1-JUN.LIS;1              9/9           2-JUN-1998 07:32:04  [TRANSLATED]    (RWED,RD,,)");
         assertTrue("Should be a file.",
                    file.isFile());
         assertEquals("1-JUN.LIS",
@@ -213,7 +213,7 @@
                      file.getGroup());
         assertEquals("TRANSLATED",
                      file.getUser());
-        checkPermisions(file);
+        checkPermisions(file, 0400);
     }
 
     /**
@@ -257,34 +257,43 @@
      * Verify that the VMS parser does NOT  set the permissions.
      * @param dir
      */
-    private void checkPermisions(FTPFile dir)
+    private void checkPermisions(FTPFile dir, int octalPerm)
     {
+        int permMask = 1<<8;
         assertTrue("Owner should not have read permission.",
-                   !dir.hasPermission(FTPFile.USER_ACCESS,
+                ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.USER_ACCESS,
                                       FTPFile.READ_PERMISSION));
+        permMask >>= 1;
         assertTrue("Owner should not have write permission.",
-                   !dir.hasPermission(FTPFile.USER_ACCESS,
+                ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.USER_ACCESS,
                                       FTPFile.WRITE_PERMISSION));
+        permMask >>= 1;
         assertTrue("Owner should not have execute permission.",
-                   !dir.hasPermission(FTPFile.USER_ACCESS,
+                ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.USER_ACCESS,
                                       FTPFile.EXECUTE_PERMISSION));
+        permMask >>= 1;
         assertTrue("Group should not have read permission.",
-                   !dir.hasPermission(FTPFile.GROUP_ACCESS,
+                ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.GROUP_ACCESS,
                                       FTPFile.READ_PERMISSION));
+        permMask >>= 1;
         assertTrue("Group should not have write permission.",
-                   !dir.hasPermission(FTPFile.GROUP_ACCESS,
+                ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.GROUP_ACCESS,
                                       FTPFile.WRITE_PERMISSION));
+        permMask >>= 1;
         assertTrue("Group should not have execute permission.",
-                   !dir.hasPermission(FTPFile.GROUP_ACCESS,
+                ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.GROUP_ACCESS,
                                       FTPFile.EXECUTE_PERMISSION));
+        permMask >>= 1;
         assertTrue("World should not have read permission.",
-                   !dir.hasPermission(FTPFile.WORLD_ACCESS,
+                ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.WORLD_ACCESS,
                                       FTPFile.READ_PERMISSION));
+        permMask >>= 1;
         assertTrue("World should not have write permission.",
-                   !dir.hasPermission(FTPFile.WORLD_ACCESS,
+                ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.WORLD_ACCESS,
                                       FTPFile.WRITE_PERMISSION));
+        permMask >>= 1;
         assertTrue("World should not have execute permission.",
-                   !dir.hasPermission(FTPFile.WORLD_ACCESS,
+                ((permMask & octalPerm) != 0) == dir.hasPermission(FTPFile.WORLD_ACCESS,
                                       FTPFile.EXECUTE_PERMISSION));
     }
 
diff --git a/src/test/org/apache/commons/net/ntp/TimeStampTest.java b/src/test/org/apache/commons/net/ntp/TimeStampTest.java
index f2d3259..7c22aff 100644
--- a/src/test/org/apache/commons/net/ntp/TimeStampTest.java
+++ b/src/test/org/apache/commons/net/ntp/TimeStampTest.java
@@ -42,10 +42,10 @@
 
     public void testCompare() {
 
-        TimeStamp ts1 = new TimeStamp(TIME1);	// Tue, Dec 17 2002 14:07:24.810 UTC
+        TimeStamp ts1 = new TimeStamp(TIME1);   // Tue, Dec 17 2002 14:07:24.810 UTC
         TimeStamp ts2 = new TimeStamp(TIME1);
-        TimeStamp ts3 = new TimeStamp(TIME2); 	// Tue, Dec 17 2002 14:07:24.810 UTC
-        TimeStamp ts4 = new TimeStamp(TIME3); 	// Tue, Dec 17 2002 14:07:25.810 UTC
+        TimeStamp ts3 = new TimeStamp(TIME2);   // Tue, Dec 17 2002 14:07:24.810 UTC
+        TimeStamp ts4 = new TimeStamp(TIME3);   // Tue, Dec 17 2002 14:07:25.810 UTC
 
         // do assertion tests on TimeStamp class
         assertEquals("equals(1,2)", ts1, ts2);
@@ -54,9 +54,9 @@
         assertEquals("hashCode(1,2)", ts1.hashCode(), ts2.hashCode());
         assertEquals("ts1==ts1", ts1, ts1);
 
-	// timestamps in ts1 (TIME1) and ts3 (TIME2) are only off by the smallest
-	// fraction of a second (~200 picoseconds) so the times are not equal but
-	// when converted to Java dates (in milliseconds) they will be equal.
+    // timestamps in ts1 (TIME1) and ts3 (TIME2) are only off by the smallest
+    // fraction of a second (~200 picoseconds) so the times are not equal but
+    // when converted to Java dates (in milliseconds) they will be equal.
         assertTrue("ts1 != ts3", !ts1.equals(ts3));
         assertTrue("compareTo(1,3)", ts1.compareTo(ts3) == -1);
         assertEquals("seconds", ts1.getSeconds(), ts3.getSeconds());
@@ -72,20 +72,20 @@
     }
 
     public void testUTCString() {
-        TimeStamp ts1 = new TimeStamp(TIME1);	// Tue, Dec 17 2002 14:07:24.810 UTC
-	String actual = ts1.toUTCString();
-	assertEquals("Tue, Dec 17 2002 14:07:24.810 UTC", actual);
+        TimeStamp ts1 = new TimeStamp(TIME1);   // Tue, Dec 17 2002 14:07:24.810 UTC
+    String actual = ts1.toUTCString();
+    assertEquals("Tue, Dec 17 2002 14:07:24.810 UTC", actual);
     }
 
     public void testDateConversion() {
-	// convert current date to NtpTimeStamp then compare Java date
-	// computed from NTP timestamp with original Java date.
-	Calendar refCal = Calendar.getInstance(java.util.TimeZone.getTimeZone("UTC"));
-	Date refDate = refCal.getTime();
-	TimeStamp ts = new TimeStamp(refDate);
-	assertEquals("refDate.getTime()", refDate.getTime(), ts.getTime());
-	Date tsDate = ts.getDate();
-	assertEquals(refDate, tsDate);
+    // convert current date to NtpTimeStamp then compare Java date
+    // computed from NTP timestamp with original Java date.
+    Calendar refCal = Calendar.getInstance(java.util.TimeZone.getTimeZone("UTC"));
+    Date refDate = refCal.getTime();
+    TimeStamp ts = new TimeStamp(refDate);
+    assertEquals("refDate.getTime()", refDate.getTime(), ts.getTime());
+    Date tsDate = ts.getDate();
+    assertEquals(refDate, tsDate);
     }
 
 }
diff --git a/src/test/org/apache/commons/net/pop3/AllTests.java b/src/test/org/apache/commons/net/pop3/AllTests.java
index 19c9fc6..431db30 100644
--- a/src/test/org/apache/commons/net/pop3/AllTests.java
+++ b/src/test/org/apache/commons/net/pop3/AllTests.java
@@ -40,14 +40,14 @@
  */
 public class AllTests {
 
-	public static Test suite() {
-		TestSuite suite =
-			new TestSuite("Test for org.apache.commons.net.pop3");
-		//$JUnit-BEGIN$
-		suite.addTest(POP3ConstructorTest.suite());
-		suite.addTest(POP3ClientTest.suite());
-		suite.addTest(POP3ClientCommandsTest.suite());
-		//$JUnit-END$
-		return suite;
-	}
+    public static Test suite() {
+        TestSuite suite =
+            new TestSuite("Test for org.apache.commons.net.pop3");
+        //$JUnit-BEGIN$
+        suite.addTest(POP3ConstructorTest.suite());
+        suite.addTest(POP3ClientTest.suite());
+        suite.addTest(POP3ClientCommandsTest.suite());
+        //$JUnit-END$
+        return suite;
+    }
 }
diff --git a/src/test/org/apache/commons/net/pop3/TestSetupParameters.java b/src/test/org/apache/commons/net/pop3/TestSetupParameters.java
index 9df6ef0..180bc28 100644
--- a/src/test/org/apache/commons/net/pop3/TestSetupParameters.java
+++ b/src/test/org/apache/commons/net/pop3/TestSetupParameters.java
@@ -43,7 +43,7 @@
 
     public static final String mailhost = "localhost";
 
-	 //Cannot be instantiated
+     //Cannot be instantiated
     private TestSetupParameters()
     {}
 }
diff --git a/src/test/org/apache/commons/net/telnet/TelnetClientTest.java b/src/test/org/apache/commons/net/telnet/TelnetClientTest.java
index 621cd51..2272289 100644
--- a/src/test/org/apache/commons/net/telnet/TelnetClientTest.java
+++ b/src/test/org/apache/commons/net/telnet/TelnetClientTest.java
@@ -91,13 +91,13 @@
            try {
                server = new TelnetTestSimpleServer(port);
                 switch (socket) {
-               		case 0:
-               		    client = new TelnetClient();
+                    case 0:
+                        client = new TelnetClient();
                         // redundant but makes code clearer.
                         client.setReaderThread(true);
-               		    break;
-               		case 1:
-               		    client = new TelnetClient();
+                        break;
+                    case 1:
+                        client = new TelnetClient();
                         TerminalTypeOptionHandler ttopt = 
                             new TerminalTypeOptionHandler("VT100", false, false, true, false);
                         EchoOptionHandler echoopt = 
@@ -108,30 +108,30 @@
                         client.addOptionHandler(ttopt);
                         client.addOptionHandler(echoopt);
                         client.addOptionHandler(gaopt);
-               		    break;
-               		case 2:
+                        break;
+                    case 2:
                         client = new TelnetClient("ANSI");
-               		    break;
-               		case 3:
+                        break;
+                    case 3:
                         client = new TelnetClient();
                         client.setReaderThread(false);
-               		    break;
+                        break;
                }
                client.connect("127.0.0.1", port);
                switch (socket) {
-               		case 0:
-               		    STANDARD = new TestConnection(server, client, port);
-               		    break;
-               		case 1:
-               		    OPTIONS = new TestConnection(server, client, port);
-               		    break;
-               		case 2:
-               		    ANSI = new TestConnection(server, client, port);
-               		    break;
-               		case 3:
-               		    NOREAD = new TestConnection(server, client, port);
-               		    break;
-               		    
+                    case 0:
+                        STANDARD = new TestConnection(server, client, port);
+                        break;
+                    case 1:
+                        OPTIONS = new TestConnection(server, client, port);
+                        break;
+                    case 2:
+                        ANSI = new TestConnection(server, client, port);
+                        break;
+                    case 3:
+                        NOREAD = new TestConnection(server, client, port);
+                        break;
+    
                }
                
                // only increment socket number on success
@@ -702,9 +702,9 @@
         boolean test2spy_ok = false;
         boolean stopspy_ok = false;
         byte expected1[] = 
-        	{ (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '1' };
+            { (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '1' };
         byte expected2[] = 
-        	{ (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '2' };
+            { (byte) 't', (byte) 'e', (byte) 's', (byte) 't', (byte) '2' };
 
 
         PipedOutputStream po = new PipedOutputStream();
@@ -760,7 +760,8 @@
     /***
      * test of setReaderThread
      ***/
-    public void testSetReaderThread() throws Exception
+    // Test is problematic (see r708403), so disabled temporarily
+    public void donttestReaderThread() throws Exception
     {
         boolean negotiation1_ok = false;
         boolean negotiation2_ok = false;
@@ -842,9 +843,9 @@
             boolean result = true;
             for(int ii=0; ii<a1.length; ii++)
             {
-            	
+
                 if(a1[ii]!= a2[ii])
-                	result = false;
+                    result = false;
             }
             return(result);
         }
@@ -880,4 +881,4 @@
         }
     }
 
-}
\ No newline at end of file
+}
diff --git a/src/test/org/apache/commons/net/time/TimeTCPClientTest.java b/src/test/org/apache/commons/net/time/TimeTCPClientTest.java
index 6b99e9d..6dce92a 100644
--- a/src/test/org/apache/commons/net/time/TimeTCPClientTest.java
+++ b/src/test/org/apache/commons/net/time/TimeTCPClientTest.java
@@ -43,16 +43,16 @@
      ***/
     protected void openConnections() throws Exception
     {
-	try {
+    try {
             server1 = new TimeTestSimpleServer(_port);
             server1.connect();
-	} catch (IOException ioe)
-	{
-	    // try again on another port
-	    _port = 4000;
+    } catch (IOException ioe)
+    {
+        // try again on another port
+        _port = 4000;
             server1 = new TimeTestSimpleServer(_port);
             server1.connect();
-	}
+    }
         server1.start();
     }
 
diff --git a/src/test/org/apache/commons/net/time/TimeTestSimpleServer.java b/src/test/org/apache/commons/net/time/TimeTestSimpleServer.java
index 7ab9f91..1a0f5ec 100644
--- a/src/test/org/apache/commons/net/time/TimeTestSimpleServer.java
+++ b/src/test/org/apache/commons/net/time/TimeTestSimpleServer.java
@@ -94,14 +94,14 @@
     public void start() throws IOException
     {
         if (server == null)
-	{
+    {
             connect();
-	}
-	if (!running)
-	{
-	    running = true;
-	    new Thread(this).start();
-	}
+    }
+    if (!running)
+    {
+        running = true;
+        new Thread(this).start();
+    }
     }
 
     public void run()
diff --git a/xdocs/changes.xml b/xdocs/changes.xml
index 3a5bc76..4f36361 100644
--- a/xdocs/changes.xml
+++ b/xdocs/changes.xml
@@ -25,73 +25,86 @@
 
 		<release version="1.5.0" date="" description="">
 			<action dev="dfs" type="fix" issue="NET-3">
-				TelnetInputStream.java: Applied Rob
-Hasselbaum's
+				TelnetInputStream.java: Applied Rob Hasselbaum's
 				&lt;rhasselbaum -> alumni.ithaca.edu&gt;
-				patch for PR 38688 fixing a
-				TelnetInputStream hang.
+				patch for PR 38688 fixing a TelnetInputStream hang.
 			</action>
-			<action dev="rwinston" type="fix"
-issue="NET-73">
-				TelnetInputStream.java: Fixing another
-potential deadlock for 
+			<action dev="rwinston" type="fix" issue="NET-73">
+				TelnetInputStream.java: Fixing another potential deadlock for 
                         telnet and FTP (patch courtesy Rob Hasselbaum).
 			</action>
 			<action dev="dfs" type="update" issue="NET-57">
-				FTP.java: Exposed control connection of
-FTP
-				class via _controlInput_ and
-_controlOutput_
+				FTP.java: Exposed control connection of FTP
+				class via _controlInput_ and _controlOutput_
 				protected member variables in response
-				to PR 38309 reported by
-				&lt;josejuan.montiel@gmail.com&gt;.
+				to PR 38309 reported by &lt;josejuan.montiel@gmail.com&gt;.
 			</action>
-			<action dev="rwinston" type="fix"
-issue="NET-68">
-				TFTPClient.java: Fix bug causing final
-packets
-				to not be sent.
+			<action dev="rwinston" type="fix" issue="NET-68">
+				TFTPClient.java: Fix bug causing final packets to not be sent.
 			</action>
-			<action dev="rwinston" type="fix"
-issue="NET-161">
-				TFTPClient.java: Fix sendFile() (related
-to NET-68).
+			<action dev="rwinston" type="fix" issue="NET-161">
+				TFTPClient.java: Fix sendFile() (related to NET-68).
 			</action>
-			<action dev="rwinston" type="fix"
-issue="NET-181">
-				TFTPClient.java: block number
-wraparound.
+			<action dev="rwinston" type="fix" issue="NET-181">
+				TFTPClient.java: block number wraparound.
 			</action>
 			<action dev="scohen" type="fix" issue="NET-16">
-				UNIXFTPEntryParser.java: support for
-group names with
-                        spaces (patch courtesy D. Kilzer).
+				UNIXFTPEntryParser.java: support for group names with spaces (patch courtesy D. Kilzer).
 			</action>
 			<action dev="scohen" type="fix" issue="NET-62">
-				DefaultFTPFileEntryParserFactory.java:
-Wrap 
-                        NoClassDefFoundError in FTP parser exception
-                        when ORO is not available.
+				DefaultFTPFileEntryParserFactory.java: 
+				Wrap NoClassDefFoundError in FTP parser exception when ORO is not available.
 			</action>
-			<action dev="rwinston" type="add"
-issue="NET-33">
-				FTPClient.java: Fix closing FTP
-ServerSocket after timeout
+			<action dev="rwinston" type="add" issue="NET-33">
+				FTPClient.java: Fix closing FTP ServerSocket after timeout
 			</action>
 			<action dev="rwinston" type="add">
-				FTPClientConfig.java: Added an FTP
-parser for Netware FTP servers.
+				FTPClientConfig.java: Added an FTP parser for Netware FTP servers.
                         Tested on Novell Netware 6.5.
 			</action>
-			<action dev="rwinston" type="fix"
-issue="NET-188">
-				FTPTimestampParserImpl.java: Fix leap
-year date parsing bug.
+			<action dev="rwinston" type="fix" issue="NET-188">
+				FTPTimestampParserImpl.java: Fix leap year date parsing bug.
 			</action>
 			<action dev="rwinston" type="fix">
-				Article.java: Fix minor issues with NNTP
-parsing.
+				Article.java: Fix minor issues with NNTP parsing.
 			</action>
+			<action dev="sebb" type="fix" issue="NET-195">
+				NtpV3Impl.java: Avoid double-checked locking
+			</action>
+			<action dev="sebb" type="fix" issue="NET-197">
+				FTPFileEntryParserImpl.java: Fix Javadoc for preParse()
+			</action>
+			<action dev="rwinston" type="fix" issue="NET-201">
+				UnixFTPEntryParser.java: Support Solaris special devices
+			</action>
+			<action dev="sebb" type="fix" issue="NET-205">
+				*FTPEntryParser.java: Keep files with unparseable dates in list
+			</action>
+			<action dev="sebb" type="fix" issue="NET-206">
+				DefaultFTPFileEntryParserFactory.java, TFTPRequestPacket.java: Fix String conversions in non-English Locales
+			</action>
+			<action dev="sebb" type="fix" issue="NET-211">
+				FTPTimestampParserImpl.java: Fix lenient future dates at year boundary
+			</action>
+            <action dev="sebb" type="fix" issue="NET-194">
+                Replace Exception with IOException
+            </action>
+            <action dev="rwinston" type="update" issue="NET-214">
+                VMS file permission parsing
+            </action>
+            <action dev="sebb" type="fix" issue="NET-208">
+                TelnetInputStream swallows interruptedexception as IOException
+            </action>
+            <action dev="sebb" type="fix" issue="NET-223">
+                the data connection socket is not closed when an IOException occurred
+            </action>
+            <action dev="sebb" type="fix" issue="NET-231">
+                ParserInitializationException when connecting to a Unix FTP server: comparison string must be upper case
+                Added check for AS/400 response.
+            </action>
+            <action dev="sebb" type="fix" issue="NET-225">
+                FTPFileEntryParserImpl.preParse() doesn't remove unparsable entries at the end of the file list
+            </action>
 		</release> 
 		
 		<release version="1.4.1" date="December 3, 2005" description="fix release to restore jdk 1.3 compatability">