(* netcgi.mli
Copyright (C) 2005-2006
Christophe Troestler
email: Christophe.Troestler@umh.ac.be
WWW: http://math.umh.ac.be/an/
This library is free software; see the file LICENSE for more information.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
LICENSE for more details.
*)
(** Common data-structures for CGI-like connectors.
*
* This library tries to minimize the use of unsafe practices. It
* cannot be bullet proof however and you should read about
* {{:http://www.w3.org/Security/Faq/wwwsf4.html}security}.
*
* REMARK: It happens frequently that hard to predict random numbers
* are needed in Web applications. The previous version of this
* library used to include some facilities for that (in the
* [Netcgi_jserv] module). They have been dropped in favor of
* {{:http://pauillac.inria.fr/~xleroy/software.html#cryptokit}Cryptokit}.
*)
(** {2 Arguments} *)
(** Represent a key-value pair of data passed to the script (including
file uploads). *)
class type cgi_argument =
object
method name : string
(** The name of the argument. *)
method value : string
(** The value of the argument, after all transfer encodings have
been removed. If the value is stored in a file, the file will
be loaded.
@raise Argument.Oversized if the argument was discarded.
@raise Failure if the object has been finalized. *)
method open_value_rd : unit -> Netchannels.in_obj_channel
(** Open the contents of the value as an input channel. This
works for all kinds of arguments, regardless of their
[#storage] and [#representation].
@raise Argument.Oversized if the argument was discarded.
@raise Failure if the object has been finalized. *)
method store : [`Memory | `File of string]
(** Tells whether the argument is stored in memory (as a string)
or as a file (the argument of [`File] being the filename). *)
method content_type : unit -> string * (string * Mimestring.s_param) list
(** Returns the content type of the header and its parameters as a
couple [(hdr, params)]. When the header is missing, the
result is [("text/plain", [])]. Below you will find access
method for frequently used parameters. *)
method charset : string
(** The [charset] parameter of the content type of the header, or
[""] when there is no such parameter, or no header. *)
method filename : string option
(** The [filename] parameter found in the header of file uploads.
When present, [Some name] is returned, and [None] otherwise.
(This is not to be confused with the possible local file
holding the data.) *)
method representation : [ `Simple of Netmime.mime_body
| `MIME of Netmime.mime_message ]
(** The representation of the argument.
- [`Simple] the value of the CGI argument is an unstructured
string value.
- [`MIME] The argument has a MIME header in addition to the
value. The MIME message is read-only. *)
method finalize : unit -> unit
(** Arguments stored in temp files must be deleted when the
argument is no longer used. You can call [finalize] to delete
such files. The method does not have any effect when [store =
`Memory]. The method never raises any exceptions. If the
file no longer exists (e.g. because it was moved away) or if
there are any problems deleting the file, the error will be
ignored.
The [finalize] method is not registered in the garbage
collector. You can do that, but it is usually better to call
this method manually. *)
(* FIXME: Should we do that at the end of the request anyway?
Since the request handler is a callback, this is possible. *)
(* FIXME: Reference counting? *)
end
(** Operations on arguments and lists of thereof. *)
module Argument :
sig
exception Oversized
val simple : string -> string -> cgi_argument
(** [simple_arg name value] creates an unstructured CGI argument
called [name] with contents [value]. *)
val mime : ?work_around_backslash_bug:bool ->
?name:string -> Netmime.mime_message -> cgi_argument
(** [mime_arg ?name msg] creates a MIME-structured CGI argument
called [name] with contents [msg]. You can create [msg] by
either {!Netmime.memory_mime_message} or
{!Netmime.file_mime_message}.
@param name set the name of the argument. If it is not given,
the name is extracted from the "Content-Disposition" field of
the [msg] header or it [""] if this field is not found.
@param work_around_backslash_bug Whether to work around a bug
found in almost all browsers regarding the treatment of
backslashes. The browsers do not quote backslashes in file
names. This breaks RFC standards, however. This argument is
[true] by default. *)
(** It is easy to manipulate lists of arguments with the [List]
module. For example, [List.filter (fun a -> a#name <> n) args]
will remove from [args] all occurrences of the argument with
name [n]. The following functions are helpers for operations
specific to arguments. *)
val clone : ?name:string -> ?value:string -> ?msg:Netmime.mime_message ->
cgi_argument -> cgi_argument
val set : cgi_argument list -> cgi_argument list -> cgi_argument list
(** [set new_args args] creates a list of argument from [args]
deleting the arguments whose name appears in [new_args] and
adding the [new_args] arguments. *)
end
(** Old deprecated writable argument type.
@deprecated Arguments are read-only. *)
class type rw_cgi_argument =
object
inherit cgi_argument
method ro : bool
method set_value : string -> unit
method open_value_wr : unit -> Netchannels.out_obj_channel
end
class simple_argument : ?ro:bool -> string -> string -> rw_cgi_argument
(** Old deprecated simple argument class.
@deprecated Use {!Netcgi.Argument.simple} instead. *)
class mime_argument : ?work_around_backslash_bug:bool ->
string -> Netmime.mime_message -> rw_cgi_argument
(** Old deprecated MIME argument class.
@deprecated Use {!Netcgi.Argument.mime} instead. *)
(** {2 Cookies} *)
(** Functions to manipulate cookies.
You should know that besides the [name] and [value] attribute,
user agents will send at most the [path], [domain] and [port] and
usually will not send them at all.
For interoperability, cookies are set using version 0 (by
Netscape) unless version 1 (RFC 2965 and the older RFC 2109)
fields are set. While version 0 is well supported by browsers,
RFC 2109 requires a recent browser and RFC 2965 is usually not
supported. You do not have to worry however, cookies are always
sent in such a way older browsers understand them -- albeit not
all attributes of course -- so your application can be ready for
the time RFC 2965 will be the norm. *)
module Cookie :
sig
type t = Netcgi_common.Cookie.t
(** Mutable cookie type. *)
val make :
?max_age:int ->
?domain:string ->
?path:string ->
?secure:bool ->
?comment:string ->
?comment_url:string ->
?ports:int list ->
string -> string -> t
(** [make ?expires ?domain ?path ?secure name value] creates a new
cookie with name [name] holding [value].
@param max_age see {!Netcgi.Cookie.set_max_age}.
Default: when user agent exits.
@param domain see {!Netcgi.Cookie.set_domain}.
Default: hostname of the server.
@param path see {!Netcgi.Cookie.set_path}.
Default: script name + path_info.
@param secure see {!Netcgi.Cookie.set_secure}. Default: [false].
@param comment see {!Netcgi.Cookie.set_comment}. Default: [""].
@param comment_url see {!Netcgi.Cookie.set_comment_url}.
Default: [""].
@param ports see {!Netcgi.Cookie.set_ports}.
Default: same port the cookie was sent.
*)
val name : t -> string
(** The name of the cookie. *)
val value : t -> string
(** The value of the cookie. *)
val domain : t -> string option
(** The domain of the cookie, if set. *)
val path : t -> string option
(** The path of the cookie, if set. *)
val ports : t -> int list option
(** [port c] the ports to which the cookie may be returned or [[]] if
not set. *)
val set_value : t -> string -> unit
(** [set_value c v] sets the value of the cookie [c] to [v]. *)
val set_max_age : t -> int option -> unit
(** [set_max_age c (Some t)] sets the lifetime of the cookie [c]
to [t] seconds. If [t <= 0], it means that the cookie should
be discarded immediately. [set_expires c None] tells the
cookie to be discarded when the user agent exits. (Despite
the fact that the name is borrowed from the version 1 of the
specification, it works transparently with version 0.) *)
val set_domain : t -> string option -> unit
(** Cookies are bound to a certain domain, i.e. the browser sends
them only when web pages of the domain are requested:
- [None]: the domain is the hostname of the server.
- [Some domain]: the domain is [domain]. *)
val set_path : t -> string option -> unit
(** Cookies are also bound to certain path prefixes, i.e. the
browser sends them only when web pages at the path or