GithubHelp home page GithubHelp logo

goftp's Introduction

goftp - an FTP client for golang

Build Status GoDoc

goftp aims to be a high-level FTP client that takes advantage of useful FTP features when supported by the server.

Here are some notable package highlights:

  • Connection pooling for parallel transfers/traversal.
  • Automatic resumption of interruped file transfers.
  • Explicit and implicit FTPS support (TLS only, no SSL).
  • IPv6 support.
  • Reasonably good automated tests that run against pure-ftpd and proftpd.

Please see the godocs for details and examples.

Pull requests or feature requests are welcome, but in the case of the former, you better add tests.

Tests

How to run tests (windows not supported):

  • ./build_test_server.sh from root goftp directory (this downloads and compiles pure-ftpd and proftpd)
  • go test from the root goftp directory

goftp's People

Contributors

bobcashstory avatar duke-4 avatar eminden avatar jonseymour avatar kucherenkovova avatar madmoose avatar muirmanders avatar recrtl avatar riderx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

goftp's Issues

Failed parsing MLSD response on some servers

Log fragment:

goftp: 0.110 #1 sending command MLSD /somedir
goftp: 0.144 #1 got 150-Using transfer connection
goftp: 0.144 error in ReadDir: failed parsing MLST entry: 

The server response was:

Type=dir;Size=0;Modify=20191124122657; subdir1<CRLF>
Type=dir;Size=0;Modify=20190808091946; subdir2<CRLF>
<CRLF>

Note the last empty line on which the parsing fails.
As to me, to fix this we could ignore empty lines in MLSD response. What do you think?

No error when unable to connect

I was running an FTP server in a local Docker container, MacOSX Mojave. I accidentally started my program while Docker was not running and noticed that it continued with its business although the FTP connection failed.

It turns out that goftp.DialConfig doesn't return an error, even though it logs the failed connection attempt.

Source:

	dialConf := goftp.Config{
		User:               "bob",
		Password:           "12345",
		ConnectionsPerHost: 1,
		Timeout:            12 * time.Hour,
		Logger:             os.Stderr,
	}
	fmt.Printf("Connecting to %s:%d...\n", "...", "...")
	client, dialErr := goftp.DialConfig(dialConf, "127.0.0.1:21")
	fmt.Println(client, dialErr)
	if dialErr != nil {
		return dialErr
	}

This outputs:

Connecting to 127.0.0.1:21...
&{{bob 12345 1 43200000000000 <nil> 0 false 0xc0000a0010 0x1509ae0 false :0 false map[]} [127.0.0.1:21] 0xc0000a2420 map[] map[] 0 0 {0 0} {13757273498589639176 1641114 0x150e0c0} false} <nil>
goftp: 0.000 #1 opening control connection to 127.0.0.1:21
goftp: 0.000 #1 closing
goftp: 0.000 #1 error connecting: dial tcp 127.0.0.1:21: connect: connection refused

Notice the <nil> value, which is a dump of dialErr, and the log output stating that the connection was refused. To fail correctly, I would probably need to run a harmless operation such as STAT on a directory before the error will appear.

EOF when transferring file

I setup the application with the following config:

config := goftp.Config{
        User:               "xxxx",
        Password:           "xxxxx",
        ConnectionsPerHost: 10,
        Timeout:            10 * time.Second,
        Logger:             os.Stderr,
        TLSConfig: &tls.Config{
            InsecureSkipVerify: true,
        },
    }

When I run it i get the following:

goftp: 0.000 #1 opening control connection to [XX.XX.XX.XX]:21
goftp: 0.058 #1 sending command AUTH TLS
goftp: 0.086 #1 got 234-Using authentication type TLS
goftp: 0.086 #1 sending command USER XXXX
goftp: 0.171 #1 got 331-Password required for XXXX
goftp: 0.171 #1 sending command PASS ******
goftp: 0.196 #1 got 230-Logged on
goftp: 0.196 #1 sending command PBSZ 0
goftp: 0.227 #1 got 200-PBSZ=0
goftp: 0.227 #1 sending command PROT P
goftp: 0.250 #1 got 200-Protection level set to P
goftp: 0.250 #1 successfully upgraded to TLS
goftp: 0.250 #1 sending command FEAT
goftp: 0.311 #1 got 211-Features:
 MDTM
 REST STREAM
 SIZE
 MLST type*;size*;modify*;
 MLSD
 AUTH SSL
 AUTH TLS
 PROT
 PBSZ
 UTF8
 CLNT
 MFMT
 EPSV
 EPRT
