ocamlnet-3.7.3/0000755000175000017500000000000012210163244011745 5ustar gerdgerdocamlnet-3.7.3/Makefile0000644000175000017500000000425512210163242013411 0ustar gerdgerd# make all: compiles the configured packages with ocamlc # make opt: compiles the configured packages with ocamlopt # make install: installs the configured packages # make clean: cleans everything up # Inclusion of Makefile.conf may fail when cleaning up: -include Makefile.conf NAME=ocamlnet TOP_DIR=. # PKGLIST: should be set in Makefile.conf. It contains the packages to # compile and to install. The following assignment sets it to its # default value if no Makefile.conf exists. PKGLIST ?= netstring cgi .PHONY: all all: for pkg in $(PKGLIST); do \ ( cd src/$$pkg && $(MAKE) -f Makefile.pre generate ) || exit; \ ( cd src/$$pkg && $(MAKE) -f Makefile.pre depend ) || exit; \ ( cd src/$$pkg && $(MAKE) all ) || exit; \ done .PHONY: opt opt: for pkg in $(PKGLIST); do \ ( cd src/$$pkg && $(MAKE) -f Makefile.pre generate ) || exit; \ ( cd src/$$pkg && $(MAKE) -f Makefile.pre depend ) || exit; \ ( cd src/$$pkg && $(MAKE) opt ) || exit; \ done .PHONY: doc doc: for pkg in src/*/.; do \ test ! -f $$pkg/Makefile -o -f $$pkg/doc-ignore || \ { ( cd $$pkg && $(MAKE) -f Makefile.pre generate ) || exit; \ ( cd $$pkg && $(MAKE) -f Makefile.pre depend ) || exit; \ ( cd $$pkg && $(MAKE) ocamldoc.dump ) || exit; \ }; \ done cd doc; $(MAKE) doc # The following PHONY rule is important for Cygwin: .PHONY: install install: for pkg in $(PKGLIST); do \ ( cd src/$$pkg && $(MAKE) -f Makefile.pre install ) || exit; \ done .PHONY: uninstall uninstall: for pkg in src/*/.; do \ test ! -f $$pkg/Makefile || \ ( cd $$pkg && $(MAKE) -f Makefile.pre uninstall); \ done .PHONY: clean clean: for pkg in src/*/.; do \ test ! -f $$pkg/Makefile || \ ( cd $$pkg && $(MAKE) -f Makefile.pre clean); \ done if test -f doc/Makefile; then cd doc && $(MAKE) clean; fi .PHONY: clean-doc clean-doc: for pkg in src/*/.; do \ test ! -f $$pkg/Makefile -o -f $$pkg/doc-ignore || \ ( cd $$pkg && $(MAKE) -f Makefile.pre clean-doc); \ done cd doc && $(MAKE) clean-doc .PHONY: CLEAN CLEAN: clean .PHONY: distclean distclean: rm -f Makefile.conf rm -rf tmp for pkg in src/*/.; do \ test ! -f $$pkg/Makefile || \ ( cd $$pkg && $(MAKE) -f Makefile.pre distclean); \ done ocamlnet-3.7.3/INSTALL0000644000175000017500000002166112210163242013002 0ustar gerdgerdHow to install ocamlnet ocamlnet is a quite large library, and is split up into several parts. Usually, it is not necessary to install all of ocamlnet, and there are configuration options allowing you to select what you want. The following table gives a rough overview. The libraries you must build at minimum are tagged as CORE. For the other libraries the configuration option is shown that will select them for build: Library Option What it provides ---------------------------------------------------------------------- cgi CORE This is an alias for netcgi1 equeue CORE Event queues equeue-gtk1 -enable-gtk Event queues - integration into lablgtk equeue-gtk2 -enable-gtk2 Event queues - integration into lablgtk2 equeue-ssl -enable-ssl Event queues - SSL support equeue-tcl -enable-tcl Event queues - integration into labltk netcamlbox CORE Multiprocessing netcgi2 CORE Web applications (revised lib) netcgi2-apache -enable-apache Web applications as Apache module netcgi2-plex CORE Web applications - support for netplex netclient CORE Clients for HTTP, FTP, Telnet nethttpd -with-nethttpd Web server nethttpd-for-netcgi2 (same as nethttpd) netmech-scram -enable-crypto SCRAM authentication mechanism netmulticore CORE Multiprocessing netplex CORE Generic server framework netshm CORE Shared memory for IPC netstring CORE String routines (e.g. URLs, HTML, Mail) netstring-pcre -enable[-full]-pcre PCRE layer netsys CORE System interfaces missing in Unix netzip -enable-zip read/write gzip data using object channels pop CORE POP3 client rpc CORE Sophisticated SunRPC/ONCRPC implementation rpc-auth-dh -with-rpc-auth-dh SunRPC/ONCRPC - Add-on for Diffie-Hellman auth rpc-auth-local CORE (*) SunRPC/ONCRPC - Add-on for local auth rpc-generator CORE SunRPC/ONCRPC - Stub generator rpc-ssl -enable-ssl SunRPC/ONCRPC - Add-on for SSL support rpc-xti CORE (*) SunRPC/ONCRPC - Add-on for XTI-only transports shell CORE Sophisticated version of Sys.command smtp CORE SMTP client ---------------------------------------------------------------------- (*) If the operation system supports it You should know that before ocamlnet-2.2 these libraries were distributed as several software packages (called ocamlnet, equeue, rpc, netclient). If you want to upgrade, you must upgrade all libraries at once and replace them with the versions coming with ocamlnet-2.2. For your convenience, the configuration options allow you to select libraries by prerequisites, e.g. -enable-ssl installs all libraries that need SSL. The following matrix shows which prerequisites are needed for which libraries: Option Prerequisite Version/Where to get/What it is ---------------------------------------------------------------------- CORE findlib >= 1.0 http://www.ocaml-programming.de/packages Library manager -enable-pcre or -enable-full-pcre pcre >= 5 (pcre-ocaml) http://www.ocaml.info/ocaml_sources Regular expressions library CHANGED IN OCAMLNET-3.6.4 !!! PLEASE READ doc/html-main/Regexp.html -enable-gtk lablgtk >= 1.2 (*) http://wwwfun.kurims.kyoto-u.ac.jp/soft/ olabl/lablgtk.html Bindings for gtk GUIs -enable-gtk2 lablgtk2 probably any (*) http://wwwfun.kurims.kyoto-u.ac.jp/soft/ olabl/lablgtk.html Bindings for gtk2 GUIs -enable-ssl ssl probably any (ocaml-ssl) http://savonet.sourceforge.net/ Bindings for openssl -enable-tcl labltk probably any part of the O'Caml distribution Bindings for tcl/tk GUIs -enable-zip camlzip >= 1.01 http://pauillac.inria.fr/~xleroy/software.html Bindings for zlib -enable-crypto cryptokit probably any Xavier Leroy's crypto package -with-nethttpd none none Note: nethttpd must be explicitly selected because it is distributed under different license conditions than the other libraries. See the file LICENSE for more. -with-auth-dh cryptgps probably any http://www.ocaml-programming.de/packages Cryptographic library Note: At runtime, -with-auth-dh needs further prerequisites, namely the so-called keyserv daemon. ---------------------------------------------------------------------- (*) The distribution of this prerequite does not include findlib support. It is, however, silently assumed the prerequisite library is installed in the findlib way. Sorry if this is inconvenient for you. In order to configure ocamlnet, just run the "configure" script with the mentioned options (-enable-X and -with-X). There are a few other options, as listed below. By default, the library archives are installed into the findlib default location. You can find out this location with the command ocamlfind printconf destdir For every ocamlnet library, a subdirectory is created where the files are installed. The few binary executables are installed into the directory where the ocaml compilers are installed. The data files are installed into the same directory as the netstring archives. The "configure" run shows all effective options. Option What it changes ---------------------------------------------------------------------- -bindir Binary executables are installed in -datadir Data files are installed in . Note: This directory is compiled into the netstring library, and cannot be changed at runtime. -equeue-tcl-defs Only if you have -enable-tcl: Sets options for the C compiler so the include files for tcl are found. E.g. -equeue-tcl-defs -I/usr/include/tcl8.4 -equeue-tcl-libs Only if you have -enable-tcl: Sets options for the linker so the tcl library is found. E.g. -equeue-tcl-libs -ltcl8.4 -auth-dh-style \n"; printf "

