     [ dupd ftp-retr 150 ftp-assert ]
     [ binary <file-writer> stream-copy ] 2bi*
     ftp-read dup 226 ftp-assert ;
+
+GENERIC# ftp-download 1 ( obj path -- )
+
+M: ftp-client ftp-download ( ftp-client path -- )
+    >r dup ftp-login r>
+    [ parent-directory ftp-cwd drop ]
+    [ file-name ftp-get drop ]
+    [ drop dispose ] 2tri ;
+
+M: string ftp-download ( string path -- )
+    >r <ftp-client> r> ftp-download ;

        swap >>host
        21 >>port
        "anonymous" >>user
        "lol@test.com" >>password ;

: add-response-line ( ftp-response string -- ftp-response )
    over strings>> push ;

    [ "\r\n" swap stream-write ]
    [ stream-flush ] tri ;

: ftp-command ( ftp-client string -- ftp-response )
    swap
    [ ftp-send ] [ ftp-read ] bi ;

: ftp-user ( ftp-client -- ftp-response )
    dup user>> "USER " prepend ftp-command ;

: ftp-password ( ftp-client -- ftp-response )
    dup password>> "PASS " prepend ftp-command ;

: ftp-set-binary ( ftp-client -- ftp-response ) "TYPE I" ftp-command ;

: ftp-pwd ( ftp-client -- ftp-response )
    "PWD" ftp-command ;

: ftp-list ( ftp-client -- ftp-response )
    "LIST" ftp-command ;

: ftp-quit ( ftp-client -- ftp-response )
    "QUIT" ftp-command ;

: ftp-cwd ( ftp-client directory -- ftp-response )
    "CWD " prepend ftp-command ;

: ftp-retr ( ftp-client filename -- ftp-response )
    "RETR " prepend ftp-command ;

: parse-epsv ( ftp-response -- port )
    strings>> first
    "|" split 2 tail* first string>number ;

: ftp-epsv ( ftp-client -- ftp-response ) "EPSV" ftp-command ;

M: ftp-client dispose ( ftp-client -- )
    [ "QUIT" ftp-command drop ] [ stream>> dispose ] bi ;