End
goftp: 0.311 #1 was ready
goftp: 0.311 #1 sending command TYPE I
goftp: 0.333 #1 got 200-Type set to I
goftp: 0.333 #1 sending command EPSV
goftp: 0.360 #1 got 229-Entering Extended Passive Mode (|||50009|)
goftp: 0.360 #1 opening data connection to [XX.XX.XX.XX]:50009
goftp: 0.385 #1 upgrading data connection to TLS
goftp: 0.385 #1 sending command STOR /incoming/test
goftp: 0.410 #1 got 150-Opening data channel for file upload to server of "/incoming/test"
panic: EOF

goroutine 1 [running]:
main.main()
    /Users/stevenjack/Projects/Personal/go-packages/src/github.com/stevenjack/ftps-service/ftps-service.go:36 +0x296
exit status 2

It seems to create the file as there's a blank file in /incoming/test, just not sure why it's not continuing the transfer? @muirmanders Any ideas?

Ability to run raw ftp commands directly

It isn't uncommon for some industries utilizing FTP to make use of SITE commands (i.e. banking). Goftp does not allow the ability to run raw FTP commands, the required functions are not exported, so I wrapped pconn.sendCommand() in order to expose the ability to send arbitrary commands to the server.

stancarney@7335f60

Is it something you might want to add to the library?

proxy support

How to make a ftp client which can support proxy?

add function to create directories recursively

The function would be added as a method to the client and could have the following signature:

func (c *Client) MkdirRecursive(path string) (string, error)

// an alternative name could be `Mkdirs`, I leave this up to you

I don't think it should ever fail if a directory already exist (no matter where in the path), but I'm open to suggestions on this part.

I'm proposing it as it seems like a generic enough feature that others might want it as well. If this seems like something you agree would be a nice addition to the lib than I wouldn't mind putting development time in to get this added as a PR.

For now I already have a first version ready, which probably has plenty of room for improvement, but it might help give the idea and show my willingness to help get this feature in this library. You can find an initial (perhaps prototype?) version I made for my project at: https://github.com/zero-os/0-Disk/blob/196c18e382ae839c9fee9bca457bea49890539ce/nbd/ardb/backup/storage_ftp.go#L214-L260

goftp tests FAIL

for anyone reading

  1. do not put goftp in /root as the tests will FAIL
  2. edit build_test_server.sh and replace curl -O http://download.pureftpd.org... with curl -k -O https://download.pureftpd.org...
  3. if you ran build_test_server.sh as root:
    • edit ftpd/users.txt and replace uid & gid (now 0:0) with numbers above 1000 (eg 1001:1001)
    • run chown -R 1001:1001 testroot (replace 1001:1001 with your numbers)
    • in ./ftpd run pure-ftpd-1.0.36/src/pure-pw mkdb users.pdb -f users.txt

tests should now work

CWD is not work

my code

ftpConfig := goftp.Config{
		User:               username,
		Password:           password,
		ConnectionsPerHost: port,
		Timeout:            10 * time.Second,
		Logger:             os.Stderr,

		//Logger: nil, //关闭日志
	}



ftpDir  := "newDir"
persistentConn, _ := client.OpenRawConn()
persistentConn.SendCommand("CWD %s", ftpDir)
defer persistentConn.Close()

client.Store(item, itemFile)

log




goftp: 0.000 #-1 opening control connection to [120.95.19.68]:21
goftp: 0.041 #-1 sending command USER xiaoming
goftp: 0.061 #-1 got 331-User xiaoming OK. Password required
goftp: 0.061 #-1 sending command PASS ******
goftp: 0.104 #-1 got 230-OK. Current directory is /   
goftp: 0.104 #-1 sending command FEAT
goftp: 0.124 #-1 got 211-Extensions supported:
 UTF8
 EPRT
 IDLE
 MDTM
 SIZE
 MFMT
 REST STREAM
 MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;
 MLSD
 PRET
 AUTH TLS
 PBSZ
 PROT
 ESTA
 PASV
 EPSV
 SPSV
 ESTP