%i — %s

\n" code info; out "

Cause of the error:

"; out "

"; out msg; out "

\n"; out "

Additional information:

"; out "

"; out html; out "

\n

"; let date = Netdate.create ~zone:Netdate.localzone now in printf "Date: %s
\n" (Netdate.format "%c" date); printf "Script: %s
\n" script_name; printf "Request method: %s
\n" env#cgi_request_method; printf "Query string: %s
\n" env#cgi_query_string; printf "Browser: %s
\n" (String.escaped env#user_agent); out "

\n"; (try let referer = env#input_header_field "referer" in printf "Go back\n" referer (* FIXME: escape *) with Not_found -> ()); out "\n\n"; env#out_channel#flush(); env#out_channel#close_out() ) with _ -> () (* We were supposed to report the error but if that itself raised an exception (e.g. the output channel was closed), there is not much we can do... *) let handle_uncaught_exn (env:cgi_environment) = function | HTTP(`Continue, _) | HTTP(`Switching_protocols, _) (* 2xx: (successful) *) | HTTP(`Ok, _) | HTTP(`Created, _) | HTTP(`Accepted, _) | HTTP(`Non_authoritative, _) | HTTP(`No_content, _) | HTTP(`Reset_content, _) | HTTP(`Partial_content, _) (* 3xx: (redirection) *) | HTTP(`Multiple_choices, _) | HTTP(`Moved_permanently, _) | HTTP(`Found, _) | HTTP(`See_other, _) | HTTP(`Not_modified, _) | HTTP(`Use_proxy, _) | HTTP(`Temporary_redirect, _) -> (* It is s a bit funny to raise an exception not indicating a failure (this library does not do it). We interpret it as a normal but early termination of the response *) env#out_channel#close_out(); (* 4xx: (client error) *) | HTTP(`Bad_request, s) -> error_page env `Bad_request [] s "You should not repeat the request without modifications." | HTTP(`Unauthorized, s) -> let challenge = "" in error_page env `Unauthorized ["WWW-Authenticate", [challenge]] s "" | HTTP(`Payment_required, s) -> error_page env `Payment_required [] s "" | HTTP(`Forbidden, s) -> error_page env `Forbidden [] s "The request should not be repeated." | HTTP(`Not_found, s) -> error_page env `Not_found [] s "The server has not found anything matching the Request-URI." | HTTP(`Method_not_allowed, s) -> (* Allow header must be sent *) let meths = List.map string_of_http_method env#config.permitted_http_methods in let allow = String.concat ", " meths in error_page env `Method_not_allowed ["Allow", [allow]] s ("Only the following methods are allowed: " ^ allow) | HTTP(`Not_acceptable, s) -> error_page env `Not_acceptable [] s "The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request." | HTTP(`Proxy_auth_required, s) -> error_page env `Proxy_auth_required [] s "Your browser must first authenticate itself with the proxy." | HTTP(`Request_timeout, s) -> error_page env `Request_timeout [] s "Your browser waited too long to send the data. You can repeat the request without modifications at any later time." | HTTP(`Conflict, s) -> error_page env `Bad_request [] s "The request could not be completed due to a conflict with the current state of the resource. Please resolve the conflict and resubmit the request. " | HTTP(`Gone, s) -> error_page env `Bad_request [] s "The requested resource is no longer available at the server and no forwarding address is known." | HTTP(`Length_required, s) -> error_page env `Bad_request [] s "Content-Length is required. You may repeat the request with a valid Content-Length." | HTTP(`Precondition_failed, s) -> error_page env `Bad_request [] s "The precondition given in one or more of the request-header fields evaluated to false when it was tested on the server. " | HTTP(`Request_entity_too_large, s) -> error_page env `Request_entity_too_large [] s "Please try again with smaller files!" | HTTP(`Request_uri_too_long, s) -> error_page env `Request_uri_too_long [] s "The server is refusing to service the request because the Request-URI is bigger than 4Mb." | HTTP(`Unsupported_media_type, s) -> let ct = String.concat ", " env#config.permitted_input_content_types in error_page env `Unsupported_media_type [] s ("The following Content-Type are authorized: " ^ ct) | HTTP(`Requested_range_not_satisfiable, s) -> error_page env `Requested_range_not_satisfiable [] s "" | HTTP(`Expectation_failed, s) -> error_page env `Expectation_failed [] s "" (* 5xx: (server error) *) | HTTP(`Internal_server_error, s) -> error_page env `Internal_server_error [] s "Please write to the author of the application to tell him!" | HTTP(`Not_implemented, s) -> error_page env `Not_implemented [] s "The server does not support the functionality required to fulfill the request." | HTTP(`Bad_gateway, s) -> error_page env `Bad_gateway [] s "The server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request." | HTTP(`Service_unavailable, s) -> error_page env `Service_unavailable [] s "The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. Please try again later." | HTTP(`Gateway_timeout, s) -> error_page env `Gateway_timeout [] s "The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server it accessed in attempting to complete the request." | HTTP(`Http_version_not_supported, s) -> error_page env `Http_version_not_supported [] s "The server does not support, or refuses to support, the HTTP protocol version that was used in the request message." (* Other exceptions *) | Exit -> (* FIXME: This is seen as an acceptable way to terminate early. *) env#out_channel#close_out() | exn -> error_page env `Internal_server_error [] (Netexn.to_string exn) "This indicates an error in the application (not in the supporting library). Please report it to the author or company that runs this software." (* REMARK: With this choice of [exn_handler], the user may add some code before and after the execution of [run_cgi] but does not have to re-raise exceptions it does not care about (as is the case if [exn_handler] is passed all exceptions as arg). *) let exn_handler_default (env:cgi_environment) ~exn_handler ~finally run_cgi = let special_exn = ref None in (try exn_handler env (fun () -> special_exn := run_cgi()); finally() with | Exit -> (* [Exit] is considered as a proper way to terminate early *) finally() | exn when env#config.default_exn_handler -> (* exception not handled (or raised) by the user provided [exn_handler] *) handle_uncaught_exn env exn; finally() ); match !special_exn with None -> () | Some e -> raise e (* Accumulate input header and CGI properties ***********************************************************************) (* The MSIE Content-Type bug is dealt with when the environment object is created. The field names of [inheader] MUST be lowercased to input to the class [environment]. *) let shift_to_lowercase = Char.code 'a' - Char.code 'A' let update_props_inheader ((name, value) as nv) (props, inheader) = if name = "CONTENT_TYPE" then (props, ("content-type", value) :: inheader) else if name = "CONTENT_LENGTH" then (props, ("content-length", value) :: inheader) else if is_prefix "HTTP_" name then ( (* Remove the "HTTP_" from the name, lowercase, and convert any '_' to '-'. *) let len = String.length name - 5 in let hname = String.sub name 5 len in for i = 0 to len - 1 do unsafe_set hname i (match unsafe_get hname i with | '_' -> '-' | 'A' .. 'Z' as c -> (* ASCII *) Char.unsafe_chr(Char.code c + shift_to_lowercase) | c -> c) done; (props, (hname, value) :: inheader) ) else (nv :: props, inheader) ocamlnet-3.7.3/src/netcgi2/netcgi_dbi.mli0000644000175000017500000000506212210163243016663 0ustar gerdgerd(* netcgi_dbi.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. *) (** Pools of connections for the ocamldbi generic database interface. *) module type DBI_DRIVER = sig type connection val connect : ?host:string -> ?port:string -> ?user:string -> ?password:string -> string -> connection val close : connection -> unit val closed : connection -> bool val commit : connection -> unit val ping : connection -> bool val rollback : connection -> unit end module type DBI_POOL = sig type connection val get : Netcgi.cgi -> ?host:string -> ?port:string -> ?user:string -> ?password:string -> string -> connection (** Example: [module MyPool = DbiPool(Dbi_postgres)] * * [let dbh = MyPool.get request "database_name"] * * Returns an unused [Dbi.connection] handle from the pool of * database handles. Or it may create a new database connection * and return that. * * The parameters uniquely identify the database name * (eg. "comments") and optional parameters. Separate pools are * maintained for each combination of parameters. * * The connection is automatically returned to the pool at the * end of the [cgi] request. After this time the connection may * be given away to another user. For this reason, the calling * code must NEVER stash the connection across requests * (instead, call [get] to get a new handle each time). * * On returning the handle to the pool, the pool performs a * ROLLBACK operation on the handle, thus losing any changes * (INSERT, etc.) made to the database. If the program wants to * preserve changes, it must perform a COMMIT operation itself, * by calling [Dbi.connection.commit]. *) end module DbiPool(Dbi_driver : DBI_DRIVER) : (DBI_POOL with type connection = Dbi_driver.connection) (** [module MyPool = DbiPool (Dbi_postgres)] * * creates a pool of PostgreSQL database handles. To use them: * * [let dbh = MyPool.get r "database_name"] * * Gets you a new or recycled database handle [dbh] which is valid until * the end of the current Apache request. *) ocamlnet-3.7.3/src/netcgi2/netcgi.mli0000644000175000017500000012021212210163243016040 0ustar gerdgerd(* 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. N.B. This module appears also as {!Nethttp.Cookie}. *) module Cookie : sig type t = Nethttp.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 max_age : t -> int option (** The expiration time of the cookie, in seconds. [None] means that the cookie will be discarded when the browser exits. This information is not returned by the browser. *) val secure : t -> bool (** Tells whether the cookie is secure. This information is not returned by the browser. *) val comment : t -> string (** Returns the comment associated to the cookie or [""] if it does not exists. This information is not returned by the browser. *) val comment_url : t -> string (** Returns the comment URL associated to the cookie or [""] if it does not exists. This information is not returned by the browser. *) 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 below are requested. - [None]: the path is script name + path_info - [Some p]: the path is [p]. With [Some "/"] you can disable the path restriction completely. *) val set_secure : t -> bool -> unit (** Cookies are also bound to the type of the web server: [set_secure false] means servers without SSL, [set_secure true] means servers with activated SSL ("https"). *) val set_comment : t -> string -> unit (** [set_comment c s] sets the comment of the cookie [c] to [s] which must be UTF-8 encoded (RFC 2279). Because cookies can store personal information, the comment should describe how the cookie will be used so the client can decide whether to allow the cookie or not. To cancel a comment, set it to [""]. Cookie version 1 (RFC 2109). *) val set_comment_url : t -> string -> unit (** [set_comment_url c url] same as {!Netcgi.Cookie.set_comment} except that the cookie comment is available on the page pointed by [url]. To cancel, set it to [""]. Cookie version 1 (RFC 2965). *) val set_ports : t -> int list option -> unit (** [set ports c (Some p)] says that the cookie [c] must only be returned if the server request comes from one of the listed ports. If [p = []], the cookie will only be sent to the request-port it was received from. [set_ports c None] says that the cookie may be sent to any port. Cookie version 1 (RFC 2965). *) val of_netscape_cookie : Nethttp.netscape_cookie -> t (** Convert a Netscape cookie to the new representation *) val to_netscape_cookie : t -> Nethttp.netscape_cookie (** Convert to Netscape cookie (with information loss) *) end (** {2 The environment of a request} *) type http_method = [`GET | `HEAD | `POST | `DELETE | `PUT] type config = Netcgi_common.config = { tmp_directory : string; (** The directory where to create temporary files. This should be an absolute path name. *) tmp_prefix : string; (** The name prefix for temporary files. This must be a non-empty string. It must not contain '/'. *) permitted_http_methods : http_method list; (** The list of accepted HTTP methods *) permitted_input_content_types : string list; (** The list of accepted content types in requests. Content type parameters (like "charset") are ignored. If the list is empty, all content types are allowed. *) input_content_length_limit : int; (** The maximum size of the request, in bytes. *) max_arguments : int; (** The maximum number of CGI arguments *) workarounds : [ `MSIE_Content_type_bug | `Backslash_bug | `Work_around_MSIE_Content_type_bug | `Work_around_backslash_bug ] list; (** The list of enabled workarounds. - [`MSIE_Content_type_bug] - [`Backslash_bug] A common error in MIME implementations is not to escape backslashes in quoted string and comments. This workaround mandates that backslashes are handled as normal characters. This is important for e.g. DOS filenames because, in the absence of this, the wrongly encoded "C:\dir\file" will be decoded as "C:dirfile". Remark: [`Work_around_MSIE_Content_type_bug] and [`Work_around_backslash_bug] are deprecated versions of, respectively, [`MSIE_Content_type_bug] and [`Backslash_bug]. *) default_exn_handler : bool; (** Whether to catch exceptions raised by the script and display an error page. This will keep the connector running even if your program has bugs in some of its components. This will however also prevent a stack trace to be printed; if you want this turn this option off. *) } val default_config : config (** The default configuration is: - [tmp_directory]: {!Netsys_tmp.tmp_directory()} - [tmp_prefix]: "netcgi" - [permitted_http_methods]: [`GET], [`HEAD], [`POST]. - [permitted_input_content_types]: ["multipart/form-data"], ["application/x-www-form-urlencoded"]. - [input_content_length_limit]: [maxint] (i.e., no limit). - [max_arguments = 10000] (for security reasons) - [workarounds]: all of them. - [default_exn_handler]: set to [true]. To create a custom configuration, it is recommended to use this syntax: {[ let custom_config = { default_config with tmp_prefix = "my_prefix" } ]} (This syntax is also robust w.r.t. the possible addition of new config flields.) *) (** The environment of a request consists of the information available besides the data sent by the user (as key-value pairs). *) class type cgi_environment = object (** {3 CGI properties} The following properties are standardised by CGI. The methods return [""] (or [None] in the case of the port number) when the property is not available. *) method cgi_gateway_interface : string method cgi_server_name : string method cgi_server_port : int option method cgi_server_protocol : string method cgi_server_software : string method cgi_request_method : string (** We recommend you to use the method {!Netcgi.cgi.request_method} which is more type-safe and informative. *) method cgi_script_name : string method cgi_path_info : string method cgi_path_translated : string method cgi_auth_type : string method cgi_remote_addr : string method cgi_remote_host : string method cgi_remote_user : string method cgi_remote_ident : string method cgi_query_string : string (** This is the row query string. The {!Netcgi.cgi} class gives you an easy access to the arguments through the [#arg...] methods. *) method protocol : Nethttp.protocol (** The server protocol in a decoded form. It can be either - [`Http((major,minor),attributes)] or - [`Other]. *) method cgi_property : ?default:string -> string -> string (** Returns a (possibly non-standard) CGI environment property. If the property is not set, [Not_found] is be raised unless the [default] argument is passed. The [default] argument determines the result of the function in this case. The method takes the case-sensitive name and returns the value of the property. Usually, these properties have uppercase names. For example, [cgi_gateway_interface] returns the same as {[ cgi_property ~default:"" "GATEWAY_INTERFACE" ]} You cannot access the fields coming from the HTTP header. Use the method [input_header_field] instead. *) method cgi_properties : (string * string) list (** Return all properties as an associative list. *) method cgi_https : bool (** A well-known extension is the HTTPS property. It indicates whether a secure connection is used (SSL/TLS). This method interprets this property and returns true if the connection is secure. This method fails if there is a HTTPS property with an unknown value. *) (** {3 Header of the incoming HTTP request.} *) method input_header : Netmime.mime_header (** The whole HTTP header. *) method input_header_field : ?default:string -> string -> string (** [#input_header_field ?default f] returns the value of a field [f] of the HTTP request header. The field name [f] is case-insensitive; if the name is a compound name, the parts are separated by "-", e.g. ["content-length"]. If there are several fields with the same name only the first field will be returned. @raise Not_found if the field does not exist, unless the [default] argument is passed. The [default] argument is the result of the function in this case. *) method multiple_input_header_field : string -> string list (** Returns the values of all fields with the passed name of the request header. *) method input_header_fields : (string * string) list (** Returns the input header as (name,value) pairs. The names may consist of lowercase or uppercase letters. *) method cookie : string -> Cookie.t (** [#cookie cn] returns the cookie with name [cn]. @raise Not_found if such a cookie does not exists. *) method cookies : Cookie.t list (** Returns the list of valid cookies found in the request header. Here "valid" means that the decode function does not raise an exception. *) method user_agent : string (** This is a convenience method that returns the ["User-agent"] field of the HTTP request header. *) method input_content_length : int (** Returns the ["Content-length"] request header field. @raise Not_found if it is not set. *) method input_content_type_string : string (** Returns the ["Content-type"] request header field as a plain string or [""] if it is not set. *) method input_content_type : unit -> string * (string * Mimestring.s_param) list (** Returns the parsed ["Content-type"] request header field. @raise Not_found if it is not set. See also {!Mimestring.scan_mime_type_ep}. *) (** {3 Response header} *) method output_header : Netmime.mime_header (** The whole HTTP response header *) method output_header_field : ?default:string -> string -> string (** Returns the value of a field of the response header. If the field does not exist, [Not_found] will be raised unless the [default] argument is passed. The [default] argument determines the result of the function in this case. If there are several fields with the same name only the first field will be returned. The anonymous string is the name of the field. The name is case-insensitive, and it does not matter whether it consists of lowercase or uppercase letters. If the name is a compound name, the parts are separated by "-", e.g. ["content-length"]. *) method multiple_output_header_field : string -> string list (** Returns the values of all fields with the passed name of the repsonse header. *) method output_header_fields : (string * string) list (** Returns the output header as (name,value) pairs. The names may consist of lowercase or uppercase letters. *) method set_output_header_field : string -> string -> unit (** Sets the value of a field of the response header. The previous value, if any, is overwritten. If there have been multiple values, all values will be removed and replaced by the single new value. *) method set_multiple_output_header_field : string -> string list -> unit (** Sets multiple values of a field of the response header. Any previous values are removed and replaced by the new values. *) method set_output_header_fields : (string * string) list -> unit (** Sets the complete response header at once. *) method set_status : Nethttp.http_status -> unit (** Sets the response status. This is by definition the same as setting the [Status] output header field. *) method send_output_header : unit -> unit (** This method will encode and send the output header to the output channel. Note that of the output_channel is [`Transactionnal] (as opposed to [`Direct]), no output will actually take place before you issue [#commit_work()] -- thus a [#rollback_work()] will also rollback the headers as expected. *) (** {3 The output channel transferring the response} *) method output_ch : Netchannels.out_obj_channel (** @deprecated Use [#out_channel] instead. *) method out_channel : Netchannels.out_obj_channel (** The "raw" output channel. In general you should use instead {!Netcgi.cgi}[#out_channnel] which supports transactions (if you choose to). Access to the "raw" channel is useful however, for example for sending images or download of files (for which transactions are not interesting but merely more work). *) (** {3 Logging} *) method log_error : string -> unit (** [#log_error msg] appends [msg] to the webserver log. *) (** {3 Miscellaneous} *) method config : config (** The configuration of the request. *) end (** {2 CGI object} *) type other_url_spec = [ `Env | `This of string | `None ] (** Determines how an URL part is generated: - [`Env]: Take the value from the environment. - [`This v]: Use this value [v]. It must already be URL-encoded. - [`None]: Do not include this part into the URL. *) type query_string_spec = [ `Env | `This of cgi_argument list | `None | `Args of rw_cgi_argument list ] (** Determines how the query part of URLs is generated: - [`Env]: The query string of the current request. - [`This l]: The query string is created from the specified argument list [l]. - [`None]: The query string is omitted. - [`Args]: {i deprecated}, use [`This] (left for backward compatibility). *) type cache_control = [ `No_cache | `Max_age of int | `Unspecified ] (** This is only a small subset of the HTTP 1.1 cache control features, but they are usually sufficient, and they work for HTTP/1.0 as well. The directives mean: - [`No_cache]: Caches are disabled. The following headers are sent: [Cache-control: no-cache], [Pragma: no-cache], [Expires:] (now - 1 second). Note that many versions of Internet Explorer have problems to process non-cached contents when TLS/SSL is used to transfer the file. Use [`Max_age] in such cases (see http://support.microsoft.com/kb/316431). - [`Max_age n]: Caches are allowed to store a copy of the response for [n] seconds. After that, the response must be revalidated. The following headers are sent: [Cache-control: max-age n], [Cache-control: must-revalidate], [Expires:] (now + [n] seconds) - [`Unspecified]: No cache control header is added to the response. Notes: - Cache control directives only apply to GET requests; POST requests are never cached. - Not only proxies are considered as cache, but also the local disk cache of the browser. - HTTP/1.0 did not specify cache behaviour as strictly as HTTP/1.1 does. Because of this the [Pragma] and [Expires] headers are sent, too. These fields are not interpreted by HTTP/1.1 clients because [Cache-control] has higher precedence. *) (** Object symbolizing a CGI-like request/response cycle. This is the minimal set of services a connector must provide. Additional methods may be defined for specific connectors. *) class type cgi = object (** {3 Arguments -- data sent to the script} *) method argument : string -> cgi_argument (** [#argument name] returns the value of the argument named [name]. If the argument appears several times, only one of its instances is used. @raise Not_found if no such argument exists. *) method argument_value : ?default:string -> string -> string (** [#argument_value] returns the value of the argument as a string. If the argument does not exist, the [default] is returned. @param default defaults to [""]. *) method argument_exists : string -> bool (** [#argument_exists] returns [false] if the named parameter is missing and [true] otherwise. *) method multiple_argument : string -> cgi_argument list (** [#multiple_argument name] returns all the values of the argument named [name]. *) method arguments : cgi_argument list (** The complete list of arguments. *) method environment : cgi_environment (** The environment object. This object is the "outer layer" of the activation object that connects it with real I/O channels. *) method request_method : [ `GET | `HEAD | `POST | `DELETE | `PUT of cgi_argument] (** The HTTP method used to make the request. *) method finalize : unit -> unit (** This method calls [#finalize] for every CGI argument (including the possible one of PUT) to ensure that all files are deleted. It also executes all functions registered with [#at_exit]. It does not close the in/out channels, however. This method is not registered in the garbage collector, and it is a bad idea to do so. However, all connectors offered in Netcgi automatically call [#finalize] at the end of the request cycle (even when its terminated by an uncaught exception when [#config.default_exn_handler] is true) so you do not have to worry much about calling it yourself. *) (** {3 Self-referencing URL} *) method url : ?protocol:Nethttp.protocol -> ?with_authority:other_url_spec -> (* default: `Env *) ?with_script_name:other_url_spec -> (* default: `Env *) ?with_path_info:other_url_spec -> (* default: `Env *) ?with_query_string:query_string_spec -> (* default: `None *) unit -> string (** Returns the URL of the current CGI-like script. (Note that it may differ from the actual URL that requested the script if, for example, rewriting rules were specified in the web server configuration.) @param protocol The URL scheme. By default, the URL scheme is used that is described in the environment @param with_authority Whether to include authority part (e.g. http or https) of the URL, and if yes, from which source. Default: [`Env]. @param with_script_name Whether to include the part of the URL path identifying the CGI script, and if yes, from which source. Default: [`Env]. @param with_path_info Whether to include the rest of the URL path exceeding the script name, and if yes, from which source. Default: [`Env]. @param with_query_string Whether to include a query string, and if yes, which one. Only arguments with [#store] being [`Memory] will be added. Default: [`None], i.e. no query string. *) (** {3 Outputting} *) method set_header : ?status:Nethttp.http_status -> ?content_type:string -> ?content_length:int -> ?set_cookie:Nethttp.cookie list -> ?set_cookies:Cookie.t list -> ?cache:cache_control -> ?filename:string -> ?language:string -> ?script_type:string -> ?style_type:string -> ?fields:(string * string list) list -> unit -> unit (** Sets the header (removing any previous one). When the output channel supports transactions, it is possible to set the header (possibly several times) until the [#out_channel] is commited for the first time or [#env#send_output_header()] is called. When there is no support for transactions, the header must be set before the first byte of output is written. If [#set_header] is called a second time, it will overwrite {i all} the header fields. @param status Sets the HTTP status of the reply according to {{:http://www.w3.org/Protocols/rfc2616}RFC 2616}. Defaults to "no status", but the server normally complements an [`Ok] status in this case. @param content_type Sets the content type. Defaults to ["text/html"]. @param content_length Sets the content length (in bytes). Default: No such field. @param set_cookie Deprecated, use [set_cookies]. @param set_cookies Sets a number of cookies. Default: [[]]. Remember that the browser may not support more than 20 cookies per web server. You can query the cookies using [env#cookies] and [env#cookie]. If you set cookies, you want to think about an appropriate [cache] setting. You may also want to add a {{:http://www.w3.org/P3P/}P3P} header (Platform for Privacy Preferences) -- otherwise your cookies may be discarded by some browsers. @param cache Sets the cache behavior for replies to GET requests. The default is [`Unspecified]. {b It is strongly recommended to specify the caching behaviour!!!} You are on the safe side with [`No_cache], forcing every page to be regenerated. If your data do not change frequently, [`Max_age n] tells the caches to store the data at most [n] seconds. @param filename Sets the filename associated with the page. This filename is taken for the "save as..." dialog. Default: [""], i.e. no filename. Note: It is bad practice if the filename contains problematic characters (backslash, double quote, space), or the names of directories. It is recommended that you set [content_type] to "application/octet-stream" for this feture to work with most browsers and, if possible, to set [content_length] because that usually improves the download dialog.) @param script_type Sets the language of the script tag (for HTML replies). It is recommended to use this field if there are [ONXXX] attributes containing scripts before the first [