Skip to content

Commit 55bfc95

Browse files
author
Rory Winston
committed
Attempt to provide a workaround for date rollback issue
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/net/branches/JDK_1_5_BRANCH@543998 13f79535-47bb-0310-9956-ffa450edef68
1 parent e5e43d7 commit 55bfc95

File tree

7 files changed

+122
-5
lines changed

7 files changed

+122
-5
lines changed

src/main/java/org/apache/commons/net/ftp/FTP.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import org.apache.commons.net.SocketClient;
3434

3535
/***
36-
* FTP provides the basic the functionality necessary to implement your
36+
* FTP provides basic functionality necessary to implement your
3737
* own FTP client. It extends org.apache.commons.net.SocketClient since
3838
* extending TelnetClient was causing unwanted behavior (like connections
3939
* that did not time out properly).
@@ -311,8 +311,7 @@ private void __getReply() throws IOException
311311
// returning too soon after encountering a naked CR or some other
312312
// anomaly.
313313
}
314-
while (!(line.length() >= 4 && line.charAt(3) != '-' &&
315-
Character.isDigit(line.charAt(0))));
314+
while ((line.length() >= 4 || line.charAt(3) == '-' || !(line.substring(0,3).matches("\\d{3}"))));
316315
// This is too strong a condition because of non-conforming ftp
317316
// servers like ftp.funet.fi which sent 226 as the last line of a
318317
// 426 multi-line reply in response to ls /. We relax the condition to

src/main/java/org/apache/commons/net/ftp/FTPClient.java

+22-1
Original file line numberDiff line numberDiff line change
@@ -2431,14 +2431,35 @@ public void configure(FTPClientConfig config) {
24312431
public void setListHiddenFiles(boolean listHiddenFiles) {
24322432
this.__listHiddenFiles = listHiddenFiles;
24332433
}
2434-
2434+
24352435
/**
24362436
* @see #setListHiddenFiles(boolean)
24372437
* @return the current state
24382438
*/
24392439
public boolean getListHiddenFiles() {
24402440
return this.__listHiddenFiles;
24412441
}
2442+
2443+
/**
2444+
*
2445+
* @return
2446+
*/
2447+
public boolean isDateRollbackPermitted() {
2448+
return __configuration.isDateRollbackPermitted();
2449+
}
2450+
2451+
/**
2452+
* Set a boolean flag that specifies whether short date timestamps on the server
2453+
* (i.e. those with no year component) can be "rolled back" by a year if the server
2454+
* timestamp is greater than the local timestamp. This is true by default.
2455+
*
2456+
* @param dateRollbackPermitted false to explicitly prevent date rollback
2457+
*/
2458+
public void setDateRollbackPermitted(boolean dateRollbackPermitted) {
2459+
__configuration.setDateRollbackPermitted(dateRollbackPermitted);
2460+
}
2461+
2462+
24422463
}
24432464

24442465
/* Emacs configuration

src/main/java/org/apache/commons/net/ftp/FTPClientConfig.java

+19
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ public class FTPClientConfig
192192
private String shortMonthNames = null;
193193
private String serverTimeZoneId = null;
194194

195+
private boolean dateRollbackPermitted = true;
196+
195197

196198
/**
197199
* The main constructor for an FTPClientConfig object
@@ -554,5 +556,22 @@ public static Collection getSupportedLanguageCodes() {
554556
return LANGUAGE_CODE_MAP.keySet();
555557
}
556558

559+
560+
/**
561+
* getter for the {@link #dateRollbackPermitted} property
562+
* @return
563+
*/
564+
public boolean isDateRollbackPermitted() {
565+
return dateRollbackPermitted;
566+
}
567+
568+
/**
569+
* @see FTPClient#setDateRollbackPermitted(boolean)
570+
*
571+
* @param dateRollbackPermitted true/false
572+
*/
573+
public void setDateRollbackPermitted(boolean dateRollbackPermitted) {
574+
this.dateRollbackPermitted = dateRollbackPermitted;
575+
}
557576

558577
}

src/main/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImpl.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.TimeZone;
2727

2828
import org.apache.commons.net.ftp.Configurable;
29+
import org.apache.commons.net.ftp.FTPClient;
2930
import org.apache.commons.net.ftp.FTPClientConfig;
3031

