(*
* <COPYRIGHT>
* Copyright 2002 Joachim Schrod Network and Publication Consultance GmbH, Gerd Stolpmann
*
* <GPL>
* This file is part of WDialog.
*
* WDialog is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* WDialog 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WDialog; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* </>
*)
(* $Id: wd_dialog.mli,v 3.7 2004-12-12 17:57:32 stolpmann Exp $
* ----------------------------------------------------------------------
*
*)
(** This module defines the base class [dialog] from which all dialog
* classes should inherit
*)
open Wd_types
open Wd_template
val dump_interactors : Format.formatter -> interactors -> unit
(** Prints a readable description of the contents of the [interactors]
* argument to the passed [formatter]. This function is a valid printer
* for the toplevel and the debugger.
*)
(** The class [dialog] is the implementation of {!Wd_types.dialog_type} that
* should be used as base definition for all dialog objects. This class
* defines all methods but [handle] and [prepare_page] - these must be
* defined in the subclasses provided by the application programmer.
* Furthermore, there are some extensions to {!Wd_types.dialog_type}
* realized as private methods to simplify access to templates.
* These additional methods begin with [t_], but are otherwise named
* like the corresponding function in the module {!Wd_template}.
*
* The class takes three anonymous parameters:
*
* - The universe for which the dialog is defined
* - The name of the dialog in the UI definition
* - The environment of the current CGI activation
*)
class virtual dialog :
universe_type ->
(* name: *) string ->
environment ->
object
inherit Wd_types.dialog_type
(** This class implements [dialog_type] *)
(** The following private methods are shortcuts for the {!Wd_template}
* module.
*)
method private t_get : string -> template
(** Returns the template *)
method private t_apply : template -> (string * tree) list -> tree
(** Applies the template, and passes the parameters to it *)
method private t_apply_byname : string -> (string * tree) list -> tree
(** Applies the named template, and passes the parameters to it *)
method private t_apply_lazily : string -> (string * tree) list -> tree
(** Constructs the expression that applies the names template on
* demand.
*)
method private t_concat : tree -> tree list -> tree
(** Concatenates the [tree list], and put the separator [tree] between
* the parts
*)
method private t_empty : tree
(** The empty XML tree *)
method private t_text : string -> tree
(** The XML tree containing this text *)
method private t_html : string -> tree
(** The XML tree containing this HTML material *)
method private t_to_string : tree -> string
(** Evaluates the XML tree in the current environment, and returns
* the corresponding output string (HTML code)
*)
method private put_tree : string -> Wd_template.tree -> unit
(** Sets the [string] variable to the string representation
* of the [tree]
*)
end
(** {b Construction}
* [new dialog universe name env]: Makes a new dialog called [name] which
* is bound to the [universe]
*
* Normally, the class [dialog] is not used directly. It is intended
* to inherit from [dialog], and to define the two methods [prepare_page]
* and [handle]; these are virtual in the base class:
*
* {[class my_dialog universe name env =
* object (self)
* inherit dialog universe name env
* method prepare_page = ...
* method handle = ...
* end]}
*
* After defining such a class, you can create a new [my_dialog] by
* [new my_dialog universe "my_dialog" env].
* However, it is not recommended to do it this way. The module {!Wd_universe}
* includes a registry of constructors, and every dialog should put
* its constructor into it:
*
* [universe # register "my_dialog" (new my_dialog)]
*
* For example, you can place this statement where you call
* {!Wd_run_cgi.run}:
*
* {[let universe = new Wd_universe.universe in
* universe # register ...;
* Wd_run_cgi.run ... ~universe]}
*
* After the dialog has been registered, you can create new instances
* of the dialog by calling [universe#create]:
*
* [let dlg = universe # create env "my_dialog"]
*)
class instant_session_manager : unit -> Wd_types.session_manager_type
(** The "instant" session manager serializes the state of the dialog,
* and includes it literally into the HTML form. The serialized string is included
* in the generated HTML forms, and passed by CGI parameter from one activation
* to the next activation. The advantages are that you need not to set up any
* database to store the sessions, and that the session state is included
* in the history of the browser. The disadvantages are increased network
* traffic, and missing protection of the session data (the end user can
* decode the session state), i.e. the class is insecure, and should only
* be used in trusted environments.
*)
exception Invalid_session_checksum
(** Raised when the session checksum as stored in the database is not the
* same that is transmitted by the browser. This normally means that a
* historic page was submitted ("Back" button).
*)
exception Session_not_found
(** Raises when the current session was not found in the database. *)
class database_session_manager :
?private_key : string ->
?enable_checksum : bool ->
allocate:(unit -> int) ->
insert:(int -> string -> unit) ->
update:(int -> string -> string -> string -> unit) ->
lookup:(int -> string -> (string * string)) ->
unit ->
Wd_types.session_manager_type
(** The database session manager allows it to store the contents of
* sessions in databases. The database table should consist of rows
* with at least the four columns
*
* - [id]: The row identifier chosen by the database system. This is
* an integer
* - [skey]: The secure key consists of 32 hex digits, and is another
* identifier for the row that is chosen by WDialog
* - [value]: The value is a large BASE64-encoded string. The length
* depends on the session size
* - [checksum]: A checksum of [value], again 32 hex digits
*
* Note that sessions stored in databases behave differently with
* respect to the history function of the browser. It is not possible
* to "go back", or to select historic pages otherwise, and submit
* them again. This will be detected by the [database_session_manager],
* and the exception [Invalid_session_checksum] will be raised. There
* is currently no way to turn this check off, nor to make the
* check more fine-grained. (Maybe an implementation with multiple
* versions of the same session is the way to go, I don't know yet.)
*
* The [database_session_manager] does never delete sessions. It is
* recommended to remove unused sessions after a timeout period.
*
* For a transaction-based DBMS, it is sufficient if the [update]
* function commits the current transaction.
*
* @param allocate The function [allocate] must allocate a new [id]
* and return it.
*
* @param insert The function [insert] must insert a new row, containing only
* the [id] and the passed [skey]; the other two fields can be
* empty (empty string, or "null").
*
* @param update The function [update] takes the [id], the [skey], the [value], and
* the [checksum] as arguments, and must update the row identified
* by [id] and [skey]. It is up to the implementation whether the
* [id] or the [skey] is the preferred lookup key; however it MUST
* be checked whether the found row has the demanded [skey] for
* security reasons; if this is not the case, the exception
* [Session_not_found] must be raised. This exception must be
* raised, too, if the row cannot be found at all. (If there are
* several matching rows, this is an implementation error!)
*
* @param lookup The function [lookup] gets the [id] and the [skey] as arguments,
* and must return the corresponding [value] and [checksum] as
* pair. Again, the exception [Session_not_found] must be raised
* if the row cannot be found, or the [skey] is wrong.
*
* @param private_key The optional argument [private_key] can be used to inject randomness
* into the algorithm that computes the secure key. This makes the
* secure key unpredictable for the user, so nobody can "hijack" a
* session by guessing the secure key.
*
* @param enable_checksum If true (the default), the checksum of the
* web request is compared with the database checksum. This ensures that
* only responses of the latest dialog state can be processed. By
* setting this parameter to [false], the checksum is ignored, and the
* user can also submit historical web forms. In general, this is a bad
* idea, and you will run into trouble, unless your application is can
* cope with that.
*
*)
(* ======================================================================
* History:
*
* $Log: wd_dialog.mli,v $
* Revision 3.7 2004-12-12 17:57:32 stolpmann
* Added <q:wd-link> and <q:wd-xlink> to generate links for
* applications that cannot use Javascript. Limited functionality, however.
* See stdlib.xml for details.
*
* Revision 3.6 2003/03/21 20:57:54 stolpmann
* ocamldoc problems
*
* Revision 3.5 2003/03/21 14:23:44 stolpmann
* ocamldoc updated
*
* Revision 3.4 2003/03/09 17:08:29 stolpmann
* New class database_session_manager
*
* Revision 3.3 2002/02/16 17:29:45 stolpmann
* mostly ocamldoc.
*
* Revision 3.2 2002/02/14 16:15:21 stolpmann
* Added copyright notice.
*
* Revision 3.1 2002/02/12 20:29:22 stolpmann
* Initial release at sourceforge.
*
* Revision 1.10 2002/02/05 18:44:16 gerd
* New: class instant_session_manager
*
* Revision 1.9 2002/01/14 15:03:24 gerd
* Major change: Typing has been completely revised, and almost
* every tiny thing has now a new type. Also renamed a lot.
*
* Revision 1.8 2000/12/21 15:00:37 gerd
* Server popups: The generated "open" function has now a second
* parameter which is passed back to the application. The Popup_request
* event gets this parameter. The parameter can be used freely by the
* application.
*
* Revision 1.7 2000/12/04 18:27:50 gerd
* Added several type and exception definitions that were
* previously only accessible in Uiobject_pre.
*
* Revision 1.6 2000/12/04 12:00:07 gerd
* Moved dump_interactors from uiobject_pre to this module.
*
* Revision 1.5 2000/11/30 18:41:11 gerd
* New interface is_server_popup_request.
* exn_default_context has been removed.
*
* Revision 1.4 2000/05/15 11:46:33 gerd
* Necessary changes for uidebugger.
*
* Revision 1.3 2000/05/08 15:31:26 gerd
* New methods: exn_object_declaration and exn_default_context.
*
* Revision 1.2 2000/04/17 10:10:52 gerd
* New Cgi module.
* File upload strongly improved.
*
* Revision 1.1 2000/04/13 17:42:58 gerd
* Initial revision.
*
*
*)