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    *   http://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  
18  package org.apache.commons.net.ftp;
19  
20  import java.io.ByteArrayInputStream;
21  import java.io.ByteArrayOutputStream;
22  import java.io.IOException;
23  import java.net.InetAddress;
24  
25  import junit.framework.TestCase;
26  
27  import org.apache.commons.net.ftp.parser.UnixFTPEntryParser;
28  
29  public class FTPClientTest extends TestCase {
30  
31      private static final class LocalClient extends FTPClient {
32  
33          private String systemType;
34  
35          @Override
36          public String getSystemType() throws IOException {
37              return systemType;
38          }
39  
40          public void setSystemType(final String type) {
41              systemType = type;
42          }
43      }
44  
45      private static final class PassiveNatWorkAroundLocalClient extends FTPClient {
46          private final String passiveModeServerIP;
47  
48          public PassiveNatWorkAroundLocalClient(final String passiveModeServerIP) {
49              this.passiveModeServerIP = passiveModeServerIP;
50          }
51  
52          @Override
53          public InetAddress getRemoteAddress() {
54              try {
55                  return InetAddress.getByName(passiveModeServerIP);
56              } catch (final Exception e) {
57                  throw new IllegalStateException(e);
58              }
59          }
60  
61      }
62  
63      private static final String[] TESTS = { "257 /path/without/quotes", "/path/without/quotes",
64  
65              "257 \"/path/with/delimiting/quotes/without/commentary\"", "/path/with/delimiting/quotes/without/commentary",
66  
67              "257 \"/path/with/quotes\"\" /inside/but/without/commentary\"", "/path/with/quotes\" /inside/but/without/commentary",
68  
69              "257 \"/path/with/quotes\"\" /inside/string\" and with commentary", "/path/with/quotes\" /inside/string",
70  
71              "257 \"/path/with/quotes\"\" /inside/string\" and with commentary that also \"contains quotes\"", "/path/with/quotes\" /inside/string",
72  
73              "257 \"/path/without/trailing/quote", // invalid syntax, return all after reply code prefix
74              "\"/path/without/trailing/quote",
75  
76              "257 root is current directory.", // NET-442
77              "root is current directory.",
78  
79              "257 \"/\"", // NET-502
80              "/", };
81  
82      public FTPClientTest(final String name) {
83          super(name);
84      }
85  
86      public void testCopyStreamListener() {
87          final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
88          assertNull(client.getCopyStreamListener());
89      }
90  
91      public void testGetActivePort() {
92          final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
93          assertEquals(0, client.getActivePort());
94      }
95  
96      public void testGetAutodetectUTF8() {
97          final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
98          assertFalse(client.getAutodetectUTF8());
99      }
100 
101     public void testGetBufferSize() {
102         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
103         assertEquals(0, client.getBufferSize());
104     }
105 
106     public void testGetControlKeepAliveReplyTimeout() {
107         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
108         assertEquals(1_000, client.getControlKeepAliveReplyTimeout());
109     }
110     
111     public void testGetControlKeepAliveTimeout() {
112         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
113         assertEquals(0, client.getControlKeepAliveTimeout());
114     }
115     
116     public void testGetCslDebug() {
117         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
118         assertNull(client.getCslDebug());
119     }
120     
121     public void testGetPassiveLocalIPAddress() {
122         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
123         assertNull(client.getPassiveLocalIPAddress());
124     }
125     
126     public void testGetPassivePort() {
127         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
128         assertEquals(-1, client.getPassivePort());
129     }
130     
131     public void testParseClient() {
132         for (int i = 0; i < TESTS.length; i += 2) {
133             assertEquals("Failed to parse", TESTS[i + 1], FTPClient.parsePathname(TESTS[i]));
134         }
135     }
136     
137 
138     public void testParsePassiveModeReplyForLocalAddressWithNatWorkaround() throws Exception {
139         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
140         client.setIpAddressFromPasvResponse(true);
141         client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
142         assertEquals("8.8.8.8", client.getPassiveHost());
143         client.setIpAddressFromPasvResponse(false);
144         client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
145         assertNull(client.getPassiveHost());
146     }
147 
148     @SuppressWarnings("deprecation") // testing deprecated code
149     public void testParsePassiveModeReplyForLocalAddressWithNatWorkaroundDisabled() throws Exception {
150         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
151         client.setPassiveNatWorkaround(false);
152         client.setIpAddressFromPasvResponse(true);
153         client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
154         assertEquals("172.16.204.138", client.getPassiveHost());
155         client.setIpAddressFromPasvResponse(false);
156         client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
157         assertNull(client.getPassiveHost());
158     }
159 
160     public void testParsePassiveModeReplyForLocalAddressWithoutNatWorkaroundStrategy() throws Exception {
161         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
162         client.setPassiveNatWorkaroundStrategy(null);
163         client.setIpAddressFromPasvResponse(true);
164         client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
165         assertEquals("172.16.204.138", client.getPassiveHost());
166         client.setIpAddressFromPasvResponse(false);
167         client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
168         assertNull(client.getPassiveHost());
169     }
170 
171     public void testParsePassiveModeReplyForLocalAddressWithSimpleNatWorkaroundStrategy() throws Exception {
172         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
173         client.setPassiveNatWorkaroundStrategy(hostname -> "4.4.4.4");
174         client.setIpAddressFromPasvResponse(true);
175         client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
176         assertEquals("4.4.4.4", client.getPassiveHost());
177         client.setIpAddressFromPasvResponse(false);
178         client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
179         assertNull(client.getPassiveHost());
180     }
181 
182     public void testParsePassiveModeReplyForNonLocalAddressWithNatWorkaround() throws Exception {
183         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
184         client.setIpAddressFromPasvResponse(true);
185         client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
186         assertEquals("8.8.4.4", client.getPassiveHost());
187         client.setIpAddressFromPasvResponse(false);
188         client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
189         assertNull(client.getPassiveHost());
190     }
191 
192     @SuppressWarnings("deprecation") // testing deprecated code
193     public void testParsePassiveModeReplyForNonLocalAddressWithNatWorkaroundDisabled() throws Exception {
194         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
195         client.setPassiveNatWorkaround(false);
196         client.setIpAddressFromPasvResponse(true);
197         client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
198         assertEquals("8.8.4.4", client.getPassiveHost());
199         client.setIpAddressFromPasvResponse(false);
200         client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
201         assertNull(client.getPassiveHost());
202     }
203 
204     public void testParsePassiveModeReplyForNonLocalAddressWithoutNatWorkaroundStrategy() throws Exception {
205         final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
206         client.setPassiveNatWorkaroundStrategy(null);
207         client.setIpAddressFromPasvResponse(true);
208         client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
209         assertEquals("8.8.4.4", client.getPassiveHost());
210         client.setIpAddressFromPasvResponse(false);
211         client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
212         assertNull(client.getPassiveHost());
213     }
214 
215     public void testParserCachingNullKey() throws Exception {
216         final LocalClient client = new LocalClient();
217         client.setSystemType(FTPClientConfig.SYST_UNIX);
218         assertNull(client.getEntryParser());
219         client.createParser(null);
220         final FTPFileEntryParser entryParser = client.getEntryParser();
221         assertNotNull(entryParser);
222         client.createParser(null);
223         assertSame(entryParser, client.getEntryParser()); // parser was cached
224         client.setSystemType(FTPClientConfig.SYST_NT);
225         client.createParser(null);
226         assertSame(entryParser, client.getEntryParser()); // parser was cached
227     }
228 
229     public void testParserCachingWithKey() throws Exception {
230         final FTPClient client = new FTPClient();
231         assertNull(client.getEntryParser());
232         client.createParser(FTPClientConfig.SYST_UNIX);
233         final FTPFileEntryParser entryParserSYST = client.getEntryParser();
234         assertNotNull(entryParserSYST);
235         client.createParser(FTPClientConfig.SYST_UNIX);
236         assertSame(entryParserSYST, client.getEntryParser()); // the previous entry was cached
237         client.createParser(FTPClientConfig.SYST_VMS);
238         final FTPFileEntryParser entryParserVMS = client.getEntryParser();
239         assertNotSame(entryParserSYST, entryParserVMS); // the previous entry was replaced
240         client.createParser(FTPClientConfig.SYST_VMS);
241         assertSame(entryParserVMS, client.getEntryParser()); // the previous entry was cached
242         client.createParser(FTPClientConfig.SYST_UNIX); // revert
243         assertNotSame(entryParserVMS, client.getEntryParser()); // the previous entry was replaced
244     }
245 
246     public void testUnparseableFiles() throws Exception {
247         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
248         baos.write("-rwxr-xr-x   2 root     root         4096 Mar  2 15:13 zxbox".getBytes());
249         baos.write(new byte[] { '\r', '\n' });
250         baos.write("zrwxr-xr-x   2 root     root         4096 Mar  2 15:13 zxbox".getBytes());
251         baos.write(new byte[] { '\r', '\n' });
252         final FTPFileEntryParser parser = new UnixFTPEntryParser();
253         final FTPClientConfig config = new FTPClientConfig();
254         FTPListParseEngine engine = new FTPListParseEngine(parser, config);
255         config.setUnparseableEntries(false);
256         engine.readServerList(new ByteArrayInputStream(baos.toByteArray()), null); // use default encoding
257         FTPFile[] files = engine.getFiles();
258         assertEquals(1, files.length);
259         config.setUnparseableEntries(true);
260         engine = new FTPListParseEngine(parser, config);
261         engine.readServerList(new ByteArrayInputStream(baos.toByteArray()), null); // use default encoding
262         files = engine.getFiles();
263         assertEquals(2, files.length);
264     }
265 }