(* $Id: ftp_client.mli 459 2006-04-30 19:49:19Z gerd $ *)
(* TODO:
*
* - Timeouts
* - Reasonable exception handling. Currently, exceptions simply fall through
* to the caller which is always Unixqueue.run
* - ftp_connected, ftp_data_conn are probably not correctly set
*)
(** FTP client
*
* Warning: Experimental code! Not all features described in this interface
* work as described!
*
* The client is currently only partially implemented. Especially, the
* STOR and STOU commands are missing. Only IPv4 is supported.
*
* It is intended to implement a large subset of RFC 959 (and later,
* the newer FTP-related RFCs). This includes support for EBCDIC,
* record files, and block mode.
*)
exception FTP_error of exn
(** Something went wrong, often on socket level *)
exception FTP_protocol_violation of string
(** The server violates the FTP specification *)
type cmd_state =
[ `Init
| `Success
| `Proto_error
| `Temp_failure
| `Perm_failure
| `Rename_seq
| `Restart_seq
| `User_pass_seq
| `User_acct_seq
| `Pass_acct_seq
| `Preliminary
]
(** The command state:
* - [`Init]: Just connected, no greeting message arrived yet
* - [`Success]: Got the greeting message/last command was successful
* - [`Proto_error]: {b currently unused}
* - [`Temp_failure]: Last command was not successful, and the code
* was between 400 and 499
* - [`Perm_failure]: Last command was not successful, and the code
* was between 500 and 599
* - [`Rename_seq]: Used instead of [`Success] after the RNFR command
* - [`Restart_seq]: Used instead of [`Success] after the REST command
* - [`User_pass_seq]: Used instead of [`Success] after the USER command
* when a password must be typed in
* - [`User_acct_seq]: Used instead of [`Success] after the USER command
* when an account ID must be typed in
* - [`Pass_acct_seq]: Used instead of [`Success] after the PASS command
* when an account iD must be typed in
* - [`Preliminary]: a reply with code 100 to 199. There will be another
* final reply for the command
*)
type port =
[ `Active of string * int * Unix.file_descr
| `Passive of string * int
| `Unspecified
]
(** The port of the data connection: [`Active] means that the server
* initiates the data connection to the listening client, and in the
* case of [`Passive] the client initiates the data connection to the
* listening server. The string argument is the IP address as dotted
* quad, the int argument is the port number, and the descriptor
* is the listening master socket.
*)
type form_code =
[ `Non_print | `Telnet | `ASA ]
(** The [form_code] has a meaning when FTP is used to print files:
* - [`Non_print]: This is not the case.
* - [`Telnet]: Telnet control codes are used for vertical movement
* - [`ASA]: ASA (Fortran) control codes are used for vertical movement
*)
type representation =
[ `ASCII of form_code option
| `EBCDIC of form_code option
| `Image
]
(** The representation of the transferred file:
* - [`ASCII]: An ASCII variant is used, i.e. the server sends files in
* ASCII encoding with CR/LF as end-of-line marker. Supported by all
* servers.
* - [`EBCDIC]: An EBCDIC variant is used, i.e. the server sends files in
* EBCDIC encoding with NEL as end-of-line marker
* - [`Image]: The file is transferred in its original binary
* representation. Supported by all servers.
*
* "Local" representations are not supported.
*
* This FTP client does not recode the files such that they match the
* selected representation. When files are downloaded, they are stored
* as they are received. When files are uploaded, they are sent as they
* are. The user of this client must do recodings when necessary
* (the class {!Ftp_data_endpoint.data_converter} may be useful for this).
*
* If no representation is selected, FTP servers assume [`ASCII None]
* as default.
*)
type structure =
[ `File_structure
| `Record_structure
]
(** The client supports two structures:
* - [`File_structure]: Files are simply contiguous streams of bytes
* - [`Record_structure]: Files are sequences of records. FTP does
* not make a difference between variable and fixed length records.
* It is not forbidden that the records are themselves structured
* into lines, in fact it can happen that end-of-line markers are
* contained in binary records. Operating systems that support
* record-structured files often store text files in this format, i.e.
* every line is stored in its own record, without end-of-line marker.
* If record structure is selected by a STRU command, it is recommended
* to use the classes {!Ftp_data_endpoint.out_record_channel} and
* {!Ftp_data_endpoint.in_record_channel} for the local representation
* of the files, otherwise the records may be incorrectly mapped
* to the local conventions.
*
* Page-structured files (i.e. indexed files) are not supported.
*
* If no structure is selected, FTP servers will assume file structure
* as default.
*)
type transmission_mode =
[ `Stream_mode
| `Block_mode
]
(** The transmission mode selects how the data are encoded in the data
* connection.
* - [`Stream_mode]: This is the simple format that is responsible for
* all the failed FTP downloads. It is supported by all FTP servers,
* actually, you cannot assume a better transmission mode from an
* unknown FTP server. It is unreliable because it cannot distinguish
* between a transmission failure and the regular end-of-file condition.
* - [`Block_mode]: This is an improved format using frames to protect
* the transmitted data. Unfortunately, almost no FTP server supports
* it.
*
* Both modes are compatible with both structures, i.e. you can transfer
* a record-structured file in stream mode and a flat file in block
* mode. However, in practise this is not the case. Servers that only
* know flat files are likely to only support stream mode, and servers
* implementing record structure imply that block transfers base on
* the record format. So the advise is to use stream mode for flat
* files, and block mode for record files.
*)
type ftp_state =
{ cmd_state : cmd_state; (** the command state *)
ftp_connected : bool; (** whether connected with the server *)
ftp_data_conn : bool; (** whether there is a clean data conn *)
ftp_user : string option; (** successfully sent user identifier *)
ftp_password : string option; (** successfully sent password *)
ftp_account : string option; (** successfully sent account identifier *)
ftp_logged_in : bool; (** whether the user is logged in *)
ftp_port : port; (** the selected port *)
ftp_repr : representation; (** the selected representation *)
ftp_structure : structure; (** the selected structure *)
ftp_trans : transmission_mode; (** the selected trans mode *)
ftp_dir : string list;
(** The current directory, expressed as list of CWD changes minus
* CDUP changes. This is only reasonable if CWD does not include
* slashes. The list is in reverse order, i.e. deepest directory
* first.
*)
ftp_features : (string * string option) list option;
(** The list of features returned by the last FEAT command.
* [None] means that no FEAT command was yet tried.
* [Some []] means that there are no features (either FEAT
* returned an empty list, or the FEAT command is not implemented
* by the server). Otherwise the list enumerates pairs
* [(label,param)] where [label] is the case-sensitive feature
* label and [param] the optional parameter. There is no
* defined order for the list of features.
*)
ftp_options : (string * string option) list;
(** Remembers the OPTS commands sent to the server. The list
* enumerates pairs [(command,optionparam)], where [command]
* is the uppercase command name the option refers to. Only
* the last negotiated [optionparam] for the command is remembered.
*)
}
(** The ftp_state reflects the knowledge of the client about what has been
* agreed upon with the server.
*)
type cmd =
[ `Connect
| `Dummy
(* RFC 959 - standard FTP *)
| `USER of string
| `PASS of string
| `ACCT of string
| `CWD of string
| `CDUP
| `SMNT of string
| `QUIT
| `REIN
| `PORT (* port is automatically chosen *)
| `PASV
| `TYPE of representation
| `STRU of structure
| `MODE of transmission_mode
| `RETR of string * (ftp_state -> Ftp_data_endpoint.local_receiver)
| `STOR of string * (ftp_state -> Ftp_data_endpoint.local_sender)
| `STOU of (unit -> Ftp_data_endpoint.local_sender)
| `APPE of string * (ftp_state -> Ftp_data_endpoint.local_sender)
| `ALLO of int * int option
| `REST of string
| `RNFR of string
| `RNTO of string
| `DELE of string
| `RMD of string
| `MKD of string
| `PWD
| `LIST of string option * (ftp_state -> Ftp_data_endpoint.local_receiver)
| `NLST of string option * (ftp_state -> Ftp_data_endpoint.local_receiver)
| `SITE of string
| `SYST
| `STAT of string option
| `HELP of string option
| `NOOP
(* Extensions *)
(* RFC 2389 - feature negotiation *)
| `FEAT
| `OPTS of string * string option
(* ExtFTP Working Group *)
| `MDTM of string
]
(** An FTP command. {b Currently, STOR, STOU and APPE are not supported.} *)
type reply = int * string
(** Reply code plus text *)
(** The client protocol interpreter..