{"size": 6682, "ext": "scrbl", "max_stars_repo_path": "pkgs/net-doc/net/scribblings/ftp.scrbl", "max_stars_repo_name": "lkh01/racket", "max_stars_repo_stars_event_min_datetime": "2018-07-05T21:18:24.000Z", "max_stars_repo_stars_event_max_datetime": "2021-06-04T14:48:37.000Z", "max_issues_repo_path": "pkgs/net-doc/net/scribblings/ftp.scrbl", "max_issues_repo_name": "lkh01/racket", "max_issues_repo_issues_event_min_datetime": "2017-05-10T07:33:20.000Z", "max_issues_repo_issues_event_max_datetime": "2018-07-19T15:49:46.000Z", "max_forks_repo_path": "pkgs/net-doc/net/scribblings/ftp.scrbl", "max_forks_repo_name": "lkh01/racket", "max_forks_repo_forks_event_min_datetime": "2016-04-25T11:47:57.000Z", "max_forks_repo_forks_event_max_datetime": "2017-05-09T14:52:48.000Z"}
{"max_stars_count": 4, "max_issues_count": 9, "max_forks_count": 3, "avg_line_length": 37.9659090909, "max_line_length": 93, "alphanum_fraction": 0.6197246333}
#lang scribble/doc
@(require "common.rkt" (for-label net/ftp net/ftp-unit net/ftp-sig))

@title[#:tag "ftp"]{FTP: Client}

@author["Micah Flatt"
        (author+email "Chen Xiao" "chenxiao770117@gmail.com")]

@defmodule[net/ftp]{The @racketmodname[net/ftp] library provides
utilities for FTP client operations.}


@section[#:tag "ftp-procs"]{Functions}

@defproc[(ftp-connection? [v any/c]) boolean?]{

Returns @racket[#t] if @racket[v] represents an FTP connection as
returned by @racket[ftp-establish-connection], @racket[#f] otherwise.}


@defproc[(ftp-establish-connection [server string?]
                                   [port-no (integer-in 0 65535)]
                                   [user string?]
                                   [passwd string?])
          ftp-connection?]{

Establishes an FTP connection with the given server using the supplied
username and password. The @racket[port-np] argument usually should be
@racket[21].}


@defproc[(ftp-close-connection [ftp-conn ftp-connection?]) void?]{

Closes an FTP connection.}


@defproc[(ftp-cd [ftp-conn ftp-connection?] [new-dir string?]) void?]{

Changes the current directory on the FTP server to @racket[new-dir].
The @racket[new-dir] argument is not interpreted at all, but simply
passed on to the server; it must not contain a newline.}

@defproc[(ftp-directory-list [ftp-conn ftp-connection?]
                             [path (or/c false/c string?) #f])
         (listof (list/c (one-of/c "-" "d" "l")
                         string?
                         string?))]{

Returns a list of files and directories in the current directory of the
server, assuming that the server provides directory information in the
quasi-standard Unix format.  If a @racket[path] argument is given, use
it instead of the current directory.

Each file or directory is represented by a list of three or four
strings.  The first string is either @racket["-"], @racket["d"], or
@racket["l"], depending on whether the items is a file, directory, or
link, respectively.  The second item is the file's date; to convert this
value to seconds consistent with @racket[file-seconds], pass the date
string to @racket[ftp-make-file-seconds].  The third string is the name
of the file or directory.  If the item is a file (the first string is
@racket["-"]), and if the line that the server replied with has a size
in the expected place, then a fourth string containing this size is
included.

Warning: the FTP protocol has no specification for the reply format, so
this information can be unreliable.}


@defproc[(ftp-make-file-seconds [ftp-date string?]) exact-integer?]{

Takes a date string produced by @racket[ftp-directory-list] and
converts it to seconds (which can be used with
@racket[seconds->date]).

Warning: the FTP protocol has no specification for the reply format, so
this information can be unreliable.}


@defproc[(ftp-download-file [ftp-conn ftp-connection?]
                            [local-dir path-string?]
                            [file string?]
                            [#:progress progress-proc
                                        (or/c #f 
                                              (-> (-> (values exact-nonnegative-integer? 
                                                              evt?)) 
                                                  any)) 
                                        #f]) 
         void?]{

Downloads @racket[file] from the server's current directory and puts
it in @racket[local-dir] using the same name. If the file already
exists in the local directory, it is replaced, but only after the
transfer succeeds (i.e., the file is first downloaded to a temporary
file in @racket[local-dir], then moved into place on success).

If @racket[progress-proc] is not @racket[#f], then it is called with a
function @racket[_get-count] that returns two values: the number of bytes
transferred so far, and an event that becomes ready when the
transferred-bye count changes. The @racket[_get-count] function can be
called in any thread and any number of times. The @racket[progress-proc] function should
return immediately, perhaps starting a thread that periodically polls
@racket[_get-count]. Do not poll too frequently, or else polling
will slow the transfer; the second argument from @racket[_get-count]
is intended to limit polling.

@racketblock[
(ftp-download-file
 ftp-conn "." "testfile"
 #:progress
 (lambda (get-count)
   (thread
    (lambda ()
      (let loop ()
        (define-values (count changed-evt) (get-count))
        (printf "~a bytes downloaded\n" count)
        (sync changed-evt)
        (loop))))))
]}

@defproc[(ftp-upload-file [ftp-conn ftp-connection?]
                          [file-path path-string?]
                          [#:progress progress-proc
                                      (or/c #f 
                                            (-> (-> (values exact-nonnegative-integer? 
                                                            evt?)) 
                                                any)) 
                                      #f])
         void?]{

Upload @racket[file-path] to the server's current directory using the same name. 
If the file already exists in the local directory, it is replaced.
The @racket[progress-proc] argument is used in the same way as in @racket[ftp-download-file],
but to report uploaded bytes instead of downloaded bytes.}

@defproc[(ftp-delete-file [ftp-conn ftp-connection?]
                          [file-path path-string?]) void?]{
Delete the remote file use the @racket[file-path] on the server.}

@defproc[(ftp-make-directory [ftp-conn ftp-connection?]
                             [dir-name string?]) void?]{
Make remote directory use the @racket[dir-name].}

@defproc[(ftp-delete-directory [ftp-conn ftp-connection?]
                               [dir-name string?]) void?]{
Delete remote directory use the @racket[dir-name].}

@defproc[(ftp-rename-file [ftp-conn ftp-connection?]
                          [origin string?]
                          [dest string?]) void?]{
Rename remote file name from @racket[origin] to @racket[dest].}


@; ----------------------------------------

@section{FTP Unit}

@margin-note{@racket[ftp@] and @racket[ftp^] are deprecated.
They exist for backward-compatibility and will likely be removed in
the future. New code should use the @racketmodname[net/ftp] module.}

@defmodule[net/ftp-unit]

@defthing[ftp@ unit?]{

Imports nothing, exports @racket[ftp^].}

@; ----------------------------------------

@section{FTP Signature}

@defmodule[net/ftp-sig]

@defsignature[ftp^ ()]{}

Includes everything exported by the @racketmodname[net/ftp] module.
