diff --git a/src/main/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java b/src/main/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java index b1ff4a623..70aef853c 100644 --- a/src/main/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java +++ b/src/main/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParser.java @@ -47,8 +47,10 @@ public class UnixFTPEntryParser extends ConfigurableFTPFileEntryParserImpl { private static final String JA_YEAR = "\u5e74"; private static final String DEFAULT_DATE_FORMAT_JA = "M'" + JA_MONTH + "' d'" + JA_DAY + "' yyyy'" + JA_YEAR + "'"; // 6月 3日 2003年 + private static final String DEFAULT_DATE_FORMAT_CN = "M'" + JA_MONTH + "' d yyyy"; // 6月 3 2003 private static final String DEFAULT_RECENT_DATE_FORMAT_JA = "M'" + JA_MONTH + "' d'" + JA_DAY + "' HH:mm"; // 8月 17日 20:10 + private static final String DEFAULT_RECENT_DATE_FORMAT_CN = "M'" + JA_MONTH + "' d HH:mm"; // 8月 17 20:10 private static final Pattern TOTAL_PATTERN = Pattern.compile("^total \\d+$"); @@ -100,7 +102,9 @@ public class UnixFTPEntryParser extends ConfigurableFTPFileEntryParserImpl { + "(" + "(?:\\d+[-/]\\d+[-/]\\d+)" + // yyyy-mm-dd "|(?:\\S{3}\\s+\\d{1,2})" + // MMM [d]d "|(?:\\d{1,2}\\s+\\S{3})" + // [d]d MMM - "|(?:\\d{1,2}" + JA_MONTH + "\\s+\\d{1,2}" + JA_DAY + ")" + ")" + "|(?:\\d{1,2}" + JA_MONTH + "\\s+\\d{1,2}" + JA_DAY + ")" + + "|(?:\\d{1,2}" + JA_MONTH + "\\s+\\d{1,2})" + + ")" + "\\s+" // separator /* * year (for non-recent standard format) - yyyy or time (for numeric or recent standard format) [h]h:mm or Japanese year - yyyyXX @@ -187,10 +191,14 @@ public FTPFile parseFTPEntry(final String entry) { name = name.replaceFirst("^\\s+", ""); } try { - if (group(19).contains(JA_MONTH)) { // special processing for Japanese format + if (group(19).contains(JA_MONTH) && group(19).contains(JA_DAY)) { // special processing for Japanese format final FTPTimestampParserImpl jaParser = new FTPTimestampParserImpl(); jaParser.configure(new FTPClientConfig(FTPClientConfig.SYST_UNIX, DEFAULT_DATE_FORMAT_JA, DEFAULT_RECENT_DATE_FORMAT_JA)); file.setTimestamp(jaParser.parseTimestamp(datestr)); + } else if (group(19).contains(JA_MONTH) && !group(19).contains(JA_DAY)) { + final FTPTimestampParserImpl jaParser = new FTPTimestampParserImpl(); + jaParser.configure(new FTPClientConfig(FTPClientConfig.SYST_UNIX, DEFAULT_DATE_FORMAT_CN, DEFAULT_RECENT_DATE_FORMAT_CN)); + file.setTimestamp(jaParser.parseTimestamp(datestr)); } else { file.setTimestamp(super.parseTimestamp(datestr)); } diff --git a/src/test/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParserTest.java b/src/test/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParserTest.java index a6addc59d..366d2ddc9 100644 --- a/src/test/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParserTest.java +++ b/src/test/java/org/apache/commons/net/ftp/parser/UnixFTPEntryParserTest.java @@ -71,6 +71,9 @@ public class UnixFTPEntryParserTest extends AbstractFTPParseTest { "-rw-r--r-- 1 1 3518644 May 25 12:12 std", "-rw-rw---- 1 ep1adm sapsys 0 6\u6708 3\u65e5 2003\u5e74 \u8a66\u9a13\u30d5\u30a1\u30a4\u30eb.csv", "-rw-rw---- 1 ep1adm sapsys 0 8\u6708 17\u65e5 20:10 caerrinf", + "-rw-r--r-- 1 1 3518644 May 25 12:12 std", "-rw-rw---- 1 ep1adm sapsys 0 6\u6708 3 2003 \u8a66\u9a13\u30d5\u30a1\u30a4\u30eb.csv", + "-rw-rw---- 1 ep1adm sapsys 0 8\u6708 17 20:10 caerrinf", + }; private void checkPermissions(final FTPFile f) { @@ -365,6 +368,34 @@ public void testParseFieldsOnFileJapaneseTime() { assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime())); } + @Test + public void testParseFieldsOnFileChineseTime() { + final FTPFile f = getParser().parseFTPEntry("-rwxr-xr-x 2 user group 4096 3\u6708 2 15:13 zxbox"); + assertNotNull(f, "Could not parse entry."); + assertTrue(f.isFile(), "Should have been a file."); + checkPermissions(f); + assertEquals(2, f.getHardLinkCount()); + assertEquals("user", f.getUser()); + assertEquals("group", f.getGroup()); + assertEquals("zxbox", f.getName()); + assertEquals(4096, f.getSize()); + + assertNotNull(f.getTimestamp(), "Timestamp not null"); + final 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())); + } + // https://mail-archives.apache.org/mod_mbox/commons-dev/200408.mbox/%3c4122F3C1.9090402@tanukisoftware.com%3e @Test public void testParseFieldsOnFileJapaneseYear() { @@ -389,6 +420,29 @@ public void testParseFieldsOnFileJapaneseYear() { assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime())); } + @Test + public void testParseFieldsOnFileChineseYear() { + final FTPFile f = getParser().parseFTPEntry("-rwxr-xr-x 2 user group 4096 3\u6708 2 2003 \u8a66\u9a13\u30d5\u30a1\u30a4\u30eb.csv"); + assertNotNull(f, "Could not parse entry."); + assertTrue(f.isFile(), "Should have been a file."); + checkPermissions(f); + assertEquals(2, f.getHardLinkCount()); + assertEquals("user", f.getUser()); + assertEquals("group", f.getGroup()); + assertEquals("\u8a66\u9a13\u30d5\u30a1\u30a4\u30eb.csv", f.getName()); + assertEquals(4096, f.getSize()); + + assertNotNull(f.getTimestamp(), "Timestamp not null"); + final Calendar cal = Calendar.getInstance(); + cal.set(Calendar.YEAR, 2003); + cal.set(Calendar.MONTH, Calendar.MARCH); + cal.set(Calendar.DATE, 2); + cal.set(Calendar.HOUR_OF_DAY, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime())); + } + @Override @Test public void testRecentPrecision() {