From 9ca943bd56b1b4602b82d993dc5bc67a7b999ece Mon Sep 17 00:00:00 2001 From: Cedric RICARD Date: Thu, 28 Aug 2008 16:24:39 +0000 Subject: [PATCH] Calexium_lib branch for MF 1.1 --- MF_1_1/CXM_errors.anubis | 41 +++++++++++++++++++++++++++++++++++++++++ MF_1_1/CXM_message_constants.anubis | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/database/db_utils.anubis | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/net_services/CXM_generic_client.anubis | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/net_services/CXM_generic_protocol.anubis | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/net_services/CXM_net_services.anubis | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/net_services_protocols/ftp_client.anubis | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/net_services_protocols/logger_service.anubis | 357 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/net_services_protocols/pkg_updater_protocol.anubis | 12 ++++++++++++ MF_1_1/web/CXM_common.anubis | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_cookies.anubis | 663 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_dojo.anubis | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_generic_form.anubis | 471 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_generic_login.anubis | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_generic_table.anubis | 786 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_html.anubis | 2395 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_http_get_common.anubis | 305 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_making_a_web_site.anubis | 4321 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_mime.anubis | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_multihost_http_server.anubis | 3851 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/CXM_web_arg_encode.anubis | 349 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MF_1_1/web/counter.anubis | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 22 files changed, 15059 insertions(+), 0 deletions(-) create mode 100644 MF_1_1/CXM_errors.anubis create mode 100644 MF_1_1/CXM_message_constants.anubis create mode 100644 MF_1_1/database/db_utils.anubis create mode 100644 MF_1_1/net_services/CXM_generic_client.anubis create mode 100644 MF_1_1/net_services/CXM_generic_protocol.anubis create mode 100644 MF_1_1/net_services/CXM_net_services.anubis create mode 100644 MF_1_1/net_services_protocols/ftp_client.anubis create mode 100644 MF_1_1/net_services_protocols/logger_service.anubis create mode 100644 MF_1_1/net_services_protocols/pkg_updater_protocol.anubis create mode 100644 MF_1_1/web/CXM_common.anubis create mode 100644 MF_1_1/web/CXM_cookies.anubis create mode 100644 MF_1_1/web/CXM_dojo.anubis create mode 100644 MF_1_1/web/CXM_generic_form.anubis create mode 100644 MF_1_1/web/CXM_generic_login.anubis create mode 100644 MF_1_1/web/CXM_generic_table.anubis create mode 100644 MF_1_1/web/CXM_html.anubis create mode 100644 MF_1_1/web/CXM_http_get_common.anubis create mode 100644 MF_1_1/web/CXM_making_a_web_site.anubis create mode 100644 MF_1_1/web/CXM_mime.anubis create mode 100644 MF_1_1/web/CXM_multihost_http_server.anubis create mode 100644 MF_1_1/web/CXM_web_arg_encode.anubis create mode 100644 MF_1_1/web/counter.anubis diff --git a/MF_1_1/CXM_errors.anubis b/MF_1_1/CXM_errors.anubis new file mode 100644 index 0000000..f9ea1ee --- /dev/null +++ b/MF_1_1/CXM_errors.anubis @@ -0,0 +1,41 @@ +/* + * Created by PyramIDE. + * User: ricard + * Date: 16/09/2007 + * Time: 21:10 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +public type GeneralError: + ok, + unknown(Word32 val), + bad_type, + bad_value, + bad_parameters, + no_init, + unknown_command, + wrong_authentification, // Wrong login or password + access_denied, // login ok but no suffisiant right to access to this area. Can be use with wrong authentification too... + io_error, // general error on reading or writing from/to IO (file, socket, etc...) + cant_start_process. // A execute to an external process has failed + +public define Word32 + to_Word32 + ( + GeneralError e + ) = + if e is + { + ok then 0, + unknown(val) then val, + bad_type then 0x1, + bad_value then 0x2, + bad_parameters then 0x3, + no_init then 0x4, + unknown_command then 0x5, + wrong_authentification then 0x6, + access_denied then 0x7, + io_error then 0x8, + cant_start_process then 0x9, + }. diff --git a/MF_1_1/CXM_message_constants.anubis b/MF_1_1/CXM_message_constants.anubis new file mode 100644 index 0000000..53a5a0e --- /dev/null +++ b/MF_1_1/CXM_message_constants.anubis @@ -0,0 +1,83 @@ +/* + * + * User: David RENE + * Date: 07/04/2007 + * Time: 16:06 + * (c) Calexium + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + + // **************** PACKAGE BUILDER *************** + +public define Word32 _CXM_PKG_MSG_BASIS = 0x33770400. // +public define Word32 _CXM_PKG_CONTAINER = 0x33770401. +public define Word32 _CXM_PKG_HEADER_PART = 0x33770402. // Header Message for Script +public define Word32 _CXM_PKG_SCRIPT_PART = 0x33770403. // Main Message for Script +public define Word32 _CXM_PKG_S_ADD_FILE = 0x33770404. // script action to add file in the destination +public define Word32 _CXM_PKG_S_RUN = 0x33770405. // script action to run a command +public define Word32 _CXM_PKG_INDEX_PART = 0x33770440. // ID of package Index part +public define Word32 _CXM_PKG_IDX_ENTRY = 0x33770441. // Index entry information + + // **************** UPDATE SERVICE *************** + +public define Word32 _CXM_UPDATE_SERVICE_MSG_BASIS = 0x33770800. // +public define Word32 _CXM_UPD_SERVICE_ID = 0x33770801. +public define Word32 _CXM_UPD_HAS_UPDATE = 0x33770802. // + + // **************** SERVICE NEGOCIATION *************** + +public define Word32 _CXM_SERVICE_NEGOCIATION_BASIS = 0x33770C00. // +public define Word32 _CXM_REQUEST_FOR_SERVICE = 0x33770C01. // + + // **************** GENERIC PROTOCOL *************** + +public define Word32 _CXM_GENERIC_PROTOCOL_BASIS = 0x33771000. // +public define Word32 _CXM_ACK = 0x33771001. // +public define Word32 _CXM_ACK_RESULT_MSG = 0x33771002. // + + // **************** FTP SERVICE *************** + +public define Word32 _CXM_FTP_SERVICE_MSG_BASIS = 0x33771400. // +public define Word32 _CXM_FTP_SERVICE_ID = 0x33771401. +public define Word32 _CXM_FTP_GET_FILE = 0x33771402. +public define Word32 _CXM_FTP_START_TRANSFERT = 0x33771403. +public define Word32 _CXM_FTP_DATA = 0x33771404. + + // ************** LOGGER SERVICE ************** + +public define Word32 _CXM_LOGGER_SERVICE_MSG_BASIS = 0x33771800. // +public define Word32 _CXM_LOGGER_SERVICE_ID = 0x33771801. +public define Word32 _CXM_LOGGER_LOG = 0x33771802. + + // ************** DOMAIN SERVICE ************** + +// MF <-> DomainManager +public define Word32 _CXM_DOMAIN_SERVICE_MSG_BASIS = 0x33771C00. // +public define Word32 _CXM_DOMAIN_SERVICE_ID = 0x33771C01. +public define Word32 _CXM_DOMAIN_PUBLISH_MF_CONFIG = 0x33771C02. +public define Word32 _CXM_DOMAIN_GET_NAME = 0x33771C03. +public define Word32 _CXM_DOMAIN_GET_MY_IP = 0x33771C04. +public define Word32 _CXM_DOMAIN_PUBLISH_MY_IP = 0x33771C05. +public define Word32 _CXM_DOMAIN_PUBLISH_DYN_TEST = 0x33771C06. +public define Word32 _CXM_DOMAIN_GET_STATUS = 0x33771C07. +public define Word32 _CXM_DOMAIN_GET_DOMAIN_INFO = 0x33771C08. + + +// DomainManager <-> Gandi +public define Word32 _CXM_GANDI_SERVICE_ID = 0x33771D00. +public define Word32 _CXM_GANDI_CHECK_AVAILABILITY = 0x33771D01. // 'NAME' (String): Base names (without extension) of the wanted domains + // --> CXM_ACK with 'DOMAINS' (String): Array of avaiblable domains +public define Word32 _CXM_GANDI_CREATE_CONTACT = 0x33771D02. // 'CLASS' (String): + // 'FIRSTNAME', 'LASTNAME', 'ADDRESS', 'ZIPCODE', 'CITY', 'COUNTRY', 'PHONE', 'EMAIL' (String) + // --> CXM_ACK with 'CONTACT_HANDLE' (String): Created handle for this contact +public define Word32 _CXM_GANDI_CREATE_DOMAIN = 0x33771D03. // 'DOMAIN' (String): Domain full name + // 'OWNER' (String): Owner handle + // --> CXM_ACK with 'DOMAIN_HANDLE' (String): Created handle for this domain + // ************** MF INSTALLER SERVICE ************** + +public define Word32 _CXM_INSTALLER_SERVICE_MSG_BASIS= 0x33772000. +public define Word32 _CXM_INSTALLER_SERVICE_ID = 0x33772001. +public define Word32 _CXM_INSTALLER_REGISTER_APP_ID = 0x33772002. +public define Word32 _CXM_INSTALLER_GET_NEW_SERIALS = 0x33772003. +public define Word32 _CXM_INSTALLER_CONFIRM_SERIALS_PUBLICATION = 0x33772004. diff --git a/MF_1_1/database/db_utils.anubis b/MF_1_1/database/db_utils.anubis new file mode 100644 index 0000000..17b7e25 --- /dev/null +++ b/MF_1_1/database/db_utils.anubis @@ -0,0 +1,121 @@ +/* + * + * User: David RENE + * Date: 11/12/2007 + * Time: 01:16 + * (c) Calexium + * + */ + +read tools/basis.anubis +read system/logger.anubis +read data_base/sqlite.anubis + +read calexium_lib/net_services_protocols/logger_service.anubis + + +define Result(SQLite3Error, SQLite3HeadersOrRow -> SQLite3Row) + sql_query_timeout + ( + SQLite3DataBase db, + String sql_command, + Int timeout + ) = + + if sql_query(db, sql_command) is + { + error(sql_error) then ( + if (sql_error.code /= 1 & sql_error.code /= 5 & sql_error.code /= 6) | now > timeout then + error(sql_error) + else + ( + if sql_error.code = 5 then + unique + else + print_db_error(sql_error) + ); + sleep(100); + sql_query_timeout(db, sql_command, timeout)), + ok(cursor) then ok(cursor) + }. + +public define Result(SQLite3Error, One) + sql_transaction + ( + SQLite3DataBase db, + String sql_command, + String message + ) = +// logDebug(debug_log, "Entering into transaction [" + message + "]."); + if db_do_transaction( + db, + (One _) |-> + if sql_query(db, sql_command) is + { + error(err) then logError("DB", db_error(err,message));failure //error in the SQL request + ok(cursor) then success(unique) + }, + success( (SQLite3Error err) |-> logError("DB", db_error(err,message))), + 60000, // max 60s + 100 // retry every 100 ms + ) is + { + error(err_and_result) then +// logDebug(debug_log, "Exiting from transaction [" + message + "] with error."); + if err_and_result is (err, mb_result) then + error(err), + ok(_) then +// logDebug(debug_log, "Exiting from transaction [" + message + "]."); + ok(unique) + }. + + +public define Maybe(SQLite3HeadersOrRow -> SQLite3Row) + sql_query_timeout + ( + SQLite3DataBase db, //database handle + String sql_query, //sql query itself + String msg //message to be shown if an error occure + ) = + //we try with 30 sec of timeout + if sql_query_timeout(db, sql_query, now + 60) is + { + error(sql_error) then logError("DB", db_error(sql_error,msg));failure, + ok(cursor) then success(cursor) + }. + +// -- Extractors HELPERS --------------- + +public define List(String) + db_get_string_list + ( + SQLite3HeadersOrRow -> SQLite3Row table_cursor, + List(String) so_far + ) = + if table_cursor(next_row) is + { + error(sql_error) then logError("DB", db_error(sql_error, "db_get_string_list")); reverse(so_far), + no_more_row then reverse(so_far), //can't find the symbol in the table, because the row is empty + row(explorer) then + with s = text(explorer)(0), + db_get_string_list(table_cursor, [s . so_far]) + }. + +public define List(Int) + db_get_integer_list + ( + SQLite3HeadersOrRow -> SQLite3Row table_cursor, + List(Int) so_far + ) = + if table_cursor(next_row) is + { + error(sql_error) then logError("DB", db_error(sql_error, "db_get_integer_list")); reverse(so_far), + no_more_row then reverse(so_far), //can't find the symbol in the table, because the row is empty + row(explorer) then + with s = (Int)db_integer(explorer)(0), + db_get_integer_list(table_cursor, [s . so_far]) + }. + + + + diff --git a/MF_1_1/net_services/CXM_generic_client.anubis b/MF_1_1/net_services/CXM_generic_client.anubis new file mode 100644 index 0000000..5c90073 --- /dev/null +++ b/MF_1_1/net_services/CXM_generic_client.anubis @@ -0,0 +1,196 @@ +/* + * Created by PyramIDE. + * User: ricard + * Date: 02/02/2008 + * Time: 11:47 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + + +read tools/basis.anubis +read system/muscle.anubis +read system/data_io.anubis +read system/convert.anubis +read system/string.anubis +read system/message_queue.anubis +read system/message_transceiver.anubis +read tools/connections.anubis + +read calexium_lib/CXM_message_constants.anubis +read calexium_lib/net_services/CXM_net_services.anubis +read calexium_lib/net_services/CXM_generic_protocol.anubis + +// --Generic types--------------------------------------------------------------------- +public type NetServiceAnswer: + netservice_error (Word32 cmd, + Word32 result_code, + String result_string), + netservice_ok (Word32 cmd, + Maybe(Message) result_msg). + +// --Generic functions--------------------------------------------------------------------- + + +public define Maybe(NetServiceAnswer) + generic_send_message + ( + MessageQueue queue, + Message msg_to_send, + Int timeout, + (String) -> One logger + )= + queue.add_Message_to_send(msg_to_send); + if queue.get_next_received_Message(timeout) is + { + timeout then logger("["+queue.get_name(unique)+"]: receive timeout");failure, + closed then logger("["+queue.get_name(unique)+"]: socket closed");failure, + msg(msg) then + if find_int32(msg, "CMD") is + { + failure then logger("["+queue.get_name(unique)+"]: CMD field not found"); failure, + success(cmd) then + if find_int32(msg, "STATUS") is + { + failure then logger("["+queue.get_name(unique)+"]: STATUS field not found"); failure, + success(v) then + if v = _CXM_OK then + success(netservice_ok(cmd, find_message(msg, "RESULT"))) + else + with error_string = if find_string(msg, "STATUS_STR") is success(s) then s else "", + success(netservice_error(cmd, v, error_string)) + } + } + }. + +public define Maybe($T) + generic_handler + ( + MessageQueue queue, + Int timeout, + Message msg_to_send, + (Message) -> Maybe($T) handler, + (String) -> One logger + )= + queue.add_Message_to_send(msg_to_send); + if queue.get_next_received_Message(timeout) is + { + timeout then logger("["+queue.get_name(unique)+"]: receive timeout");failure, + closed then logger("["+queue.get_name(unique)+"]: socket closed");failure, + msg(msg) then + if find_int32(msg, "STATUS") is + { + failure then logger("["+queue.get_name(unique)+"]: status not found");failure, + success(v) then + if v = _CXM_OK then + //println("generic_handler("+queue.get_name(unique)+"): message status ok"); + if find_message(msg, "RESULT") is + { + failure then logger("["+queue.get_name(unique)+"]: can't find RESULT");failure, + success(result) then handler(result) + } + else + logger("["+queue.get_name(unique)+"]: message status ERROR");failure + } + }. + +public define (MessageQueue, String) -> Maybe($T) + make_generic_handler + ( + Int timeout, + Message msg_to_send, + (Message) -> Maybe($T) handler, + (String) -> One logger + ) = + (MessageQueue queue, String timestamp) |-> + generic_handler(queue, timeout, msg_to_send, handler, logger). + +define Maybe($T) + generic_request_for_service + ( + MessageQueue queue, + Word32 service_id, + Word32 service_version, + (MessageQueue, String) -> Maybe($T) handler, + (String) -> One logger + )= + with test_msg = message(_CXM_REQUEST_FOR_SERVICE), + forget(add_int32(test_msg, "SERVICE", service_id)); + forget(add_int32(test_msg, "VERSION", service_version)); + queue.add_Message_to_send(test_msg); + if queue.get_next_received_Message(10) is + { + timeout then logger("["+queue.get_name(unique)+"]: requesting service receive timeout");failure, + closed then logger("["+queue.get_name(unique)+"]: requesting service socket closed");failure, + msg(msg) then + if find_int32(msg, "STATUS") is + { + failure then logger("["+queue.get_name(unique)+"]: requesting service STATUS not found");failure, + success(v) then + if v = _CXM_OK then + if find_message(msg, "RESULT") is + { + failure then logger("["+queue.get_name(unique)+"]: requesting service RESULT not found");failure, + success(result) then + with timestamp = if find_string(result, "TIMESTAMP") is + { + failure then logger("["+queue.get_name(unique)+"]: requesting service TIMESTAMP not found"); "", + success(timestamp) then timestamp + }, + handler(queue, timestamp) + } + else + logger("["+queue.get_name(unique)+"]: requested service started won't start");failure + } + }. + +public define Maybe($T) + generic_connect_to_net_service + ( + String queue_name, + Word32 server, + Word32 port, + Word32 service_id, + Word32 service_version, + (MessageQueue, String) -> Maybe($T) handler, + (String) -> One logger + ) + = + if connect( server, port) is + { + error(_) then logger(queue_name + ": Can't connect to domain manager ["+ip_addr_to_string(server)+":"+port+"]");failure, + ok(conn) then + with queue = create_MessageQueue(queue_name), + message_transceiver(tcp(conn), queue); + with result = generic_request_for_service(queue, service_id, service_version, handler, logger), + queue.quit(unique); + //logInfo(debug_log,"domain_manager client quit"); + result + }. + +public define Maybe($T) + generic_connect_to_net_service_SSL + ( + String queue_name, + String server_name, + Word32 server_ip, + Word32 port, + (Maybe(X509)) -> Bool accept_policy, // your policy for accepting the server certificate in + // case of an invalid, non trusted or missing certificate + Word32 service_id, + Word32 service_version, + (MessageQueue, String) -> Maybe($T) handler, + (String) -> One logger + ) + = + if open_SSL_connection( server_name, server_ip, port, accept_policy) is + { + error(_) then logger(queue_name + ": Can't connect to domain manager ["+ip_addr_to_string(server_ip)+":"+port+"]");failure, + ok(conn) then + with queue = create_MessageQueue(queue_name), + message_transceiver(ssl(conn), queue); + with result = generic_request_for_service(queue, service_id, service_version, handler, logger), + queue.quit(unique); + //logInfo(debug_log,"domain_manager client quit"); + result + }. diff --git a/MF_1_1/net_services/CXM_generic_protocol.anubis b/MF_1_1/net_services/CXM_generic_protocol.anubis new file mode 100644 index 0000000..82f3a8d --- /dev/null +++ b/MF_1_1/net_services/CXM_generic_protocol.anubis @@ -0,0 +1,144 @@ +/* + * + * User: David RENE + * Date: 25/04/2007 + * Time: 16:20 + * (c) Calexium + * + */ + +read system/muscle.anubis +read system/data_io.anubis +read system/string.anubis +read tools/basis.anubis +read system/message_queue.anubis +read calexium_lib/CXM_message_constants.anubis + +public define Word32 _CXM_OK = 0. +public define Word32 _CXM_ERROR = 1. +public define Word32 _CXM_UNKNOW_CMD = 2. +public define Word32 _CXM_UNKNOW_SERVICE = 3. + +public type ProtocolResult: + failure, + timeout, + unknow_cmd, + error, + ok, + ok_msg(Message). + +public define One + send_ACK_error + ( + MessageQueue queue, + Word32 cmd_id, + Word32 error_code, + String error_string, + )= + with err_msg = message(_CXM_ACK), + forget(add_int32(err_msg, "CMD", cmd_id)); + forget(add_int32(err_msg, "STATUS", error_code)); + (if error_string /= "" then forget(add_string(err_msg, "STATUS_STR", error_string)) + else unique); + forget(queue.add_Message_to_send(err_msg)). + +public define One + send_ACK_error + ( + MessageQueue queue, + Word32 cmd_id + )= + send_ACK_error(queue, cmd_id, _CXM_ERROR, ""). + +public define One + send_ACK_ok + ( + MessageQueue queue, + Word32 cmd_id + )= + with ok_msg = message(_CXM_ACK), + forget(add_int32(ok_msg, "CMD", cmd_id)); + forget(add_int32(ok_msg, "STATUS", _CXM_OK)); + forget(queue.add_Message_to_send(ok_msg)) + . + +public define One + send_ACK_ok + ( + MessageQueue queue, + Word32 cmd_id, + Message result + )= + with ok_msg = message(_CXM_ACK), + forget(add_int32(ok_msg, "CMD", cmd_id)); + forget(add_int32(ok_msg, "STATUS", _CXM_OK)); + forget(add_message(ok_msg, "RESULT", result)); + forget(queue.add_Message_to_send(ok_msg)) + . + +public define One + send_result + ( + MessageQueue queue, + Word32 cmd_id, + Maybe(Message) mb_msg + )= + if mb_msg is + { + failure then send_ACK_error(queue, cmd_id), + success(msg) then send_ACK_ok(queue, cmd_id, msg) + }. + +public define One + send_result + ( + MessageQueue queue, + Word32 cmd_id, + Bool result + )= + if result then + send_ACK_ok(queue, cmd_id) + else + send_ACK_error(queue, cmd_id). + +public define ProtocolResult + wait_for_reply + ( + MessageQueue mQ, + Word32 wait_cmd, + Int t_out + ) = + if mQ.get_next_received_Message(t_out) is + { + timeout then timeout, + closed then failure, //println("wait_for_reply closed"); + + msg(_msg) then + if *_msg.what = _CXM_ACK then + if find_int32(_msg, "CMD") is + { + failure then failure, //println("wait_for_reply CMD"); + success(cmd) then +// println("wait_for_reply CMD="+to_hexa(cmd)); + if find_int32(_msg, "STATUS") is + { + failure then failure, //println("wait_for_reply STATUS"); + success(status) then + if cmd = wait_cmd & status = _CXM_OK then + if find_message(_msg, "RESULT") is + { + failure then ok, + success(ok_message) then ok_msg(ok_message) + } + else if cmd = wait_cmd & status = _CXM_ERROR then + error + else if cmd = wait_cmd & status = _CXM_UNKNOW_CMD then + unknow_cmd + else + failure //println("wait_for_reply "); + } + } + else + failure //println("wait_for_reply not ACK"); + }. + diff --git a/MF_1_1/net_services/CXM_net_services.anubis b/MF_1_1/net_services/CXM_net_services.anubis new file mode 100644 index 0000000..144faf4 --- /dev/null +++ b/MF_1_1/net_services/CXM_net_services.anubis @@ -0,0 +1,192 @@ +/* + * + * User: David RENE + * Date: 25/04/2007 + * Time: 11:01 + * (c) Calexium + * + */ +read tools/basis.anubis +read system/convert.anubis +read system/string.anubis +read system/muscle.anubis +read system/data_io.anubis +read system/message_queue.anubis +read system/message_transceiver.anubis +read CXM_generic_protocol.anubis +read calexium_lib/CXM_message_constants.anubis + +public type NetService: + net_service( + Word32 version, + Word32 id, + String name, + (MessageQueue, String, String) -> One handler // Parameters are MessageQueue, peer IP and timestamp string + ). + +define One + print_services + ( + List(NetService) net_services + ) = + map_forget((NetService net_s)|-> + println(" id : 0x"+ to_hexa(net_s.id)); + println(" version : " + to_String(net_s.version)); + println(" name : "+ net_s.name ); + println("----------------------------------------") + ,net_services). + + /** Try to find the service_id in services_list. If the service is found in that list + * the corresponding NetService object is return + */ +define Maybe(NetService) + find_service + ( + List(NetService) services_list, + Word32 service_id, + Word32 service_version + )= + if services_list is + { + [] then failure, + [h.t] then + if h.id = service_id & h.version >=+ service_version then + success(h) + else + find_service(t, service_id, service_version) + }. + + /** Check if the muscle message msg has the correct fields for requesting a net_services + * if we found "service" and "version" fields on the message, we try to find if the service + * referenced in "service" is available in net_services list + */ +define Maybe(NetService) + has_service + ( + MessageQueue queue, + Message msg, + List(NetService) net_services + )= + if find_int32(msg, "SERVICE") is + { + failure then //send_ACK_error(queue, _CXM_REQUEST_FOR_SERVICE); failure, + // old names... should be removed soon + if find_int32(msg, "service") is + { + failure then send_ACK_error(queue, _CXM_REQUEST_FOR_SERVICE); failure, + success(service_id) then + if find_int32(msg, "version") is + { + failure then send_ACK_error(queue, _CXM_REQUEST_FOR_SERVICE);failure, + success(service_version) then find_service(net_services, service_id, service_version) + } + } + + success(service_id) then + if find_int32(msg, "VERSION") is + { + failure then send_ACK_error(queue, _CXM_REQUEST_FOR_SERVICE);failure, + success(service_version) then find_service(net_services, service_id, service_version) + } + }. + +define String + get_time_stamp + = + with time = (UTime) unow, + "<"+virtual_machine_id+"@"+time.seconds+">". + + /** This message_received function just handle the negociation process the available net_services. + * In other words, it only recognize the _CXM_REQUEST_FOR_SERVICE message and try to launch the + * corresponding servcice + */ + +define One + service_negociation + ( + MessageQueue queue, + Message msg, + List(NetService) net_services, + String peer + )= + //TODO DR add a real management of error + //println("Service NEGOCIATION [" + to_hexa(*msg.what) + "] received"); + if * msg.what = _CXM_REQUEST_FOR_SERVICE then + if has_service(queue, msg, net_services) is + { + failure then + send_ACK_error(queue, _CXM_REQUEST_FOR_SERVICE, _CXM_UNKNOW_SERVICE, "Unknown service") + success(net_service) then + with result = message(0), + timestamp = get_time_stamp, + forget(add_string(result, "TIMESTAMP", timestamp)); + send_ACK_ok(queue, _CXM_REQUEST_FOR_SERVICE, result); + net_service.handler(queue, peer, timestamp) + } + else + send_ACK_error(queue, *msg.what, _CXM_UNKNOW_CMD, "Unknown command [" + (*msg.what) + "]") + . + + /** + * this function unflatten muscle message and give the correct message to service_negociation function + */ +define One + message_receiver + ( + MessageQueue queue, + List(NetService) net_services, + String peer + ) = + if queue.quit_requested(unique) then + unique + else + //println("PRE SERVICE message_receiver "+"["+virtual_machine_id + "]"); + if queue.get_next_received_Message(1) is + { + timeout then //println("PRE timeout"); + message_receiver(queue, net_services, peer), + closed then //println("PRE closed"); + unique, + msg(msg) then unique; //println("PRE negociation"); + service_negociation(queue, msg, net_services, peer); + message_receiver(queue, net_services, peer) + }. + +define Server -> (RWStream) -> One + net_services_handler + ( + List(NetService) net_services, + ) = + (Server server) |-> (RWStream conn) |-> + if remote_IP_address_and_port(conn) is (num_peer,_) then + //convert IP address of the client to string + with peer = ip_addr_to_string(num_peer), + //println("NET SERVICES Accepting connection with "+peer); + + //now managing the list of SERVICES + with queue = create_MessageQueue("CXM Net Services"), + message_transceiver(conn, queue); + message_receiver(queue, net_services, peer). + + +public define Maybe(Server) + start_net_services + ( + List(NetService) net_services, + Word32 network_port, + Var(Bool) shutdown_required + )= + if start_server(0, + network_port, + net_services_handler(net_services), + (One u) |-> unique) is + { + cannot_create_the_socket then println("Cannot create the listening socket."); failure, + cannot_bind_to_port then println("Cannot bind to port " + network_port ); failure, + cannot_listen_on_port then println("Cannot listen on port " + network_port); failure, + ok(server) then + println("Net services started on port " + network_port); + println("------ Available services ------"); + print_services(net_services); + success(server) + }. diff --git a/MF_1_1/net_services_protocols/ftp_client.anubis b/MF_1_1/net_services_protocols/ftp_client.anubis new file mode 100644 index 0000000..dc3dc6d --- /dev/null +++ b/MF_1_1/net_services_protocols/ftp_client.anubis @@ -0,0 +1,155 @@ +/* + * + * User: David RENE + * Date: 11/05/2007 + * Time: 22:34 + * (c) Calexium + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +read calexium_lib/CXM_message_constants.anubis +read calexium_lib/net_services/CXM_generic_protocol.anubis +read system/message_queue.anubis +read system/message_transceiver.anubis +read system/muscle.anubis +read system/files.anubis +read tools/basis.anubis + +define Maybe(One) + receive_data + ( + MessageQueue mQ, + WStream fd, + Int so_far, + Int left_read + )= + //println("receive_data "); + if mQ.get_next_received_Message(30) is + { + timeout then failure, + closed then failure, + msg(_msg) then + with last_block = if find_bool(_msg, "End") is {failure then false, success(r) then r}, + if find_raw(_msg, "Data") is + { + failure then println("Can't find raw Data"); send_ACK_error(mQ, _CXM_FTP_DATA); failure, + success(data) then + if write(fd, data) is + { + failure then println("Can't write into file"); send_ACK_error(mQ, _CXM_FTP_DATA);failure, + success(len) then + send_ACK_ok(mQ, _CXM_FTP_DATA); + if last_block then + println("File received successfully"); + //TODO this is a big hack, we must check if all data are sent from the mQ + sleep(10000); + success(unique) + else +// println("Bytes received : " + (so_far + len)); + receive_data(mQ, fd, so_far + len, left_read - len) + } + } + } + . + +define Maybe(One) + start_get_file_transtert + ( + MessageQueue mQ, + String local_file, + Int size + )= + make_directories(local_file); + if file(local_file, new) is + { + failure then println("Can't create \""+local_file+"\" file"); failure, + success(fd) then //the local file is open + with start = message(_CXM_FTP_START_TRANSFERT), + mQ.add_Message_to_send(start); + receive_data(mQ, weaken(fd), 0, size) + } + . + +define Maybe(One) + get_file + ( + MessageQueue mQ, + String remote_file, + String local_file + )= + with get_file_msg = message(_CXM_FTP_GET_FILE), + if add_string(get_file_msg, "FileName", remote_file) is + { + failure then failure, + success(_) then + mQ.add_Message_to_send(get_file_msg); + if wait_for_reply(mQ, _CXM_FTP_GET_FILE, 30) is + { + failure then println("get_file failure");failure, + timeout then println("get_file timeout");failure, + unknow_cmd then println("get_file unknow_cmd");failure, + error then println("get_file remote error msg");failure, + ok then println("get_file ok");failure, + ok_msg(msg)then + if find_int32(msg, "FileSize") is + { + failure then println("file size not found"); failure, + success(size) then println("file size "+size); + start_get_file_transtert(mQ, local_file, to_Int(size)) + } + } + }. + + +define Bool + request_for_service + ( + MessageQueue queue + )= + with test_msg = message(_CXM_REQUEST_FOR_SERVICE), + forget(add_int32(test_msg, "service", _CXM_FTP_SERVICE_ID)); + forget(add_int32(test_msg, "version", 1)); + queue.add_Message_to_send(test_msg); + if queue.get_next_received_Message(30) is + { + timeout then println("request_for_service receive timeout");false, + closed then println("request_for_service socket closed");false, + msg(msg) then + if find_int32(msg, "STATUS") is + { + failure then println("status not found");false, + success(v) then + if v = _CXM_OK then + true + else + false + } + }. + +public define Maybe(One) + ftp_get_file + ( + String server, + Word32 ip_port, + String remote_file, + String local_file + )= + if dns(server) is ok(ip_adr) then + if connect( ip_adr, ip_port) is + { + error(_) then println("can't connect to ftp server"); failure, + ok(conn) then + with queue = create_MessageQueue("ftp_get_file"), + message_transceiver(conn, queue); + if request_for_service(queue) then + with result = get_file(queue, remote_file, local_file), + queue.quit(unique);result + else + queue.quit(unique); + println("Service not found");failure + } + else + println("server "+server+" DNS error");failure + . + diff --git a/MF_1_1/net_services_protocols/logger_service.anubis b/MF_1_1/net_services_protocols/logger_service.anubis new file mode 100644 index 0000000..d0f0cee --- /dev/null +++ b/MF_1_1/net_services_protocols/logger_service.anubis @@ -0,0 +1,357 @@ +/* + * + * User: David RENE + * Date: 29/07/2007 + * Time: 02:04 + * (c) Calexium + * + */ + +read tools/basis.anubis +read system/muscle.anubis +read system/data_io.anubis +read system/convert.anubis +read system/string.anubis +read system/logger.anubis +read system/message_queue.anubis +read system/message_transceiver.anubis + +read calexium_lib/CXM_message_constants.anubis +read calexium_lib/net_services/CXM_net_services.anubis +read calexium_lib/net_services/CXM_generic_protocol.anubis + +// Special non-existing file. This is a work arround for a impossibility to define global configuration in anubis. +// So this file allows you to specify on which UDP port the logger server is listening. +// You have to provide this file in your base source directory (or any other folder which is scanned by the compilater, +// and you define a function named 'logger_port' which simply return the port number as an Word32. +// Example: +// public define Word32 logger_port = 33610. +read logger_config.anubis + +public define Word32 logger_srv_version = 1. + + /** + * has_update scan the given message for finding corresponding available update + * package for the application. The request message come with AppId field which contain + * package or application signature and CurrentVersion field which is current version + * installed on the requester. + * + * --- REQUEST message format + * msg [_CXM_UPD_HAS_UPDATE] + * string "AppId" = hash or unique signature of the package + * string "CurrentVersion" = current version installed on the remote caller + * + * --- ANSWER message format + * + * ERROR case message format + * msg [_CXM_ACK] + * int32 "CMD" = _CXM_UPD_HAS_UPDATE + * int32 "STATUS" = _CXM_ERROR + * + * OK without update available + * msg [_CXM_ACK] + * int32 "CMD" = _CXM_UPD_HAS_UPDATE + * int32 "STATUS" = _CXM_OK + * msg "RESULT" [_CXM_ACK_RESULT_MSG] + * int32 "PackageStatus" = no_update // numerical value = 0 + * + */ + +define Bool + process_log + ( + Logger log, + Message msg + )= + if find_string(msg, "LogString") is + { + failure then logError(log, "process_log can't find LogString");false, + success(log_string) then + if find_int32(msg, "Level") is + { + failure then logError(log, "process_log can't find Level");false, + success(int_level) then + if find_int32(msg, "Thread") is + { + failure then logError(log, "process_log can't find Level");false, + success(thread_id) then + with level = get_LogLevel_from_value(to_Int(int_level)), + if level is logTrace then + if find_string(msg, "LogMask") is + { + failure then logError(log, "process_log can't find LogMask");false, + success(log_mask) then logTrace(log, logMask(log_mask), log_string, thread_id); true + } + else doLog(log, log_string, level, thread_id); true +// { +// logNone then true, +// logCriticalError then logCriticalError(log, log_string); true, +// logError then logError(log, log_string); true, +// logWarning then logWarning(log, log_string); true, +// logInfo then logInfo(log, log_string); true, +// logDebug then logDebug(log, log_string); true +// logTrace then +// if find_string(msg, "LogMask") is +// { +// failure then logError(log, "process_log can't find LogMask");false, +// success(log_mask) then logTrace(log, logMask(log_mask),log_string); true +// } +// } + } + } + }. + +define Bool + process_log + ( + List(Logger) logs, + Message msg + )= + if find_string(msg, "LogName") is + { + failure then println("process_log can't find LogName");false, + success(log_name) then + if get_logger(logs, log_name) is + { + failure then println("can't find log ["+log_name+"]");false, + success(log) then process_log(log, msg) + } + }. + + /** message_received is the principal + */ + /* + define One + message_received + ( + MessageQueue queue, + List(Logger) logs, + Message msg + )= + with msg_what = *msg.what, + if msg_what = _CXM_LOGGER_LOG then + send_result(queue, _CXM_LOGGER_LOG, process_log(logs, msg)) + else + println("wrong message_received is not _CXM_LOGGER_LOG ");unique + . + + define One + logger_handler + ( + MessageQueue queue, + List(Logger) logs + )= + if queue.get_next_received_Message(1) is + { + timeout then //println("logger_handler timeout ["+queue.get_name(unique)+"]"); + logger_handler(queue, logs), + closed then //println("logger_handler closed ["+queue.get_name(unique)+"]"); + unique, + msg(msg) then //println("logger_handler msg received ["+queue.get_name(unique)+"]"); + message_received(queue, logs, msg); + logger_handler(queue, logs) + }. + + public define NetService + logger_service + ( + List(Logger) logs + )= + net_service( + logger_srv_version, + _CXM_LOGGER_SERVICE_ID, //id of the service declared in CXM_message_constants + "Logger service", //human readable name of the service + ( + MessageQueue queue, + String peer + ) |-> logger_handler(queue, logs)). + + */ + /****************** LOCAL UDP SERVICE *************/ + + +public define String + data_preview + ( + ByteArray data, + Int max + ) = + with l = length(data), + firsts_bytes = extract(data, 0, max), + "Length=" + l + "; String='"+to_string(firsts_bytes)+"' Buffer=[" + to_ascii(firsts_bytes) + (if l > max then "...]" else "]"). + + +define (UDP_Socket, ByteArray, Truncation, Word32, Word32) -> One + make_udp_handler + ( + List(Logger) logs, + Logger debug_logger + ) = + ( + UDP_Socket socket, + ByteArray data, + Truncation truncation, + Word32 ip_address, + Word32 ip_port + ) |-> + with ip = ip_addr_to_string(ip_address), + logTrace(debug_logger, logMask("Logger"), "LoggerServer: data received (" + length(data) + " bytes) from IP " + ip + "... "); + if receive_message_from_io(make_data_io(data)) is + { + failure then logWarning(debug_logger, "LoggerServer: Bad data packet received from IP " + ip + ": " + data_preview(data, 20)), + success(msg) then + if *msg.what = _CXM_LOGGER_LOG then + forget(process_log(logs, msg)) + else + println("LoggerService: wrong message_received. [" + to_hexa(*msg.what) + "] is not _CXM_LOGGER_LOG ") + }. + +define One + my_notify + ( + One dummy + ) = + unique. + +public define Maybe(UDP_Server) + start_logger_server + ( + List(Logger) logs, + Logger debug_logger + ) = + if start_udp_server(0, + logger_port, + make_udp_handler(logs, debug_logger), + 8*1024, + my_notify) is + { + cannot_create_the_socket then logError(debug_logger, "Cannot create the listening socket."); failure, + cannot_bind_address_port then logError(debug_logger, "Cannot bind to port " + logger_port + ".");failure, + access_denied then logError(debug_logger, "Cannot listen on port " + logger_port + ".");failure, + ok(server) then logInfo(debug_logger, "LocalLog Server started on port " + logger_port + "."); success(server) + }. + + + /****************** CLIENT PART *******************/ + +/* + define One + send_log_msg + ( + MessageQueue queue, + Message log_msg + )= + with test_msg = message(_CXM_REQUEST_FOR_SERVICE), + forget(add_int32(test_msg, "service", _CXM_LOGGER_SERVICE_ID)); + forget(add_int32(test_msg, "version", 1)); + queue.add_Message_to_send(test_msg); + if queue.get_next_received_Message(30) is + { + timeout then println("send_log_msg receive timeout"), + closed then println("send_log_msg socket closed"), + msg(msg) then + if find_int32(msg, "STATUS") is + { + failure then println("status not found"), + success(v) then + if v = _CXM_OK then + queue.add_Message_to_send(log_msg); + forget(wait_for_reply(queue, _CXM_LOGGER_LOG, 30)) + else + println("requested service started won't start") + } + }. +*/ + +define One + local_net_logger + ( + String logger_server, + Message log_message + )= + forget(send_message_by_udp(log_message, ip_address((127,0,0,1)), logger_port)). + +/* if find_string(log_message, "LogString") is + { + failure then println("process_log can't find LogString"), + success(log_string) then println(log_string) + }. + if connect( ip_address((127,0,0,1)), 33125) is + { + error(_) then println("can't connect to logger server ["+logger_server+"]"); + forget(process_log(fullLogger, log_message)), + ok(conn) then + with queue = create_MessageQueue("net logger sender"), + message_transceiver(conn, queue); + send_log_msg(queue, log_message); + queue.quit(unique) + }.*/ + +define Message + create_log_msg + ( + String logger_name, + String log_string, + Int level + )= + with string = if length(log_string) > 1024 then (if sub_string(log_string, 0, 1024) is success(s) then s else "?") + "..." + else log_string, + with log_msg = message(_CXM_LOGGER_LOG), + forget(add_string(log_msg, "LogName", logger_name)); + forget(add_string(log_msg, "LogString", string)); + forget(add_int32(log_msg, "Level", truncate_to_Word32(level))); + forget(add_int32(log_msg, "Thread", virtual_machine_id)); + log_msg + . + +public define One + logNone( + String logger_name, + String log_string + )= + local_net_logger("127.0.0.1", create_log_msg(logger_name, log_string, 0)). + +public define One + logCriticalError( + String logger_name, + String log_string + )= + local_net_logger("127.0.0.1", create_log_msg(logger_name, log_string, 1)). + +public define One + logError( + String logger_name, + String log_string + )= + local_net_logger("127.0.0.1", create_log_msg(logger_name, log_string, 2)). + +public define One + logWarning( + String logger_name, + String log_string + )= + local_net_logger("127.0.0.1", create_log_msg(logger_name, log_string, 3)). + +public define One + logInfo( + String logger_name, + String log_string + )= + local_net_logger("127.0.0.1", create_log_msg(logger_name, log_string, 4)). + +public define One + logDebug( + String logger_name, + String log_string + )= + local_net_logger("127.0.0.1", create_log_msg(logger_name, log_string, 5)). + +public define One + logTrace( + String logger_name, + LogMask log_mask, + String log_string + )= + with log_msg = create_log_msg(logger_name, log_string, 6), + forget(add_string(log_msg, "LogMask", log_mask.mask)); + local_net_logger("127.0.0.1", log_msg). diff --git a/MF_1_1/net_services_protocols/pkg_updater_protocol.anubis b/MF_1_1/net_services_protocols/pkg_updater_protocol.anubis new file mode 100644 index 0000000..a1cbc45 --- /dev/null +++ b/MF_1_1/net_services_protocols/pkg_updater_protocol.anubis @@ -0,0 +1,12 @@ +/* + * + * User: David RENE + * Date: 26/04/2007 + * Time: 19:08 + * (c) Calexium + * + */ + + +public define Word32 no_update = 0. +public define Word32 update_available = 1. diff --git a/MF_1_1/web/CXM_common.anubis b/MF_1_1/web/CXM_common.anubis new file mode 100644 index 0000000..5578e78 --- /dev/null +++ b/MF_1_1/web/CXM_common.anubis @@ -0,0 +1,192 @@ + + *Project* The Anubis Project + *Title* Some common stuff for the web. + + *Copyright* Copyright (c) Alain Prouté 2003. + + + + *Author* Alain Prouté + + *Public* + *Name* HTTP_header + *Description* + +read system/string.anubis + +/** + * The type 'HTTP_header' describes HTTP headers, which are just pairs '(name,value)'. + */ +public type HTTP_header: + http_header(String name, + String value). + + +public define Maybe(String) + http_header_value + ( + List(HTTP_header) l, + String name + ) = + if l is + { + [ ] then failure, + [h . t] then if h is + { + http_header(n, v) then //print("DEBUG: http_header_value --> HEADER = " + n + ":" + v + "\n"); + if insensitive_equal(name, n) then success(v) + else http_header_value(t, name), + } + }. + + *Name* Web_arg + *Description* + + The type 'Web_arg' describes 'web arguments'. A web argument is either a pair + '(name,value)' (for example it may be 'web_arg("password","foobar")', if the client + clicks on the submit button of a form containing a password input field named + 'password'), or an uploaded file. In this last case, it is a triplet containing the + name of the file upload input field, the value of this input field (name of the + uploaded file), and the name of the temporary file as saved by the server in its + 'upload temporary directory'; see 'web/http_server.anubis' and the 'upload' Web_item in + 'web/html.anubis'). + +public type Web_arg: + web_arg(String name, + String value), + upload (String name, // name of corresponding 'upload' Web_item + String value, // name of uploaded file + String temp_file_path). // temporary file path (relative to server directory) + + + *Name* Web_arg_value + *Description* + Of course, within the body of a 'web page' operation, you may want to recover the value + of a particular web argument. To that end, use the operation 'web_arg_value', which + takes 2 argument: + + - the list of all web arguments (the operand of the web page operation), + - the name of the argument whose value is wanted. + + This operation has the following return type: + +public type Web_arg_value: + not_found, + found(String value). + + *Name* Web_arg_value + *Description* + If the requested argument name is not found in the list, 'not_found' is + returned. Otherwise, the value returned by 'web_arg_value' has the form 'found(v)', + where 'v' is the value of the argument. + + The operation 'web_arg_value' is defined below. + +public define Web_arg_value + web_arg_value + ( + List(Web_arg) l, + String name + ) = + if l is + { + [ ] then not_found, + [h . t] then if h is + { + web_arg(n,v) then + if name=n + then found(v) + else web_arg_value(t,name), + + upload(n,v,tfn) then + if name=n + then found(v) + else web_arg_value(t,name) + } + }. + + *Ignore* + +public define Maybe((String,String)) + file_upload_value + ( + List(Web_arg) l, + String name + ) = + if l is + { + [ ] then failure, + [h . t] then if h is + { + web_arg(_,_) then file_upload_value(t,name), + upload(n,v,tfn) then + if n = name + then success((v,tfn)) + else file_upload_value(t,name) + } + }. + +public type Redirection: + redirect(String required_uri, // URI required by the client + String required_host, // value of 'Host' HTTP header sent by the client + String corresponding_uri). // URI which will be served to the client + +public type Redirections: + redirection_list(List(Redirection) redirections), + redirection_fn((String input_uri, // URI required by the client + String host) -> String f). // value of 'Host' HTTP header sent by the client + + + Now, you may also want to recover web argument values which have been encoded (by + 'web_arg_encode'). In this case, use the following: + +read CXM_web_arg_encode.anubis + + +public define Maybe($T) + decode_web_arg_value + ( + List(Web_arg) l, + String name + ) = + if web_arg_value(l,name) is + { + not_found then failure, + found(v) then web_arg_decode(v) + }. + +public define List(String) + web_arg_list_values + ( + List(Web_arg) l, + String name + ) = + if l is + { + [] then [], + [h . t] then + if h is web_arg(n, v) then + if n = name then + [ v . web_arg_list_values(t, name)] + else + web_arg_list_values(t, name) + else + web_arg_list_values(t, name) + + } + . + +public define String + dump_web_arg_values + ( + List(Web_arg) l, + ) = + if l is + { + [ ] then "\n", + [h . t] then if h is + { + web_arg(n,v) then "\n["+n+"] = '"+v+"'" + dump_web_arg_values(t), + upload(n,v,tfn) then "\n["+n+"] = '"+v+"'" + dump_web_arg_values(t) + } + }. diff --git a/MF_1_1/web/CXM_cookies.anubis b/MF_1_1/web/CXM_cookies.anubis new file mode 100644 index 0000000..5393c78 --- /dev/null +++ b/MF_1_1/web/CXM_cookies.anubis @@ -0,0 +1,663 @@ + + *Project* The Anubis Project + + *Title* Managing Cookies. + + *Copyright* Copyright (c) Alain Prouté 2001. + + + *Author* Alain Prouté + + + + +read tools/basis.anubis +read system/string.anubis +read CXM_common.anubis +read CXM_html.anubis +read CXM_http_get_common.anubis + + + *Overview* + Cookies are defined in RFC 2109. Here is the corresponding Anubis type: + + Each cookie has an server name (the name of the server who constructed the cookie), a + name, a value, and several attributes. + +public type Cookie: + cookie(String server_name, // of the server who sent the cookie + String name, // of the cookie + String value, // of the cookie + // attributes: + Maybe(String) comment, // cookies may have human readable comments + Maybe(String) domain, // domain name as sent by the server + Int validity, // cookie still valid if this is > now + Maybe(String) path, // server path for which the cookie is valid + Bool secure, // if true, do not send this cookie over an insecure link + Int version). // Cookie version (normally 1: rfc 2109) + + + Cookies are sent by servers through 'Set-Cookie' HTTP headers. The function + 'get_cookies' retrieves a list of cookies from a list of HTTP headers. + +public define List(Cookie) + get_cookies + ( + String server_name, // name of server who sent the cookies + List(HTTP_header) headers // HTTP headers sent by this server + ). + +public define Maybe(Cookie) + find_cookie + ( + String name, + List(Cookie) cookies + ). + + + + + + Normally, this function is used on the list of HTTP headers returned by either + 'http_get' of 'https_get'. + + + Before they can be sent back to their origin server, cookies must be reformated, in + order to produce 'Cookie' HTTP headers: + +public define List(HTTP_header) + reformat_cookies + ( + String server_name, + String uri, + List(Cookie) cookies + ). + + The result of 'reformat_cookies' may be appended to the list of headers given as + argument to 'http_get' or to 'https_get'. + + In the meantime, you may examine and maybe discard cookies, you may 'save' them into a + file, and 'retrieve' them later. + + + + + ------- That all for the public part. ------------------------------------------------- + + + Here is the syntax of a 'Set-Cookie' header (according to RFC 2109): + + set-cookie = "Set-Cookie:" cookies + cookies = 1#cookie + cookie = NAME "=" VALUE *(";" cookie-av) + NAME = token + VALUE = value + value = token | quoted-string + cookie-av = "Comment" "=" value + | "Domain" "=" value + | "Max-Age" "=" value + | "Path" "=" value + | "Secure" + | "Version" "=" 1*DIGIT + + + According to RFC 2616 (obsolating RFC 2068) defining HTTP 1.1, 'control characters' are + 0 to 31 and DEL (127). A 'separator' is one of: + + ( ) < > @ , ; : \ " / [ ] ? = { } 32(space) and 9(tab) " + + Now, a token is a non empty sequence of ASCII characters (0 to 127), but not including + any control character or any separator. As a consequence, characters admissible in a + 'RFC 2616 token' are: + + 33 ! + 35 to 39 # $ & ' + 42 43 * + + 45 46 - . + 48 to 57 0 ... 9 + 65 to 90 A ... Z + 94 to 122 ^ _ ` a ... z + 124 126 | ~ + +define Bool + is_token_char + ( + Word8 c + ) = + if c +< 33 then false else + if c +< 34 then true else + if c +< 35 then false else + if c +< 40 then true else + if c +< 42 then false else + if c +< 44 then true else + if c +< 45 then false else + if c +< 47 then true else + if c +< 48 then false else + if c +< 58 then true else + if c +< 65 then false else + if c +< 91 then true else + if c +< 94 then false else + if c +< 123 then true else + if c +< 124 then false else + if c = 124 then true else + c = 126. + + + From the grammar, it is clear that atomic entities (called 'tokens' by YACC) are: + + - tokens (in the sens of RFC 2616) some of which have to be recognized as keywords + - quoted strings + - equal sign + - colon + - semi-colon + + Hence, the following type: + +public type Atom: + end_of_input, + error, + comment, + domain, + max_age, + path, + secure, + version, + token(String), + quoted_string(String), + equals, + colon, + semi_colon. + + +variable List(Atom) unput_atoms = []. + +define One + unput_atom + ( + Atom a + ) = + unput_atoms <- [a . *unput_atoms]. + +define Atom + recognize_keyword + ( + String s + ) = + with l = to_lower(s), + if l = "comment" then comment else + if l = "domain" then domain else + if l = "max-age" then max_age else + if l = "path" then path else + if l = "secure" then secure else + if l = "version" then version else + token(s). + + +variable String input = "". From which cookies will be read. +variable Int index = 0. Current position within 'input'. + +define Maybe(Word8) + next_char + = + if nth(*index,*input) is + { + failure then failure, + success(c) then + index <- *index+1; + success(c) + }. + +define One + unput_char + = + index <- *index-1. + +define Atom + read_token + ( + List(Word8) so_far // contains at least 1 character + ) = + if next_char is + { + failure then recognize_keyword(implode(reverse(so_far))), + success(c) then + if is_token_char(c) + then read_token([c . so_far]) + else unput_char; recognize_keyword(implode(reverse(so_far))) + }. + +define Atom + read_quoted_string + ( + List(Word8) so_far + ) = + if next_char is + { + failure then quoted_string(implode(reverse(so_far))), + success(c) then + if c = '\"' + then quoted_string(implode(reverse(so_far))) + else read_quoted_string([c . so_far]) + }. + +define Bool + is_blank + ( + Word8 c + ) = + c +=< ' '. + + Reading an atom from the input: + +define Atom + read_atom + = + if *unput_atoms is + { + [ ] then + if next_char is + { + failure then end_of_input, + success(c) then + if is_blank(c) then read_atom else // skip blanks + if is_token_char(c) then read_token([c]) else + if c = '\"' then read_quoted_string([]) else + if c = '=' then equals else + if c = ':' then colon else + if c = ';' then semi_colon else + error + }, + [h . t] then + unput_atoms <- t; h + }. + + + Reading an attribute-value pair. + +type AttrVal: + comment(String), + domain(String), + max_age(String), + path(String), + secure, + version(String). + +define String + read_eq_value + = + with e = read_atom, + if e is equals then + ( + with a = read_atom, + if a is token(n) then n else + if a is quoted_string(s) then s else + unput_atom(a); "" + ) + else unput_atom(e); "". + + +define Maybe(AttrVal) + read_attr_val + = + if read_atom is semi_colon then + with a = read_atom, + if a is + { + end_of_input then failure, + error then failure, + comment then success(comment(read_eq_value)), + domain then success(domain(read_eq_value)), + max_age then success(max_age(read_eq_value)), + path then success(path(read_eq_value)), + secure then success(secure), + version then success(version(read_eq_value)), + token(_) then unput_atom(a); failure, + quoted_string(_) then unput_atom(a); failure, + equals then unput_atom(a); failure, + colon then unput_atom(a); failure, + semi_colon then unput_atom(a); failure, + } + else failure. + + + Getting attributes from a List(AttrVal). + +define Maybe(String) + get_comment + ( + List(AttrVal) l + ) = + if l is + { + [ ] then failure, + [h . t] then if h is comment(c) + then success(c) + else get_comment(t) + }. + +define Maybe(String) + get_domain + ( + List(AttrVal) l + ) = + if l is + { + [ ] then failure, + [h . t] then if h is domain(s) + then success(s) + else get_domain(t) + }. + +define Int + get_validity + ( + List(AttrVal) l + ) = + if l is + { + [ ] then 0, + [h . t] then if h is max_age(a) + then if decimal_scan(a) is + { + failure then 0, + success(n) then n+now + } + else get_validity(t) + }. + +define Maybe(String) + get_path + ( + List(AttrVal) l + ) = + if l is + { + [ ] then failure, + [h . t] then if h is path(p) + then success(p) + else get_path(t) + }. + +define Bool + get_secure + ( + List(AttrVal) l + ) = + if l is + { + [ ] then false, + [h . t] then if h is secure + then true + else get_secure(t) + }. + +define Int + get_version + ( + List(AttrVal) l + ) = + if l is + { + [ ] then 0, + [h . t] then if h is version(v) + then if decimal_scan(v) is + { + failure then 0, + success(n) then n + } + else get_version(t) + }. + + + Reading a cookie: + +variable String server_name = "". + +define Maybe(Cookie) + read_cookie_n_e_v + ( + String name, + String value, + List(AttrVal) so_far + ) = + if read_attr_val is + { + failure then success(cookie( + *server_name, + name, + value, + get_comment(so_far), + get_domain(so_far), + get_validity(so_far), + get_path(so_far), + get_secure(so_far), + get_version(so_far) + )), + + success(av) then read_cookie_n_e_v(name,value,[av . so_far]) + }. + +define Maybe(Cookie) + read_cookie_n_e + ( + String name + ) = + with a = read_atom, + if a is token(value) then read_cookie_n_e_v(name,value,[]) else + if a is quoted_string(value) then read_cookie_n_e_v(name,value,[]) else + unput_atom(a); failure. + +define Maybe(Cookie) + read_cookie_n + ( + String name + ) = + with a = read_atom, + if a is equals + then read_cookie_n_e(name) + else unput_atom(a); failure. + + +define Maybe(Cookie) + read_cookie + = + with a = read_atom, + if a is token(name) + then read_cookie_n(name) + else unput_atom(a); failure. + + +define List(Cookie) + read_cookies + ( + List(Cookie) so_far + ) = + if read_cookie is + { + failure then so_far, + success(c) then read_cookies([c . so_far]) + }. + + +define List(Cookie) + get_cookies + ( + String svn, + HTTP_header h + ) = + if h is http_header(n,v) then + if to_lower(n) = "set-cookie" + then ( + unput_atoms <- []; + input <- v; + index <- 0; + server_name <- svn; + read_cookies([]) + ) + else []. + +public define List(Cookie) + get_cookies + ( + String server_name, + List(HTTP_header) headers + ) = + if headers is + { + [ ] then [ ], + [h . t] then + append(get_cookies(server_name,h),get_cookies(server_name,t)) + }. + + +public define Maybe(Cookie) + find_cookie + ( + String name, + List(Cookie) cookies + ) + = + if cookies is + { + [] then failure, + [h . t] then + if h is cookie(s, n, v, _, _, _, _, _, _) then + if name = n then success(h) + else find_cookie(name, t) + }. + +public define String + get_cookie_value + ( + String name, + List(Cookie) cookies + ) + = + if find_cookie(name, cookies) is + { + failure then "", + success(c) then if c is cookie(_, _, v, _, _, _, _, _, _) then v + }. + + *** Reformating cookies. ************************************************************** + + Cookies should be resent reformated according to the following grammar (copy-pasted + from RFC 2109): + + cookie = "Cookie:" cookie-version + 1*((";" | ",") cookie-value) + cookie-value = NAME "=" VALUE [";" path] [";" domain] + cookie-version = "$Version" "=" value + NAME = attr + VALUE = value + path = "$Path" "=" value + domain = "$Domain" "=" value + + +define HTTP_header + reformat_cookie + ( + Cookie c + ) = + if c is cookie(sn,n,v,mbc,mbd,vld,mbp,sec,ver) then + http_header("Cookie", + "$Version=" + to_decimal(ver) + + ";" + n + "=\"" + v + "\"" + + if mbp is + { + failure then "", + success(p) then ";$Path=\"" + p + "\"" + } + + if mbd is + { + failure then "", + success(d) then ";$Domain=\"" + d + "\"" + } + ). + + + According to RFC 2109, a cookie may be sent to a server if: + + (1) server name in the cookie is the name of the server, + (2) if 'Path' attribute is present, its value must match the URI, + (3) the cookie is still valid (validity = 0 means indefinitely valid). + + define Bool + path_match + ( + Maybe(String) cookie_path, + String uri + ) = + if cookie_path is + { + failure then true, + success(p) then + + }. + + + Checking if the path matches: + + +define Bool + path_match + ( + Maybe(String) mbp, + String uri + ) = + true. + + + The next function verifies if a cookie satisfies the rules. + +define Bool + may_resend_cookie + ( + String server_name, + String uri, + Cookie c + ) = + if c is cookie(sn,n,v,mbc,mbd,vld,mbp,sec,ver) then + if sn = server_name + then ( + if path_match(mbp,uri) + then ( + if vld = 0 then true else vld > now + ) + else false + ) + else false. + + + The next function reformat all cookies which satisfy the 'resend' rules. + +public define List(HTTP_header) + reformat_cookies + ( + String server_name, + String uri, + List(Cookie) cookies + ) = + if cookies is + { + [ ] then [ ], + [h . t] then + if may_resend_cookie(server_name,uri,h) + then [reformat_cookie(h) . reformat_cookies(server_name,uri,t)] + else reformat_cookies(server_name,uri,t) + }. + + + + + + See test_cookies.anubis for a test of this program. + + + + + + + + + diff --git a/MF_1_1/web/CXM_dojo.anubis b/MF_1_1/web/CXM_dojo.anubis new file mode 100644 index 0000000..8e869e3 --- /dev/null +++ b/MF_1_1/web/CXM_dojo.anubis @@ -0,0 +1,124 @@ +/* + * Created by PyramIDE. + * User: Steve Marechal + * Date: 11/06/2008 + * Time: 09:54 + * + */ + +read calexium_lib/web/CXM_making_a_web_site.anubis +read tools/basis.anubis // required for 'make_directory' +read locale/L3LanguageInfo.anubis + +read mailfountain_constants.anubis +read mailfountain_types.anubis +read calexium_lib/web/CXM_common.anubis +read calexium_lib/web/CXM_making_a_web_site.anubis +read calexium_lib/web/CXM_multihost_http_server.anubis +read common/language_management.anubis + +read tools/mf_loggers.anubis +read calexium_lib/net_services_protocols/logger_service.anubis +read system/logger.anubis + +public type Dojo_Grid_Data : + grid_data(String). + +public define HTML_Off_Form + dojo_button + ( + String name, + String execute, + String id, + ) + = + literal(" + ") +. + +public define HTML_Off_Form + dojo_dialog + ( + String name, + String dialog_id, + String execute, + ) + = + sequence[ + dojo_button(name,"dijit.byId('"+dialog_id+"').show()", "dialog_id"), + div([attr("dojoType", "dijit.Dialog"), id(dialog_id), title(name), attr("execute", execute)], + table([], + empty, + [ + row([], [cell([], literal(""))]), + row([], [cell([columns(2), h_center], literal(""))]), + ], + empty)), + literal("
"), +// literal(" +//
+// +// +// +// +// +// +// +// +//
+//
+//

