Browse Source

Add support for another listing format

Julian Kornberger 10 years ago
parent
commit
94120171fb
2 changed files with 72 additions and 34 deletions
  1. 66 34
      ftp.go
  2. 6 0
      parse_test.go

+ 66 - 34
ftp.go

@@ -290,45 +290,77 @@ func (c *ServerConn) cmdDataConnFrom(offset uint64, format string, args ...inter
 // parseListLine parses the various non-standard format returned by the LIST
 // parseListLine parses the various non-standard format returned by the LIST
 // FTP command.
 // FTP command.
 func parseListLine(line string) (*Entry, error) {
 func parseListLine(line string) (*Entry, error) {
-	fields := strings.Fields(line)
-	if len(fields) < 9 {
-		return nil, errors.New("Unsupported LIST line")
-	}
-
-	e := &Entry{}
-	switch fields[0][0] {
-	case '-':
-		e.Type = EntryTypeFile
-	case 'd':
-		e.Type = EntryTypeFolder
-	case 'l':
-		e.Type = EntryTypeLink
-	default:
-		return nil, errors.New("Unknown entry type")
-	}
+	if strings.HasPrefix(line, "modify=") {
+		e := &Entry{}
+		arr := strings.Split(line, "; ")
+		e.Name = arr[1]
+
+		for _, field := range strings.Split(arr[0], ";") {
+			i := strings.Index(field, "=")
+			if i < 1 {
+				return nil, errors.New("Unsupported LIST line")
+			}
+
+			key := field[:i]
+			value := field[i+1:]
+
+			switch key {
+			case "modify":
+				e.Time, _ = time.Parse("20060102150405", value)
+			case "type":
+				switch value {
+				case "dir", "cdir", "pdir":
+					e.Type = EntryTypeFolder
+				case "file":
+					e.Type = EntryTypeFile
+				}
+			case "size":
+				e.Size, _ = strconv.ParseUint(value, 0, 64)
+			}
+		}
+		return e, nil
+
+	} else {
+		fields := strings.Fields(line)
+		if len(fields) < 9 {
+			return nil, errors.New("Unsupported LIST line")
+		}
+
+		e := &Entry{}
+		switch fields[0][0] {
+		case '-':
+			e.Type = EntryTypeFile
+		case 'd':
+			e.Type = EntryTypeFolder
+		case 'l':
+			e.Type = EntryTypeLink
+		default:
+			return nil, errors.New("Unknown entry type")
+		}
 
 
-	if e.Type == EntryTypeFile {
-		size, err := strconv.ParseUint(fields[4], 10, 0)
+		if e.Type == EntryTypeFile {
+			size, err := strconv.ParseUint(fields[4], 10, 0)
+			if err != nil {
+				return nil, err
+			}
+			e.Size = size
+		}
+		var timeStr string
+		if strings.Contains(fields[7], ":") { // this year
+			thisYear, _, _ := time.Now().Date()
+			timeStr = fields[6] + " " + fields[5] + " " + strconv.Itoa(thisYear)[2:4] + " " + fields[7] + " GMT"
+		} else { // not this year
+			timeStr = fields[6] + " " + fields[5] + " " + fields[7][2:4] + " " + "00:00" + " GMT"
+		}
+		t, err := time.Parse("_2 Jan 06 15:04 MST", timeStr)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
-		e.Size = size
-	}
-	var timeStr string
-	if strings.Contains(fields[7], ":") { // this year
-		thisYear, _, _ := time.Now().Date()
-		timeStr = fields[6] + " " + fields[5] + " " + strconv.Itoa(thisYear)[2:4] + " " + fields[7] + " GMT"
-	} else { // not this year
-		timeStr = fields[6] + " " + fields[5] + " " + fields[7][2:4] + " " + "00:00" + " GMT"
-	}
-	t, err := time.Parse("_2 Jan 06 15:04 MST", timeStr)
-	if err != nil {
-		return nil, err
-	}
-	e.Time = t
+		e.Time = t
 
 
-	e.Name = strings.Join(fields[8:], " ")
-	return e, nil
+		e.Name = strings.Join(fields[8:], " ")
+		return e, nil
+	}
 }
 }
 
 
 // NameList issues an NLST FTP command.
 // NameList issues an NLST FTP command.

+ 6 - 0
parse_test.go

@@ -26,6 +26,12 @@ var listTests = []line{
 	{"d---------   1 owner    group               0 May  9 19:45 Softlib", "Softlib", 0, EntryTypeFolder, time.Date(thisYear, time.May, 9, 19, 45, 0, 0, time.UTC)},
 	{"d---------   1 owner    group               0 May  9 19:45 Softlib", "Softlib", 0, EntryTypeFolder, time.Date(thisYear, time.May, 9, 19, 45, 0, 0, time.UTC)},
 	// WFTPD for MSDOS
 	// WFTPD for MSDOS
 	{"-rwxrwxrwx   1 noone    nogroup      322 Aug 19  1996 message.ftp", "message.ftp", 322, EntryTypeFile, time.Date(1996, time.August, 19, 0, 0, 0, 0, time.UTC)},
 	{"-rwxrwxrwx   1 noone    nogroup      322 Aug 19  1996 message.ftp", "message.ftp", 322, EntryTypeFile, time.Date(1996, time.August, 19, 0, 0, 0, 0, time.UTC)},
+	// Some other
+	{"modify=20150813224845;perm=fle;type=cdir;unique=119FBB87U4;UNIX.group=0;UNIX.mode=0755;UNIX.owner=0; .", ".", 0, EntryTypeFolder, time.Date(2015, time.August, 13, 22, 48, 45, 0, time.UTC)},
+	{"modify=20150813224845;perm=fle;type=pdir;unique=119FBB87U4;UNIX.group=0;UNIX.mode=0755;UNIX.owner=0; ..", "..", 0, EntryTypeFolder, time.Date(2015, time.August, 13, 22, 48, 45, 0, time.UTC)},
+	{"modify=20150806235817;perm=fle;type=dir;unique=1B20F360U4;UNIX.group=0;UNIX.mode=0755;UNIX.owner=0; movies", "movies", 0, EntryTypeFolder, time.Date(2015, time.August, 6, 23, 58, 17, 0, time.UTC)},
+	{"modify=20150814172949;perm=flcdmpe;type=dir;unique=85A0C168U4;UNIX.group=0;UNIX.mode=0777;UNIX.owner=0; _upload", "_upload", 0, EntryTypeFolder, time.Date(2015, time.August, 14, 17, 29, 49, 0, time.UTC)},
+	{"modify=20150813175250;perm=adfr;size=951;type=file;unique=119FBB87UE;UNIX.group=0;UNIX.mode=0644;UNIX.owner=0; welcome.msg", "welcome.msg", 951, EntryTypeFile, time.Date(2015, time.August, 13, 17, 52, 50, 0, time.UTC)},
 }
 }
 
 
 // Not supported, at least we should properly return failure
 // Not supported, at least we should properly return failure