End.
newDir/
goftp: 0.128 #-1 sending command CWD newDir/
goftp: 0.147 #-1 got 250-OK. Current directory is /newDir
goftp: 0.147 #-1 closing




uploadFile:1.txt
goftp: 0.294 #1 opening control connection to [120.95.19.68]:21
goftp: 0.332 #1 sending command USER xiaoming
goftp: 0.351 #1 got 331-User xiaoming OK. Password required
goftp: 0.351 #1 sending command PASS ******

#  why  
goftp: 0.392 #1 got 230-OK. Current directory is /
goftp: 0.392 #1 sending command FEAT

Repeat PROT P after EPSV

First, thank you for this great library!
In my setup, the server is a FileZilla server 0.9.41 behind a firewall. I have found that this server needs the PROT P command repeated after an EPSV. I have patched your library locally to issue such a PROT P in persistentConn.requestPassive() right before the function returns from the EPSV path, which works for my use case. I am sure that this needs to be done in a better way, as most use cases seem not to require this extra PROT P (possibly it even breaks some use cases). So maybe it should be an option in goftp.Config.

Failing data connection with STARTTLS (Explicit TLS): tls session not reused

When trying to connect to ftp servers with STARTTLS (Explicit TLS) the data connection will fail with common ftp server configurations, because the tls session is not reused on the client.

Error-Message on client:
425-Unable to build data connection: Operation not permitted

Error-Message on server:
client did not reuse SSL session, rejecting data connection

Btw. this is no firewall issue: a plain connection (without encryption) works fine.

Also the data connection works, if i change the ftp server configuration (here ProFTPD) and add
TLSOptions NoSessionReuseRequired.
But this does not solve my problem, since I want to use goftp to connect to remote servers and the above configuration flag is uncommon. So i think the ssl session resuage should be solved in goftp client code.

Client log:

goftp: 0.000 #1 opening control connection to [127.0.0.1]:21
goftp: 0.003 #1 sending command AUTH TLS
goftp: 0.004 #1 got 234-AUTH TLS successful
goftp: 0.004 #1 sending command USER username
goftp: 0.025 #1 got 331-Password required for username
goftp: 0.025 #1 sending command PASS ******
goftp: 0.026 #1 got 230-User username logged in
goftp: 0.026 #1 sending command PBSZ 0
goftp: 0.027 #1 got 200-PBSZ 0 successful
goftp: 0.027 #1 sending command PROT P
goftp: 0.027 #1 got 200-Protection set to Private
goftp: 0.027 #1 successfully upgraded to TLS
goftp: 0.027 #1 sending command FEAT
goftp: 0.027 #1 got 211-Features:
 SITE MKDIR
 PBSZ
 AUTH TLS
 MFF modify;UNIX.group;UNIX.mode;
 REST STREAM
 MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.mode*;UNIX.owner*;
 UTF8
 EPRT
 SITE SYMLINK
 EPSV
 SITE UTIME
 MDTM
 SITE RMDIR
 SSCN
 TVFS
 SITE COPY
 MFMT
 SIZE
 PROT
 LANG de-DE.UTF-8*
 CCC
End
goftp: 0.027 #1 sending command EPSV
goftp: 0.028 #1 got 229-Entering Extended Passive Mode (|||4771|)
goftp: 0.028 #1 opening data connection to [127.0.0.1]:4771
goftp: 0.028 #1 upgrading data connection to TLS
goftp: 0.028 #1 sending command MLSD /
goftp: 0.028 #1 got 150-Opening ASCII mode data connection for MLSD
goftp: 0.035 #1 unexpected result: 425-Unable to build data connection: Operation not permitted

Server log (ProFTPD):

2020-01-16 10:27:53,153 mod_tls/2.6[7869]: TLS/TLS-C requested, starting TLS handshake
2020-01-16 10:27:53,173 mod_tls/2.6[7869]: client supports secure renegotiations
2020-01-16 10:27:53,173 mod_tls/2.6[7869]: TLSv1.2 connection accepted, using cipher ECDHE-RSA-AES128-GCM-SHA256 (128 bits)
2020-01-16 10:27:53,176 mod_tls/2.6[7869]: Protection set to Private
2020-01-16 10:27:53,177 mod_tls/2.6[7869]: starting TLS negotiation on data connection
2020-01-16 10:27:53,183 mod_tls/2.6[7869]: client did not reuse SSL session, rejecting data connection (see the NoSessionReuseRequired TLSOptions parameter)
2020-01-16 10:27:53,184 mod_tls/2.6[7869]: unable to open data connection: TLS negotiation failed

