diff --git a/ftp.go b/ftp.go index 66dcf54..6eb30cb 100644 --- a/ftp.go +++ b/ftp.go @@ -4,13 +4,13 @@ package ftp import ( "bufio" "errors" - "fmt" "io" "net" "net/textproto" "strconv" "strings" "time" + "unicode" ) // EntryType describes the different types of an Entry. @@ -337,26 +337,42 @@ func parseRFC3659ListLine(line string) (*Entry, error) { return e, nil } -// parse file or folder name with multiple spaces -func parseLsListLineName(line string, fields []string, offset int) string { - if offset < 1 { - return "" +// parse file or folder name with starting or containing multiple whitespaces +func fieldsLsList(s string) []string { + n := 8 + fields := make([]string, 0, n) + fieldStart := -1 + nextbreak := false + for i, c := range s { + if unicode.IsSpace(c) { + if fieldStart >= 0 { + fields = append(fields, s[fieldStart:i]) + fieldStart = -1 + } + if nextbreak { + fields = append(fields, s[i+1:]) + break + } + } else { + if fieldStart == -1 { + fieldStart = i + if len(fields) == n-1 { + nextbreak = true + } + } + } } - - match := fmt.Sprintf(" %s ", fields[offset-1]) - index := strings.Index(line, match) - if index == -1 { - return "" + if fieldStart != -1 { + fields = append(fields, s[fieldStart:]) } - - index += len(match) - return strings.TrimSpace(line[index:]) + return fields } // parseLsListLine parses a directory line in a format based on the output of // the UNIX ls command. func parseLsListLine(line string) (*Entry, error) { - fields := strings.Fields(line) + fields := fieldsLsList(line) + if len(fields) >= 7 && fields[1] == "folder" && fields[2] == "0" { e := &Entry{ Type: EntryTypeFolder, @@ -412,10 +428,7 @@ func parseLsListLine(line string) (*Entry, error) { return nil, err } - e.Name = parseLsListLineName(line, fields, 8) - if len(e.Name) == 0 { - e.Name = strings.Join(fields[8:], " ") - } + e.Name = fields[8] return e, nil } diff --git a/parse_test.go b/parse_test.go index aa9dba3..3a92ed1 100644 --- a/parse_test.go +++ b/parse_test.go @@ -25,6 +25,8 @@ var listTests = []line{ {"drwxr-xr-x 3 110 1002 3 Dec 02 2009 pub", "pub", 0, EntryTypeFolder, time.Date(2009, time.December, 2, 0, 0, 0, 0, time.UTC)}, {"drwxr-xr-x 3 110 1002 3 Dec 02 2009 p u b", "p u b", 0, EntryTypeFolder, time.Date(2009, time.December, 2, 0, 0, 0, 0, time.UTC)}, {"-rw-r--r-- 1 marketwired marketwired 12016 Mar 16 2016 2016031611G087802-001.newsml", "2016031611G087802-001.newsml", 12016, EntryTypeFile, time.Date(2016, time.March, 16, 0, 0, 0, 0, time.UTC)}, + {"-rw-r--r-- 1 marketwired marketwired 2016 Mar 16 2016 2016031611G087802-001.newsml", "2016031611G087802-001.newsml", 2016, EntryTypeFile, time.Date(2016, time.March, 16, 0, 0, 0, 0, time.UTC)}, + {"-rw-r--r-- 1 marketwired marketwired 12016 Mar 16 2016 2016031611G087802-001.newsml ", " 2016031611G087802-001.newsml ", 12016, EntryTypeFile, time.Date(2016, time.March, 16, 0, 0, 0, 0, time.UTC)}, {"-rwxr-xr-x 3 110 1002 1234567 Dec 02 2009 fileName", "fileName", 1234567, EntryTypeFile, time.Date(2009, time.December, 2, 0, 0, 0, 0, time.UTC)}, {"lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin", "bin -> usr/bin", 0, EntryTypeLink, time.Date(thisYear, time.January, 25, 0, 17, 0, 0, time.UTC)},