View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.net.ftp.parser;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import java.io.ByteArrayInputStream;
26  import java.io.IOException;
27  import java.nio.charset.StandardCharsets;
28  import java.nio.file.Files;
29  import java.nio.file.Paths;
30  import java.util.Calendar;
31  
32  import org.apache.commons.net.ftp.FTPClientConfig;
33  import org.apache.commons.net.ftp.FTPFile;
34  import org.apache.commons.net.ftp.FTPFileEntryParser;
35  import org.apache.commons.net.ftp.FTPListParseEngine;
36  import org.junit.jupiter.api.Test;
37  
38  /**
39   */
40  class OS400FTPEntryParserTest extends CompositeFTPParseTestFramework {
41      private static final String[][] badsamples = {
42              { "PEP              4019 04/03/18 18:58:16 STMF       einladung.zip", "PEP               422 03/24 14:06:26 *STMF      readme",
43                      "PEP              6409 04/03/24 30:06:29 *STMF      build.xml", "PEP USR         36864 04/03/24 14:06:34 *DIR       dir1/",
44                      "PEP             3686404/03/24 14:06:47 *DIR       zdir2/" },
45  
46              { "----rwxr-x   1PEP       0           4019 Mar 18 18:58 einladung.zip", "----rwxr-x   1 PEP      0  xx        422 Mar 24 14:06 readme",
47                      "----rwxr-x   1 PEP      0           8492 Apr 07 30:13 build.xml", "d---rwxr-x   2 PEP      0          45056Mar 24 14:06 zdir2" } };
48  
49      private static final String[][] goodsamples = {
50              { "PEP              4019 04/03/18 18:58:16 *STMF      einladung.zip", "PEP               422 04/03/24 14:06:26 *STMF      readme",
51                      "PEP              6409 04/03/24 14:06:29 *STMF      build.xml", "PEP             36864 04/03/24 14:06:34 *DIR       dir1/",
52                      "PEP             36864 04/03/24 14:06:47 *DIR       zdir2/" },
53              { "----rwxr-x   1 PEP      0           4019 Mar 18 18:58 einladung.zip", "----rwxr-x   1 PEP      0            422 Mar 24 14:06 readme",
54                      "----rwxr-x   1 PEP      0           8492 Apr 07 07:13 build.xml", "d---rwxr-x   2 PEP      0          45056 Mar 24 14:06 dir1",
55                      "d---rwxr-x   2 PEP      0          45056 Mar 24 14:06 zdir2" } };
56  
57      @Override
58      protected void doAdditionalGoodTests(final String test, final FTPFile f) {
59          if (test.startsWith("d")) {
60              assertEquals(FTPFile.DIRECTORY_TYPE, f.getType(), "directory.type");
61          }
62      }
63  
64      /**
65       * @see AbstractFTPParseTest#getBadListing()
66       */
67      @Override
68      protected String[][] getBadListings() {
69          return badsamples;
70      }
71  
72      /**
73       * @see AbstractFTPParseTest#getGoodListing()
74       */
75      @Override
76      protected String[][] getGoodListings() {
77          return goodsamples;
78      }
79  
80      /**
81       * @see AbstractFTPParseTest#getParser()
82       */
83      @Override
84      protected FTPFileEntryParser getParser() {
85          return new CompositeFileEntryParser(new FTPFileEntryParser[] { new OS400FTPEntryParser(), new UnixFTPEntryParser()});
86      }
87  
88      @Override
89      @Test
90      void testDefaultPrecision() {
91          testPrecision("PEP              4019 04/03/18 18:58:16 *STMF      einladung.zip", CalendarUnit.SECOND);
92      }
93  
94      /**
95       * Tries to reproduce a fuzzing failure.
96       */
97      @Test
98      void testFuzz() throws IOException {
99          final byte[] allBytes = Files.readAllBytes(
100                 Paths.get("src/main/resources/org/apache/commons/net/fuzzer/clusterfuzz-testcase-minimized-OS400FTPEntryParserFuzzer-4734635798495232"));
101         final OS400FTPEntryParser parser = new OS400FTPEntryParser();
102         parser.configure(null);
103         final FTPListParseEngine engine = new FTPListParseEngine(parser);
104         // FTPListParseEngine
105         engine.readServerList(new ByteArrayInputStream(allBytes), null); // use default encoding
106         final FTPFile[] files = engine.getFiles();
107         assertEquals(0, files.length);
108         // OS400FTPEntryParser
109         final String string = new String(allBytes, StandardCharsets.UTF_8);
110         assertTrue(parser.matches(string));
111         assertNull(parser.parseFTPEntry(string));
112     }
113 
114     @Test
115     void testNET573() {
116         final FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_AS400);
117         conf.setDefaultDateFormatStr("MM/dd/yy HH:mm:ss");
118         final FTPFileEntryParser parser = new OS400FTPEntryParser(conf);
119 
120         final FTPFile f = parser.parseFTPEntry("ZFTPDEV 9069 05/20/15 15:36:52 *STMF /DRV/AUDWRKSHET/AUDWRK0204232015114625.PDF");
121         assertNotNull(f, "Could not parse entry.");
122         assertNotNull(f.getTimestamp(), "Could not parse timestamp.");
123         assertFalse(f.isDirectory(), "Should not have been a directory.");
124         assertEquals("ZFTPDEV", f.getUser());
125         assertEquals("AUDWRK0204232015114625.PDF", f.getName());
126         assertEquals(9069, f.getSize());
127 
128         final Calendar cal = Calendar.getInstance();
129         cal.set(Calendar.YEAR, 2015);
130         cal.set(Calendar.MONTH, Calendar.MAY);
131         cal.set(Calendar.DAY_OF_MONTH, 20);
132         cal.set(Calendar.HOUR_OF_DAY, 15);
133         cal.set(Calendar.MINUTE, 36);
134         cal.set(Calendar.SECOND, 52);
135 
136         assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime()));
137     }
138 
139     /**
140      * @see AbstractFTPParseTest#testParseFieldsOnDirectory()
141      */
142     @Override
143     @Test
144     void testParseFieldsOnDirectory() throws Exception {
145         final FTPFile f = getParser().parseFTPEntry("PEP             36864 04/03/24 14:06:34 *DIR       dir1/");
146         assertNotNull(f, "Could not parse entry.");
147         assertTrue(f.isDirectory(), "Should have been a directory.");
148         assertEquals("PEP", f.getUser());
149         assertEquals("dir1", f.getName());
150         assertEquals(36864, f.getSize());
151 
152         final Calendar cal = Calendar.getInstance();
153         cal.set(Calendar.MONTH, Calendar.MARCH);
154 
155         cal.set(Calendar.YEAR, 2004);
156         cal.set(Calendar.DAY_OF_MONTH, 24);
157         cal.set(Calendar.HOUR_OF_DAY, 14);
158         cal.set(Calendar.MINUTE, 6);
159         cal.set(Calendar.SECOND, 34);
160 
161         assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime()));
162     }
163 
164     /**
165      * @see AbstractFTPParseTest#testParseFieldsOnFile()
166      */
167     @Override
168     @Test
169     void testParseFieldsOnFile() throws Exception {
170         final FTPFile f = getParser().parseFTPEntry("PEP              5000000000 04/03/24 14:06:29 *STMF      build.xml");
171         assertNotNull(f, "Could not parse entry.");
172         assertTrue(f.isFile(), "Should have been a file.");
173         assertEquals("PEP", f.getUser());
174         assertEquals("build.xml", f.getName());
175         assertEquals(5000000000L, f.getSize());
176 
177         final Calendar cal = Calendar.getInstance();
178 
179         cal.set(Calendar.DAY_OF_MONTH, 24);
180         cal.set(Calendar.MONTH, Calendar.MARCH);
181         cal.set(Calendar.YEAR, 2004);
182         cal.set(Calendar.HOUR_OF_DAY, 14);
183         cal.set(Calendar.MINUTE, 6);
184         cal.set(Calendar.SECOND, 29);
185         assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime()));
186     }
187 
188     /**
189      * Test file names with spaces.
190      */
191     @Test
192     void testParseFileNameWithSpaces() {
193         final FTPFile f = getParser().parseFTPEntry("MYUSER              3 06/12/21 12:00:00 *STMF      file with space.txt");
194         assertNotNull(f, "Could not parse entry.");
195         assertTrue(f.isFile(), "Should have been a file.");
196         assertEquals("file with space.txt", f.getName());
197     }
198 
199     @Override
200     @Test
201     void testRecentPrecision() {
202         testPrecision("----rwxr-x   1 PEP      0           4019 Mar 18 18:58 einladung.zip", CalendarUnit.MINUTE);
203     }
204 
205 }