Retrieve as a readable stream ?

Hello,

First of all, thank you for making this, connection pooling is the killer feature I needed goftp.
Looking at:

func (c *Client) Retrieve(path string, dest io.Writer) error

my library needs to return an io.Reader but I'm not sure which approach would be the best (I'm migrating this project to golang) .

Now I got something like this:

func (f Ftp) Cat(path string) (io.Reader, error) {
	pr, pw := io.Pipe()
	go func() {
		if err := f.client.Retrieve(path, pw); err != nil {
			pr.CloseWithError(NewError("Problem", 409))
		}
		pw.Close()
	}()
	return pr, nil
}

But the draback is it's a dirty hack :/

The buffer approach is working fine but would be too taxing in term of RAM.

Can you advice? I've been spending hours on this already and can't find an efficient solution that's using both stream and proper error handling

MLSD [...] command not understood

I'm trying to use ReadDir() on ftp.openbsd.org and I get :

unexpected respone: 500-'MLSD /pub/OpenBSD/snapshots/octeon': command not understood.

出错的时候,数据连接没有关闭

connGetter, err := pconn.prepareDataConn()
if err != nil {
pconn.debug("error preparing data connection: %s", err)
return 0, err
}

var cmd string
if dest == nil && src != nil {
	cmd = "STOR"
} else if dest != nil && src == nil {
	cmd = "RETR"
} else {
	panic("this shouldn't happen")
}

err = pconn.sendCommandExpected(replyGroupPreliminaryReply, "%s %s", cmd, path)
if err != nil {
	return 0, err

--------------------------------->>
}

dc, err := connGetter()
if err != nil {
	pconn.debug("error getting data connection: %s", err)
	return 0, err
}

出错的时候,数据连接没有关闭

error in ReadDir: failed parsing LIST entry: in Microsoft FTP Service

** It is Microsoft FTP Service**

my code

# the user and  password  is no ture
ftpConfig := goftp.Config{
		User:               "test",
		Password:           "test",
		ConnectionsPerHost: 21,
		Timeout:            10 * time.Second,
		Logger:             os.Stderr,
	}

	client, err := goftp.DialConfig(ftpConfig, "ftp6335015.host107.sanfengyun.cn")
	if err != nil {
		panic(err)
	}

	client.ReadDir("/Web/")

log

goftp: 0.000 #1 opening control connection to [43.226.149.107]:21
goftp: 0.122 #1 sending command USER ftp6335015
goftp: 0.185 #1 got 331-Password required
goftp: 0.185 #1 sending command PASS ******
goftp: 0.246 #1 got 230-User logged in.
goftp: 0.246 #1 sending command FEAT
goftp: 0.308 #1 got 211-Extended features supported:
 LANG EN*
 UTF8
 AUTH TLS;TLS-C;SSL;TLS-P;
 PBSZ
 PROT C;P;
 CCC
 HOST
 SIZE
 MDTM
 REST STREAM
END
goftp: 0.310 #1 sending command EPSV
goftp: 0.371 #1 got 229-Entering Extended Passive Mode (|||56622|)
goftp: 0.371 #1 opening data connection to [43.226.149.107]:56622
goftp: 0.433 #1 sending command MLSD /Web/
goftp: 0.493 #1 got 500-Command not understood.
goftp: 0.493 #1 was ready
goftp: 0.494 #1 sending command EPSV
goftp: 0.555 #1 got 229-Entering Extended Passive Mode (|||56623|)
goftp: 0.556 #1 opening data connection to [43.226.149.107]:56623
goftp: 0.624 #1 sending command LIST /Web/
goftp: 0.687 #1 got 125-Data connection already open; Transfer starting.
goftp: 0.691 error in ReadDir: failed parsing LIST entry: 10-30-19  06:07PM                  133 2.ht

unexpected response: 550-SSL/TLS required on the control channel (go lang)(Please help me out )