") + ] +. + +public define HTML_Off_Form + dojo_grid + ( + String id, + String colum1, + String colum2, + String colum3, + String colum4, + Bool can_edit + ) + = + literal(" +
") +. + + +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), "", [], []). + + diff --git a/MF_1_1/web/CXM_generic_form.anubis b/MF_1_1/web/CXM_generic_form.anubis new file mode 100644 index 0000000..3a68ce5 --- /dev/null +++ b/MF_1_1/web/CXM_generic_form.anubis @@ -0,0 +1,471 @@ + + + + *Project* The Anubis Project + + *Title* + + *Copyright* Copyright (c) Alain Prouté 2005. + + + *Author* Alain Prouté + + + + In this file we rationalize the construction of forms. + + + +read CXM_making_a_web_site.anubis +read tools/basis.anubis + + +public type Mandatory: // used to mark fields as mandatory. + mandatory, + non_mandatory. + +public type Width: + small, + narrow, + wide, + custom(Int). + +public type FormFieldWidth: + auto, + custom(Int). + + + + Sorts of fields that you can put in a form: + +public type FormField: + + //--- title field --------------------------------------------------------------------- + title (String text), + title (Int text_size, + String text), + title_f (List(Text_Option) -> HTML_In_Form), + + //--- message field ------------------------------------------------------------------- + message (Result(String,String) msg), + message_f (Result(List(Text_Option) -> HTML_In_Form,List(Text_Option) -> HTML_In_Form)), + + //--- text input field ---------------------------------------------------------------- + input (WebArgName web_arg_name, + String tag, + Width width, + InitialValue init_value, + Mandatory mandatory), + input (WebArgName web_arg_name, + Width width, + InitialValue init_value), + input_f (WebArgName web_arg_name, + List(Text_Option) -> HTML_In_Form tag, + Width width, + InitialValue init_value, + Mandatory mandatory), + + //--- password input field ------------------------------------------------------------ + password_input (WebArgName web_arg_name, + String tag, + Mandatory mandatory), + password_input_f (WebArgName web_arg_name, + List(Text_Option) -> HTML_In_Form tag, + Mandatory mandatory), + + //--- explanation field --------------------------------------------------------------- + explain (String text), + explain (String text, + FormFieldWidth width), + explain_f (List(Text_Option) -> HTML_In_Form), + + //--- selector field ------------------------------------------------------------------ + selector (WebArgName web_arg_name, + String tag, + List(String) items, + Maybe(InitialValue) selected, + Mandatory mandatory), + selector_f (WebArgName web_arg_name, + List(Text_Option) -> HTML_In_Form, + List(String) items, + Maybe(InitialValue) selected, + Mandatory mandatory), + selector_c (WebArgName web_arg_name, + String tag, + List((WebArgValue,String)) items, + Maybe(InitialValue) selected, + Mandatory mandatory), + + + + //--- checkbox field ------------------------------------------------------------------ + checkbox (WebArgName web_arg_name, + String tag, + Bool checked, + Mandatory mandatory), + // the same one, but with the tag on the right of the checkbox + checkboxr (WebArgName web_arg_name, + String tag, + Bool checked, + Mandatory mandatory), + checkbox_f (WebArgName web_arg_name, + List(Text_Option) -> HTML_In_Form, + Bool checked, + Mandatory mandatory), + + //--- radio-button field -------------------------------------------------------------- + radio_button (WebArgName web_arg_name, + WebArgValue web_arg_value, + String tag, + Bool checked, + Mandatory mandatory), + // the same one, but with the tag on the right of the radio_button + radio_buttonr (WebArgName web_arg_name, + WebArgValue web_arg_value, + String tag, + Bool checked, + Mandatory mandatory), + + //--- text area field ----------------------------------------------------------------- + text_area (WebArgName web_arg_name, + InitialValue initial_text), + text_area (WebArgName web_arg_name, + String tag, + InitialValue initial_text), + text_area (WebArgName web_arg_name, + String tag, + InitialValue initial_text, + Int width, + Int height), + + //--- fields table -------------------------------------------------------------------- + fields_table (String tag, + List(FormField) fields), + + //--- fields line --------------------------------------------------------------------- + fields_line (String tag, + List(FormField) fields), + fields_line (List(FormField) fields), + + //--- preview field ------------------------------------------------------------------- + preview (String html_text), + + //--- submit button ------------------------------------------------------------------- + submit (String action_name, + Maybe(String) label, + String button_text, + List((String,String)) extra_operands). + + + Convenience functions: + +public define FormField title(List(Text_Option) -> HTML_In_Form f) = title_f(f). +public define FormField + message(Result(List(Text_Option) -> HTML_In_Form,List(Text_Option) -> HTML_In_Form) f) = message_f(f). +public define FormField input(WebArgName web_arg_name, + List(Text_Option) -> HTML_In_Form tag, + Width width, + InitialValue init_value, + Mandatory mandatory) + = input_f(web_arg_name,tag,width,init_value,mandatory). +public define FormField password_input(WebArgName web_arg_name, + List(Text_Option) -> HTML_In_Form tag, + Mandatory mandatory) + = password_input_f(web_arg_name,tag,mandatory). +public define FormField explain(List(Text_Option) -> HTML_In_Form f) = explain_f(f). +public define FormField selector(WebArgName web_arg_name, + List(Text_Option) -> HTML_In_Form f, + List(String) items, + Maybe(InitialValue) selected, + Mandatory mandatory) + = selector_f(web_arg_name,f,items,selected,mandatory). +public define FormField checkbox(WebArgName web_arg_name, + List(Text_Option) -> HTML_In_Form f, + Bool checked, + Mandatory mandatory) + = checkbox_f(web_arg_name,f,checked,mandatory). + + Make the form itself with: + +public define HTML_Off_Form + generic_form + ( + String form_name, + RGB background_color, + Int width, + List(FormField) fields + ). + + + + --- That's all for the public part ! -------------------------------------------------- + +// TO DO update code of CXM generic form +define HTML_Row(HTML_In_Form) + format_form_field + ( + FormField ff + ) = + with star = (Mandatory m) |-> (HTML_In_Form)text([color(rgb(255,0,0)),size(12)], + if m is + { + mandatory then "*", + non_mandatory then "" + }), + row( + if ff is + { + title(t) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([columns(3),h_center],text([size(16),bold,color(rgb(0,0,0))],t)) + ], + + title(s,t) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([columns(3),h_center],text([size(s),bold,color(rgb(0,0,0))],t)) + ], + + title_f(t) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([columns(3),h_center],t([size(16),bold,color(rgb(0,0,0))])) + ], + + message(r) then (List(HTML_Cell(HTML_In_Form))) if r is + { + error(msg) then [cell([columns(3),h_center], + text([size(10),color(rgb(240,0,0))],msg))] + ok(msg) then [cell([columns(3),h_center], + text([size(10),color(rgb(0,150,0))],msg))] + }, + + message_f(r) then (List(HTML_Cell(HTML_In_Form))) if r is + { + error(msg) then [cell([columns(3),h_center], + msg([size(10),color(rgb(240,0,0))]))] + ok(msg) then [cell([columns(3),h_center], + msg([size(10),color(rgb(0,150,0))]))] + }, + + input(wan,tag,w,init,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], text([size(10)],tag)), + cell([width(7) ], star(mand)), + cell([left ], text_input([], "",htmlId(""),wan,init,if w is + { + small then 10, + narrow then 50, + wide then 70, + custom(n) then n + })) + ], + + input(wan,w,init) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([left,columns(3) ], text_input([], "", htmlId(""), wan,init,if w is + { + small then 10, + narrow then 30, + wide then 70, + custom(n) then n + })) + ], + + input_f(wan,tag,w,init,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], tag([size(10)])), + cell([width(7) ], star(mand)), + cell([left ], text_input([], "", htmlId(""),wan,init,if w is + { + small then 15, + narrow then 30, + wide then 70, + custom(n) then n + })) + ], + + password_input(wan,tag,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], text([size(10)],tag)), + cell([width(7) ], star(mand)), + cell([left ], password_input([], "",htmlId(""), wan, init(""), 30)) + ], + + password_input_f(wan,tag,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], tag([size(10)])), + cell([width(7) ], star(mand)), + cell([left ], password_input([], "",htmlId(""), wan, init(""), 30)) + ], + + explain(t) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([columns(3),h_center], + table([nude],[row(cell([width(500)], + paragraph([/*justified,*/size(10),color(rgb(0,100,0))],literal(t))))])) + ], + + explain(t,w) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([columns(3),h_center], + table([nude],[row(cell( + if w is + { + auto then [], + custom(i) then [width(i)] + }, + paragraph([/*justified,*/size(10),color(rgb(0,100,0))], literal(t))))])) + ], + + explain_f(t) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([columns(3),h_center], + table([nude],[row(cell([width(500)], + t([/*justified,*/size(10),color(rgb(0,100,0))])))])) + ], + + selector(wan,tag,items,selected,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], text([size(10)],tag)), + cell([width(7)], star(mand)), + cell([left ], if selected is + { + failure then selector([], "", htmlId(""), wan,1,items) + success(sel) then selector([], "", htmlId(""), wan,1,items, sel) + }) + ], + + selector_f(wan,tag,items,selected,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], tag([size(10)])), + cell([width(7)], star(mand)), + cell([left ], if selected is + { + failure then selector([], "", htmlId(""), wan,1,items) + success(sel) then selector([], "", htmlId(""), wan,1,items, sel) + }) + ], + + selector_c(wan,tag,items,selected,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], text([size(10)],tag)), + cell([width(7)], star(mand)), + cell([left ], if selected is + { + failure then selector_c([], "", htmlId(""), wan,1,items) + success(sel) then selector_c([], "", htmlId(""), wan,1,items,sel) + }) + ], + + checkbox(wan,tag,checked,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], text([size(10)],tag)), + cell([width(7)], star(mand)), + cell([left ], check_box([], "",htmlId(""),wan, wav(wan.name),checked)) + ], + + checkboxr(wan,tag,checked,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], check_box([], "",htmlId(""),wan, wav(wan.name),checked)), + cell([width(7)], star(mand)), + cell([left ], text([size(10)],tag)) + ], + + checkbox_f(wan,tag,checked,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], tag([size(10)])), + cell([width(7)], star(mand)), + cell([left ], check_box([], "",htmlId(""),wan,wav(wan.name),checked)) + ], + + radio_button(wan,wav,tag,checked,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], text([size(10)],tag)), + cell([width(7)], star(mand)), + cell([left ], radio_button([], "", htmlId(""), wan, wav, checked)) + ], + + radio_buttonr(wan,wav,tag,checked,mand) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right ], radio_button([], "", htmlId(""), wan, wav, checked)), + cell([width(7)], star(mand)), + cell([left ], text([size(10)],tag)) + ], + + text_area(wan,tx) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([h_center,columns(3)],text_area([wrap_lines],wan,tx,75,10)) + ], + + text_area(wan,tag,tx) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right,top], text([size(10)],tag)), + cell([width(7)], text([],"")), + cell([h_center],text_area([wrap_lines],wan,tx,75,10)) + ], + + text_area(wan,tag,tx,w,h) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right,top], text([size(10)],tag)), + cell([width(7)], text([],"")), + cell([h_center],text_area([wrap_lines],wan,tx,w,h)) + ], + + fields_table(tag,fields) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right,top], text([size(10)],tag)), + cell([width(7)], text([],"")), + cell([left,top], table([],map((FormField ff2) |-> format_form_field(ff2),fields))) + ], + + fields_line(tag,fields) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([right,top], text([size(10)],tag)), + cell([width(7)], text([],"")), + cell([left,top], table([nude],[row([], //border(0,0,3,rgb(0,0,0)) + map((FormField ff2) |-> cell([top],table([nude],[format_form_field(ff2)])),fields))])) + ], + + fields_line(fields) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([left,top,columns(3)], table([nude],[row([], + map((FormField ff2) |-> cell([top],table([nude],[format_form_field(ff2)])),fields))])) + ], + + preview(html_text) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([top,left,columns(3),background_color(rgb(255,255,255))], + table([border(0,8,0,rgb(0,0,0))], + [row(cell([left,top,height(200)],literal(html_text)))])) + ], + + submit(action_name,mb_label,button_text,extra_operands) then (List(HTML_Cell(HTML_In_Form))) + [ + cell([columns(3),right],actioner(same, + if mb_label is + { + failure then same, + success(n) then same(n) + }, + submit([], button_text), + action_name, + extra_operands)) + ] + }). + + + +// TO DO update code of CXM generic form +public define HTML_Off_Form + generic_form + ( + String form_name, + RGB bg_color, + Int w, + List(FormField) fields + ) = + table([border(0,0,5,bg_color),percentage_width(100), + background_color(bg_color)],[row(cell([h_center], + form(form_name,[],table([border(0,2,0,bg_color)], + map(format_form_field, fields)))))]). + + diff --git a/MF_1_1/web/CXM_generic_login.anubis b/MF_1_1/web/CXM_generic_login.anubis new file mode 100644 index 0000000..f1db55d --- /dev/null +++ b/MF_1_1/web/CXM_generic_login.anubis @@ -0,0 +1,116 @@ + + + + + Rationalisation de la gestion des logins et des mots de passe + +read CXM_common.anubis +read CXM_making_a_web_site.anubis +read CXM_generic_form.anubis + + + + + *** (1) Connection sur site sécurisée + + ou formulaire de saisie du login et du mot de passe + + + Le formulaire de saisie du login et du mot de passe pour se connecter à un site https + se compose : + .1. d'un éventuel message pour alerter que la paire (login,passwd) est erronée, + .2. du formulaire proprement dit pour lequel il faut donner : + - le titre du formulaire + - les textes figurant devant les 2 texts input + - le text du bouton submit + - le nom de l'action, + - la couleur de fond + + + +public define HTML_Off_Form + login_form + ( + String wrong_message, + RGB background_color, + String title_text, + String pseudo_text, + String passwd_text, + String submit_text, + String login_action + ). + + + + + *** (2) Vérification de la saisie + + +public define Maybe($User) + check_login_passwd + ( + String -> Maybe($User) check_pseudo, + $User -> ByteArray get_passwd, + List(Web_arg) lwa + ). + + + + --- That's all for the public part ! -------------------------------------------------- + + + + *** [1] Connection sur site sécurisée + +public define HTML_Off_Form + login_form + ( + String wrong_message, + RGB background_color, + String title_text, + String pseudo_text, + String passwd_text, + String submit_text, + String login_action + ) = + generic_form + ("login_form",background_color,700, + [ + title (title_text), + explain (wrong_message), + input ("pseudo",pseudo_text,narrow,"",mandatory), + password_input ("passwd",passwd_text,mandatory), + submit (login_action,failure,submit_text,[]) + ]). + + + + *** [2] Vérification de la saisie + +public define Maybe($User) + check_login_passwd + ( + String -> Maybe($User) check_pseudo, + $User -> ByteArray get_passwd, + List(Web_arg) lwa + ) = + if web_arg_value(lwa,"pseudo") is + { + not_found then failure, + found(ps) then + if web_arg_value(lwa,"passwd") is + { + not_found then failure, + found(pwd) then + if check_pseudo(ps) is + { + failure then failure, + success(user) then + if sha1(to_byte_array(pwd))=get_passwd(user) + then success(user) + else failure + } + }}. + + + diff --git a/MF_1_1/web/CXM_generic_table.anubis b/MF_1_1/web/CXM_generic_table.anubis new file mode 100644 index 0000000..26f8bbb --- /dev/null +++ b/MF_1_1/web/CXM_generic_table.anubis @@ -0,0 +1,786 @@ + + *Project* The Anubis Project + + *Title* Generic table page. + + *Copyright* Copyright (c) Alain Prouté 2004. + + + *Author* Alain Prouté + *Author* Olivier Duvernois + + + + ---------------------------------------------------------------------------------------- + + + + +read tools/basis.anubis +read CXM_common.anubis +read CXM_making_a_web_site.anubis + + + The purpose is to print on a html browser a table from a List($Data) using the function + 'generic_table()' describe below. + + Note : the explanations are only given for HTML_Item and its components. But they are + also available for HTML_Form and HTML_Element and their components. + + + A table may have the following look : + + +-----+----------+--------+-----------------------+ ............... + | | | | name 3 | + | num | name1 | name2 |-----------+-----------+ columns_name + | | | | name 31 | name 32 | + +-----+----------+--------+-----------+-----------+ ............... + | 1 | data11 | data12 | data131 | data132 | line 1 with background color a + +-----+----------+--------+-----------+-----------+ ............... + | 2 | data21 | data22 | data231 | data232 | line 2 with background color b + +-----+----------+--------+-----------+-----------+ ............... + | 3 | data31 | data32 | data331 | data332 | line 3 with background color a + +-----+----------+--------+-----------+-----------+ ............... + + | n | datan1 | datan2 | datan31 | datan32 | line n with background color ? + +-----+----------+--------+-----------+-----------+ ............... + |total| total1 | | | total32 | total line + +-----+----------+--------+-----------+-----------+ ............... + + For the total-line, assuming that datax1 to dataxn and datax32 to datan32 are numbers + (Int, Float or Maybe(Float)). + + + The columns name are just a List(Item_Row). + + The column 'num' is in the case you want to enumerate your data. The existence of this + column depends on the line function. + + Lines are given by the function : (RGB color,Int num,$Data d) -> Item_Row + + where : - (RGB)color is the color of the background of the row (the 'a color' or 'b + color'); + - (Int)num the number of the data (to enumerate). + + So, this function must be written something like : + + (RGB color, Int num,$Data d) |-> + row([background_color(color)], // and of course possibly other row-options + [ + cell([], (Int -> $HTML)(num) ) + . ($Data -> List(Cell))d // how data is printed in cells + ]). + + But, for the above convenient function with no enumeration, you can only write : + + (RGB color, $Data d) |-> + row([background_color(color)], // and of course possibly other row-options + ($Data -> List(Cell))d // how data is printed in cells + ). + + + If you want to sum by column your data, use the following type : + +public type Total_Line($Data,$Upplet,$Row): + no_total, + total + ( + ($Upplet,$Data) -> $Upplet sum_functions, + $Upplet -> $Row print_total_line, + $Upplet initial_value + ). + + $Row is for HTML_Row($HTML). + $Upplet represents the components of $Data that will be sum. + + Example : + with the above sheme table, $Data is something like : + type $Data + data + ( + Data1 d1, + Data2 d2 + Data3 d3 + ). + and type Data3: + data3 + ( + Data31 d31, + Data32 d32 + ). + + So $Upplet will be (Data1,Data32) : sums are wanted for those 2 datum + + The function ($Upplet,$Data) -> $Upplet will be written like : + ($Upplet u,$Data d) -> if u is (u1,u2) then (u1+d1(d), u2+d32(d3(d))) + + (if of course (Data1 + Data1) and (Data32 + Data32) are defined). + + + + - Several columns - + ------------------- + + If you want to print your data on sevaral columns (i.e. considering the above table + scheme as a column), you must specify the number of columns. You will obtain : + + Here is a List($Data) : l = [a,b,c,d,e,f,g,h,i,j,k,l,m]; + and f : (RGB,Int,$Data) -> Item_Row + You want to print this list on 3 columns. + The result will be : + + + +-----------+-----------+-----------+ + | col.names | col.names | col.names | + +-----------+-----------+-----------+ + | f(a) | f(f) | f(k) | + +-----------+-----------+-----------+ + | f(b) | f(g) | f(l) | + +-----------+-----------+-----------+ Each column is a table as defined + | f(c) | f(h) | f(m) | above. + +-----------+-----------+-----------+ + | f(d) | f(i) | | + +-----------+-----------+-----------+ + | f(e) | f(j) | | + +-----------+-----------+-----------+ + + + If several columns are required, it's also asked for spaces between two colums. + + So use the following type : + +public type HowManyColumns: + _1, + several (Int col_nb, + Int spacer). + + + + + - Now the Generic table definition - + ------------------------------------ + + Here is the most customizable generic table. Below, they are some convenience functions. + +public define HTML_Off_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) columns_name, + HowManyColumns number_of_columns, + (RGB,Int,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color, + Total_Line($Data,$Upplet,HTML_Row(HTML_Off_Form)) total_line + ). + +public define HTML_In_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) columns_name, + HowManyColumns number_of_columns, + (RGB,Int,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color, + Total_Line($Data,$Upplet,HTML_Row(HTML_In_Form)) total_line + ). + + + + Note : + List(Table_Option) : if you choose 'nude' (i.e. border(0,0,0)), don't forget a + horizontal spacer between the cells contain in the 'line_format' row. If you don't put + any, each data will be closer to the next one. + + + + - Convenience functions - + ------------------------- + + 1/ Table without multicolumns, enumeration and total-line: + +public define HTML_Off_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) columns_name, + (RGB,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color + ). + +public define HTML_In_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) columns_name, + (RGB,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color + ). + + + + 2/ Table with total-line and without multicolumns, enumeration. + + +public define HTML_Off_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) columns_name, + (RGB,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color, + Total_Line($Data,$Upplet,HTML_Row(HTML_Off_Form)) total_line + ). + +public define HTML_In_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) columns_name, + (RGB,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color, + Total_Line($Data,$Upplet,HTML_Row(HTML_In_Form)) total_line + ). + + + 3/ Table with multicolumns, enumeration, but without total + +public define HTML_Off_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) columns_name, + HowManyColumns number_of_columns, + (RGB,Int,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color + ). + +public define HTML_In_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) columns_name, + HowManyColumns number_of_columns, + (RGB,Int,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color + ). + + + + 4/ Table with multicolumns and without enumeration & total + +public define HTML_Off_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) columns_name, + HowManyColumns number_of_columns, + (RGB,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color + ). + +public define HTML_In_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) columns_name, + HowManyColumns number_of_columns, + (RGB,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color + ). + + + --- That's all for public part. ------------------------------------------------------------------------- + + + When the datum $Data must be presented on several columns, the initial list must be + re-composed : sot the type Print_Table. + +type Print_Table($Data): + print_table + ( + $Data data, + Int num + ). + + + *** Transform List($Data) into List(Print_Table($Data)) + + +define (List(Print_Table($Data)),List($Data)) + get_n_elements + ( + List($Data) l, + List(Print_Table($Data)) result, + Int n, + Int ct, // counter + Int num + ) = + if l is + { + [] then (reverse(result),[]), + [h . t] then + if ct = n + then (reverse([print_table(h,num+1) .result]),t) + else get_n_elements(t,[print_table(h,num+1) . result],n,ct+1,num+1) + }. + + +define List(List(Print_Table($Data))) + short_lists + ( + List($Data) l, + Int nb, // number of element of short list + Int ct // counter for numbering data (initialized at 0) + ) = + if get_n_elements(l,[],nb,1,ct) is (result,unused) + then if unused is + { + [] then [result], + [_ . _] then [result . short_lists(unused,nb,ct+nb)] + }. + + + - Generic row - + --------------- + +define (List(HTML_Row($HTML)),$Upplet) + generic_rows + ( + List(Print_Table($Data)) lpt, + (RGB,Int,$Data) -> HTML_Row($HTML) line_format, + RGB a_color, + RGB b_color, + ($Upplet,$Data) -> $Upplet do_sum, + List(HTML_Row($HTML)) rows, + $Upplet sum + ) = + if lpt is + { + [] then (reverse(rows),sum), + [h . t] then + generic_rows(t,line_format,b_color,a_color,do_sum, + [line_format(a_color,num(h),data(h)) . rows],do_sum(sum,data(h))) + }. + + + + - HTML_In_Form - + ---------------- + +define List(HTML_Cell(HTML_In_Form)) + generic_cells + ( + List(List(Print_Table($Data))) print_data, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) names, + (RGB,Int,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color, + ($Upplet,$Data) -> $Upplet do_sum, + $Upplet -> HTML_Row(HTML_In_Form) total_line, + $Upplet value, + Int spacer + ) = + if print_data is + { + [] then (List(HTML_Cell(HTML_In_Form))) [], + [h . t] then + if generic_rows(h,line_format,a_color,b_color,do_sum,(List(HTML_Row(HTML_In_Form)))[],value) is + (rows,new_value) then + if t is [] + then [cell([top],table(lto,names+rows+[total_line(new_value)]))] + else [ + cell([top],table(lto,append(names,rows))) + . if spacer = 0 + then generic_cells + (t,lto,names,line_format,a_color,b_color,do_sum,total_line,new_value,spacer) + else [cell([width(spacer)],text([],"")) + . generic_cells + (t,lto,names,line_format,a_color,b_color,do_sum,total_line,new_value,spacer)] + ] + }. + +public define Int + Int x (mod Int y) + = + if x / y is + { + failure then 0, + success(result) then + if result is (q, r) then r + }. + + + +public define HTML_In_Form + generic_table + ( + List($Data) l, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) names, + HowManyColumns hm_col, + (RGB,Int,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color, + Total_Line($Data,$Upplet,HTML_Row(HTML_In_Form)) total_line + ) = + table([], + if l is [] + then [] + else + with nbl = length(l), + [ + row([], + if total_line is + { + no_total then + with col_nb = if hm_col is + { + _1 then 1, + several(n,_) then n + }, + with spacer = if hm_col is + { + _1 then 0, + several(n,sp) then sp + }, + generic_cells + (short_lists(l,nbl\col_nb + if (nbl (mod col_nb)) > 0 then 1 else 0,0), + lto,names,line_format,a_color,b_color, + (One u,$Data d) |-> unique,(One _) |-> row([],[]),unique,spacer), + total(sum_fct,total_line,init) then + with col_nb = if hm_col is + { + _1 then 1, + several(n,_) then n + }, + with spacer = if hm_col is + { + _1 then 0, + several(n,sp) then sp + }, + generic_cells + ( + short_lists(l,nbl\col_nb + if (nbl (mod col_nb)) > 0 then 1 else 0,0), + lto,names,line_format,a_color,b_color, + sum_fct,total_line,init,spacer + ) + }) + ]). + + + - HTML_Off_Form - + ---------------- + +define List(HTML_Cell(HTML_Off_Form)) + generic_cells + ( + List(List(Print_Table($Data))) print_data, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) names, + (RGB,Int,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color, + ($Upplet,$Data) -> $Upplet do_sum, + $Upplet -> HTML_Row(HTML_Off_Form) total_line, + $Upplet value, + Int spacer + ) = + if print_data is + { + [] then (List(HTML_Cell(HTML_Off_Form))) [], + [h . t] then + if generic_rows(h,line_format,a_color,b_color,do_sum,(List(HTML_Row(HTML_Off_Form)))[],value) is + (rows,new_value) then + if t is [] + then [cell([top],table(lto,(names+rows+[total_line(new_value)])))] + else [ + cell([top],table(lto,append(names,rows))) + . if spacer =0 + then generic_cells + (t,lto,names,line_format,a_color,b_color,do_sum,total_line,new_value,spacer) + else [cell([width(spacer)],text([],"")) + . generic_cells + (t,lto,names,line_format,a_color,b_color,do_sum,total_line,new_value,spacer)] + ] + }. + +public define HTML_Off_Form + generic_table + ( + List($Data) l, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) names, + HowManyColumns hm_col, + (RGB,Int,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color, + Total_Line($Data,$Upplet,HTML_Row(HTML_Off_Form)) total_line + ) = + table([], + with nbl = length(l), + [ + row([], + if total_line is + { + no_total then + with col_nb = if hm_col is + { + _1 then 1, + several(n,_) then n + }, + with spacer = if hm_col is + { + _1 then 0, + several(n,sp) then sp + }, + generic_cells + ( + short_lists(l,nbl\col_nb + if (nbl (mod col_nb)) > 0 then 1 else 0,0), + lto,names,line_format,a_color,b_color, + (One u,$Data d) |-> unique,(One _) |-> row([],[]),unique,spacer + ), + total(sum_fct,total_line,init) then + with col_nb = if hm_col is + { + _1 then 1, + several(n,_) then n + }, + with spacer = if hm_col is + { + _1 then 0, + several(n,sp) then sp + }, + generic_cells + ( + short_lists(l,nbl\col_nb + if (nbl (mod col_nb)) > 0 then 1 else 0,0), + lto,names,line_format,a_color,b_color, + sum_fct,total_line,init,spacer + ) + }) + ]). + + + + - Convenience functions : + +public define HTML_Off_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) columns_name, + (RGB,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color + ) = + generic_table + ( + (List($Data)) data, + (List(Table_Option)) lto, + (List(HTML_Row(HTML_Off_Form))) columns_name, + (HowManyColumns) _1, + ((RGB,Int,$Data) -> HTML_Row(HTML_Off_Form)) (RGB r,Int n,$Data d) |-> line_format(r,d), + (RGB) a_color, + (RGB) b_color, + (Total_Line($Data,$Data,HTML_Row(HTML_Off_Form))) no_total + ). + +public define HTML_In_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) columns_name, + (RGB,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color + ) = + generic_table + ( + (List($Data)) data, + (List(Table_Option)) lto, + (List(HTML_Row(HTML_In_Form))) columns_name, + (HowManyColumns) _1, + ((RGB,Int,$Data) -> HTML_Row(HTML_In_Form)) (RGB r,Int n,$Data d) |-> line_format(r,d), + (RGB) a_color, + (RGB) b_color, + (Total_Line($Data,$Data,HTML_Row(HTML_In_Form))) no_total + ). + + + 2/ Table with total-line and without multicolumns, enumeration. + + +public define HTML_Off_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) columns_name, + (RGB,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color, + Total_Line($Data,$Upplet,HTML_Row(HTML_Off_Form)) total_line + ) = + generic_table + ( + (List($Data)) data, + (List(Table_Option)) lto, + (List(HTML_Row(HTML_Off_Form))) columns_name, + (HowManyColumns) _1, + ((RGB,Int,$Data) -> HTML_Row(HTML_Off_Form)) (RGB r,Int n,$Data d) |-> line_format(r,d), + (RGB) a_color, + (RGB) b_color, + (Total_Line($Data,$Upplet,(HTML_Row(HTML_Off_Form)))) total_line + ). + +public define HTML_In_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) columns_name, + (RGB,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color, + Total_Line($Data,$Upplet,HTML_Row(HTML_In_Form)) total_line + ) = + generic_table + ( + (List($Data)) data, + (List(Table_Option)) lto, + (List(HTML_Row(HTML_In_Form))) columns_name, + (HowManyColumns) _1, + ((RGB,Int,$Data) -> HTML_Row(HTML_In_Form)) (RGB r,Int n,$Data d) |-> line_format(r,d), + (RGB) a_color, + (RGB) b_color, + (Total_Line($Data,$Upplet,(HTML_Row(HTML_In_Form)))) total_line + ). + + + + + 3/ Table with multicolumns, enumeration, but without total + +public define HTML_Off_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) columns_name, + HowManyColumns number_of_columns, + (RGB,Int,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color + ) = + generic_table + ( + (List($Data)) data, + (List(Table_Option)) lto, + (List(HTML_Row(HTML_Off_Form))) columns_name, + (HowManyColumns) number_of_columns, + ((RGB,Int,$Data) -> HTML_Row(HTML_Off_Form)) (RGB r,Int n,$Data d) |-> line_format(r,n,d), + (RGB) a_color, + (RGB) b_color, + (Total_Line($Data,$Data,(HTML_Row(HTML_Off_Form)))) no_total + ). + + +public define HTML_In_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) columns_name, + HowManyColumns number_of_columns, + (RGB,Int,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color + ) = + generic_table + ( + (List($Data)) data, + (List(Table_Option)) lto, + (List(HTML_Row(HTML_In_Form))) columns_name, + (HowManyColumns) number_of_columns, + ((RGB,Int,$Data) -> HTML_Row(HTML_In_Form)) (RGB r,Int n,$Data d) |-> line_format(r,n,d), + (RGB) a_color, + (RGB) b_color, + (Total_Line($Data,$Data,(HTML_Row(HTML_In_Form)))) no_total + ). + + + + 4/ Table with multicolumns and without enumeration & total + +public define HTML_Off_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_Off_Form)) columns_name, + HowManyColumns number_of_columns, + (RGB,$Data) -> HTML_Row(HTML_Off_Form) line_format, + RGB a_color, + RGB b_color + ) = + generic_table + ( + (List($Data)) data, + (List(Table_Option)) lto, + (List(HTML_Row(HTML_Off_Form))) columns_name, + (HowManyColumns) number_of_columns, + ((RGB,Int,$Data) -> HTML_Row(HTML_Off_Form)) (RGB r,Int n,$Data d) |-> line_format(r,d), + (RGB) a_color, + (RGB) b_color, + (Total_Line($Data,$Data,(HTML_Row(HTML_Off_Form)))) no_total + ). + + +public define HTML_In_Form + generic_table + ( + List($Data) data, + List(Table_Option) lto, + List(HTML_Row(HTML_In_Form)) columns_name, + HowManyColumns number_of_columns, + (RGB,$Data) -> HTML_Row(HTML_In_Form) line_format, + RGB a_color, + RGB b_color + ) = + generic_table + ( + (List($Data)) data, + (List(Table_Option)) lto, + (List(HTML_Row(HTML_In_Form))) columns_name, + (HowManyColumns) number_of_columns, + ((RGB,Int,$Data) -> HTML_Row(HTML_In_Form)) (RGB r,Int n,$Data d) |-> line_format(r,d), + (RGB) a_color, + (RGB) b_color, + (Total_Line($Data,$Data,(HTML_Row(HTML_In_Form)))) no_total + ). + + + + diff --git a/MF_1_1/web/CXM_html.anubis b/MF_1_1/web/CXM_html.anubis new file mode 100644 index 0000000..441d387 --- /dev/null +++ b/MF_1_1/web/CXM_html.anubis @@ -0,0 +1,2395 @@ + + *Project* The Anubis Project + *Title* Producing HTML/Javascript code. + + *Copyright* Copyright (c) Alain Prouté 2001. + +read tools/basis.anubis +read system/string.anubis + + + + *** Managing Web Arguments. + + When a client submits a form, he sends informations to the server. This information is + transformed by the server into a list of data of type 'Web_arg'. This is the reason why + a 'web page' operation always has a unique argument of type 'List(Web_arg)'. + + The type 'Web_arg' is defined in 'web/common.anubis' as follows: + + public type Web_arg: + web_arg(String name, + String value), + upload (String name, + String value, + String temp_file_path). + +read CXM_common.anubis + + In other words, a 'web argument' is just a pair made of the name of the argument, and + the value of the argument, and both are character strings. 'upload' will be explained + later. + + + The next variable is a multipurpose counter (used to generate unique names). + +variable Int web_count = 0. + +define Int + new_web_count + = + web_count <- *web_count+1; + *web_count. + + + Names for Web colors. + +public type Web_color_name: + aliceblue, + antiquewhite1, + antiquewhite2, + antiquewhite3, + antiquewhite4, + aquamarine1, + aquamarine2, + aquamarine3, + aquamarine4, + azure1, + azure2, + azure3, + azure4, + yellow. + + + and so on ... (see below why I did not do more). + + + + Web colors. + +public type Web_color: + rgb(Word8,Word8,Word8), /* give the color by its components */ + _(Web_color_name). /* or by its name */ + + + + + The following produces '' tags, which are put in the head of the document. + +public type WebMeta: + keywords(List(String)), + refresh(String url, Int delay), // in seconds + meta(String name, String content), + http_equiv(String name, String content). + + + + + + ******************************************************* + * Web items * + * (the many kinds of things one may put in a page) * + ******************************************************* + + +public type Web_item: + [ ], /* empty (invisible) item */ + ... this is a cross recursive type. + + + + + Options for web page body. + +public type LayerDisposition: + horizontal, + vertical. + +public type FollowPathCommand: // this type is used by the Web_body_option 'follow_path'. + pos(Int x, // x coordinate of position + Int y, // y coordinate of position + Int image_number, // the image to display at that position + Int delay). // wait that milliseconds before leaving this position + +public type Web_body_option: + background_color(Web_color), /* color for the background */ + // + // 'psychedelic_background' produces a background color which is continuously changing. + // 'average' is the average luminosity of the color. 'amplitude' is the maximal variation + // the luminosity around the average. 'delay' is the number of milliseconds between two + // color changes. For example, you may try 'psychedelic_background(200,50,1000)', which + // produces a background whose color changes very slowly (this is not tiring) among rather + // light pastel colors. + // + psychedelic_background(Int average, /* average light (0 to 255) */ + Int amplitude, /* amplitude of variation of light */ + Int delay), /* in milliseconds */ + background_image(String file_name), /* name of image file for the background */ + // + // 'scrolling_layer' produces a layer above the page which is scrolling continuously either + // vertically or horizontally. The 'content' is indefinitly repeated. + // + scrolling_layer(LayerDisposition, + Int steps, /* number of pixels of each move */ + Int margin, /* measured from left or top in pixels */ + Int delay, /* milliseconds for one move */ + Web_item content, /* content of layer (will be repeated) */ + Int period), /* number of pixels between two instances of 'content' */ + // + // 'bounce' shows its content above the page and let it move and bounce on the edges of a rectangle. + // The rectangle is determined by the last 4 arguments. + // + bounce(Web_item content, + Int left, + Int right, + Int top, + Int bottom), + // + // put something over the page in any position you want: + // + over(Web_item content, + Int left, + Int top), + // + // follow_path: let a changing image follow a path on the screen. This gadget shows + // an image following a polygonal path on the screen. The image may change at regular + // intervals, thus providing extra animation. The images are displayed in the order + // they are given in the first argument. When the last image has been displayed, the + // first image is displayed again, and so on. The path is a sequence of absolute positions + // on screen (actually in the browser's window or frame), which is followed in the + // order given in the 'path' argument. If 'loop' is true, the path is followed again and again. + // Otherwise, it is followed only once. If you want to make a closed loop, the last + // position must be the same as the first one. 'steps' is the number of pixels of distance + // between two successive positions of the image, and 'delay' the number of milliseconds + // between two successive positions. 'change_every' is the number of steps (a 'step' is + // passing from one position to the next one) after which the displayed image is replaced + // by the next image. + // + // Each position 'pos(x,y,i,d)' has 4 parameters. 'x' and 'y' are the coordinates of the + // position in the browser's window or frame. 'i' is the number of the image to display + // at this position (i.e. the rank of the image in the list 'filename'. The first one has + // rank 0). 'd' is the delay in milliseconds to wait before leaving that position. + // + follow_path(List(String) filenames, /* the changing images which follows the path */ + Int change_every, /* number of steps betwen two changes */ + List(FollowPathCommand) path, /* the polygonal path and commands */ + Bool loop, /* if true do it repeatedly, otherwise only once */ + Int steps, /* approximative distance (in pixels) between two + successive positions */ + Int delay), /* milliseconds between two successive positions */ + + load_image(String name), /* load an image (for next page), which is not displayed */ + left_margin(Int), /* left margin for document */ + top_margin(Int), /* top margin for document */ + margin_width(Int), + margin_height(Int), + reload_frame(String name, /* name of target frame */ + String url), /* url to load in this frame */ + onload(String function_name). /* nom de la fonction javascript (sans les '()') */ + +public type BodyOnload: + reload_frame(String name, String url). + +variable List(BodyOnload) body_onloads = [ ]. + +define One + add_body_onload + ( + BodyOnload item + ) = + body_onloads <- [item . *body_onloads]. + +define Printable_tree + format + ( + BodyOnload item + ) = + if item is + { + reload_frame(name,url) then (Printable_tree) + [ " window.open('",url,"','",name,"');" ] + }. + +define Printable_tree + format + ( + List(BodyOnload) l + ) = + if l is + { + [ ] then (Printable_tree)[ ], + [h . t] then (Printable_tree) + [format(h) . format(t)] + }. + + +---- Body of a web page. -------------------------------------------- +public type Page_body: + body(List(Web_body_option), /* list of body options */ + Web_item content). /* the content of the page */ + + +public type VFrame: + frame(Int height, + Printable_tree url, + String name). + +---- Web pages. ----------------------------------------------------- +public type Web_page: + web_page(String title, /* title appearing on top of browser */ + List(WebMeta) meta_tags, + Printable_tree head_scripts, /* scripts à placer dans la balise head */ + Page_body body), /* body of page */ + standard_frameset(String title, + List(WebMeta) meta_tags, + Int height, /* height of 'top menu' (pixels) */ + Int width, /* width of 'left menu' (pixels) */ + Printable_tree main). /* url for main */ + + +---------+--------------------------+ + | | ^ | + |<-width->| top height | + | | v | + | left +--------------------------+ + | | | + | | main | + | | | + | | | + | | | + +---------+--------------------------+ + + Note: top and left frames must be loaded through the Web_body_option 'reload_frame'. + + +public define Web_page + web_page + ( + String title, + Page_body body + ) = + web_page(title,[],[], body). + +public define Web_page + web_page + ( + String title, + List(WebMeta) meta_tags, + Page_body body + ) = + + web_page(title, meta_tags, [], body). + + public define Web_page +web_page + ( + String title, + Printable_tree head_scripts, + Page_body body + ) = + + web_page(title, [], head_scripts, body). + +public define Web_page +standard_frameset + ( + String title, + Int height, + Int width, + Printable_tree main + ) = + + standard_frameset(title, [], height, width, main). + + +variable Printable_tree scripts = []. + +define One + add_script + ( + Printable_tree script + ) = + scripts <- [*scripts . script]. + + + + ---- Non empty web items. ------------------------------------------- + + We have already seen the empty web item. Together with the following one, it enables to + make (pseudo-)lists of web items, which will be presented one after the other (from + left to right) in the browser's window. + +public type Web_item: + [Web_item . Web_item],... + + + A web item may be a simple string or a simple integer: + +public type Web_item: + text(String), + text_pt(Printable_tree), + text_nowrap(String), + text_nowrap_pt(Printable_tree), + par(String), + preformated_text(String text), + integer(Int), + float(Float,Int),... + + + You may want to center a web item in a page. Just enclose it into + 'center(...)': + +public type Web_item: + center(Web_item),... + + + You may want to write characters of a given item with a big font: + +public type Web_item: + bigger(Int,Web_item), + smaller(Int,Web_item), + bold(Web_item), + italic(Web_item), + big(Web_item), + very_big(Web_item),... + + + Most of the previous are subsumed by 'style': + +public type WebStyle: + background_image(String file_name), + background_color(Web_color color), + background_transparent, + background_repeat_horizontal, // repeat the background image only horizontally + background_repeat_vertical, + background_no_repeat, + color(Web_color color), + float_to_left, // the web item will float to the left and text will wrap around + float_to_right, + font_family(String font_name), // "verdana" "helvetica" "times" etc... + font_size(Int size), + italic, + oblique, + small_capitals, + bold, + bolder, + lighter, + line_height(Int height), + text_center, + text_left, + text_right, + text_justify, + text_underline, + text_blink, + text_line_through, + width(Int n). + + + +public type Web_item: + style(List(WebStyle) styles, Web_item content),... + + +public type Web_item: + spacer(Int width, Int height), + image(String file_name), /* image */ + image_d(String file_name, String description), + image_pt(Printable_tree file_name), + on_image(String file_name, Web_item content), + turning_images(NonEmptyList(String) filenames, Int millisecs),... + + + + A 'rollover' has the same role as a submit button or link, but it is prettier. It is + made of two images. The first one 'image_on' determines the aspect of the button when + the mouse cursor is on it. The other one 'image_off' determines the aspect of the + button when the mouse cursor is anywhere else. The two images should be of the same + size, otherwise bad effects may occur. The last operand 'description' is a small text + which describes the role of the button. It appears in a bubble in the browser's window. + +public type Web_item: + rollover(List(String) preload_images, // images to preload before the rollover is effective + String url, // URL with possible web arguments + String target, + String image_on, // file name of 'highlighted' image + String image_off, // file name of 'non highlighted' image + String description), // short behavior description + rollover(List(String) preload_images, + String url, + String target, + String image_on, + String image_off, + Int width, + Int height, + String description), ... + + + Mouse sensitive images are images with predefined zones which are clickable. When + clicking in a zone, the specified corresponding URL is loaded by the browser. If two + zones overlap, the first one (in the order they are defined) is selected. + + Zones are of 3 sorts: rectangles, circles and polygons. Point's coordinates are + specified as pairs of integers (of anonymous agglomeration type (Int,Int)). The + first coordinate counts pixels from the left of the image. The second coordinate counts + pixels from the top of the image. With polygons, you can construct zones which are + almost as complicated as you want. You may also construct a zone as the overlapping of + several zones with the same URL. + +public type Mouse_Sensitive_Zone: + rectangle + ( + (Int,Int) left_top, + (Int,Int) right_bottom, + String url + ), + circle + ( + (Int,Int) center, + Int radius, + String url + ), + polygon + ( + List((Int,Int)) vertices, + String url + ). + +public type Web_item: + mouse_sensitive_image(String image_file_name, // the image itself + List(Mouse_Sensitive_Zone) zones),... + + + In project: mouse sensitive images, whose zones behave like submission buttons (to be + used within a form). + + +public type Web_item: + background_sound(String sound_file_name, + Bool loop),... + + + + ************************* + * FORMS * + ************************* + + + Use 'forms' in order to get informations back from the client. The constructor 'form' + take 2 arguments: + + - the name of the form, which must be the name of an Anubis web + page. Indeed, when the user will submit the form, this page will + be sent to him. + - the content of the form, which may be any web item, but which + normally (amongh other things) contains input fields and a + submit button. + +public type Web_item: + form(Printable_tree name, + Web_item content), + form_target(Printable_tree name, + Web_item content, + String target), + form(Printable_tree name, + String label_name, + Web_item content), + form_name(String form_name, // option name de form + Web_item content),... + + public define Web_item +form + ( + Printable_tree name, + Web_item content + ) = + + form("", name, content). + + Within a form, you may put 'text input fields', that the client may + edit. The constructor 'text_input' has the following arguments: + + - name of input field. This will be the name of the correponding + web argument in the Anubis web page referred to by the form. + - size of field (as it appears on client screen), + - initial value of field (the text that appears in the field, when + the client downloads the page). + + + public type Text_Input_Option + +public type Web_item: + text_input(String name, /* text field to be documented by user */ + Int size, + String initial_value),... + + public define Web_item + text_input + ( + String name, + Int size, + String initial_value + ) = + + + text_input( (List(Text_Input_Option)) [], name, size, initial_value). + + +public type Web_item: + password_input(String name, + Int size), + text_area(String name, + Int columns, + Int rows, + String initial_text), + upload(String name, Int size),... + + + + +public type Web_item: + submit(String button_text), /* submit button with text on it */ + submit_pt(Printable_tree button_text), + submit(String name, String text), + submit_close(String name, String text), + submit_pt2(String name, Printable_tree text), + image_submit(String name, String image_file_name), + image_submit(String name, String value, String image_file, Web_item content), + hl_image_submit(String action_name, + String value, + String image_name, + String image_file, + String hl_image_file), + text_submit(String name, String value, String text), + web_submit(String web_args, Web_item content), + button(String name, String text, String on_click_fonction, Int width, Int height),... + + +public type Web_item: /* mark the form with an information */ + mark(String name, String value), + mark_pt(String name, Printable_tree value),... + +public type Web_item: + close_button, /* button that closes the window */ + close_button(String image_file_name), ... + + + + ********************************* + * LABELS * + ********************************* + + + A 'label' is just a name that you may give to a position in a document. Use the + following invisible Web_item 'label' to this end. Now, you can also create links in + the same document, which, when clicked by the user, scroll the document, so that the + position whose name is the given label is shown just at the top of the browser's + window. + +public type Web_item: + label(String label_name), /* give a name to a position in the page */ + go_to_label(String label_name, /* a link for jumping to a label */ + Web_item content),... + + + + ******************************** + * TABLES * + ******************************** + + + A web item may be a table. A table is produced by the constructor + 'table' from the type 'Web_item'. This constructor takes 2 + arguments: + + - a list of 'table options', + - a list of 'table rows'. + + Of course, you use as many options as you want, including + none (if you do not want any option, put the empty list '[ ]' as + this argument). Some options have precedence over others. For example + a background image will hide the background color. + + Table options are defined below: + +public type Table_option: + + /* use a color as a background for the table, if you want it to + be different from the background of the page */ + background_color(Web_color), + + /* or use an image as the background of the table */ + background_image(String file_name), + + /* draw a border line around the table (and around each cell in + the table). You may also specify a geometry (in pixels) for the + border. This makes the 'in relief' part of the border appear + more or less wide. You may also specify a color for the border. */ + border, + nude, /* equivalent to 'border(0,0,0)' (below) */ + border(Int, /* width of exterior (pixels) */ + Int, /* width of top */ + Int), /* width of interior */ + border_color(Web_color), + absolute_width(Int). + + + + A 'table row' is made of a list of 'row options', and a list of + 'cells'. A 'cell' itself has a list of 'cell options', and a web item, + which is its content. We begin by the description of options. + + +public type Row_option: + /* following concerns the horizontal positions of items within the + cells of the row */ + left, + h_center, + right, + /* the following concerns the vertical positions of items, within + the cells of the row */ + top, + v_center, + bottom, + absolute_height(Int), + base_line, + /* set the background color of all cells in the row */ + background_color(Web_color). + + + +public type Cell_option: + /* all row options are available for individual cells, and apply + here only to one cell. */ + left, + h_center, + right, + top, + v_center, + bottom, + base_line, + background_color(Web_color), + /* you can set the width of the cell either absolutely (in pixels) + or as a percentage of the width of the table. */ + background_image(String file_name), + absolute_width(Int), + relative_width(Int), + absolute_height(Int), + relative_height(Int), + /* a cell may span over several columns or rows in the table */ + columns(Int), + rows(Int), + nowrap. + + +public type Cell: + cell(List(Cell_option), + Web_item). + +public type Table_row: + row(List(Row_option), + List(Cell)). + +public define Table_row row(Web_item i) = row([],[cell([],i)]). +public define Table_row row(Cell c) = row([],[c]). +public define Table_row row(List(Cell) l) = row([],l). + + +public type Web_item: + table(List(Table_option), + List(Table_row)),... + +public type Web_item: + list(List(Web_item)),... + +public type Web_item: + link(String name, Web_item), + link(String name, String target, Web_item),... + +public type Web_item: + link_for_download(String filename, Web_item),... // the filename is relative to the public directory + +public type Web_item: + mail_to(String addr, Web_item),... + + +public type Web_item: + select(String name, + Int size, + List(String) choices), + select(String name, + Int size, + List(String) choices, + String selected), + immediate_select(String name, // selection will immediately submit the form + Int size, + List(String) choices),... + + +public type Web_item: + radio_button (Printable_tree name, String value), + checked_radio_button (Printable_tree name, String value), + check_box (Printable_tree name, String value), + checked_box (Printable_tree name, String value),... + + +public type Web_item: + link_to_window(Printable_tree name, Web_item), + link_to_window(Printable_tree name, String window_name, Web_item), + link_to_window_with_ticket(String name, + String web_args, + String window_name, + Web_item content, + Int width, + Int height), + link_to_window_with_ticket_and_scroll + (String name, + String web_args, + String window_name, + Web_item content, + Int width, + Int height), + link_to_window_with_ticket_and_scroll + (String name, + String label_name, + String web_args, + String window_name, + Web_item content, + Int width, + Int height), + link_to_frame (Printable_tree name, String frame_name, Web_item). + + + +---- Formating operations (Anubis --> HTML/Javascript) --------------------------- + + Stupid operation formating a web color name. + +public define String + format + ( + Web_color_name n + ) = + if n is + { + aliceblue then "aliceblue", + antiquewhite1 then "antiquewhite1", + antiquewhite2 then "antiquewhite2", + antiquewhite3 then "antiquewhite3", + antiquewhite4 then "antiquewhite4", + aquamarine1 then "aquamarine1", + aquamarine2 then "aquamarine2", + aquamarine3 then "aquamarine3", + aquamarine4 then "aquamarine4", + azure1 then "azure1", + azure2 then "azure2", + azure3 then "azure3", + azure4 then "azure4", + yellow then "yellow", + }. + + Anubis really needs some system of 'macros' to avoid this... + + + Formating a web color. + +public define String + format + ( + Web_color wc + ) = + if wc is + { + rgb(r,g,b) then "\"#" + to_hexa(r) + to_hexa(g) + to_hexa(b) + "\"", + _(c) then format(c) + }. + +public define String + format_without_quotes + ( + Web_color wc + ) = + if wc is + { + rgb(r,g,b) then "#" + to_hexa(r) + to_hexa(g) + to_hexa(b) + "", + _(c) then format(c) + }. + +define Printable_tree + format + ( + Web_color c + ) = [(String)format(c)]. + +public define String + format_without_sharp + ( + Web_color wc + ) = + if wc is + { + rgb(r,g,b) then "" + to_hexa(r) + to_hexa(g) + to_hexa(b) + "", + _(c) then format(c) + }. + +define Printable_tree + format_without_sharp + ( + Web_color c + ) = [(String)format_without_sharp(c)]. + + +define Printable_tree + [Word32 x . Printable_tree t] + = + [to_Int(x) . t]. + +define Printable_tree + psychedelic_bg + ( + Int average, + Int amplitude, + Int delay + ) = + with ampl = if amplitude >= 120 then 120 else + if amplitude =< 1 then 1 else amplitude, + with aver = if average+ampl >= 254 then 254-ampl + else if average-ampl =< 1 then 1+ampl else average, + [ ""]. + + +define List(Web_body_option) + replace_background_init + ( + List(Web_body_option) l, + Int average, + Int amplitude, + Int delay + ) = + if l is + { + [ ] then [ ], + [h . t] then + if h is background_color(_) + then [background_color(rgb(truncate_to_Word8(average+amplitude), + truncate_to_Word8(average), + truncate_to_Word8(average-amplitude))) + . replace_background_init(t,average,amplitude,delay)] + else [h . replace_background_init(t,average,amplitude,delay)] + }. + +define Maybe((Int,Int,Int)) + get_psy + ( + List(Web_body_option) l + ) = + if l is + { + [ ] then failure, + [h . t] then + if h is psychedelic_background(a,f,d) + then success((a,f,d)) + else get_psy(t) + }. + +define List(Web_body_option) + prepare + ( + List(Web_body_option) l + ) = + if get_psy(l) is + { + failure then l, + success(op) then if op is (a,f,d) then + replace_background_init(l,a,f,d) + }. + + +public define Printable_tree + format + ( + String c_ticket, + String s_ticket, + Web_item i + ). + +define Printable_tree + move_layer_command + ( + String property, + Int n, + Int num, + Int i, + Int period + ) = + if i >= num then [ ] else + [" if (document.layers)", + " { document.nslay",n,"_",i,".",property,"=layp",n,"+(",((i-1)),"); } ", + " else ", + " { ielay",n,"_",i,".style.",property,"=layp",n,"+(",(i-1)*period,"); } " + . move_layer_command(property,n,num,i+1,period)]. + +define Printable_tree + format_layers + ( + LayerDisposition disp, + Int margin, + Web_item content, + Int n, + Int num, + Int i, + Int period + ) = + if i >= num then [ ] else + ["", + "
", + format("","",content), + "
" . format_layers(disp,margin,content,n,num,i+1,period)]. + +define Printable_tree + s_layer + ( + LayerDisposition disp, + Int steps, + Int margin, + Int delay, + Web_item content, + Int period, + Int num + ) = + with n = new_web_count, + [ "", + format_layers(disp,margin,content,n,num,0,period), + ]. + + +define Printable_tree + over + ( + Web_item i, + Int left, + Int top + ) = + with n = new_web_count, + [ "", + "
", + format("","",i), + "
" + ]. + +define Printable_tree + bnce + ( + Web_item i, + Int left, + Int right, + Int top, + Int bottom + ) = + with n = new_web_count, + [ "", + "", + "
", + format("","",i), + "
" + ]. + + +define Printable_tree + folp_switch + ( + Int n, + Int i, + List(FollowPathCommand) path, + Bool loop, + Int steps + ) = + if path is + { + [ ] then [ ], + [p0 . t0] then if p0 is pos(x0,y0,i0,d0) then + if t0 is + { + [ ] then if loop + then [" default: ", + " folpx",n,"=",x0,"; folpy",n,"=",y0,"; ", + " folpseg",n,"=0; ", + " folpwait",n,"=",d0,";", + " if(document.layers)", + " document.nslay",n,".document.folpim",n,".src=folpimages",n,"[",i0,"].src;", + " else document.folpim",n,".src=folpimages",n,"[",i0,"].src;", + " folpstpmax",n," = 0;", + " folpstp",n,"=0;", + " folpdx",n,"=0; ", + " folpdy",n,"=0; ", + " break;"] + else [" default: folpend",n,"=1; break; "], + [p1 . t1] then if p1 is pos(x1,y1,i1,d1) then + [ " case ",i,": ", + " folpx",n,"=",x0,"; folpy",n,"=",y0,"; ", + " folpseg",n,"=",i+1,"; ", + " folpwait",n,"=",d0,";", + " if(document.layers)", + " document.nslay",n,".document.folpim",n,".src=folpimages",n,"[",i0,"].src;", + " else document.folpim",n,".src=folpimages",n,"[",i0,"].src;", + " folpstpmax",n," = ", + "Math.round(Math.sqrt(Math.pow(",x1,"-",x0,",2)+Math.pow(",y1,"-",y0,",2))/",steps,");", + " folpstp",n,"=0;", + " folpdx",n,"=((",x1,"-",x0,")/folpstpmax",n,"); ", + " folpdy",n,"=((",y1,"-",y0,")/folpstpmax",n,"); ", + " break; " + . folp_switch(n,i+1,t0,loop,steps) ] + }}. + +define Printable_tree + set_folpimages + ( + Int n, + List(String) filenames, + Int i, + ) = + if filenames is + { + [ ] then [ ], + [h . t] then + [ " folpimages",n,"[",i,"].src=\"",h,"\";" + . set_folpimages(n,t,i+1)] + }. + +define Printable_tree + follow_path + ( + List(String) filenames, + Int change_every, + List(FollowPathCommand) path, + Bool loop, + Int steps, + Int delay + ) = + if filenames is + { + [ ] then (print("Error in usage of 'follow_path': 'filenames' must be non empty."); []), + [im1 . other_ims] then + if steps < 1 then (print("Error in usage of 'follow_path': 'step' must be >= 1."); [ ]) else + if path is + { + [ ] then [ ], + [p0 . t0] then if p0 is pos(x0,y0,i0,d0) then + if t0 is + { + [ ] then + (print("Error in usage of 'follow_path': 'path' must have at least 2 positions."); []), + [p1 . t1] then if p1 is pos(x1,y1,i1,d1) then + with n = new_web_count, + [ + "", + "
", + "", + "
", + "", + ] + }}}. + + +public type ImageToLoad: + simple(String image_name), + with_rollover(String image_name, + String rollover_name). + +variable List(ImageToLoad) images_to_load = []. + +public define Printable_tree + format + ( + Web_body_option o + ) = + if o is + { + background_color(c) then [" bgcolor=" , (String)format(c)], + psychedelic_background(a,f,d) then add_script(psychedelic_bg(a,f,d)); [ ], + background_image(n) then [" background=", n], + scrolling_layer(disp,st,m,t,c,p) then add_script(s_layer(disp,st,m,t,c,p,2000\p)); [ ], + bounce(i,l,r,t,b) then add_script(bnce(i,l,r,t,b)); [ ], + over(i,l,t) then add_script(over(i,l,t)); [ ], + follow_path(li,ns,p,l,s,d) then add_script(follow_path(li,ns,p,l,s,d)); [ ], + load_image(n) then images_to_load <- [simple(n) . *images_to_load]; [ ], + left_margin(n) then [" leftmargin=", n], + top_margin(n) then [" topmargin=", n], + margin_width(n) then [" marginwidth=", n], + margin_height(n) then [" marginheight=", n], + reload_frame(n,url) then add_body_onload(reload_frame(n,url)); [ ], + onload(n) then [" onLoad=\"", n, "()\""] + }. + +define Printable_tree + preload_list + ( + List(ImageToLoad) images, + Int n, + ) = + if images is + { + [ ] then [ ], + [h . t] then + [" preloaded_images[",n,"].src = '",image_name(h),"';", + if h is + { + simple(_) then [], + with_rollover(n1,r) then + [" preloaded_images[",n1,"].onload = 'allow_rollover(\"",r,"\")';"] + } + . preload_list(t,n-1)] + }. + +define Printable_tree + load_image_script + ( + List(ImageToLoad) images + ) = + if images is + { + [ ] then [ ], + [_ . _] then + [ + "" + ] + }. + + +public define Printable_tree format(String c_ticket, + String s_ticket, + Web_item i). + + +public define Printable_tree + format(List(Table_option) l) = + if l is + { + [ ] then [ ], + [h . t] then [if h is + { + background_color(c) then [" bgcolor=", (String)format(c)], + background_image(f) then [" background=",f], + border then [" border"], + nude then [" border=\"0\" cellspacing=\"0\" cellpadding=\"0\""], + border(e,top,i) then [" border=",e," cellspacing=",top," cellpadding=",i], + border_color(c) then [" bordercolor=", (String)format(c)], + absolute_width(n) then [" width=",n] + }, format(t)] + }. + + + +public define Printable_tree + format(List(Row_option) l) = + if l is + { + [ ] then [ ], + [first . others] then [if first is + { + left then [" align=left"], + h_center then [" align=center"], + right then [" align=right"], + top then [" valign=top"], + v_center then [" valign=center"], + bottom then [" valign=bottom"], + absolute_height(n) then [" height=\"",n,"\""], + base_line then [" valign=baseline"], + background_color(c) then [" bgcolor=",(String)format(c)] + }, + format(others)] + }. + + + + +public define Int + percentage(Int n) = + if n < 0 then 0 + else if n > 100 then 100 + else n. + + public define Int percentage(Int n) = n. + + + + +public define Printable_tree + format + ( + List(Web_body_option) l + ) = + if l is + { + [ ] then [ ], + [h . t] then [format(h) . format(t)] + }. + + + + +public define Printable_tree + format(List(Cell_option) l) = + if l is + { + [ ] then [ ], + [first . others] then + [if first is + { + left then (Printable_tree)[" align=left"], + h_center then (Printable_tree)[" align=center"], + right then (Printable_tree)[" align=right"], + top then (Printable_tree)[" valign=top"], + v_center then (Printable_tree)[" valign=center"], + bottom then (Printable_tree)[" valign=bottom"], + base_line then (Printable_tree)[" valign=baseline"], + background_color(c) then (Printable_tree)[" bgcolor=",(String)format(c)], + background_image(n) then (Printable_tree)[" style=\"background: url(",n,")\""], + absolute_width(w) then (Printable_tree)[" width=",w], + relative_width(r) then (Printable_tree)[" width=",percentage(r),""], + absolute_height(h) then (Printable_tree)[" height=",h], + relative_height(r) then (Printable_tree)[" height=",percentage(r),""], + columns(n) then (Printable_tree)[" colspan=",n], + rows(n) then (Printable_tree)[" rowspan=",n], + nowrap then (Printable_tree)[" nowrap"] + } + . format(others)] + }. + + + +public define Printable_tree + format + ( + String c_ticket, + String s_ticket, + List(Cell) l + ) = + if l is + { + [ ] then [ ], + [first . others] then + [if first is cell(options,item) then + ["", + format(c_ticket,s_ticket,item),""], + format(c_ticket,s_ticket,others)] + }. + + +public define Printable_tree + format + ( + String c_ticket, + String s_ticket, + List(Table_row) l + ) = + if l is + { + [ ] then [ ], + [first_row . other_rows] + then [if first_row is + { + row(options,cells) then + [ "", + format(c_ticket,s_ticket,cells),""] + }, + format(c_ticket,s_ticket,other_rows)] + }. + + +public define Printable_tree + format_choices + ( + List(String) l + ) = + if l is + { + [ ] then [ ], + [h . t] then ["