3132
/**
@@ -44,6 +45,7 @@ public class FTPTimestampParserImpl implements
4445
private SimpleDateFormat defaultDateFormat;
4546
private SimpleDateFormat recentDateFormat;
4647
private boolean lenientFutureDates = false;
48+
private boolean dateRollbackPermitted = true;
4749

4850

4951
/**
@@ -91,7 +93,7 @@ public Calendar parseTimestamp(String timestampStr) throws ParseException {
9193
// slightly in the future to roll back a full year. (Bug 35181)
9294
now.add(Calendar.DATE, 1);
9395
}
94-
if (working.after(now)) {
96+
if (working.after(now) && isDateRollbackPermitted()) {
9597
working.add(Calendar.YEAR, -1);
9698
}
9799
} else {
@@ -244,6 +246,8 @@ public void configure(FTPClientConfig config) {
244246
setServerTimeZone(config.getServerTimeZoneId());
245247

246248
this.lenientFutureDates = config.isLenientFutureDates();
249+
250+
this.dateRollbackPermitted = config.isDateRollbackPermitted();
247251
}
248252
/**
249253
* @return Returns the lenientFutureDates.
@@ -257,4 +261,19 @@ boolean isLenientFutureDates() {
257261
void setLenientFutureDates(boolean lenientFutureDates) {
258262
this.lenientFutureDates = lenientFutureDates;
259263
}
264+
265+
/**
266+
* @returns the {@link #dateRollbackPermitted} property
267+
*/
268+
boolean isDateRollbackPermitted() {
269+
return dateRollbackPermitted;
270+
}
271+
272+
/**
273+
* @see FTPClient#setDateRollbackPermitted(boolean)
274+
* @param dateRollbackPermitted
275+
*/
276+
void setDateRollbackPermitted(boolean dateRollbackPermitted) {
277+
this.dateRollbackPermitted = dateRollbackPermitted;
278+
}
260279
}

src/main/java/org/apache/commons/net/io/CopyStreamException.java

+8
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,12 @@ public IOException getIOException()
6868
{
6969
return ioException;
7070
}
71+
72+
/**
73+
* Returns the original {@link IOException}
74+
*/
75+
@Override
76+
public Throwable getCause() {
77+
return getIOException();
78+
}
7179
}

src/site/xdoc/changes.xml

+8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ limitations under the License.
2323

2424
<body>
2525
<release version="2.0" date="" description="Java 5.0 release">
26+
<action dev="rwinston" type="update" issue="NET-159">
27+
Add a setDateRollbackPermitted() method to disable rolling
28+
back dates by 1 year when only short date format is
29+
available, and server timstamp is ahead of local.
30+
</action>
31+
<action dev="rwinston" type="update" issue="NET-153">
32+
Add getCause() to CopyStreamException
33+
</action>
2634
<action dev="rwinston" type="update" issue="NET-155">
2735
Change NNTPClient/NewsgroupInfo article counts from int to long
2836
</action>

src/test/java/org/apache/commons/net/ftp/parser/FTPTimestampParserImplTest.java

+43
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,49 @@ public void testParseTimestampAcrossTimeZones() {
158158
}
159159

160160

161+
public void testParseWithoutDateRollback() {
162+
FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
163+
164+
// Client calendar
165+
Calendar now = Calendar.getInstance();
166+
167+
// Server calendar - same TZ, +1 hour drift
168+
Calendar working = Calendar.getInstance();
169+
working.add(Calendar.HOUR_OF_DAY, 1);
170+
171+
// Create a dummy timestamp
172+
SimpleDateFormat formatter = new SimpleDateFormat("MMM d HH:mm");
173+
String timestamp = formatter.format(working.getTime());
174+
175+
Calendar server = null;
176+
177+
try {
178+
server = parser.parseTimestamp(timestamp);
179+
} catch (ParseException e) {
180+
e.printStackTrace();
181+
}
182+
183+
// As the server's clock is (client clock + 1 hour), the date should have rolled back
184+
// by a full year
185+
assertTrue( server.get(Calendar.YEAR) == now.get(Calendar.YEAR) - 1 );
186+
187+
/* Now, we attempt to parse the same timestamp, but explicitly disallow */
188+
/* date rollback */
189+
190+
// Set property directly on parser (normally we would set it via the FTPClientConfig instance)
191+
parser.setDateRollbackPermitted(false);
192+
193+
try {
194+
server = parser.parseTimestamp(timestamp);
195+
} catch (ParseException e) {
196+
e.printStackTrace();
197+
}
198+
199+
// The local and remote year value should be equal
200+
assertTrue( server.get(Calendar.YEAR) == now.get(Calendar.YEAR) );
201+
}
202+
203+
161204
public void testParser() {
162205
FTPTimestampParserImpl parser = new FTPTimestampParserImpl();
163206
try {

0 commit comments

Comments
 (0)