ftpconfig := goftp.Config{

	User:     "*****",
	Password: "*****",
	TLSMode:  0,
}


fmt.Println(ftpconfig)

client, err := goftp.DialConfig(ftpconfig, "******")  # In place of stars i am giving Ip address
if err != nil {
	fmt.Println(err)
}
defer client.Close()

fmt.Println("connected to ftp server successfully!!!")
filename := []string{}

dir, err := client.ReadDir("/")
if err != nil {
	fmt.Println(err)
}
c := 0
fmt.Println(c, dir, filename)

my output :

connected to ftp server successfully!!!
unexpected response: 550-SSL/TLS required on the control channel
0 [] []

Error storing files

Cannot store files I dont have idea of FTP server and version, but this is the log
230 Login successful.
TYPE I 200 Switching to Binary mode.
OPTS UTF8 ON
200 Always in UTF8 mode.
PASV
227 Entering Passive Mode (XXX,XX,16,74,24,231)
STOR Regularizacion/20191911.csv
150 Ok to send data.
readfrom tcp XXX.XX.76.170:59524->XXX.XX.16.74:6375: invalid argument

I've test filezilla FTP server for testing and is working, but with some FTP servers doesn't work....

Stat does not work for directories on servers without MLST

This is a documented bug, but I think it would be useful to have it fixed. This will enable Walk for these servers.

One work-around I see is to do a LIST on the parent directory and scan through the result for the target. Although, maybe someone has a better option?

I think it would also be nice if the library selected the right behaviour with the results of FEAT, rather than issuing MLST and handling the failure every time, see file_system.go#L170.

Thanks!

proxy support

This is a duplicate of #20 but I couldn't find a way to reopen it.

How can we configure the ftp connection to use a proxy? My network requires the use of a proxy in order to access the internet. I've tried setting FTP_PROXY as per the standard, but it didn't work. The connection still attempts to go direct, and thus times out.

ReadDir timeout because of weird port usage

Hello!
I am getting a weird issue while a code similar to the example with config.

After I used the DialConfig function with an url containing a specific port, I try to read the content of a directory which fails becausey

dial tcp <my correct server ip>:<a random port that changes from run to run>: i/o timeout

The random port ends up in the 2xxx range

On the context : I get this error when running the code behind a company firewall. It works fine on my laptop with more a more open internet access

I wonder if this is an issue with pooling or if I have an issue with the firewall which could be fixed with the ActiveListenAddr param?

Thank you and have a nice day

Go module version tags?

I see this package doesn't have any tagged versions right now. Would you consider adding versions to make it easier to use with modules?

error parsing PASV response ('EPSV': command not understood.)

The FTP server I'm using seems to not support the EPSV command. I can't change the FTP server.

goftp: 0.000 #1 opening control connection to [192.168.0.1]:21
goftp: 0.045 #1 sending command USER username
goftp: 0.046 #1 got 331-Password required for username.
goftp: 0.046 #1 sending command PASS ******
goftp: 0.049 #1 got 230-User username logged in.
goftp: 0.049 #1 sending command FEAT
goftp: 0.050 #1 got 500-'FEAT': command not understood.
goftp: 0.051 #1 server doesn't support FEAT: 500-'FEAT': command not understood.
goftp: 0.051 #1 was ready
goftp: 0.052 #1 sending command TYPE I
goftp: 0.053 #1 got 200-Type set to I.
goftp: 0.053 #1 sending command EPSV
goftp: 0.055 #1 got 500-'EPSV': command not understood.
goftp: 0.055 #1 server doesn't support EPSV: 500-'EPSV': command not understood.
goftp: 0.056 #1 sending command PASV
goftp: 0.057 #1 got 227-Entering Passive Mode (192,168,0,1,15,155)
goftp: 0.057 #1 error opening data connection: error parsing PASV response ('EPSV': command not understood.)
panic: error parsing PASV response ('EPSV': command not understood.)

How to support SOCKS ?

Hi,

please how can I do to support, i.e.

dialer, err := proxy.SOCKS5("tcp", socksUrl, &proxy.Auth{User: socksUser, Password: socksPassword}, proxy.Direct) ?

Thank you !

Folder containing closing bracket ] don't MLSD / LIST content

Hi,

