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  package org.apache.commons.net.ftp.parser;
18  
19  import java.util.Calendar;
20  
21  import junit.framework.TestSuite;
22  
23  import org.apache.commons.net.ftp.FTPFile;
24  import org.apache.commons.net.ftp.FTPFileEntryParser;
25  
26  /**
27   * @author <a href="mailto:scohen@apache.org">Steve Cohen</a>
28   * @version $Id: UnixFTPEntryParserTest.java 629276 2008-02-19 23:31:25Z rwinston $
29   */
30  public class UnixFTPEntryParserTest extends FTPParseTestFramework {
31  
32      private static final String[] badsamples = {
33              "zrwxr-xr-x   2 root     root         4096 Mar  2 15:13 zxbox",
34              "dxrwr-xr-x   2 root     root         4096 Aug 24  2001 zxjdbc",
35              "drwxr-xr-x   2 root     root         4096 Jam  4 00:03 zziplib",
36              "drwxr-xr-x   2 root     99           4096 Feb 23 30:01 zzplayer",
37              "drwxr-xr-x   2 root     root         4096 Aug 36  2001 zztpp",
38              "-rw-r--r--   1 14       staff       80284 Aug 22  zxJDBC-1.2.3.tar.gz",
39              "-rw-r--r--   1 14       staff      119:26 Aug 22  2000 zxJDBC-1.2.3.zip",
40              /*"-rw-r--r--   1 ftp      no group    83853 Jan 22  2001 zxJDBC-1.2.4.tar.gz",*/
41              "-rw-r--r--   1ftp       nogroup    126552 Jan 22  2001 zxJDBC-1.2.4.zip",
42              "-rw-r--r--   1 root     root       190144 2001-04-27 zxJDBC-2.0.1b1.zip",
43              "-rw-r--r--   1 root     root       111325 Apr -7 18:79 zxJDBC-2.0.1b1.tar.gz" };
44  
45      private static final String[] goodsamples = 
46      {
47              "-rw-r--r--   1 500      500            21 Aug  8 14:14 JB3-TES1.gz",
48              "-rwxr-xr-x   2 root     root         4096 Mar  2 15:13 zxbox",
49              "drwxr-xr-x   2 root     root         4096 Aug 24  2001 zxjdbc",
50              "drwxr-xr-x   2 root     root         4096 Jan  4 00:03 zziplib",
51              "drwxr-xr-x   2 root     99           4096 Feb 23  2001 zzplayer",
52              "drwxr-xr-x   2 root     root         4096 Aug  6  2001 zztpp",
53              "drwxr-xr-x 1 usernameftp 512 Jan 29 23:32 prog",
54              "lrw-r--r--   1 14       14          80284 Aug 22  2000 zxJDBC-1.2.3.tar.gz",
55              "frw-r--r--   1 14       staff      119926 Aug 22  2000 zxJDBC-1.2.3.zip",
56              "crw-r--r--   1 ftp      nogroup     83853 Jan 22  2001 zxJDBC-1.2.4.tar.gz",
57              "brw-r--r--   1 ftp      nogroup    126552 Jan 22  2001 zxJDBC-1.2.4.zip",
58              "-rw-r--r--   1 root     root       111325 Apr 27  2001 zxJDBC-2.0.1b1.tar.gz",
59              "-rw-r--r--   1 root     root       190144 Apr 27  2001 zxJDBC-2.0.1b1.zip",
60              "-rwxr-xr-x   2 500      500           166 Nov  2  2001 73131-testtes1.afp",
61              "-rw-r--r--   1 500      500           166 Nov  9  2001 73131-testtes1.AFP",
62              "-rw-r--r--   1 500      500           166 Nov 12  2001 73131-testtes2.afp",
63              "-rw-r--r--   1 500      500           166 Nov 12  2001 73131-testtes2.AFP",
64              "-rw-r--r--   1 500      500       2040000 Aug  5 07:35 testRemoteUPCopyNIX",
65              "-rw-r--r--   1 500      500       2040000 Aug  5 07:31 testRemoteUPDCopyNIX",
66              "-rw-r--r--   1 500      500       2040000 Aug  5 07:31 testRemoteUPVCopyNIX",
67              "-rw-r--r-T   1 500      500             0 Mar 25 08:20 testSticky",
68              "-rwxr-xr-t   1 500      500             0 Mar 25 08:21 testStickyExec",
69              "-rwSr-Sr--   1 500      500             0 Mar 25 08:22 testSuid",
70              "-rwsr-sr--   1 500      500             0 Mar 25 08:23 testSuidExec",
71              "-rwsr-sr--   1 500      500             0 Mar 25 0:23 testSuidExec2",
72              "drwxrwx---+ 23 500     500    0 Jan 10 13:09 testACL",
73              "-rw-r--r--   1 1        3518644 May 25 12:12 std",
74              "lrwxrwxrwx   1 neeme neeme             23 Mar  2 18:06 macros -> ./../../global/macros/.",
75              "-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",
76              "crw-r----- 1 root kmem 0, 27 Jan 30 11:42 kmem",  //FreeBSD device
77              "crw-------   1 root     sys      109,767 Jul  2  2004 pci@1c,600000:devctl" //Solaris device
78  
79  
80          };
81  
82      /**
83       * @see junit.framework.TestCase#TestCase(String)
84       */
85      public UnixFTPEntryParserTest(String name) {
86          super(name);
87      }
88  
89      /**
90       * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing()
91       */
92      @Override
93      protected String[] getBadListing() {
94          return (badsamples);
95      }
96  
97      /**
98       * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing()
99       */
100     @Override
101     protected String[] getGoodListing() {
102         return (goodsamples);
103     }
104     
105     /**
106      */
107     public void testNumericDateFormat()
108     {
109         String testNumericDF = 
110             "-rw-r-----   1 neeme neeme   346 2005-04-08 11:22 services.vsp";
111         String testNumericDF2 = 
112             "lrwxrwxrwx   1 neeme neeme    23 2005-03-02 18:06 macros -> ./../../global/macros/.";
113 
114         UnixFTPEntryParser parser = 
115             new UnixFTPEntryParser(UnixFTPEntryParser.NUMERIC_DATE_CONFIG);
116         
117         FTPFile f = parser.parseFTPEntry(testNumericDF);
118         assertNotNull("Failed to parse " + testNumericDF,
119                       f);
120         
121         
122         Calendar cal = Calendar.getInstance();
123         cal.clear();
124         cal.set(Calendar.YEAR, 2005);
125         cal.set(Calendar.MONTH, Calendar.APRIL);
126 
127         cal.set(Calendar.DATE, 8);
128         cal.set(Calendar.HOUR_OF_DAY, 11);
129         cal.set(Calendar.MINUTE, 22);
130         assertEquals(cal.getTime(), f.getTimestamp().getTime());
131 
132         FTPFile f2 = parser.parseFTPEntry(testNumericDF2);
133         assertNotNull("Failed to parse " + testNumericDF2,
134                       f2);
135         assertEquals("symbolic link", "./../../global/macros/.", f2.getLink());
136 
137     }
138 
139 
140     /**
141      * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getParser()
142      */
143     @Override
144     protected FTPFileEntryParser getParser() {
145         return (new UnixFTPEntryParser());
146     }
147     
148     public void testOwnerNameWithSpaces() {
149         FTPFile f = getParser().parseFTPEntry("drwxr-xr-x   2 john smith     group         4096 Mar  2 15:13 zxbox");
150         assertNotNull(f);
151         assertEquals("john smith", f.getUser());
152     }
153     
154     public void testOwnerANdGroupNameWithSpaces() {
155         FTPFile f = getParser().parseFTPEntry("drwxr-xr-x   2 john smith     test group         4096 Mar  2 15:13 zxbox");
156         assertNotNull(f);
157         assertEquals("john smith", f.getUser());
158         assertEquals("test group", f.getGroup());
159     }
160     
161     public void testGroupNameWithSpaces() {
162         FTPFile f = getParser().parseFTPEntry("drwx------ 4 maxm Domain Users 512 Oct 2 10:59 .metadata");
163         assertNotNull(f);
164         assertEquals("maxm", f.getUser());
165         assertEquals("Domain Users", f.getGroup());
166     }
167 	
168 	public void testTrailingSpaces() {
169 		FTPFile f = getParser().parseFTPEntry("drwxr-xr-x   2 john smith     group         4096 Mar  2 15:13 zxbox     ");
170 		assertNotNull(f);
171 		assertEquals(f.getName(), "zxbox     ");	
172 	}
173 	
174 	public void testNameWIthPunctuation() {
175 		FTPFile f = getParser().parseFTPEntry("drwx------ 4 maxm Domain Users 512 Oct 2 10:59 abc(test)123.pdf");
176 		assertNotNull(f);
177 		assertEquals(f.getName(), "abc(test)123.pdf");
178 		
179 	}
180 
181     /**
182      * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnDirectory()
183      */
184     @Override
185     public void testParseFieldsOnDirectory() throws Exception {
186         FTPFile f = getParser().parseFTPEntry("drwxr-xr-x   2 user     group         4096 Mar  2 15:13 zxbox");
187         assertNotNull("Could not parse entry.", f);
188         assertTrue("Should have been a directory.", f.isDirectory());
189         checkPermissions(f);
190         assertEquals(2, f.getHardLinkCount());
191         assertEquals("user", f.getUser());
192         assertEquals("group", f.getGroup());
193         assertEquals("zxbox", f.getName());
194         assertEquals(4096, f.getSize());
195 
196         Calendar cal = Calendar.getInstance();
197         cal.set(Calendar.MONTH, Calendar.MARCH);
198 
199         cal.set(Calendar.DATE, 1);
200         cal.set(Calendar.HOUR_OF_DAY, 0);
201         cal.set(Calendar.MINUTE, 0);
202         cal.set(Calendar.SECOND, 0);
203         if (f.getTimestamp().getTime().before(cal.getTime())) {
204             cal.add(Calendar.YEAR, -1);
205         }
206         cal.set(Calendar.DATE, 2);
207         cal.set(Calendar.HOUR_OF_DAY, 15);
208         cal.set(Calendar.MINUTE, 13);
209 
210         assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp()
211                 .getTime()));
212     }
213 
214     
215     /**
216      * Method checkPermissions.
217      * Verify that the persmissions were properly set.
218      * @param f
219      */
220     private void checkPermissions(FTPFile f) {
221         assertTrue("Should have user read permission.", f.hasPermission(
222                 FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION));
223         assertTrue("Should have user write permission.", f.hasPermission(
224                 FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION));
225         assertTrue("Should have user execute permission.", f.hasPermission(
226                 FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION));
227         assertTrue("Should have group read permission.", f.hasPermission(
228                 FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION));
229         assertTrue("Should NOT have group write permission.", !f.hasPermission(
230                 FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION));
231         assertTrue("Should have group execute permission.", f.hasPermission(
232                 FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION));
233         assertTrue("Should have world read permission.", f.hasPermission(
234                 FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION));
235         assertTrue("Should NOT have world write permission.", !f.hasPermission(
236                 FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION));
237         assertTrue("Should have world execute permission.", f.hasPermission(
238                 FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION));
239     }
240 
241     /**
242      * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#testParseFieldsOnFile()
243      */
244     @Override
245     public void testParseFieldsOnFile() throws Exception {
246         FTPFile f = getParser()
247                 .parseFTPEntry(
248                         "-rwxr-xr-x   2 user     my group 500        5000000000 Mar  2 15:13 zxbox");
249         assertNotNull("Could not parse entry.", f);
250         assertTrue("Should have been a file.", f.isFile());
251         checkPermissions(f);
252         assertEquals(2, f.getHardLinkCount());
253         assertEquals("user", f.getUser());
254         assertEquals("my group 500", f.getGroup());
255         assertEquals("zxbox", f.getName());
256         assertEquals(5000000000L, f.getSize());
257 
258         Calendar cal = Calendar.getInstance();
259         cal.set(Calendar.MONTH, Calendar.MARCH);
260 
261         cal.set(Calendar.DATE, 1);
262         cal.set(Calendar.HOUR_OF_DAY, 0);
263         cal.set(Calendar.MINUTE, 0);
264         cal.set(Calendar.SECOND, 0);
265         if (f.getTimestamp().getTime().before(cal.getTime())) {
266             cal.add(Calendar.YEAR, -1);
267         }
268         cal.set(Calendar.DATE, 2);
269         cal.set(Calendar.HOUR_OF_DAY, 15);
270         cal.set(Calendar.MINUTE, 13);
271         assertEquals(df.format(cal.getTime()), df.format(f.getTimestamp().getTime()));
272     }
273     
274 
275     /**
276      * Method suite.
277      * @return TestSuite
278      */
279     public static TestSuite suite() {
280         return (new TestSuite(UnixFTPEntryParserTest.class));
281     }
282     
283     
284     /* 
285      * @param test
286      * @param f
287      */
288     @Override
289     protected void doAdditionalGoodTests(String test, FTPFile f) {
290         String link = f.getLink();
291         if (null != link) {
292             int linklen = link.length();
293             if (linklen > 0) {
294                 assertEquals(link, test.substring(test.length() - linklen));
295                 assertEquals(f.getType(), FTPFile.SYMBOLIC_LINK_TYPE);
296             }
297         }
298         int type = f.getType();
299         switch (test.charAt(0))
300         {
301         case 'd':
302             assertEquals("Type of "+ test, type, FTPFile.DIRECTORY_TYPE);
303             break;
304         case 'l':
305              assertEquals("Type of "+ test, type, FTPFile.SYMBOLIC_LINK_TYPE);
306              break;
307         case 'b':
308         case 'c':
309             assertEquals(0, f.getHardLinkCount());
310         case 'f':
311         case '-':
312             assertEquals("Type of "+ test, type, FTPFile.FILE_TYPE);
313             break;
314         default:
315             assertEquals("Type of "+ test, type, FTPFile.UNKNOWN_TYPE);
316         }
317         
318         for (int access = FTPFile.USER_ACCESS; 
319             access <= FTPFile.WORLD_ACCESS; access++) 
320         {
321             for (int perm = FTPFile.READ_PERMISSION; 
322                 perm <= FTPFile.EXECUTE_PERMISSION; perm++)
323             {
324                 int pos = 3*access + perm + 1;
325                 char permchar = test.charAt(pos);
326                 assertEquals("Permission " + test.substring(1,10), 
327                         Boolean.valueOf(f.hasPermission(access, perm)), 
328                         Boolean.valueOf(permchar != '-' && !Character.isUpperCase(permchar))); 
329             }
330         }
331 
332     }
333 }