From fcad893ae782599c4bafbe8d104c8f63cb7d4cc5 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Sun, 13 Sep 2020 11:08:48 +0100 Subject: [PATCH] Implement PRET command for distributed ftp servers, eg drftpd See: https://tools.ietf.org/html/draft-dd-pret-00 Fixes #197 --- ftp.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ftp.go b/ftp.go index b7c0392..11f6289 100644 --- a/ftp.go +++ b/ftp.go @@ -38,6 +38,7 @@ type ServerConn struct { features map[string]string skipEPSV bool mlstSupported bool + usePRET bool } // DialOption represents an option to start a new connection with Dial @@ -280,6 +281,9 @@ func (c *ServerConn) Login(user, password string) error { if _, mlstSupported := c.features["MLST"]; mlstSupported { c.mlstSupported = true } + if _, usePRET := c.features["PRET"]; usePRET { + c.usePRET = true + } // Switch to binary mode if _, _, err = c.cmd(StatusCommandOK, "TYPE I"); err != nil { @@ -486,6 +490,15 @@ func (c *ServerConn) cmd(expected int, format string, args ...interface{}) (int, // cmdDataConnFrom executes a command which require a FTP data connection. // Issues a REST FTP command to specify the number of bytes to skip for the transfer. func (c *ServerConn) cmdDataConnFrom(offset uint64, format string, args ...interface{}) (net.Conn, error) { + // If server requires PRET send the PRET command to warm it up + // See: https://tools.ietf.org/html/draft-dd-pret-00 + if c.usePRET { + _, _, err := c.cmd(-1, "PRET "+format, args...) + if err != nil { + return nil, err + } + } + conn, err := c.openDataConn() if err != nil { return nil, err