001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.net.ftp.parser;
018    
019    import java.util.Calendar;
020    
021    import junit.framework.TestSuite;
022    
023    import org.apache.commons.net.ftp.FTPFile;
024    import org.apache.commons.net.ftp.FTPFileEntryParser;
025    
026    /**
027     * @author <a href="mailto:scohen@apache.org">Steve Cohen</a>
028     * @version $Id: UnixFTPEntryParserTest.java 629276 2008-02-19 23:31:25Z rwinston $
029     */
030    public class UnixFTPEntryParserTest extends FTPParseTestFramework {
031    
032        private static final String[] badsamples = {
033                "zrwxr-xr-x   2 root     root         4096 Mar  2 15:13 zxbox",
034                "dxrwr-xr-x   2 root     root         4096 Aug 24  2001 zxjdbc",
035                "drwxr-xr-x   2 root     root         4096 Jam  4 00:03 zziplib",
036                "drwxr-xr-x   2 root     99           4096 Feb 23 30:01 zzplayer",
037                "drwxr-xr-x   2 root     root         4096 Aug 36  2001 zztpp",
038                "-rw-r--r--   1 14       staff       80284 Aug 22  zxJDBC-1.2.3.tar.gz",
039                "-rw-r--r--   1 14       staff      119:26 Aug 22  2000 zxJDBC-1.2.3.zip",
040                /*"-rw-r--r--   1 ftp      no group    83853 Jan 22  2001 zxJDBC-1.2.4.tar.gz",*/
041                "-rw-r--r--   1ftp       nogroup    126552 Jan 22  2001 zxJDBC-1.2.4.zip",
042                "-rw-r--r--   1 root     root       190144 2001-04-27 zxJDBC-2.0.1b1.zip",
043                "-rw-r--r--   1 root     root       111325 Apr -7 18:79 zxJDBC-2.0.1b1.tar.gz" };
044    
045        private static final String[] goodsamples = 
046        {
047                "-rw-r--r--   1 500      500            21 Aug  8 14:14 JB3-TES1.gz",
048                "-rwxr-xr-x   2 root     root         4096 Mar  2 15:13 zxbox",
049                "drwxr-xr-x   2 root     root         4096 Aug 24  2001 zxjdbc",
050                "drwxr-xr-x   2 root     root         4096 Jan  4 00:03 zziplib",
051                "drwxr-xr-x   2 root     99           4096 Feb 23  2001 zzplayer",
052                "drwxr-xr-x   2 root     root         4096 Aug  6  2001 zztpp",
053                "drwxr-xr-x 1 usernameftp 512 Jan 29 23:32 prog",
054                "lrw-r--r--   1 14       14          80284 Aug 22  2000 zxJDBC-1.2.3.tar.gz",
055                "frw-r--r--   1 14       staff      119926 Aug 22  2000 zxJDBC-1.2.3.zip",
056                "crw-r--r--   1 ftp      nogroup     83853 Jan 22  2001 zxJDBC-1.2.4.tar.gz",
057                "brw-r--r--   1 ftp      nogroup    126552 Jan 22  2001 zxJDBC-1.2.4.zip",
058                "-rw-r--r--   1 root     root       111325 Apr 27  2001 zxJDBC-2.0.1b1.tar.gz",
059                "-rw-r--r--   1 root     root       190144 Apr 27  2001 zxJDBC-2.0.1b1.zip",
060                "-rwxr-xr-x   2 500      500           166 Nov  2  2001 73131-testtes1.afp",
061                "-rw-r--r--   1 500      500           166 Nov  9  2001 73131-testtes1.AFP",
062                "-rw-r--r--   1 500      500           166 Nov 12  2001 73131-testtes2.afp",
063                "-rw-r--r--   1 500      500           166 Nov 12  2001 73131-testtes2.AFP",
064                "-rw-r--r--   1 500      500       2040000 Aug  5 07:35 testRemoteUPCopyNIX",
065                "-rw-r--r--   1 500      500       2040000 Aug  5 07:31 testRemoteUPDCopyNIX",
066                "-rw-r--r--   1 500      500       2040000 Aug  5 07:31 testRemoteUPVCopyNIX",
067                "-rw-r--r-T   1 500      500             0 Mar 25 08:20 testSticky",
068                "-rwxr-xr-t   1 500      500             0 Mar 25 08:21 testStickyExec",
069                "-rwSr-Sr--   1 500      500             0 Mar 25 08:22 testSuid",
070                "-rwsr-sr--   1 500      500             0 Mar 25 08:23 testSuidExec",
071                "-rwsr-sr--   1 500      500             0 Mar 25 0:23 testSuidExec2",
072                "drwxrwx---+ 23 500     500    0 Jan 10 13:09 testACL",
073                "-rw-r--r--   1 1        3518644 May 25 12:12 std",
074                "lrwxrwxrwx   1 neeme neeme             23 Mar  2 18:06 macros -> ./../../global/macros/.",
075                "-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",
076                "crw-r----- 1 root kmem 0, 27 Jan 30 11:42 kmem",  //FreeBSD device
077                "crw-------   1 root     sys      109,767 Jul  2  2004 pci@1c,600000:devctl" //Solaris device
078    
079    
080            };
081    
082        /**
083         * @see junit.framework.TestCase#TestCase(String)
084         */
085        public UnixFTPEntryParserTest(String name) {
086            super(name);
087        }
088    
089        /**
090         * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getBadListing()
091         */
092        @Override
093        protected String[] getBadListing() {
094            return (badsamples);
095        }
096    
097        /**
098         * @see org.apache.commons.net.ftp.parser.FTPParseTestFramework#getGoodListing()
099         */
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    }