I've got an issue while trying to list content using ReadDir (MLSD or LIST) on a folder containing a closing bracket char like /test/brackets/test_[brackets] :

goftp: 0.269 #1 opening control connection to ******
goftp: 0.310 #1 sending command AUTH TLS
goftp: 0.330 #1 got 234-AUTH TLS OK.
goftp: 0.332 #1 sending command USER ******
goftp: 0.399 #1 got 331-User ****** OK. Password required
goftp: 0.400 #1 sending command PASS ******
goftp: 0.438 #1 got 230-This server supports FXP transfers
OK. Current restricted directory is /
goftp: 0.439 #1 sending command PBSZ 0
goftp: 0.459 #1 got 200-PBSZ=0
goftp: 0.460 #1 sending command PROT P
goftp: 0.481 #1 got 200-Data protection level set to "private"
goftp: 0.482 #1 successfully upgraded to TLS
goftp: 0.483 #1 sending command FEAT
goftp: 0.503 #1 got 211-Extensions supported:
 EPRT
 IDLE
 MDTM
 SIZE
 MFMT
 REST STREAM
 MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;
 MLSD
 AUTH TLS
 PBSZ
 PROT
 UTF8
 ESTA
 PASV
 EPSV
 SPSV
End.
goftp: 0.506 #1 sending command EPSV
goftp: 0.527 #1 got 500-Unknown command
goftp: 0.528 #1 server doesn't support EPSV: 500-Unknown command
goftp: 0.529 #1 sending command PASV
goftp: 0.549 #1 got 227-Entering Passive Mode (******,196,51)
goftp: 0.550 #1 opening data connection to ******:50227
goftp: 0.812 #1 upgrading data connection to TLS
goftp: 0.813 #1 sending command MLSD /test/brackets/test_[brackets]
goftp: 0.835 #1 got 150-Accepted data connection
goftp: 0.883 #1 closing

It returns an empty []os.FileInfo but this folder contains files. Do you have any idea?

Thanks!

Retrieve a file from offset?

can this feature be supported where user can specify from where to read?

Current :-

func (c *Client) Retrieve(path string, dest io.Writer) error {

Need :-

func (c *Client) RetrieveFrom(path string, dest io.Writer,bytesSoFar int64) error {

Microsoft FTP Service

Dear author, Is it possible to add support of LIST command output regex matching for Microsoft FTP service ?

failed parsing LIST entry: 10-09-20 09:36PM

aspnet_client

The raw LIST data can be smh like this:

10-09-20  09:36PM       <DIR>          aspnet_client
10-16-20  05:20PM                 6989 Biography.html
10-16-20  05:20PM                 4761 Contact.html
10-09-20  09:36PM       <DIR>          css
10-09-20  09:36PM       <DIR>          geometry
10-09-20  09:36PM       <DIR>          hostmysite.com
10-09-20  09:37PM       <DIR>          image
10-09-20  09:36PM                10309 index.asp
10-16-20  05:21PM                 7236 index.html
10-16-20  05:21PM                15518 Old schedules.html
10-09-20  09:36PM                 4143 page2.html
10-16-20  05:21PM                12736 Programs & Workshops.html
10-09-20  09:36PM                   68 readme.txt
10-16-20  05:21PM                24617 Resume.html
10-16-20  05:21PM                 6238 Schedule.html
10-09-20  09:36PM                 5940 susanwilsonhandweaving.com_1601667712516.php
10-09-20  09:36PM                97485 SWHandweaving-new, with logo.ims
10-09-20  09:36PM                16009 SWHandweaving.ims
10-09-20  09:36PM               102937 SWHandweaving2015.ims
10-16-20  05:21PM               102248 SWHandweaving2018.ims
10-09-20  09:37PM       <DIR>          tmp
10-09-20  09:36PM                  420 web.config

I can show my fast implementation of this, may be it can be integrated

Future of goftp

Hello @muirdm,

I am wondering if I could help with the maintenance of goftp.

I need to add support for the z/OS FTP server for a project of mine. I also see several implementations in the community for Windows FTP Support. Reviewing PR #56 made it clear that my work would conflict.

I also see a few other PRs that I will need to merge into my work. #52 #53

I am sure your life is busy so I am wondering if I can be of help getting through a few PRs?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.