Cyberduck Mountain Duck CLI

Changeset 11457


Ignore:
Timestamp:
Jun 28, 2013 9:53:21 AM (7 years ago)
Author:
dkocher
Message:

Extract list readers and add tests.

Location:
trunk
Files:
5 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/ch/cyberduck/core/ftp/FTPPath.java

    r11327 r11457  
    2626import ch.cyberduck.core.Preferences;
    2727import ch.cyberduck.core.StreamListener;
    28 import ch.cyberduck.core.date.MDTMMillisecondsDateFormatter;
    2928import ch.cyberduck.core.date.MDTMSecondsDateFormatter;
    3029import ch.cyberduck.core.date.UserDateFormatterFactory;
     
    4241import org.apache.commons.net.ftp.FTP;
    4342import org.apache.commons.net.ftp.FTPCommand;
    44 import org.apache.commons.net.ftp.FTPFile;
    4543import org.apache.commons.net.ftp.FTPFileEntryParser;
    4644import org.apache.commons.net.ftp.FTPReply;
     
    5250import java.net.SocketTimeoutException;
    5351import java.text.MessageFormat;
    54 import java.text.ParseException;
    5552import java.util.ArrayList;
    56 import java.util.Calendar;
    5753import java.util.Date;
    58 import java.util.HashMap;
    5954import java.util.List;
    60 import java.util.Map;
    6155import java.util.TimeZone;
    62 import java.util.regex.Matcher;
    63 import java.util.regex.Pattern;
    6456
    6557/**
     
    186178                            }
    187179                        }
    188                         success = this.parseListResponse(children, parser, result);
     180                        success = new FTPListResponseReader().read(children, session, this, parser, result);
    189181                    }
    190182                    else {
     
    217209                                // The presence of the MLST feature indicates that both MLST and MLSD are supported.
    218210                                && session.getClient().isFeatureSupported(FTPCommand.MLST)) {
    219                             success = parseMlsdResponse(children, session.getClient().list(FTPCommand.MLSD));
     211                            success = new FTPMlsdListResponseReader().read(children, session, FTPPath.this,
     212                                    null, session.getClient().list(FTPCommand.MLSD));
    220213                            if(!success) {
    221214                                session.setMlsdListSupportedEnabled(false);
     
    226219                            if(session.isExtendedListEnabled()) {
    227220                                try {
    228                                     success = parseListResponse(children, parser, session.getClient().list(FTPCommand.LIST, "-a"));
     221                                    success = new FTPListResponseReader().read(children, session, FTPPath.this,
     222                                            parser, session.getClient().list(FTPCommand.LIST, "-a"));
    229223                                }
    230224                                catch(FTPException e) {
     
    234228                            if(!success) {
    235229                                // LIST -a listing failed or not enabled
    236                                 success = parseListResponse(children, parser, session.getClient().list(FTPCommand.LIST));
     230                                success = new FTPListResponseReader().read(children, session, FTPPath.this,
     231                                        parser, session.getClient().list(FTPCommand.LIST));
    237232                            }
    238233                        }
     
    270265    }
    271266
    272     /**
    273      * The "facts" for a file in a reply to a MLSx command consist of
    274      * information about that file.  The facts are a series of keyword=value
    275      * pairs each followed by semi-colon (";") characters.  An individual
    276      * fact may not contain a semi-colon in its name or value.  The complete
    277      * series of facts may not contain the space character.  See the
    278      * definition or "RCHAR" in section 2.1 for a list of the characters
    279      * that can occur in a fact value.  Not all are applicable to all facts.
    280      * <p/>
    281      * A sample of a typical series of facts would be: (spread over two
    282      * lines for presentation here only)
    283      * <p/>
    284      * size=4161;lang=en-US;modify=19970214165800;create=19961001124534;
    285      * type=file;x.myfact=foo,bar;
    286      * <p/>
    287      * This document defines a standard set of facts as follows:
    288      * <p/>
    289      * size       -- Size in octets
    290      * modify     -- Last modification time
    291      * create     -- Creation time
    292      * type       -- Entry type
    293      * unique     -- Unique id of file/directory
    294      * perm       -- File permissions, whether read, write, execute is
    295      * allowed for the login id.
    296      * lang       -- Language of the file name per IANA [11] registry.
    297      * media-type -- MIME media-type of file contents per IANA registry.
    298      * charset    -- Character set per IANA registry (if not UTF-8)
    299      *
    300      * @param line The "facts" for a file in a reply to a MLSx command
    301      * @return Parsed keys and values
    302      */
    303     protected Map<String, Map<String, String>> parseFacts(String line) {
    304         final Pattern p = Pattern.compile("\\s?(\\S+\\=\\S+;)*\\s(.*)");
    305         final Matcher result = p.matcher(line);
    306         Map<String, Map<String, String>> file = new HashMap<String, Map<String, String>>();
    307         if(result.matches()) {
    308             final String filename = result.group(2);
    309             final Map<String, String> facts = new HashMap<String, String>();
    310             for(String fact : result.group(1).split(";")) {
    311                 String key = StringUtils.substringBefore(fact, "=");
    312                 if(StringUtils.isBlank(key)) {
    313                     continue;
    314                 }
    315                 String value = StringUtils.substringAfter(fact, "=");
    316                 if(StringUtils.isBlank(value)) {
    317                     continue;
    318                 }
    319                 facts.put(key.toLowerCase(java.util.Locale.ENGLISH), value);
    320             }
    321             file.put(filename, facts);
    322             return file;
    323         }
    324         log.warn("No match for " + line);
    325         return null;
    326     }
    327 
    328     /**
    329      * Parse response of MLSD
    330      *
    331      * @param children List to add parsed lines
    332      * @param replies  Lines
    333      * @return True if parsing is successful
    334      */
    335     protected boolean parseMlsdResponse(final AttributedList<Path> children, List<String> replies) {
    336 
    337         if(null == replies) {
    338             // This is an empty directory
    339             return false;
    340         }
    341         boolean success = false; // At least one entry successfully parsed
    342         for(String line : replies) {
    343             final Map<String, Map<String, String>> file = this.parseFacts(line);
    344             if(null == file) {
    345                 log.error(String.format("Error parsing line %s", line));
    346                 continue;
    347             }
    348             for(String name : file.keySet()) {
    349                 final Path parsed = new FTPPath(session, this, Path.getName(name), FILE_TYPE);
    350                 // size       -- Size in octets
    351                 // modify     -- Last modification time
    352                 // create     -- Creation time
    353                 // type       -- Entry type
    354                 // unique     -- Unique id of file/directory
    355                 // perm       -- File permissions, whether read, write, execute is allowed for the login id.
    356                 // lang       -- Language of the file name per IANA [11] registry.
    357                 // media-type -- MIME media-type of file contents per IANA registry.
    358                 // charset    -- Character set per IANA registry (if not UTF-8)
    359                 for(Map<String, String> facts : file.values()) {
    360                     if(!facts.containsKey("type")) {
    361                         log.error(String.format("No type fact in line %s", line));
    362                         continue;
    363                     }
    364                     if("dir".equals(facts.get("type").toLowerCase(java.util.Locale.ENGLISH))) {
    365                         parsed.attributes().setType(DIRECTORY_TYPE);
    366                     }
    367                     else if("file".equals(facts.get("type").toLowerCase(java.util.Locale.ENGLISH))) {
    368                         parsed.attributes().setType(FILE_TYPE);
    369                     }
    370                     else {
    371                         log.warn("Ignored type: " + line);
    372                         break;
    373                     }
    374                     if(name.contains(String.valueOf(DELIMITER))) {
    375                         if(!name.startsWith(this.getAbsolute() + Path.DELIMITER)) {
    376                             // Workaround for #2434.
    377                             log.warn("Skip listing entry with delimiter:" + name);
    378                             continue;
    379                         }
    380                     }
    381                     if(!success) {
    382                         if("dir".equals(facts.get("type").toLowerCase(java.util.Locale.ENGLISH)) && this.getName().equals(name)) {
    383                             log.warn("Possibly bogus response:" + line);
    384                         }
    385                         else {
    386                             success = true;
    387                         }
    388                     }
    389                     if(facts.containsKey("size")) {
    390                         parsed.attributes().setSize(Long.parseLong(facts.get("size")));
    391                     }
    392                     if(facts.containsKey("unix.uid")) {
    393                         parsed.attributes().setOwner(facts.get("unix.uid"));
    394                     }
    395                     if(facts.containsKey("unix.owner")) {
    396                         parsed.attributes().setOwner(facts.get("unix.owner"));
    397                     }
    398                     if(facts.containsKey("unix.gid")) {
    399                         parsed.attributes().setGroup(facts.get("unix.gid"));
    400                     }
    401                     if(facts.containsKey("unix.group")) {
    402                         parsed.attributes().setGroup(facts.get("unix.group"));
    403                     }
    404                     if(facts.containsKey("unix.mode")) {
    405                         try {
    406                             parsed.attributes().setPermission(new Permission(Integer.parseInt(facts.get("unix.mode"))));
    407                         }
    408                         catch(NumberFormatException e) {
    409                             log.error(String.format("Failed to parse fact %s", facts.get("unix.mode")));
    410                         }
    411                     }
    412                     if(facts.containsKey("modify")) {
    413                         parsed.attributes().setModificationDate(this.parseTimestamp(facts.get("modify")));
    414                     }
    415                     if(facts.containsKey("create")) {
    416                         parsed.attributes().setCreationDate(this.parseTimestamp(facts.get("create")));
    417                     }
    418                     if(facts.containsKey("charset")) {
    419                         if(!facts.get("charset").equalsIgnoreCase(session.getEncoding())) {
    420                             log.error(String.format("Incompatible charset %s but session is configured with %s",
    421                                     facts.get("charset"), session.getEncoding()));
    422                         }
    423                     }
    424                     children.add(parsed);
    425                 }
    426             }
    427         }
    428         return success;
    429     }
    430 
    431     protected boolean parseListResponse(final AttributedList<Path> children,
    432                                         final FTPFileEntryParser parser, final List<String> replies) {
    433         if(null == replies) {
    434             // This is an empty directory
    435             return false;
    436         }
    437         boolean success = false;
    438         for(String line : replies) {
    439             final FTPFile f = parser.parseFTPEntry(line);
    440             if(null == f) {
    441                 continue;
    442             }
    443             final String name = f.getName();
    444             if(!success) {
    445                 // Workaround for #2410. STAT only returns ls of directory itself
    446                 // Workaround for #2434. STAT of symbolic link directory only lists the directory itself.
    447                 if(this.getAbsolute().equals(name)) {
    448                     log.warn(String.format("Skip %s", f.getName()));
    449                     continue;
    450                 }
    451                 if(name.contains(String.valueOf(DELIMITER))) {
    452                     if(!name.startsWith(this.getAbsolute() + Path.DELIMITER)) {
    453                         // Workaround for #2434.
    454                         log.warn("Skip listing entry with delimiter:" + name);
    455                         continue;
    456                     }
    457                 }
    458             }
    459             success = true;
    460             if(name.equals(".") || name.equals("..")) {
    461                 if(log.isDebugEnabled()) {
    462                     log.debug(String.format("Skip %s", f.getName()));
    463                 }
    464                 continue;
    465             }
    466             final Path parsed = new FTPPath(session, this,
    467                     Path.getName(name), f.getType() == FTPFile.DIRECTORY_TYPE ? DIRECTORY_TYPE : FILE_TYPE);
    468             switch(f.getType()) {
    469                 case FTPFile.SYMBOLIC_LINK_TYPE:
    470                     // Symbolic link target may be an absolute or relative path
    471                     if(f.getLink().startsWith(String.valueOf(Path.DELIMITER))) {
    472                         parsed.setSymlinkTarget(new FTPPath(session, f.getLink(), parsed.attributes().getType()));
    473                     }
    474                     else {
    475                         parsed.setSymlinkTarget(new FTPPath(session, this, f.getLink(), parsed.attributes().getType()));
    476                     }
    477                     parsed.attributes().setType(SYMBOLIC_LINK_TYPE | FILE_TYPE);
    478                     break;
    479             }
    480             if(parsed.attributes().isFile()) {
    481                 parsed.attributes().setSize(f.getSize());
    482             }
    483             parsed.attributes().setOwner(f.getUser());
    484             parsed.attributes().setGroup(f.getGroup());
    485             if(session.isPermissionSupported(parser)) {
    486                 parsed.attributes().setPermission(new Permission(
    487                         new boolean[][]{
    488                                 {f.hasPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION),
    489                                         f.hasPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION),
    490                                         f.hasPermission(FTPFile.USER_ACCESS, FTPFile.EXECUTE_PERMISSION)
    491                                 },
    492                                 {f.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.READ_PERMISSION),
    493                                         f.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.WRITE_PERMISSION),
    494                                         f.hasPermission(FTPFile.GROUP_ACCESS, FTPFile.EXECUTE_PERMISSION)
    495                                 },
    496                                 {f.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.READ_PERMISSION),
    497                                         f.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.WRITE_PERMISSION),
    498                                         f.hasPermission(FTPFile.WORLD_ACCESS, FTPFile.EXECUTE_PERMISSION)
    499                                 }
    500                         }
    501                 ));
    502             }
    503             final Calendar timestamp = f.getTimestamp();
    504             if(timestamp != null) {
    505                 parsed.attributes().setModificationDate(timestamp.getTimeInMillis());
    506             }
    507             children.add(parsed);
    508         }
    509         return success;
    510     }
    511 
    512267    @Override
    513268    public void mkdir() throws BackgroundException {
     
    565320    }
    566321
    567     /**
    568      * Parse the timestamp using the MTDM format
    569      *
    570      * @param timestamp Date string
    571      * @return Milliseconds
    572      */
    573     public long parseTimestamp(final String timestamp) {
    574         if(null == timestamp) {
    575             return -1;
    576         }
    577         try {
    578             Date parsed = new MDTMSecondsDateFormatter().parse(timestamp);
    579             return parsed.getTime();
    580         }
    581         catch(ParseException e) {
    582             log.warn("Failed to parse timestamp:" + e.getMessage());
    583             try {
    584                 Date parsed = new MDTMMillisecondsDateFormatter().parse(timestamp);
    585                 return parsed.getTime();
    586             }
    587             catch(ParseException f) {
    588                 log.warn("Failed to parse timestamp:" + f.getMessage());
    589             }
    590         }
    591         log.error(String.format("Failed to parse timestamp %s", timestamp));
    592         return -1;
    593     }
    594 
    595322    @Override
    596323    public void readTimestamp() throws BackgroundException {
     
    602329                final String timestamp = session.getClient().getModificationTime(this.getAbsolute());
    603330                if(null != timestamp) {
    604                     attributes().setModificationDate(this.parseTimestamp(timestamp));
     331                    attributes().setModificationDate(new FTPMlsdListResponseReader().parseTimestamp(timestamp));
    605332                }
    606333            }
  • trunk/test/ch/cyberduck/core/ftp/FTPPathTest.java

    r11327 r11457  
    2020 */
    2121
    22 import ch.cyberduck.core.*;
     22import ch.cyberduck.core.AbstractTestCase;
     23import ch.cyberduck.core.ConnectionCanceledException;
     24import ch.cyberduck.core.Credentials;
     25import ch.cyberduck.core.DisabledLoginController;
     26import ch.cyberduck.core.Host;
     27import ch.cyberduck.core.Path;
     28import ch.cyberduck.core.Preferences;
     29import ch.cyberduck.core.Protocol;
    2330import ch.cyberduck.core.threading.BackgroundException;
    2431import ch.cyberduck.core.transfer.TransferStatus;
    2532
    26 import org.apache.commons.net.ftp.FTPFileEntryParser;
    27 import org.junit.Ignore;
    2833import org.junit.Test;
    2934
    3035import java.io.IOException;
    31 import java.util.Arrays;
    32 import java.util.Calendar;
    33 import java.util.Collections;
    34 import java.util.TimeZone;
    3536import java.util.concurrent.atomic.AtomicInteger;
    3637
     
    4142 */
    4243public class FTPPathTest extends AbstractTestCase {
    43 
    44     @Test
    45     public void test3243() {
    46         FTPFileEntryParser parser = new FTPParserSelector().getParser("UNIX");
    47 
    48         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    49                 "/SunnyD", Path.DIRECTORY_TYPE);
    50         assertEquals("SunnyD", path.getName());
    51         assertEquals("/SunnyD", path.getAbsolute());
    52 
    53         final AttributedList<Path> list = new AttributedList<Path>();
    54         final boolean success = path.parseListResponse(list, parser,
    55                 Collections.singletonList(" drwxrwx--x 1 owner group          512 Jun 12 15:40 SunnyD"));
    56 
    57         assertFalse(success);
    58         assertTrue(list.isEmpty());
    59     }
    60 
    61     @Test
    62     public void testParseSymbolicLink() {
    63         FTPFileEntryParser parser = new FTPParserSelector().getParser("UNIX");
    64 
    65         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    66                 "/", Path.DIRECTORY_TYPE);
    67         assertEquals("/", path.getName());
    68         assertEquals("/", path.getAbsolute());
    69 
    70         final AttributedList<Path> list = new AttributedList<Path>();
    71         final boolean success = path.parseListResponse(list, parser,
    72                 Collections.singletonList("lrwxrwxrwx    1 mk basicgrp       27 Sep 23  2004 www -> /www/basic/mk"));
    73 
    74         assertTrue(success);
    75         assertFalse(list.isEmpty());
    76         assertTrue(list.get(0).attributes().isSymbolicLink());
    77         assertEquals("/www/basic/mk", list.get(0).getSymlinkTarget().getAbsolute());
    78     }
    79 
    80     @Test
    81     public void test3763() {
    82         FTPFileEntryParser parser = new FTPParserSelector().getParser("UNIX");
    83 
    84         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    85                 "/www", Path.DIRECTORY_TYPE);
    86         assertEquals("www", path.getName());
    87         assertEquals("/www", path.getAbsolute());
    88 
    89         final AttributedList<Path> list = new AttributedList<Path>();
    90         final boolean success = path.parseListResponse(list, parser,
    91                 Collections.singletonList("lrwxrwxrwx    1 mk basicgrp       27 Sep 23  2004 /home/mk/www -> /www/basic/mk"));
    92 
    93         assertFalse(success);
    94         assertTrue(list.isEmpty());
    95     }
    96 
    97     @Test
    98     public void testMlsd() {
    99         final AttributedList<Path> children = new AttributedList<Path>();
    100 
    101         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    102                 "/www", Path.DIRECTORY_TYPE);
    103 
    104         String[] replies = new String[]{
    105                 "Type=file;Perm=awr;Unique=keVO1+8G4; writable",
    106                 "Type=file;Perm=r;Unique=keVO1+IH4;  leading space",
    107                 "Type=dir;Perm=cpmel;Unique=keVO1+7G4; incoming",
    108         };
    109 
    110         boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    111         assertTrue(success);
    112         assertEquals(3, children.size());
    113         assertEquals("writable", children.get(0).getName());
    114         assertTrue(children.get(0).attributes().isFile());
    115         assertEquals(" leading space", children.get(1).getName());
    116         assertTrue(children.get(1).attributes().isFile());
    117         assertTrue(children.get(2).attributes().isDirectory());
    118     }
    119 
    120     @Test
    121     public void testMlsdCdir() {
    122         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    123                 "/www", Path.DIRECTORY_TYPE);
    124 
    125         {
    126             final AttributedList<Path> children = new AttributedList<Path>();
    127             String[] replies = new String[]{
    128                     "Type=cdir;Perm=el;Unique=keVO1+ZF4; test", //skipped
    129             };
    130 
    131             boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    132             assertFalse(success);
    133             assertEquals(0, children.size());
    134         }
    135         {
    136             final AttributedList<Path> children = new AttributedList<Path>();
    137             String[] replies = new String[]{
    138                     "Type=cdir;Modify=19990112033515; /iana/assignments/character-set-info", //skipped
    139             };
    140 
    141             boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    142             assertFalse(success);
    143             assertEquals(0, children.size());
    144         }
    145     }
    146 
    147     @Test
    148     public void testMlsdPdir() {
    149         final AttributedList<Path> children = new AttributedList<Path>();
    150 
    151         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    152                 "/www", Path.DIRECTORY_TYPE);
    153 
    154         String[] replies = new String[]{
    155                 "Type=pdir;Perm=e;Unique=keVO1+d?3; ..", //skipped
    156         };
    157 
    158         boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    159         assertFalse(success);
    160         assertEquals(0, children.size());
    161     }
    162 
    163     @Test
    164     public void testMlsdDirInvalid() {
    165         final AttributedList<Path> children = new AttributedList<Path>();
    166 
    167         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    168                 "/www", Path.DIRECTORY_TYPE);
    169 
    170         String[] replies = new String[]{
    171                 "Type=dir;Unique=aaaaacUYqaaa;Perm=cpmel; /", //skipped
    172         };
    173 
    174         boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    175         assertFalse(success);
    176         assertEquals(0, children.size());
    177     }
    178 
    179     public void testSkipParentDir() {
    180         final AttributedList<Path> children = new AttributedList<Path>();
    181 
    182         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    183                 "/www", Path.DIRECTORY_TYPE);
    184 
    185         String[] replies = new String[]{
    186                 "Type=pdir;Unique=aaaaacUYqaaa;Perm=cpmel; /",
    187                 "Type=pdir;Unique=aaaaacUYqaaa;Perm=cpmel; ..",
    188                 "Type=file;Unique=aaab8bUYqaaa;Perm=rf;Size=34589; ftpd.c"
    189         };
    190 
    191         boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    192         assertTrue(success);
    193         assertEquals(1, children.size());
    194         assertEquals("ftpd.c", children.get(0).getName());
    195     }
    196 
    197     @Test
    198     public void testSize() {
    199         final AttributedList<Path> children = new AttributedList<Path>();
    200 
    201         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    202                 "/www", Path.DIRECTORY_TYPE);
    203 
    204         String[] replies = new String[]{
    205                 "Type=file;Unique=aaab8bUYqaaa;Perm=rf;Size=34589; ftpd.c"
    206         };
    207 
    208         boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    209         assertTrue(success);
    210         assertEquals(1, children.size());
    211         assertEquals(34589, children.get(0).attributes().getSize());
    212     }
    213 
    214     @Test
    215     public void testTimestamp() {
    216         final AttributedList<Path> children = new AttributedList<Path>();
    217 
    218         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    219                 "/www", Path.DIRECTORY_TYPE);
    220 
    221         String[] replies = new String[]{
    222                 "Type=dir;Modify=19990112033045; text" //yyyyMMddHHmmss
    223         };
    224 
    225         boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    226         assertTrue(success);
    227         assertEquals(1, children.size());
    228         Calendar date = Calendar.getInstance(TimeZone.getDefault());
    229         date.set(1999, Calendar.JANUARY, 12, 3, 30, 45);
    230         date.set(Calendar.MILLISECOND, 0);
    231         assertEquals(date.getTime().getTime(), children.get(0).attributes().getModificationDate());
    232     }
    233 
    234     @Test
    235     public void testBrokenMlsd() {
    236         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    237                 "/Dummies_Infoblaetter", Path.DIRECTORY_TYPE);
    238 
    239         {
    240             final AttributedList<Path> children = new AttributedList<Path>();
    241             String[] replies = new String[]{
    242                     "Type=dir;Modify=20101209140859;Win32.ea=0x00000010; Dummies_Infoblaetter",
    243             };
    244 
    245             boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    246             assertFalse(success);
    247             assertEquals(1, children.size());
    248         }
    249         {
    250             final AttributedList<Path> children = new AttributedList<Path>();
    251             String[] replies = new String[]{
    252                     "Type=dir;Modify=20101209140859;Win32.ea=0x00000010; Dummies_Infoblaetter",
    253                     "Type=file;Unique=aaab8bUYqaaa;Perm=rf;Size=34589; ftpd.c"
    254             };
    255 
    256             boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    257             assertTrue(success);
    258             assertEquals(2, children.size());
    259         }
    260         {
    261             final AttributedList<Path> children = new AttributedList<Path>();
    262             String[] replies = new String[]{
    263                     "Type=file;Unique=aaab8bUYqaaa;Perm=rf;Size=34589; ftpd.c",
    264                     "Type=dir;Modify=20101209140859;Win32.ea=0x00000010; Dummies_Infoblaetter"
    265             };
    266 
    267             boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    268             assertTrue(success);
    269             assertEquals(2, children.size());
    270         }
    271     }
    272 
    273     @Test
    274     public void testParseMlsdMode() {
    275         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    276                 "/www", Path.DIRECTORY_TYPE);
    277 
    278         {
    279             final AttributedList<Path> children = new AttributedList<Path>();
    280             String[] replies = new String[]{
    281                     "modify=19990307234236;perm=adfr;size=60;type=file;unique=FE03U10001724;UNIX.group=1001;UNIX.mode=0664;UNIX.owner=2000; kalahari.diz"
    282             };
    283 
    284             boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    285             assertTrue(success);
    286             assertEquals(1, children.size());
    287             assertEquals("664", children.get(0).attributes().getPermission().getOctalString());
    288         }
    289         {
    290             final AttributedList<Path> children = new AttributedList<Path>();
    291             String[] replies = new String[]{
    292                     "modify=20090210192929;perm=fle;type=dir;unique=FE03U10006D95;UNIX.group=1001;UNIX.mode=02775;UNIX.owner=2000; tangerine"
    293             };
    294 
    295             boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    296             assertTrue(success);
    297             assertEquals(1, children.size());
    298             assertEquals("775", children.get(0).attributes().getPermission().getOctalString());
    299         }
    300     }
    301 
    302     @Test
    303     @Ignore
    304     public void testParseMlsdSymbolic() {
    305         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    306                 "/www", Path.DIRECTORY_TYPE);
    307 
    308         {
    309             final AttributedList<Path> children = new AttributedList<Path>();
    310             String[] replies = new String[]{
    311                     "Type=OS.unix=slink:/foobar;Perm=;Unique=keVO1+4G4; foobar"
    312             };
    313 
    314             boolean success = path.parseMlsdResponse(children, Arrays.asList(replies));
    315             assertTrue(success);
    316             assertEquals(1, children.size());
    317             assertEquals("/foobar", children.get(0).getSymlinkTarget().getAbsolute());
    318         }
    319     }
    320 
    321     @Test
    322     public void testParseAbsolutePaths() {
    323         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    324                 "/data/FTP_pub", Path.DIRECTORY_TYPE);
    325 
    326         {
    327             final AttributedList<Path> children = new AttributedList<Path>();
    328             String[] replies = new String[]{
    329                     "- [RWCEAFMS] Petersm                             0 May 05  2004 /data/FTP_pub/WelcomeTo_PeakFTP"
    330             };
    331 
    332             boolean success = path.parseListResponse(children, new FTPParserSelector().getParser("NETWARE  Type : L8"),
    333                     Arrays.asList(replies));
    334             assertTrue(success);
    335             assertEquals(1, children.size());
    336             assertEquals("WelcomeTo_PeakFTP", children.get(0).getName());
    337             assertEquals("/data/FTP_pub", children.get(0).getParent().getAbsolute());
    338         }
    339     }
    340 
    341     @Test
    342     @Ignore
    343     public void testParseHardlinkCountBadFormat() {
    344         FTPPath path = (FTPPath) PathFactory.createPath(SessionFactory.createSession(new Host(Protocol.FTP, "localhost")),
    345                 "/store/public/brain", Path.DIRECTORY_TYPE);
    346 
    347         {
    348             final AttributedList<Path> children = new AttributedList<Path>();
    349             String[] replies = new String[]{
    350                     "drwx------+111 mi       public       198 Dec 17 12:29 unsorted"
    351             };
    352 
    353             boolean success = path.parseListResponse(children, new FTPParserSelector().getParser("UNIX"),
    354                     Arrays.asList(replies));
    355             assertTrue(success);
    356             assertEquals(1, children.size());
    357             assertEquals("unsorted", children.get(0).getName());
    358             assertEquals("/store/public/brain", children.get(0).getParent().getAbsolute());
    359         }
    360     }
    36144
    36245    @Test
Note: See TracChangeset for help on using the changeset viewer.
swiss made software