"),
+ ]),
+
+ input_hidden(the_id, val) then
+ literal(""),
+ }
+.
+
+define List(HTML_Off_Form)
+ inputs_in_dialog
+ (
+ List(InputDial) inputs_data
+ )=
+ if inputs_data is
+ {
+ [] then [],
+ [h . t] then [input_in_dialog(h) . inputs_in_dialog(t)]
+ }.
+
+public define HTML_Off_Form
+ dijit_dialog
+ (
+ String name,
+ String dialog_id,
+ String execute,
+ String ok_label,
+ Maybe(String) cancel,
+ List(InputDial) inputs_data,
+ Maybe(String) do_cancel
+ )
+ =
+ sequence([
+ div([attr("dojoType", "dijit.Dialog"), id(dialog_id), title(name), attr("execute", execute)],
+ sequence([
+ sequence(inputs_in_dialog(inputs_data)),
+ literal("" +
+ if cancel is
+ {
+ failure then "",
+ success(cancel_label) then ""
+ }),
+ literal(" ")
+ ])
+ )
+ ])
+.
+
+public define HTML_Off_Form
+ dojo_dialog
+ (
+ String name,
+ String dialog_id,
+ String execute,
+ String ok_label,
+ Maybe(String) cancel,
+ List(InputDial) inputs_data,
+ Maybe(String) do_cancel
+ )
+ =
+ sequence[
+ dojo_button(name,"dijit.byId('"+dialog_id+"').show()", dialog_id + "_button"),
+ dijit_dialog(name, dialog_id, execute, ok_label, cancel, inputs_data, do_cancel)
+ ]
+.
+
+
+
+
+public type DojoGridEditor:
+ inputEditor,
+ boolEditor,
+ selectEditor(List(String) options),
+ alwaysOnEditor.
+
+public type DojoGridDefaultColumn:
+ dojo_grid_default_column(
+ String styles,
+ Maybe(String) width,
+ Maybe(DojoGridEditor) editor).
+
+public type DojoGridColumn:
+ dojo_grid_column( String label,
+ String field_name,
+ Maybe(String) width,
+ Maybe(DojoGridEditor) editor).
+
+public type DojoGridView:
+ dojo_grid_view(
+ Maybe(DojoGridDefaultColumn) default_column,
+ List(DojoGridColumn) columns).
+
+public type DojoGridLayout:
+ dojo_grid_layout(
+ Maybe(String) selectable_row_header_width,
+ List(DojoGridView) views).
+
+define String to_String(DojoGridEditor editor) =
+ "editor: " +
+ if editor is
+ {
+ inputEditor then "dojox.grid.editors.Input",
+ boolEditor then "dojox.grid.editors.Bool",
+ selectEditor(options) then "dojox.grid.editors.Select, options: [" + join(",", map((String o) |-> "\"" + o + "\"", options)) + "]",
+ alwaysOnEditor then "dojox.grid.editors.AlwaysOn"
+ }.
+
+define String to_String(DojoGridView view) =
+ "{ " + (if view.default_column is success(col) then
+ (if col is dojo_grid_default_column(styles, mb_width, mb_editor) then
+ "defaultCell: {"
+ + "styles: \"" + styles + "\""
+ + (if mb_width is success(w) then ", width=\"" + w + "\"" else "")
+ + (if mb_editor is success(e) then ", " + to_String(e) else "")
+ + "}, ")
+ else "")
+ + "cells: [[" + join(",", map((DojoGridColumn col) |->
+ if col is dojo_grid_column(label, field, mb_width, mb_editor) then
+ "{"
+ + "name: \"" + label + "\""
+ + "field: \"" + field + "\""
+ + (if mb_width is success(w) then ", width=\"" + w + "\"" else "")
+ + (if mb_editor is success(e) then ", " + to_String(e) else "")
+ + "}",
+ view.columns)) + "]]"
+ +"}".
+
+
+public define String
+ dojo_make_grid_script
+ (
+ HtmlId html_id,
+ DojoGridLayout layout,
+ String layout_name,
+ String store_name,
+ Bool can_edit
+ )
+ =
+"".
+
+public define HTML_Off_Form
+ dojo_make_grid_script
+ (
+ HtmlId html_id,
+ List(String) columns,
+ Bool can_edit
+ )
+ =
+ literal(
+"").
+
+public define HTML_Off_Form
+ dojo_grid
+ (
+ HtmlId html_id,
+ Int rowsPerPage,
+ List(Table_Option) attributes,
+ )=
+ table([attr("dojoType", "dojox.grid.DataGrid"), attr("id", html_id.id), attr("jsId", html_id.id),
+ class("soria"), attr("singleClickEdit", "true"), attr("rowsPerPage", to_decimal(rowsPerPage)) . attributes],
+ empty, [], empty).
+
+
+public define HTML_Off_Form
+ dojo_grid
+ (
+ HtmlId html_id,
+ List(CoreAttrs) attributes,
+// List(GridColumn) columns,
+ String colum1,
+ String colum2,
+ String colum3,
+ String colum4,
+ Bool can_edit
+ )
+ =
+ sequence([
+ literal(
+
+""),
+ div_empty([id(html_id.id) . attributes /*attr("dojoType", "dojox.Grid"), */]),
+ ]).
+//").
+
+
+public define HTML_Off_Form
+ dojo_message_box
+ (
+ HTML_Off_Form name1,
+ HTML_Off_Form name2,
+ )
+ =
+ sequence([
+ literal(" "),
+ div([class("message_box")],
+ sequence([
+ div([id("node3"), class("box nopad hidden")], name1),
+ div([id("node4"), class("box two nopad")], name2),
+ ])),
+ literal(" "),
+ ]).
+
+
+
+public define HTML_Off_Form
+ dojo_tooltip
+ (
+ String title,
+ String keyword,
+ ) =
+ actioner(same,same, link([id("dojo_tip_" + keyword),class("dojoToolTip")],title, success(title)), "show_address_mailing", [("address_mailing", keyword)], []).
+ //actioner(same, same, push_button([id("dojo_tip_" + keyword), class("in"), event(onclick,"new_search(this)")], keyword), "", [], []).
+
+
+public type BorderContainerRegion:
+ center,
+ top,
+ bottom,
+ leading,
+ trailing,
+ left,
+ right.
+
+define String
+ to_String
+ (
+ BorderContainerRegion region
+ )=
+ if region is
+ {
+ center then "center",
+ top then "top",
+ bottom then "bottom",
+ leading then "leading",
+ trailing then "trailing",
+ left then "left",
+ right then "right"
+ }.
+
+public type BorderContainerDesign:
+ headline,
+ sidebar.
+
+define String
+ to_String
+ (
+ BorderContainerDesign design
+ )=
+ if design is
+ {
+ headline then "headline",
+ sidebar then "sidebar"
+ }.
+
+
+public define HTML_Off_Form
+ dojo_ContentPane
+ (
+ List(CoreAttrs) attributes,
+ BorderContainerRegion region,
+ Bool splitter,
+ HTML_Off_Form content
+ ) =
+ div([ attr("dojoType", "dijit.layout.ContentPane"),
+ attr("region", to_String(region)),
+ attr("splitter", if splitter then "true" else "false") . attributes ],
+ content).
+
+public define HTML_In_Form
+ dojo_ContentPane
+ (
+ List(CoreAttrs) attributes,
+ BorderContainerRegion region,
+ Bool splitter,
+ HTML_In_Form content
+ ) =
+ div([ attr("dojoType", "dijit.layout.ContentPane"),
+ attr("region", to_String(region)),
+ attr("splitter", if splitter then "true" else "false") . attributes ],
+ content).
+
+public define HTML_Off_Form
+ dojo_TabContainer
+ (
+ List(CoreAttrs) attributes,
+ HTML_Off_Form content
+ ) =
+ div([attr("dojoType", "dijit.layout.TabContainer") . attributes ],
+ content).
+
+
+public define HTML_Off_Form
+ dojo_BorderContainer
+ (
+ List(CoreAttrs) attributes,
+ Maybe(String) the_title,
+ BorderContainerDesign design,
+ Bool live_splitter,
+ Bool persist,
+ Bool closable,
+ String container,
+ HTML_Off_Form content
+ ) =
+ with the_attributes = (List(CoreAttrs)) [attr("dojoType", "dijit.layout.BorderContainer"), attr("dojoAttachPoint", container),
+ attr("design", to_String(design)), attr("liveSplitters", live_splitter), attr("persist", persist),
+ attr("closable",closable) . attributes ],
+ total_attributes = if the_title is
+ {
+ failure then the_attributes,
+ success(t) then [title(t) . the_attributes]
+ },
+ div(total_attributes, content).
+
+public define HTML_In_Form
+ dojo_BorderContainer
+ (
+ List(CoreAttrs) attributes,
+ Maybe(String) the_title,
+ BorderContainerDesign design,
+ Bool live_splitter,
+ Bool persist,
+ Bool closable,
+ String container,
+ HTML_In_Form content
+ ) =
+ with the_attributes = (List(CoreAttrs)) [attr("dojoType", "dijit.layout.BorderContainer"), attr("dojoAttachPoint", container),
+ attr("design", to_String(design)), attr("liveSplitters", live_splitter), attr("persist", persist),
+ attr("closable",closable) . attributes ],
+ total_attributes = if the_title is
+ {
+ failure then the_attributes,
+ success(t) then [title(t) . the_attributes]
+ },
+ div(total_attributes, content).
+
+public define HTML_Off_Form
+ dojo_tree
+ (
+ List(CoreAttrs) attributes,
+ )=
+ div_empty(attributes).
+
+
+
+public define HTML_Off_Form
+ dojo_Toolbar
+ (
+ List(CoreAttrs) attributes,
+ HTML_Off_Form content
+ )=
+ div([attr("dojoType", "dijit.Toolbar") . attributes ],
+ content).
+
+
+public define HTML_Off_Form
+ dojo_tooltip
+ (
+ List(CoreAttrs) attributes,
+ List(Text_Option) txt_attr,
+ HtmlId html_id,
+ String label,
+ HTML_Off_Form tooltip_content,
+ )=
+ sequence([
+ text([id(html_id.id) . txt_attr], label),
+ div([id(html_id.id + "_tt"), attr("connectId", html_id.id), attr("dojoType", "dijit.Tooltip") . attributes], tooltip_content)
+ ]).
+
+
+public define HTML_Off_Form
+ dojo_button
+ (
+ HtmlId html_id,
+// Maybe(String) class,
+ String name,
+ String iconclass,
+ Maybe(String) tip_msg,
+ String execute,
+ )=
+ literal("
+ " +
+ if tip_msg is
+ {
+ failure then "",
+ success(tip) then
+ "" + tip + ""
+ }).
+
+public define HTML_In_Form
+ dojo_button
+ (
+ HtmlId html_id,
+// Maybe(String) class,
+ String name,
+ String iconclass,
+ Maybe(String) tip_msg,
+ String execute,
+ )=
+ literal("
+ " +
+ if tip_msg is
+ {
+ failure then "",
+ success(tip) then
+ "" + tip + ""
+ }).
+
+
+public define HTML_Off_Form
+ dojo_declaration
+ (
+ String name,
+ List(CoreAttrs) attributes,
+ HTML_Off_Form content
+ )=
+ div([attr("dojoType", "dijit.Declaration"), attr("widgetClass", name) . attributes ],
+ content).
+
+
+public define HTML_In_Form
+ dojo_declaration
+ (
+ String name,
+ List(CoreAttrs) attributes,
+ HTML_In_Form content
+ )=
+ div([attr("dojoType", "dijit.Declaration"), attr("widgetClass", name) . attributes ],
+ content).
+
+public define HTML_Off_Form
+ dojo_editor
+ (
+ List(CoreAttrs) attributes,
+ HtmlId html_id,
+ WebArgName input_name,
+ HTML_Off_Form text,
+ )=
+ div([id(html_id.id), attr("name", input_name.name), attr("dojoType", "dijit.Editor")
+ ,attr("extraPlugins", "['|', 'foreColor','hiliteColor',{name:'dojox.editor.plugins.FontChoice', command:'fontName', generic:true},'fontSize','formatBlock','|','createLink','insertImage']")
+ . attributes], text).
+
+ public define HTML_In_Form
+ dojo_button
+ (
+ HtmlId html_id,
+ String name,
+ String iconclass,
+ Maybe(String) tip_msg,
+ String execute,
+ )=
+ literal("
+ " +
+ if tip_msg is
+ {
+ failure then "",
+ success(tip) then
+ "" + tip + ""
+ }).
+
+public define HTML_In_Form
+ dojo_checkbox
+ (
+ List(InputAttrs) attributes,
+ WebArgName name,
+ HtmlId id,
+ String label,
+ WebArgValue val,
+ Bool checked,
+ )=
+ check_box_r([attr("dojoType", "dijit.form.CheckBox") . attributes] , label, id, name, val, checked).
+
+public define HTML_In_Form
+ dojo_combobox
+ (
+ List(InputAttrs) attributes,
+ WebArgName name,
+ HtmlId id,
+ String label,
+ List((List(CoreAttrs),WebArgValue,String)) list_data,
+ InitialValue selected,
+ )=
+ // selector_c([attr("dojoType", "dijit.form.ComboBox") . attributes], label, id, name, 1, list_data, selected, non_mandatory).
+ selector_c(attributes, label, id, name, 1, list_data, selected).
+
+public define HTML_Off_Form
+ dojo_toaster
+ (
+ List(CoreAttrs) attributes,
+ HtmlId html_id,
+ String message_topic,
+ Position_Direction position_direction,
+ Bool separator,
+ Maybe(Int) duration
+ )=
+ div(append(append(if separator then [attr("separator","<hr>")]
+ else [],
+ if duration is
+ {
+ failure then [],
+ success(dur) then [attr("duration", abs_to_decimal(dur))]
+ }),
+ [attr("dojoType", "dojox.widget.Toaster"), attr("messageTopic", message_topic),
+ attr("positionDirection", pos_dir_to_str(position_direction)), id(html_id.id)
+ . attributes ]),
+ literal("")).
+
+public define HTML_Off_Form
+ dojo_progressBar
+ (
+ List(CoreAttrs) attributes,
+ List(Text_Option) attributes_text,
+ HtmlId html_id,
+ String label
+ )=
+ sequence([
+ text([id("text_" + html_id.id), class("progress_bar") . attributes_text], label),
+ div([id(html_id.id), class("progress_bar"), attr("indeterminate", "true"), attr("dojoType", "dijit.ProgressBar") . attributes], literal(""))
+ ]).
+
+public define HTML_Off_Form
+ dojo_progressBar
+ (
+ List(CoreAttrs) attributes,
+ List(Text_Option) attributes_text,
+ HtmlId html_id,
+ String label,
+ Int progress,
+ Int maximum
+ )=
+ sequence([
+ text([id("text_" + html_id.id), class("progress_bar") . attributes_text], label),
+ div([id(html_id.id),
+ class("progress_bar"),
+ attr("maximum", abs_to_decimal(maximum)),
+ attr("progress", abs_to_decimal(progress)),
+ attr("dojoType", "dijit.ProgressBar") . attributes], literal(""))
+ ]).
+
+define Maybe(Int)
+ string_to_month
+ (
+ String month_s
+ )=
+ with month = to_lower(month_s),
+ if month = "jan" then success(1)
+ else if month = "feb" then success(2)
+ else if month = "mar" then success(3)
+ else if month = "apr" then success(4)
+ else if month = "may" then success(5)
+ else if month = "jun" then success(6)
+ else if month = "jul" then success(7)
+ else if month = "aug" then success(8)
+ else if month = "sep" then success(9)
+ else if month = "oct" then success(10)
+ else if month = "nov" then success(11)
+ else if month = "dec" then success(12)
+ else failure
+ .
+
+
+// 'Thu Jan 14 2010 00:00:00 GMT+0100' must be replaced by '2010-01-14 00:00:00'
+
+
+
+public define Maybe(String)
+ dojo_date_to_db_datetime
+ (
+ String data
+ )=
+ with list_data = split_by_token(data, ' '),
+ if nth(2, list_data) is
+ {
+ failure then failure,
+ success(day) then
+ if nth(1, list_data) is
+ {
+ failure then failure,
+ success(month) then
+ if nth(3, list_data) is
+ {
+ failure then failure,
+ success(year) then
+ if nth(4, list_data) is
+ {
+ failure then failure,
+ success(hour) then
+ if string_to_month(month) is
+ {
+ failure then failure,
+ success(month_int) then
+ success(year+"-"+month_int+"-"+day+" "+hour)
+ }
+ }
+ }
+ }
+ }.
+
+public define List(HTML_Head_Tag)
+ dojo_defaults
+ =
+ [
+ // js(js_file("js/dojo/dojo.js", [attr("djConfig", "parseOnLoad: true, isDebug: " + (if debug_mode then "true" else "false") + ", usePlainJson: true")])),
+ js(js_file("js/dojo/dojo/dojo.js", [attr("djConfig", "parseOnLoad: true, isDebug: false, usePlainJson: true")])),
+ js(js_file("js/dojo/dijit/dijit.js")),
+ //css(css_file("js/dojo/dojo/resources/dojo.css"))
+ ].
+
+
+public define List(HTML_Head_Tag)
+ dojo_init
+ (
+ String web_dir,
+ String theme_name
+ )
+ =
+ with theme_name =
+ if file_exists(web_dir+"/public/js/dojo/dijit/themes/"+theme_name+"/"+theme_name+".css")then theme_name else "claro",
+ [ css(css_file("js/dojo/dijit/themes/"+theme_name+"/"+theme_name+".css")) .
+ [ css(css_file("js/dojo/dijit/themes/"+theme_name+"/"+theme_name+"_rtl.css")) . dojo_defaults ]
+ ]
+ .
diff --git a/web/CXM_making_a_web_site.anubis b/web/CXM_making_a_web_site.anubis
index b0100bb..d13da3e 100644
--- a/web/CXM_making_a_web_site.anubis
+++ b/web/CXM_making_a_web_site.anubis
@@ -1,4726 +1,4732 @@
-
-
- *Project* Anubis
-
- *Title* Making interactive Web sites.
-
- *Copyright* Copyright (c) Alain Prouté 2004-2005.
- Copyright (c) Calexium 2007.
-
-
- *Authors* Alain Prouté
- David René
-
- *Revised* May 2007
-
-
- *Overview*
-
- In this file we propose simple tools for making well structured interactive and secured
- web sites.
-
-
- ----------------------------------- Table of Contents ---------------------------------
-
- * (1) Structure of a web site.
- ** (1.1) Three sorts of data.
- ** (1.2) How requests are handled.
- ** (1.3) What web pages are made of.
- ** (1.4) Actions.
- ** (1.5) States.
-
- * (2) Carrying on.
- ** (2.1) Describing your web sites.
- ** (2.2) Directories on the server's disk.
- ** (2.3) Starting your web sites.
-
- * (3) The HTML interface.
- ** (3.1) Types used by the HTML interface.
- ** (3.2) ``in form'' versus ``off form''.
- ** (3.3) Defining your own style.
- ** (3.4) Actioners and forms.
- ** (3.5) Local popup.
-
- ---------------------------------------------------------------------------------------
-
-
-read tools/basis.anubis
-read tools/printable_tree.anubis
-read tools/base64.anubis
-read system/string.anubis
-read system/logger.anubis
-read CXM_common.anubis
-read CXM_multihost_http_server.anubis
-read web/mime.anubis
-read CXM_cookies.anubis
-
-
- * (1) Structure of a web site.
-
- First of all we need to explain what a web site should be made of. Ideally, the
- visitor (also called the 'client') should see the web site working as any other
- interactive computer software. So, it should be clear that a 'session' (i.e. a visit
- to the web site, including the consultation of several pages) is some kind of
- conversation between the visitor and the web site, and that the web site should
- maintain a 'current state' of this conversation. At each new request (click) from the
- visitor, this state must be updated. This whole conversation is called a 'session' and
- should not be confused with a single request.
-
-
-
- ** (1.1) Three sorts of data.
-
- All the data needed for putting a web site at work may be dispatched into three
- categories:
-
- 1. Constant data (data that never change). These data may be hard coded into the
- Anubis source files of the web site.
-
- 2. Permanent data (data which always exist independantly of the users connected to
- the web site). These data are normally recorded into data bases.
-
- 3. Session data (data which depend on a particular visitor and which exist only
- during the time he visits the web site). These data are stored into so-called
- 'states'.
-
-
- It is important to determine which data belongs to which category. This is part of your
- design decisions.
-
-
-
- ** (1.2) How requests are handled.
-
- We want to separate the following two functionalities (which are used at each request
- (click) during a single session):
-
- - computing the new state from the previous state and from the client request, and
- updating the data base,
-
- - computing the page to be sent to the client from the new current state and from
- the informations in the data base.
-
-
- The next picture shows the structure we have in mind:
-
-
- request +---------+ HTML page (with a hidden state name)
- .-------------------| client |<--------------.
- | .-----------------| | |
- | | previous state +---------+ |
- | | name (if any) |
- | | | client side
- ............................................................................
- | | | server side
- | | |
- | | .-------------------. |
- | | | previous state | |
- V V V | |
- +---------------+ +---------------+ +--------------+
- | compute state | | server's disk | | compute page |
- +---------------+ +---------------+ +--------------+
- ^ | | ^ ^ ^ ^ ^
- | | | | | | | |
- | | `--------------------+--------------------' | |
- | | new state | | |
- read | `------------------------+--------------------' |
- write | new state name |
- update V |
- +-----------+ |
- | data base |--------------------------------------------'
- +-----------+ read only
-
-
- When the client begins a session, there is no previous state. In this case, a default
- 'initial state' is used instead.
-
- The data base may be updated by 'compute state' box, but should not be update by the
- 'compute page' box. The 'compute page' box should be allowed only to read the data
- base.
-
- In this file, all the above stuff is defined, except the 'compute state' and 'compute
- page' boxes. You just have to provide the function for computing a new state (compute
- state) and the function for computing the page (compute page) from the new state. You
- don't have to worry about state names, saving and retrieving states and the like.
-
-
-
-
-
- ** (1.3) What web pages are made of.
-
- What the client can see in his browser's window may be called a 'page'. Within a page,
- we have several sorts of components:
-
- - 'local' components, i.e. all components which do not open a connection, like
- texts, images, etc... possibly using JavaScript programmation,
-
- - 'actioners', which, when clicked upon, open a connection with our web site; they
- may appear as links or buttons, etc...
-
- - 'foreign links', which when clicked upon, open a connection with another web site
- (or ours eventually).
-
- Of course, what an actioner does is just ask our web site to perform an action. To that
- end, the actioner essentially sends the name of the action to be performed. However, it
- may be necessary to provide additional informations which may be seen as 'operands' of
- the action. In order to attach operands to an action, HTML provides the notion of
- 'form'. Indeed, a form contains essentially a set of input fields into which the client
- may put values for the required operands of the action, and a submit button, which is
- the actioner itself. Notice that a single form may contain several submit buttons,
- which simply means that there are several distincts actions taking the same set of
- operands.
-
- Restrictions must be put on the use of all theses gadgets. Indeed, for example,
- putting a form within another form is officially meaningless in HTML, and the client's
- browser may be seriously disturbed by this. In this file, we propose an interface to
- the HTML language, which forbids such meaningless things, simply by imposing a strict
- typing of HTML concepts.
-
- Each web site may be accessible through two communication channels:
-
- - a non secured channel (HTTP),
- - a secured channel (HTTPS).
-
- Nevertheless, the whole thing should be considered as a single web site. For example,
- you may have a secured page, obtained through HTTPS, containing public images obtained
- through HTTP. An actioner in a non secured page may open a secured connection, and
- conversely.
-
- Summarizing, a web page is made of local elements, foreign links and actioners.
- Actioners receive operands from forms, and they also choose to communicate through the
- non secured or through the secured channel.
-
-
-
- +-------------------+
- | page |
- | | +---------------+
- | +--------------+ | | next page |
- | | form | | | (non secured) |
- | | +----------+ | | HTTP | |
- | | | actioner |---------------------------->| |
- | | +----------+ | | +---------------+
- | | | |
- | | +----------+ | | +---------------+
- | | | actioner |---------------------------->| next page |
- | | +----------+ | | HTTPS | (secured) |
- | | | | | |
- | +--------------+ | | |
- | | +---------------+
- | |
- +-------------------+
-
-
- Notice that actioners need no be necessarily put into forms. In that case, they work as
- ordinary links, but they still may receive operands as we shall see.
-
-
-
-
- ** (1.4) Actions.
-
- The client opens a new connection with our web site whenever he clicks on an
- actioner. The result is that a request is sent, essentially made of a list of 'web
- arguments'. Each web argument is a pair (name,value). One of these web arguments, the
- 'action' web argument (whose name is "a"), determines the action to be performed. The
- other web arguments (not including "s", used to identify the state) are the operands
- for this action.
-
- Hence, the 'compute state' box in the picture above, splits naturally into as many
- sub-boxes as there are actions. For this reason, we define the following type for
- representing actions (where '$State' is the type representing session informations):
-
-public type Web_Action($State):
- http_action (String name, // name of action
- ($State) -> Bool allow, // true if action allowed
- (HTTP_Info http_info,
- List(Web_arg) web_args, // actually only 'operands' web arguments
- $State state) -> $State do_it),
- https_action (String name, // name of action
- ($State) -> Bool allow, // true if action allowed
- (HTTP_Info http_info,
- List(Web_arg) web_args, // actually only 'operands' web arguments
- $State state) -> $State do_it),
- http_https_action (String name,
- ($State) -> Bool allow,
- (HTTP_Info http_info,
- List(Web_arg) web_args,
- $State state) -> $State do_it).
-
- 'http_action's are executed only under HTTP, and 'https_action's are executed only
- under HTTPS. 'http_https_action's may be executed under both types of connections.
-
- Each action has a name, which is used to identify the action. Each action also has a
- function 'allow' whose job is to verify that the action is allowed in the current
- state, and a function 'do_it' for performing the action. The function 'do_it' receives
- a lot of informations:
-
- - 'HTTP informations':
- - the IP address of the client,
- - the URI requested by the client (after redirection),
- - the list of HTTP headers generated by the client's browser,
- - the list of web arguments sent by the client (except "s" and "a"),
- - the previous state (or the 'initial' or 'ticket expired' state if no previous
- state can be found).
-
- In most cases, HTTP informations are not used. This is the reason why they are gathered
- for simplicity into a unique datum of type 'HTTP_Info'.
-
-// For your convenience, we introduce the following simpler variants:
-//
-//public define Web_Action($State)
-// http_action
-// (
-// String name,
-// $State -> Bool allow,
-// (List(Web_arg),$State) -> $State do_it
-// ) =
-// http_action(name,
-// (Maybe($State) ms) |-> if ms is
-// {
-// failure then true,
-// success(s) then allow(s)
-// },
-// (HTTP_Info h, List(Web_arg) l, Maybe($State) s) |-> if s is
-// {
-// failure then (failure, []),
-// success(s2) then (success(do_it(l,s2)), [])
-// }).
-//
-//public define Web_Action($State)
-// https_action
-// (
-// String name,
-// $State -> Bool allow,
-// (List(Web_arg),$State) -> $State do_it
-// ) =
-// https_action(name,
-// (Maybe($State) ms) |-> if ms is
-// {
-// failure then true,
-// success(s) then allow(s)
-// },
-// (HTTP_Info h, List(Web_arg) l, Maybe($State) s) |-> if s is
-// {
-// failure then (failure, []),
-// success(s2) then (success(do_it(l,s2)), [])
-// }).
-//
-//public define Web_Action($State)
-// http_https_action
-// (
-// String name,
-// $State -> Bool allow,
-// (List(Web_arg),$State) -> $State do_it
-// ) =
-// http_https_action(name,
-// (Maybe($State) ms) |-> if ms is
-// {
-// failure then true,
-// success(s) then allow(s)
-// },
-// (HTTP_Info h, List(Web_arg) l, Maybe($State) s) |-> if s is
-// {
-// failure then (failure, []),
-// success(s2) then (success(do_it(l,s2)), [])
-// }).
-
-
-
- When you define your web site, you must provide the list of all the actions of the
- site. When a new state has been computed, a graphical representation of this state
- must be sent to the client. To that end, you must provide a function (named below
- 'compute_page') of type:
-
- $State -> HTTP_Answer
-
- where the type 'HTTP_Answer' (defined below in this file) abstractly represents HTML
- pages.
-
-public type HTTP_Answer:...
-
- It should be clear that states and pages are deeply linked together. Indeed, we really
- understand the page shown to the client as a representation of the current state of the
- conversation between the client and the web site, but also containing informations
- taken from the data bases.
-
-
-
-
-
- ** (1.5) States.
-
- Now, we explain how you can define the type (say 'State') to be used as an instance of
- the type parameter '$State'. The following is just a suggestion.
-
- Each state determines a page (since 'compute_page' computes a page from a
- state). However, some components of the state may be independant of the page. It may be
- the case for example for the indication of the natural language used by the
- client. Hence, a state should be made of (at least) two parts:
-
- - informations which are the same for all pages,
- - informations which are particular to each page.
-
- For example, you could define:
-
- type Page: // one alternative per page, with particular informations
- login(...), // in the components
- main_page(...),
- ...etc...
-
- Now, the type 'State' could be defined as follows:
-
- type State:
- state(Language, // informations valid for all pages
- ...,
- Page). // informations particular to a page
-
- However, if you are making a secured web site within which clients should be identified
- (by id and password), it may be a good idea to have two sorts of states, one for non
- identified clients and one for identified clients. In this case, define the type
- 'State' as follows (this is just a suggestion):
-
- type State:
- non_identified(Language),
- identified(String id,
- Language,
- Page).
-
- When a request arrives, check if the previous state is 'identified(...)' or
- 'non_identified(...)', and don't provide access to certain pages to non identified
- clients. This is required for security.
-
- Some more words on security. If your site needs to identify clients, define the
- initial state as 'non_identified(...)'. Construct a 'login' page, and check the id and
- password of the client. If the id and password are correct, then change the state of
- the client to 'identified(...)'. No other action should be able to do that. Now, be
- confident that clients cannot forge states. The only information they have is the name
- of a state, not the state itself which is never sent over the network, but only stored
- on the server's disk. The name of the state is constructed using strong cryptographical
- methods (sha1). If everything (since the 'login' page) is performed under HTTPS, even
- state names cannot be seen by a third party. So, if the system retrieves a previous
- state of the form 'identified(...)', you can be confident that your client is well
- identified, and you can send him confidential informations.
-
- States have a limited life time. It may happen that a client clicks on a button at a
- time its state is out of date. In this case, this system considers that the new state
- is a special state named 'ticket expired'. You must provide a function producing this
- state when you describe your web site. The page corresponding to this state must just
- inform the client that he/she waited a too long time before clicking on a button, and
- has to restart (a new conversation) from the begining.
-
-
-
- * (2) Carrying on.
-
- ** (2.1) Describing your web sites.
-
- Before you may start your web site, you must describe it, i.e. produce a datum of the
- opaque type 'Web_Site'.
-
-public type Web_Site:...
-
- Producing such a datum may be performed by:
-
-public define Web_Site
- make_web_site_description
- (
- List(String) common_names, // for example: ["www.our-business.com",
- // "192.168.0.1"]
- // the second one is just for testing
- String site_directory, // where 'public' and other directories are
- // located (should NOT end with '/')
- String state_directory,
- One -> One init,
- (HTTP_Info,
- List(Web_arg),
- Bool is_https) -> $State initial_state,
- ($State expired,
- Maybe(String),
- HTTP_Info,
- List(Web_arg),
- Bool is_https) -> $State ticket_expired_state,
- (Maybe(String),
- HTTP_Info,
- List(Web_arg),
- Bool is_https) -> $State ticket_lost_state,
- List(Web_Action($State)) actions,
- $State -> HTTP_Answer compute_page,
- $State -> List(HTTP_header) additional_headers,
- Int timeout, // seconds (todo: minutes)
- Redirections redirections,
- String charset,
- List(String) journal_extensions,
- List(String) journal_headers,
- String authorization_secret,
- List(MIME) known_mime_types,
- (String action_name,
- List(Web_arg) args)-> One before_send_file
- ).
-
-
- Explanations:
-
- 'common_names' is the list of names of the site (the name the browser must send as the
- value of the 'Host' HTTP header in order to access the site must be in that list). Such
- a name generally looks like this:
-
- www.somewhere.com
-
- If you are using HTTPS, you also have an 'X.509 SSL server certificate'. The name of
- the site must be exactly the same as the name on the certificate (which is precisely
- called the 'common name' in the X.509 jargon). If the two names do not match, the site
- will still work, but the transaction will not be transparent to the client. His browser
- will complain that the name of the certificate does not match the name of the site, and
- he will have to accept the certificate manually.
-
- 'site_directory' is the absolute path to the directory where the files needed by the
- site are located. Usually this directory looks like:
-
- my_anubis/web_sites/www.somewhere.com
-
- However, this information is not computed from 'common_name', so that you can change
- the common name (for example temporarily, for networking reasons) without loosing
- access to the files.
-
- 'ticket_expired_state(expired_state,http_info,lwa,is_https)' must produce the state
- whose graphical representation is a page explaining to the user that its 'ticket' (or
- 'session information') has expired, and that he/she must close all popup windows and
- start a new session. The arguments of the function contain the previous (expired)
- state and all current informations concerning the user. This arguments may be useful
- for example for producing the expiration message in the language chosen by the user.
- You can also (and this may be much smarter) send a 'ticket prolongation page'
- (including a new login for example), and resume the same conversation, since you have
- all the pertinent informations at hand. In the case the ticket is definitely lost, the
- second fonction 'ticket_lost_state' is used.
-
- Notice that despite the fact that the parameter $State is involved in the arguments of
- the above function, the type 'Web_Site' does not depend on this parameter. This allows
- to produce lists of web site descriptions, where each description may be constructed
- with a different instance of $State. This is required because distinct sites must have
- distinct types of session informations. This is made possible by the fact that the
- type is obscure, and the constructor replaced by a function which assembles
- 'ticket_expired_state', ticket_lost_state', 'actions' and 'compute_page' into a single
- entity not depending on $State. You should have a look to the private part of this file
- if you want more precisions about this programming technique.
-
- 'charset' is a string which will determine the character encoding to be used by the
- browser. Typically, this string is one of: "UTF-8", "ISO-8859-1", "Windows-1252",
- etc...
-
- 'before_send_file' is a function which is executed just before the HTTP server sends a
- file. It gets an action name and the web arguments received with the request for that
- file. Notice that this action name and these web arguments may be put into a
- 'private_download' element, and will come back to the server at the time of the
- download.
-
-
-
- ** (2.2) Directories on the server's disk.
-
- The description of your site contains the name of the directory within which the
- required files are located. This may be for example:
-
- my_anubis/web_sites/www.our-business.com/
-
- This is called the 'site directory' (for the given site). Within the site directory,
- the following directories are created by this program:
-
- states
- public
- journal
- private_download
- upload_temporary
-
- The directory 'states' is used for storing states (session informations). Out of date
- states are automatically removed after some time.
-
- The tree rooted at 'public' contains files that the server is allowed to send to the
- clients. For security reasons, the server never sends a file which is not within the
- tree whose root is this 'public' directory (except for the 'private download' mecanism;
- see 'web/multihost_http_server.anubis'). Also, the MIME type (see 'web/mime.anubis')
- must have been recognized before the file may be sent.
-
- The directory 'journal' contains the jounal files. The roles of the remaining
- directories 'private_download' and 'upload_temporary' is explained in
- 'multihost_http_server.anubis', where you will also find further informations on
- 'public' and 'journal'.
-
-
-
-
- ** (2.3) Web servers parameters.
-
- The web servers have several parameters useful for administration. They are described
- as follows:
-
- public type WebServersParameters:
- wsparms(Var(Bool) shutdown_required,
-
-
-
-
- ** (2.4) Starting your web sites.
-
- When you have described all your web sites (you may want to have several web sites, and
- they are distinguished by their 'common name'), you may start them all together using
- 'start_web_sites' below. This function returns a result of the following type:
-
-public type Start_Web_Sites_Result:
- cannot_bind_to_port(Word32),
- cannot_bind_to_port(Word32,Word32),
- ok(Server http_server,
- Server https_server).
-
- Indeed, it may happen that the system cannot bind (begin to listen) to one of the two
- ports (or to both). The main reason is that another server is already listening on that
- port. Another reason may be that 'anbexec' has not been correctly installed, i.e. that
- the 's' bit has not been set for 'user' and 'group' (there is not such problem under
- Windows). Also notice that the Linux kernel may need a rather long time (up to several
- minutes) before liberating a listening port. Now, if the system can bind to the two
- ports, the pair of the two servers is returned. Two tools are useful for manipulating
- servers:
-
- shutdown of type Server -> One
- is_down of type Server -> Bool
-
- They are defined in 'predefined.anubis' (together with the type 'Server').
-
-
-public define Start_Web_Sites_Result
- start_web_sites
- (
- Word32 ip_address, // the IP address shared by the web sites
- Word32 http_port, // usually: 80
- Word32 https_port, // usually: 443
- String ssl_certificate_common_name,
- List(Web_Site) web_sites, // web sites to be started
- (One) -> Bool shutdown_required
- ).
-
- 'ip_address' is the IP address on which the two servers listen. If you put 0, the
- servers listen on all the IP addresses of the machine. This may be useful if the
- machine has several network interfaces.
-
- 'ssl_certificate_common_name' is the common name of the SSL certificate that 'anbexec'
- loads when it starts. One instance of 'anbexec' cannot handle more than one SSL server
- certificate. This is due to a problem of conception of SSL itself. See the book 'SSL
- and TLS' by Eric Rescorla (at Addison Wesley) for more explanations.
-
- Notice that the number of servers is always 2, regardless of the number of web sites
- you are starting.
-
- The dynamic variable 'shutdown_required' may be used to control the shutdown of the two
- servers from within the web site (typically the administration part). The servers will
- shutdown as soon as this variable contains 'true'. So you must provide a variable
- containing 'false' otherwise your servers will not run. You may also use the primitive
- 'must_restart' (see 'predefined.anubis') to control the restarting of your servers.
-
-
-
-
-
-
- * (3) The HTML interface.
-
- We propose an interface to dynamic HTML. Dynamic HTML includes HTML, and a combination
- of CSS (Cascading Style Sheet) and JavaScript techniques for making HTML elements more
- reactive and attractive on the client side.
-
-
- ** (3.1) Types used by the HTML interface.
-
- For easy reference, we gather below the definitions of all the types used by the HTML
- interface, and we comment them immediately.
-
-
-public type HTML_Size:
- absolute(Int), // in pixels
- percentage(Int).
-
-
-public type Text_Option:
- size(Int), // size of character font to use
- font(String), // name of character font to use (such as "helvetica",...)
- color(RGB), // color to be used for characters
- italic,
- oblique,
- small_capitals,
- bold,
- underlined,
- left_justified,
- right_justified,
- justified, // justified on both sides
- line_through,
- nowrap,
- class(String), //CSS class
- id(String),
- style(String),
- title(String),
- attr(String, String).
-
-public define Text_Option
- tooltip(String s) = title(s).
-
- A list of 'Text_Option' must be given with each text you want to put in your page.
-
- This indicate the way of reading text.
-public type Reading_Way:
- ltr, //the text is readable from "Left To Right" like english
- rtl. //the text is readable from "Right To Left" like arabic
-
-
-// Following types are define to prohib any arguments order error
-
-/**
- * String value for 'id' attribut
- */
-public type HtmlId:
- htmlId(String id).
-
-/**
- * String value for 'class' attribut
- */
-public type HtmlClass:
- htmlClass(String class).
-
-/**
- * Name used in arguments list when form is submitted.
- */
-public type WebArgName:
- wan(String name).
-
-/**
- * Value passed to arguments list when form is submitted (for RadioButton and CheckBox).
- */
-public type WebArgValue:
- wav(String value).
-
-/**
- * Initial value of an input field.
- */
-public type InitialValue:
- init(String value).
-
-public define Printable_tree [HtmlId x . Printable_tree y] = str_pt(x.id, y).
-public define Printable_tree [HtmlClass x . Printable_tree y] = str_pt(x.class, y).
-public define Printable_tree [WebArgName x . Printable_tree y] = str_pt(x.name, y).
-public define Printable_tree [WebArgValue x . Printable_tree y] = str_pt(x.value, y).
-public define Printable_tree [InitialValue x . Printable_tree y] = str_pt(x.value, y).
-
-
-public type HtmlEvents:
- // Form element events
- onchange,
- onsubmit,
- onreset,
- onselect,
- onblur,
- onfocus,
- // Keyboard events (Not valid in base, bdo, br, frame, frameset, head, html, iframe, meta, param, script, style, and title elements.)
- onkeydown,
- onkeypress,
- onkeyup,
- // Mouse events (Not valid in base, bdo, br, frame, frameset, head, html, iframe, meta, param, script, style, and title elements.)
- onclick,
- ondblclick,
- onmousedown,
- onmousemove,
- onmouseout,
- onmouseover,
- onmouseup.
-
-public type CoreAttrs:
- id (String),
- class (String),
- style (String),
- title (String),
- lang (String),
- dir (Reading_Way),
- accesskey (Word8),
- tabindex (Int),
- attr (String, String),
- event (HtmlEvents, String).
-
-public define CoreAttrs attr(String name, Bool value) = attr(name, if value then "true" else "false").
-
-public type InputAttrs:
- class (String),
- style (String),
- title (String),
- lang (String),
- dir (Reading_Way),
- accesskey (Word8),
- tabindex (Int),
- attr (String, String),
- event (HtmlEvents, String).
-
-public define InputAttrs attr(String name, Bool value) = attr(name, if value then "true" else "false").
-
-public define CoreAttrs
- tooltip(String s) = title(s).
-public define InputAttrs
- tooltip(String s) = title(s).
-
-public type I18n:
- lang (String),
- dir (Reading_Way).
-
-//public type DIV_Option:
-// id (String),
-// class (String),
-// style (String),
-// tooltip (String),
-// lang (String),
-// dir (Reading_Way),
-// attr (String, String),
-// event (HtmlEvents, String).
-//
-
- A list of 'DIV_Option' must be given with each DIV you want to put in your page.
-
-define String event_name
- (
- HtmlEvents e
- ) =
- if e is
- {
- // Form element events
- onchange then "onchange",
- onsubmit then "onsubmit",
- onreset then "onreset",
- onselect then "onselect",
- onblur then "onblur",
- onfocus then "onfocus",
- // Keyboard events
- onkeydown then "onkeydown",
- onkeypress then "onkeypress",
- onkeyup then "onkeyup",
- // Mouse events
- onclick then "onclick",
- ondblclick then "ondblclick",
- onmousedown then "onmousedown",
- onmousemove then "onmousemove",
- onmouseout then "onmouseout",
- onmouseover then "onmouseover",
- onmouseup then "onmouseup"
- }.
-
-public type Table_Option:
- background_color(RGB), // applied to all cells in the table
- background_image(String url),
- border(Int width_of_outer_edge, // if not present, all values are 0
- Int width_of_top_of_relief,
- Int width_of_inner_edge,
- RGB border_color),
- width(Int), // sets a minimal width for the table
- percentage_width(Int),
- attr(String name, String value),
- class(String class_name).
-
-
-public define Table_Option nude = border(0,0,0,rgb(0,0,0)).
-
-
- A list of 'Table_Option' must be given with each table.
-
-
-public type BackgroundOption:
- repeat, // repeat the background in both directions
- repeat_horizontal, // repeat the background only horizontally
- repeat_vertical, // repeat the background only verticall
- no_repeat, // don't repeat the background
- center.
-
-
-public type Cell_Option:
- core_attrs(List(CoreAttrs)),
- left, // put the content of the cell on the left
- h_center, // center the content of the cell horizontally
- right, // put the content of the cell on the right
- top, // put the content of the cell upwards
- v_center, // center the content of tye cell vertically,
- bottom, // put the content of the cell downwards
- base_line, // align the content vertically according to base lines
- background_color(RGB),
- background_image(String url, BackgroundOption),
- width(Int), // sets a minimal width for the cell
- percentage_width(Int),
- height(Int), // sets a minimal height for the cell
- columns(Int), // lets the cell span over several columns
- rows(Int), // lets the cell span over several rows
- nowrap, // do not allow text wrapping within the cell
- class(String class_name).
-
- A list of 'Cell_Option' must be given with each cell and each row in a table. Options
- given with a row apply to all the cells in the row, but are superseded by options given
- with cells, which apply only to the cell they are given with.
-
-
-public type HTML_Cell($T):
- cell(List(Cell_Option) options, $T content).
-
-public type HTML_Header_Cell($T):
- header_cell(List(Cell_Option) options, $T content).
-
- The parameter $T is later instantiated either to 'HTML_In_Form' or to 'HTML_Off_Form',
- depending on where you put your table (within a form or not within a form). For your
- convenience, we define the following particular case:
-
-public define HTML_Cell($T)
- cell
- (
- $T content
- ) =
- cell([],content).
-
-public define HTML_Header_Cell($T)
- header_cell
- (
- $T content
- ) =
- header_cell([],content).
-
-
-public type HTML_Row($T):
- row(List(Cell_Option) options, List(HTML_Cell($T)) cells).
-
-public type HTML_Header_Row($T):
- empty,
- header_row(List(Cell_Option) options, List(HTML_Header_Cell($T)) cells).
-
-public type HTML_Footer_Row($T):
- empty,
- footer_row(List(Cell_Option) options, List(HTML_Cell($T)) cells).
-
- Same remark as for 'HTML_Cell($T)'. We define several convenience functions:
-
-public define HTML_Row($T)
- row
- (
- List(HTML_Cell($T)) cells
- ) =
- row([],cells).
-
-public define HTML_Row($T)
- row
- (
- HTML_Cell($T) cell
- ) =
- row([],[cell]).
-
-public define HTML_Header_Row($T)
- header_row
- (
- List(HTML_Header_Cell($T)) cells
- ) =
- header_row([],cells).
-
-public define HTML_Header_Row($T)
- header_row
- (
- HTML_Header_Cell($T) cell
- ) =
- header_row([],[cell]).
-
-public type Actioner_Connection:
- same, // use same type of connection as current page
- http, // use non secured connection
- https. // use secured connection
-
-public type Other_Window_Option:
- resizable, // the new window may be resized by the client
- scrollbars, // the new window has scrollbars
- width(Int), // the new window has the specified width
- height(Int). // the new window has the specified height
-
-public type Actioner_Target:
- same,
- same (String label),
- other(String window_name, List(Other_Window_Option)).
-
-public type Actioner_Aspect:
- link (List(Text_Option), String text, Maybe(String) name),// hypertext link
- img_link (String img_url, String alt_text),
- push_button (List(CoreAttrs),String text),
- button (String url_off, String url_on), // rollover button
- button (String url_off, String url_on, Int w, Int h), // idem with size
- submit (List(CoreAttrs),String text),
- immediate_selector (List(CoreAttrs),WebArgName name, Int size, List((WebArgValue,String)) choices),
- immediate_selector (List(CoreAttrs),WebArgName name, Int size, List((WebArgValue,String)) choices, InitialValue selected).
-
-
-
-public type Actioner_Local_Action:
- close_window.
-
-
-public define Actioner_Aspect
- link
- (
- List(Text_Option) options,
- String text
- ) =
- link(options, text, failure).
-
-public define Actioner_Aspect
- link
- (
- String text
- ) =
- link([], text, failure).
-
-
-public define Actioner_Aspect
- link
- (
- List(Text_Option) options,
- Int i
- ) =
- link(options,to_decimal(i), failure).
-
-public define Actioner_Aspect
- link
- (
- Int i
- ) =
- link([], i).
-
-public define Actioner_Aspect
- button
- (
- String url_img
- ) =
- button(url_img,url_img).
-
- Actioners are explained in details below.
-
-
-public type TextAreaOption:
- input_attrs(List(InputAttrs)),
- disabled,
- read_only,
- wrap_lines.
-
-public type CSS_Style:
- text_options(List(Text_Option)).
-
-public type CSS_File:
- css_file(String file_name).
-
-public type JS_Attribute:
- attr (String, String).
-
-public type JS_File:
- js_file(String file_name,
- List(JS_Attribute) attributes).
-
-public type Script:
- script( String script_type,
- String content).
-
-public define JS_File
- js_file
- (
- String file_name
- ) =
- js_file(file_name, []).
-
-public type HTML_Meta:...
-
-public type HTML_Off_Form:...
-
-public type HTML_Head_Tag:
- meta(HTML_Meta),
- title(String),
- js(JS_File),
- js_inline(Script),
- css(CSS_File),
- css_inline(String css_styles) /* Note: tags are not necessaries */
- .
-
- /* It contains
- * - a List of HTML_Head_Tag representing necessaries head tags for the content. ex: jquery js files, js script, css specific styles, ...
- * - a HTML_Off_Form representing the HTML code for the part of the page we want to display
- */
-public type HTML_Partial_Content:
- partial_content
- (
- List(HTML_Head_Tag),
- HTML_Off_Form
- )
- .
-
-
-public define List(HTML_Head_Tag)
- to_HTML_Head_Tag
- (
- List(CSS_File) css_file_list
- )=
- map((CSS_File css_f) |-> css(css_f), css_file_list).
-
-public define List(HTML_Head_Tag)
- to_HTML_Head_Tag
- (
- List(JS_File) js_file_list
- )=
- map((JS_File js_f) |-> js(js_f), js_file_list).
-
-public type HTML_In_Form:
- literal_pt (Printable_tree),
- literal (String),
- sequence (List(HTML_In_Form) items),
- text (List(Text_Option), String the_text),
- preformated (List(Text_Option), String),
- paragraph (List(Text_Option), HTML_In_Form content),
- image (List(CoreAttrs), String url, String alternate),
- image (List(CoreAttrs), String url, String alternate, Int width, Int height),
- table (List(Table_Option), HTML_Header_Row(HTML_In_Form), List(HTML_Row(HTML_In_Form)), HTML_Footer_Row(HTML_In_Form)),
- center (HTML_In_Form),
- mail_to (String email, HTML_In_Form element),
- scroller (Int width, Int height,
- Int content_width, Int content_height,
- HTML_In_Form content),
- actioner (Actioner_Connection, Actioner_Target, Actioner_Aspect,
- String action_name, List((String,String)) extra_ops,
- List(Actioner_Local_Action)),
- foreign_link_new (Actioner_Target, Actioner_Aspect, String url),
- foreign_link (List(Text_Option), String url),
- foreign_link (List(Text_Option), String url, String name),
- private_download (String abs_path, String name, String extra_ext,
- Maybe((String,List((String,String)))) action),
- text_input (List(InputAttrs), String label_text, HtmlId id, WebArgName name, InitialValue init, Int width),
- text_input_ro (List(InputAttrs), String label_text, HtmlId id, WebArgName name, InitialValue init, Int width),
- password_input (List(InputAttrs), String label_text, HtmlId id, WebArgName name, InitialValue init, Int width),
- text_area (List(TextAreaOption), String label_text, HtmlId id, WebArgName name, InitialValue init, Int width, Int height),
- file_upload (List(InputAttrs), String label, HtmlId id, WebArgName name, Int width),
- selector (List(InputAttrs), String label_text, HtmlId id, WebArgName name, Int size, List(String) choices),
- selector (List(InputAttrs), String label_text, HtmlId id, WebArgName name, Int size, List(String) choices, InitialValue selected),
- // List((String,String)) = List((code,name)) where :
- // code is the web-arg value
- // name appears in selector
- selector_c (List(InputAttrs), String label_text, HtmlId id, WebArgName name, Int size, List((WebArgValue,String)) choices),
- selector_c (List(InputAttrs), String label_text, HtmlId id, WebArgName name, Int size, List((WebArgValue,String)) choices, InitialValue selected),
- radio_button (List(InputAttrs), String label_text, HtmlId id, WebArgName name, WebArgValue value, Bool checked),
- radio_button_r (List(InputAttrs), String label_text, HtmlId id, WebArgName name, WebArgValue value, Bool checked),
- check_box (List(InputAttrs), String label_text, HtmlId id, WebArgName name, WebArgValue value, Bool checked),
- check_box_r (List(InputAttrs), String label_text, HtmlId id, WebArgName name, WebArgValue value, Bool checked),
- div (List(CoreAttrs), HTML_In_Form content),
- div_empty (List(CoreAttrs)),
- hidden (HtmlId id, WebArgName name, InitialValue init).
-
-
- 'HTML_In_Form' defines all the elements you may put within a form. We define a
- convenience function:
-
-public define HTML_In_Form literal(Printable_tree t) = literal_pt(t).
-
-public define HTML_In_Form image(String url) = image([], url, url).
-
-public define HTML_In_Form image(String url, Int width, Int height) = image([], url, url, width, height).
-
-public define HTML_In_Form
- foreign_link
- (
- Int tsize,
- String url,
- String name
- ) =
- foreign_link([size(tsize)],url,name).
-
-public define HTML_In_Form
- actioner
- (
- Actioner_Connection conn,
- Actioner_Target targ,
- Actioner_Aspect asp,
- String action_name,
- List((String,String)) extra_ops
- ) =
- actioner(conn,targ,asp,action_name,extra_ops,[]).
-
-public define HTML_In_Form
- actioner
- (
- Actioner_Connection conn,
- Actioner_Target targ,
- Actioner_Aspect asp,
- ) =
- actioner(conn, targ, asp, "", [], []).
-
-
-public define HTML_In_Form
- text_area
- (
- WebArgName name,
- InitialValue init,
- Int width,
- Int height
- ) =
- text_area([], "", htmlId(""), name,init,width,height).
-
-public define HTML_In_Form
- text_area
- (
- List(TextAreaOption) options,
- WebArgName name,
- InitialValue init,
- Int width,
- Int height
- ) =
- text_area(options, "", htmlId(""), name,init,width,height).
-
-public define HTML_In_Form
- table
- (
- List(HTML_Row(HTML_In_Form)) rows
- ) =
- table([],empty,rows,empty).
-
-public define HTML_In_Form
- table
- (
- List(Table_Option) options,
- List(HTML_Row(HTML_In_Form)) rows
- ) =
- table(options,empty,rows,empty).
-
-public define HTML_In_Form
- table
- (
- HTML_Header_Row(HTML_In_Form) h_row,
- List(HTML_Row(HTML_In_Form)) rows
- ) =
- table([],h_row,rows,empty).
-
-public define HTML_In_Form
- table
- (
- List(Table_Option) options,
- HTML_Header_Row(HTML_In_Form) h_row,
- List(HTML_Row(HTML_In_Form)) rows
- ) =
- table(options,h_row,rows,empty).
-
-public define HTML_In_Form
- private_download
- (
- String abs_path,
- String name,
- String extra_ext
- ) =
- private_download(abs_path,name,extra_ext,failure).
-
-public define HTML_In_Form
- private_download
- (
- String abs_path,
- String name,
- String extra_ext,
- String action_name,
- List((String,String)) args
- ) =
- private_download(abs_path,name,extra_ext,success((action_name,args))).
-
-public define HTML_In_Form
- text
- (
- String s
- ) =
- text([],s).
-
-public define HTML_In_Form
- radio_button (List(InputAttrs) options, String label_text, WebArgName n, WebArgValue value, Bool checked)
- = radio_button (options, label_text, htmlId(n.name), n, value, checked).
-
-public define HTML_In_Form
- radio_button_r (List(InputAttrs) options, String label_text, WebArgName n, WebArgValue value, Bool checked)
- = radio_button_r (options, label_text, htmlId(n.name), n, value, checked).
-
-public define HTML_In_Form
- check_box (List(InputAttrs) options, String label_text, WebArgName n, WebArgValue value, Bool checked)
- = check_box (options, label_text, htmlId(n.name), n, value, checked).
-
-public define HTML_In_Form
- check_box_r (List(InputAttrs) options, String label_text, WebArgName n, WebArgValue value, Bool checked)
- = check_box_r (options, label_text, htmlId(n.name), n, value, checked).
-
-public define HTML_In_Form
- file_upload (WebArgName name, Int width)
- = file_upload([], "", htmlId(""), name, width).
-
-public define HTML_In_Form
- hidden (WebArgName name, InitialValue init)
- = if name is wan(web_name) then
- hidden(htmlId(web_name), name, init).
-
-public type HTML_Body:...
-
-public type HTML_Off_Form:
- literal_pt (Printable_tree),
- literal (String),
- sequence (List(HTML_Off_Form) items),
- text (List(Text_Option), String the_text),
- preformated (List(Text_Option), String),
- paragraph (List(Text_Option), HTML_Off_Form content),
- image (List(CoreAttrs), String url, String alternate),
- image (List(CoreAttrs), String url, String alternate, Int width, Int height),
- table (List(Table_Option), HTML_Header_Row(HTML_Off_Form), List(HTML_Row(HTML_Off_Form)), HTML_Footer_Row(HTML_Off_Form)),
- center (HTML_Off_Form),
- mail_to (String email, HTML_Off_Form element),
- scroller (Int width, Int height,
- Int content_width, Int content_height,
- HTML_Off_Form content),
- fixed_size (HTML_Size width, HTML_Size height, HTML_Off_Form content),
- fixed_size_2 (HTML_Size width, HTML_Size height, String name_of_HTML_file),
- actioner (Actioner_Connection, Actioner_Target, Actioner_Aspect,
- String action_name, List((String,String)) extra_ops,
- List(Actioner_Local_Action)),
- actioner (Actioner_Connection, Actioner_Target, Actioner_Aspect,
- String action_name, List((String,String)) extra_ops,
- List(Actioner_Local_Action), String form_name),
- foreign_link_new (Actioner_Target, Actioner_Aspect, String url),
- foreign_link (List(Text_Option), String url),
- foreign_link (List(Text_Option), String url, String name),
- private_download (String abs_path, String name, String extra_ext,
- Maybe((String,List((String,String)))) action),
- label (String name),
- form (HtmlId form_id, List(CoreAttrs), HTML_In_Form content),
- form (HtmlId form_id, List(CoreAttrs),
- String action_name, List((String,String)) extra_ops,
- HTML_In_Form content),
- div (List(CoreAttrs), HTML_Off_Form content),
- div_empty (List(CoreAttrs)),
- iframe (List(CoreAttrs),
- List(CSS_Style) /*styles*/,
- List(CSS_File) /*css_files*/,
- List(JS_File) /*js_files*/,
- HTML_Body /*body*/).
-
- 'HTML_Off_Form' defines all the elements you may put outside any form.
-
-
-public define HTML_Off_Form image(String url) = image([], url, url).
-
-public define HTML_Off_Form image(String url, Int width, Int height) = image([], url, url, width, height).
-
-public define HTML_Off_Form
- form
- (
- String form_name,
- List(CoreAttrs) options,
- HTML_In_Form content
- ) =
- form(htmlId(form_name), options, content).
-
-public define HTML_Off_Form
- form
- (
- String form_name,
- List(CoreAttrs) options,
- String action_name,
- List((String,String)) extra_ops,
- HTML_In_Form content
- ) =
- form(htmlId(form_name), options, action_name, extra_ops, content).
-
-
-public define HTML_Off_Form literal(Printable_tree t) = literal_pt(t).
-public define HTML_Off_Form fixed_size(HTML_Size width, HTML_Size height, String name_of_HTML_file)
- = fixed_size_2(width,height,name_of_HTML_file).
-
-
-public define HTML_Off_Form
- foreign_link
- (
- Int tsize,
- String url,
- String name
- ) =
- foreign_link([size(tsize)],url,name).
-
-
-public define HTML_Off_Form
- actioner
- (
- Actioner_Connection conn,
- Actioner_Target targ,
- Actioner_Aspect asp,
- String action_name,
- List((String,String)) extra_ops
- ) =
- actioner(conn,targ,asp,action_name,extra_ops,[]).
-
-public define HTML_Off_Form
- table
- (
- List(HTML_Row(HTML_Off_Form)) rows
- ) =
- table([],empty,rows,empty).
-
-public define HTML_Off_Form
- table
- (
- List(Table_Option) options,
- List(HTML_Row(HTML_Off_Form)) rows
- ) =
- table(options,empty,rows,empty).
-
-public define HTML_Off_Form
- table
- (
- HTML_Header_Row(HTML_Off_Form) h_row,
- List(HTML_Row(HTML_Off_Form)) rows
- ) =
- table([],h_row,rows,empty).
-
-public define HTML_Off_Form
- table
- (
- List(Table_Option) options,
- HTML_Header_Row(HTML_Off_Form) h_row,
- List(HTML_Row(HTML_Off_Form)) rows
- ) =
- table(options,h_row,rows,empty).
-
- We add two convenience functions for 'row'. The reason why we add two functions, one
- for 'HTML_In_Form' and one for 'HTML_Off_Form', is that adding a schema with an
- arbitrary '$T' creates too many ambiguities. This is due to the fact that, if we do so,
- the arguments of the function do not refer to any of the types defined here.
-
-public define HTML_Row(HTML_In_Form)
- row
- (
- HTML_In_Form content
- ) =
- row([],[cell([],content)]).
-
-public define HTML_Row(HTML_Off_Form)
- row
- (
- HTML_Off_Form content
- ) =
- row([],[cell([],content)]).
-
-
-public define HTML_Off_Form
- private_download
- (
- String abs_path,
- String name,
- String extra_ext
- ) =
- private_download(abs_path,name,extra_ext,failure).
-
-
-public define HTML_Off_Form
- private_download
- (
- String abs_path,
- String name,
- String extra_ext,
- String action_name,
- List((String,String)) args
- ) =
- private_download(abs_path,name,extra_ext,success((action_name,args))).
-
-public define HTML_Off_Form
- text
- (
- List(Text_Option) lto,
- Int i
- ) =
- text(lto,to_decimal(i)).
-
-
-public define HTML_Off_Form
- text
- (
- Int i
- ) =
- text([],i).
-
-public define HTML_Off_Form
- text
- (
- String s
- ) =
- text([],s).
-
- - Cell a gap between two other cells :
-
-public define HTML_Cell(HTML_Off_Form)
- width_gap
- (
- Int w
- ) =
- cell([width(w)],text([],"")).
-
-public define HTML_Cell(HTML_In_Form)
- width_gap
- (
- Int w
- ) =
- cell([width(w)],text([],"")).
-
-
- - Row a gap between two other rows :
-
-public define HTML_Row(HTML_Off_Form)
- height_gap
- (
- Int h
- ) =
- row([],[cell([height(h)],text([],""))]).
-
-public define HTML_Row(HTML_In_Form)
- height_gap
- (
- Int h
- ) =
- row([],[cell([height(h)],text([],""))]).
-
-
- Notice that the two types have alternatives in common (same name, same arguments types,
- up to the value of the parameter $T), which correspond to elements which may be put
- anywhere in the page.
-
-
-public define HTML_Partial_Content
- partial_content
- (
- HTML_Off_Form content
- )=
- partial_content([], content).
-
-public define HTML_Partial_Content
- partial_content
- (
- List(HTML_Head_Tag) tags,
- HTML_Partial_Content p_content
- )=
- if p_content is partial_content(ptags, html) then
- partial_content(tags + ptags, html).
-
-define HTML_Partial_Content
- list_to_pcontent
- (
- List(HTML_Partial_Content) l_p_content,
- List(HTML_Head_Tag) so_far_tags,
- List(HTML_Off_Form) so_far_html
- )=
- if l_p_content is
- {
- [] then partial_content(so_far_tags, sequence(reverse(so_far_html))),
- [h . t] then
- //extract resurgent type and symbols of h
- if h is partial_content(tags, html) then
- list_to_pcontent(t, so_far_tags + tags, [html . so_far_html])
- }.
-
-public define HTML_Partial_Content
- partial_content
- (
- List(HTML_Partial_Content) l_p_content
- )=
- list_to_pcontent(l_p_content, [], []).
-
-
-
-define String
- format
- (
- List(Text_Option) l
- ).
-
-
-
-
-define Printable_tree
- format_css_styles
- (
- List(CSS_Style) l
- ) =
- if l is
- {
- [ ] then [ ],
- [h . t] then
- [ if h is
- {
- text_options(tos) then
- [" body, span, p { ", format(tos), " }\n" ]
- }
- . format_css_styles(t)]
- }.
-
-
-
-public type HTML_Meta:
- keywords (List(String)),
- refresh (Actioner_Connection connection,
- Actioner_Target target,
- String action_name,
- Int delay), // in seconds
- refresh (String url, Int delay), // in seconds
- meta (String name, String content),
- http_equiv (String name, String content),
- generic_meta (List((String,String))),
- literal (String).
-
- Meta tags are put in the 'head' of the HTML page.
-
-
-public type Body_Option:
- core_attrs(List(CoreAttrs)),
- background_color (RGB),
- background_image (String url),
- background_image (String url, List(BackgroundOption)).
-
-public type HTML_Body:
- body(List(Body_Option) options, HTML_Off_Form content).
-
-
-public type HTTP_Answer:
- html_page (HTTP_Status /*http_status*/,
- List(HTML_Head_Tag) /*html tags*/,
- HTML_Body /*body*/),
- html_page (HTTP_Status /*http_status*/,
- String /*title*/,
- List(HTML_Meta) /*meta_tags*/,
- List(CSS_Style) /*styles*/,
- List(CSS_File) /*css_files*/,
- List(JS_File) /*js_files*/,
- List(Script) /*script*/,
- HTML_Body /*body*/),
- plain_text (HTTP_Status /*http_status*/,
- String /*text*/),
- custom_text (HTTP_Status /*http_status*/,
- String /*mime_type*/,
- String /*content*/),
- custom_binary(HTTP_Status /*http_status*/,
- String /*mime_type*/,
- ByteArray /*content*/,
- List(HTTP_header)/*other headers*/),
- custom_tree (HTTP_Status /*http_status*/,
- String /*mime_type*/,
- Printable_tree /*content*/),
- http_raw (Printable_tree),
- html_content (HTTP_Status /*http_status*/,
- HTML_Off_Form).
-
-
-public define HTTP_Answer
- html_page
- (
- String title,
- List(HTML_Meta) metas,
- HTML_Body body
- ) =
- html_page(http_ok, title,metas,[],[],[],[],body).
-
-public define HTTP_Answer
- html_page
- (
- String title,
- List(HTML_Meta) metas,
- List(CSS_Style) styles,
- HTML_Body body
- ) =
- html_page(http_ok, title, metas, styles, [], [], [], body).
-
- 'HTTP_Answer' represents the final product of the construction of a web page.
-
-
-
-
- *** (3.2) ``in form'' versus ``off form''.
-
- There is a variety of HTML elements: texts, buttons, links, forms, inputs, etc... Some
- of them may have a content, which is yet another HTML element (or several). Hence, it
- is meaningful to say that an element is 'within' another one. Now, putting any element
- within any other one may be meaningless. For example, an input element must be put
- within a form (otherwise, it is useless), and a from within another form has no precise
- meaning (and is forbidden by the HTML specification).
-
- Actually, the main criterium is ``within a form or not within a form''. So, HTML
- elements in a given page are separated into two categories: those who are within a
- form, and the others. Nevertheless, there are elements which may belong to both
- categories, like images and texts. We want to make use of the strong typing mecanism of
- Anubis in order to forbid non meaningful placement of elements.
-
- The type 'HTML_In_Form' defines elements to be put within forms. Similarly,
- 'HTML_Off_Form' defines elements not to be put within forms. Both types are recursive,
- and 'HTML_Off_Form' refers to 'HTML_In_Form' (via the 'form' alternative, of course),
- but the two types are not cross recursive. This is the reason why it is impossible to
- put a form within a form. In order to construct a web page, you essentially have to
- produce a datum of type 'HTML_Off_Form' (maybe containing data of type 'HTML_In_Form').
-
- In practice, you don't have to worry so much about these two types, because elements
- which may be put anywhere are constructed for both types by functions with the same
- name and the same arguments. Hence, for both types, you just write the same thing. You
- are warned by the compiler only when you try to put an element at a place it is not
- allowed.
-
-
-
- *** (3.3) Defining your own style.
-
- We provide generic tools for constructing HTML elements. However, your web site needs
- to have a ``style''.
-
- To that end, you need to write down a set of ``styling functions'', using the tools
- defined here. These styling functions allow the introduction of your colors and other
- visual characteristics into the constructed elements once and for all. For example, you
- may want all your texts to be rendered in the ``Helvetica'' font, in size 14 and using
- some 'text_color'. You may write something like this:
-
- define RGB text_color = rgb(10,40,40).
-
- define HTML_Off_Form
- text
- (
- String the_text
- ) =
- text([font("helvetica"),size(14),color(text_color)],
- the_text).
-
- (and the same one for type 'HTML_In_Form') so that in order to put a piece of text in a
- page, you just write:
-
- text("... some text ...")
-
- and you don't have to provide the font, size and color for each text. If you want to
- have several styles of text presentation, you just write several sets of such
- convenience functions. This also suggests a trick. You may want for example different
- colors for 'in form' texts and 'off form' texts. This may be achieved automatically by
- defining two functions as above, with the same name and same argument type, but
- returning either a 'HTML_In_Form' or a 'HTML_Off_Form'.
-
- If this preliminary work is well done, you will not waste your time later when you
- concentrate on the actual informational content of your pages.
-
- This general principle should be applied to all sorts of elements. This is the best
- thing to do in order to separate the functions defining the visual style from the
- functions defining the informational content itself, so that changing the style without
- changing the content becomes easy. This is also the best way for having a clean and
- easily readable source for your web site.
-
-
-
-
-
- *** (3.4) Actioners and forms.
-
- We have gathered several notions from HTML into that of an 'actioner'. An actioner is
- an HTML element which opens a connection to our server when clicked upon. Actioners may
- have different visual aspects. They may look like hypertext links or like buttons
- (rollovers), or even like selectors (with immediate action). In any case, their
- behavior is the same: they open a connection to our server, and send a set of 'web
- arguments', i.e. pairs 'name=value'. Among these web arguments, one of them denotes
- the action to be performed, and the others should be considered as operands for this
- action. Actually, the precise behavior of the actioner has several variants.
-
- The connection with the server may be secured (HTTPS) or non secured (HTTP). See the
- type 'Actioner_Connection' above.
-
- You must also choose where the answer must be rendered. This may be in the same window
- or in another window (or frame). If it is in another window, the name of that window
- must be given. If the window does not exist, the browser will create it. Optionally,
- you may give the dimensions of the new window and other characteristics. See the type
- 'Actioner_Target' above.
-
- The actioner also has a visual aspect. See the type 'Actioner_Aspect' above. In the
- case of a rollover button, you provide the URLs of two images (of the same size)
- representing the button:
-
- url_off: to be used when the mouse is not over the button,
- url_on: to be used when the mouse is over the button.
-
- You can also create rollover buttons without creating images. Just use the second
- alternative named 'button'. The server creates the images automatically.
-
- The purpose of forms is just to give operands to actioners. If the actioner is placed
- within a form, all the input elements which are within this form provide operands to
- the actioner (except sometimes when they are not set by the client). If it is not put
- within a form, the actioner gets no operand, except if the name of a form is explicitly
- given, in which case the actioner gets all the inputs from that form as
- operands. Furthermore, you may want to give extra operands to the actioner. This may be
- useful for separating families of actioners with the same action name. Extra operands
- 'name=value' must be given in the form of pairs '(name,value)'.
-
- Notice that the name of a form may be used by an actioner which is off the form, so as
- to get the operands provided by this form. Also notice that several actioners may refer
- to the same form, being either in the form, or referring to the form from the
- outside. These actioners simply get the same set of operands, even if they correspond
- to distinct actions.
-
- Input elements may be put only within a form.
-
-
-
- *** (3.5) Local popup.
-
- This element looks like a link or a rollover button. When this button is clicked upon,
- a 'popup window' appears. Actually, this popup window is just a layer in the same HTML
- page, which becomes suddenly visible. It is realized with a '
' HTML tag. In
- particular, clicking on the button does not open any connection. This is why it is
- called 'local'. The arguments have the following roles:
-
- Actioner_Aspect aspect of the button (same semantics as for actioners)
- content content of the popup window
- x, y, position of the popup window on the HTML page (not relative
- to the button but to the page itself)
- title title of the popup window
- color color of the title bar and close button in the popup window.
- A lightened version of this color is used for the background
- of the popup window.
- width width of the title bar
-
-
-
-
-
- --- That's all for the public part ! --------------------------------------------------
-
-
-
-
-
- ----------------------------------- Table of Contents ---------------------------------
-
- *** [1] States.
- *** [1.1] Saving and retrieving states.
- *** [1.2] Deleting out of date states.
-
- *** [2] Tools.
- *** [2.1] Directories.
- *** [2.2] Secondary documents.
-
- *** [3] Managing web arguments.
- *** [3.1] Prefixing web arguments names.
- *** [3.2] Separating web arguments.
- *** [3.3] Applying an action.
-
- *** [4] Web site descriptions and the 'awp handlers'.
- *** [4.1] The type 'Web_Site'.
- *** [4.2] Making a web site description.
- *** [4.3] Starting the servers.
-
- *** [5] HTML Formating.
- *** [5.1] The type 'HTML_Any($T)'.
- *** [5.2] Formating a color.
- *** [5.3] Creating buttons.
- *** [5.4] Formating an actioner.
- *** [5.5] Formating a private download link.
- *** [5.6] Formating rows and cells in a table.
- *** [5.7] Formating elements which may be put anywhere.
- *** [5.8] Formating 'in form' elements.
- *** [5.9] Formating 'off form' elements.
- *** [5.10] Formating meta-tags.
-
- ---------------------------------------------------------------------------------------
-
-
-
-
-public define String
- doctype_w3c_header
- =
- "\n".
-
-public define String
- html_header
- =
- "\n".
-
-
- *** [1] States.
-
- We have to define functions for saving a state, retrieving a state, deleting out of
- date states. We need one such function per web site. The types of the first two
- functions depend on the parameter $State. This is not the case of the third one. The
- fact that the instance of $State is variable from one web sites to the other implies
- rather subtle manipulations using full functionality.
-
-
- *** [1.1] Saving and retrieving states.
-
- Each state is saved into a file on the server's disk (in the directory represented by
- the symbol 'state_directory', which is 'my_anubis/web_sites/common_name/states'). The
- state is saved together with a time stamp whose value is obtained by adding the current
- time to the given timeout for states. The state receives a name obtained by hashing
- (using sha1) the content of the file itself, and then encoding the hash with
- 'web_arg_encode'. The name of the file into which the state is saved is the
- concatenation of "s" and the name of the state.
-
-read CXM_web_arg_encode.anubis
-
- The tool below constructs the function which is able to save a state on the server's
- disk.
-
-define ($State s) -> String // the function constructed returns the name of the state
- make_save_state_function
- (
- Int timeout,
- String state_directory
- ) =
- ($State s) |->
- with time_stamp = now+timeout,
- to_be_saved = (time_stamp,s),
- state_name = web_arg_encode(sha1(s)),
- if save(to_be_saved,state_directory+"/s"+state_name) is ok
- then state_name
- else (print("Cannot create state file in '"+state_directory+"'.\n"); "").
-
-
- When a request arrives, we need to retrieve the previous state from the server's
- disk. We receive the name of that state. If the state is out of date, the state file is
- kept 3 days, and then deleted.
-
-type PreviousState($State):
- not_found, // cannot retrieve the previous state
- out_of_date($State), // the previous state is out of date
- still_valid($State). // the previous state is still valid
-
-define (String state_name) -> PreviousState($State)
- make_retrieve_state_function
- (
- String state_directory
- ) =
- (String state_name) |->
- with file_path = state_directory+"/s"+state_name,
- if (RetrieveResult((Int,$State)))retrieve(file_path) is ok(d)
- then (
- if d is (time_stamp,s) then
- if time_stamp < now
- then (
- forget(remove(file_path));
- out_of_date(s)
- )
- else still_valid(s) // state has been successfully retrieved
- )
- else not_found.
-
-
-
- *** [1.2] Deleting out of date states.
-
- We also need to delete states which are out of date and which will never be deleted by
- the above method. This may be performed by a machine doing this periodically (say once
- per states life time period).
-
-define (List(String) file_names) -> One
- make_delete_out_of_date_states_function
- (
- Maybe($State) dummy,
- String state_directory
- ) =
- (List(String) file_names) |-df->
- if file_names is
- {
- [ ] then unique,
- [h . t] then
- with file_path = state_directory+"/"+h,
- if (RetrieveResult((Int,$State)))retrieve(file_path) is ok(d)
- then (
- if d is (time_stamp,data) then
- if time_stamp < now
- then (forget(remove(file_path)); df(t))
- else df(t)
- )
- else (forget(remove(file_path)); df(t))
- }.
-
-
- The 'labelled arrow' |-df-> is documented in 'documentation/en/anubis_doc.txt'.
-
- Note: The argument 'dummy' (of type Maybe($State)) is not used in the body of the
- function (hence its name). Nevertheless, it is required. Indeed, the Anubis compiler
- does not accept a parameter in the body of a function (here the parameter is required
- by the use of 'retrieve') if this parameter does not appear in the type of the
- function. This is because this would create ambiguities that no explicit typing may
- ever resolve. If you put a double slash in front of the declaration of 'dummy' above,
- and if you compile this file, you will get a message like this one:
-
- Error in 'making_a_web_site.anubis', line 1300, column 7:
- A definition may not contain parameters which are not present
- in the declaration part (hidden parameters):
- $State
-
- The type of the function constructed by 'make_delete_out_of_date_states_function' is
- independant of the parameter $State. This is important because this allows to create
- the list of such functions for all web sites. From this list, it is possible to call
- the functions one after the other, so deleting out of date states for all web
- sites. Actually, the next function receives a list of pairs (state_directory,function),
- one for each web site.
-
-define One
- delete_out_of_date_states // for all web sites
- (
- List((String, List(String) -> One)) directories_and_functions
- ) =
- if directories_and_functions is
- {
- [ ] then unique,
- [h . t] then if h is (state_directory,function) then
- function(directory_list(state_directory,"s*"));
- delete_out_of_date_states(t)
- }.
-
-
- The above function must be called periodically in a separate virtual machine. The
- period we have choosen is (rather logically) the life time of states itself. This may
- be achieved by an 'infinite' loop, using a 'sleep(timeout)'. However, the loop must not
- be really infinite, because the servers may be shutdown. Hence, our loop must test
- (rather frequently; say every second) if the servers are down. If they are, the loop
- must be exited.
-
-define One
- delete_states_loop
- (
- List((String,List(String) -> One)) directories_and_functions,
- Int timeout,
- Int next_time,
- Server http_server,
- Server https_server,
- (One) -> Bool shutdown_required
- ) =
- if shutdown_required(unique)
- then (shutdown(http_server); shutdown(https_server))
- else unique;
- if (is_down(http_server) & is_down(https_server))
- then unique
- else if now > next_time
- then
- (
- delete_out_of_date_states(directories_and_functions);
- delete_states_loop(directories_and_functions,
- timeout,
- now+timeout,
- http_server,
- https_server,
- shutdown_required)
- )
- else
- (
- sleep(1000); // sleep just one second and try again
- delete_states_loop(directories_and_functions,
- timeout,
- next_time,
- http_server,
- https_server,
- shutdown_required)
- ).
-
- The above loop must be run in a separate virtual machine. This will be done just after
- the two servers are started.
-
-
-
-
-
- *** [2] Tools.
-
- *** [2.1] Directories.
-
- We need a tool for creating directories (if needed).
-
- (This tool has been moved to 'tools/basis.anubis').
-
-
-
-
- *** [2.2] Secondary documents.
-
- Some HTML elements (like '