Files
Geneweb/lib/GWPARAM.ml
2024-03-05 22:01:20 +01:00

179 lines
6.2 KiB
OCaml

(** This module allows plugins to modify geneweb configuration.
This approch is preffered to Functors or library variants
for simple functions if it does not come with a performance cost.
*)
let nb_errors = ref 0
let errors_undef = ref []
let errors_other = ref []
let set_vars = ref []
let gwd_cmd = ref ""
type syslog_level =
[ `LOG_ALERT
| `LOG_CRIT
| `LOG_DEBUG
| `LOG_EMERG
| `LOG_ERR
| `LOG_INFO
| `LOG_NOTICE
| `LOG_WARNING ]
module Default = struct
let init () = Secure.add_assets Filename.current_dir_name
let base_path pref bname =
List.fold_right Filename.concat (Secure.base_dir () :: pref) bname
let bpath bname = Filename.concat (Secure.base_dir ()) bname
(** [output_error ?headers ?content conf code]
Send the http status [code], [headers] and
[content] if provided, or default content otherwise.
*)
let output_error =
let output_file conf fn =
let ic = open_in fn in
try
in_channel_length ic |> really_input_string ic
|> Output.print_sstring conf;
close_in ic
with _ -> ( try close_in ic with _ -> ())
in
fun ?(headers = []) ?(content : Adef.safe_string option) conf code ->
Output.status conf code;
List.iter (Output.header conf "%s") headers;
Output.print_string conf (Adef.encoded "<h1>Incorrect request</h1>");
match content with
| Some content -> Output.print_string conf content
| None -> (
let code =
match code with
| Def.Bad_Request -> "400"
| Unauthorized -> "401"
| Forbidden -> "403"
| Not_Found -> "404"
| Conflict -> "409"
| Internal_Server_Error -> "500"
| Service_Unavailable -> "503"
| OK | Moved_Temporarily -> assert false
in
let fname lang =
code ^ "-" ^ lang ^ ".html"
|> Filename.concat "etc" |> Mutil.search_asset_opt
in
match fname conf.lang with
| Some fn -> output_file conf fn
| None -> (
match fname "en" with
| Some fn -> output_file conf fn
| None -> Output.print_sstring conf ""))
(** Calcul les droits de visualisation d'une personne en
fonction de son age.
Renvoie (dans l'ordre des tests) :
- Vrai si : magicien ou ami ou la personne est public
- Vrai si : la personne est en si_titre, si elle a au moins un
titre et que public_if_title = yes dans le fichier gwf
- Faux si : la personne n'est pas décédée et private_years > 0
- Vrai si : la personne est plus agée (en fonction de la date de
naissance ou de la date de baptème) que privates_years
- Faux si : la personne est plus jeune (en fonction de la date de
naissance ou de la date de baptème) que privates_years
- Vrai si : la personne est décédée depuis plus de privates_years
- Faux si : la personne est décédée depuis moins de privates_years
- Vrai si : la personne a entre 80 et 120 ans et qu'elle n'est pas
privée et public_if_no_date = yes
- Vrai si : la personne s'est mariée depuis plus de private_years
- Faux dans tous les autres cas *)
let p_auth conf base p =
conf.Config.wizard || conf.friend
|| Gwdb.get_access p = Public
|| conf.public_if_titles
&& Gwdb.get_access p = IfTitles
&& Gwdb.nobtitles base conf.allowed_titles conf.denied_titles p <> []
||
let death = Gwdb.get_death p in
if death = NotDead then conf.private_years < 1
else
let check_date d lim none =
match d with
| None -> none ()
| Some d ->
let a = Date.time_elapsed d conf.today in
if a.Def.year > lim then true
else if a.year < conf.private_years then false
else a.month > 0 || a.day > 0
in
check_date (Gwdb.get_birth p |> Date.cdate_to_dmy_opt) conf.private_years
@@ fun () ->
check_date
(Gwdb.get_baptism p |> Date.cdate_to_dmy_opt)
conf.private_years
@@ fun () ->
check_date
(Gwdb.get_death p |> Date.dmy_of_death)
conf.private_years_death
@@ fun () ->
(Gwdb.get_access p <> Def.Private && conf.public_if_no_date)
||
let families = Gwdb.get_family p in
let len = Array.length families in
let rec loop i =
i < len
&& check_date
(Array.get families i |> Gwdb.foi base |> Gwdb.get_marriage
|> Date.cdate_to_dmy_opt)
conf.private_years_marriage
(fun () -> loop (i + 1))
in
loop 0
let syslog (level : syslog_level) msg =
let tm = Unix.(time () |> localtime) in
let level =
match level with
| `LOG_EMERG -> "EMERGENCY"
| `LOG_ALERT -> "ALERT"
| `LOG_CRIT -> "CRITICAL"
| `LOG_ERR -> "ERROR"
| `LOG_WARNING -> "WARNING"
| `LOG_NOTICE -> "NOTICE"
| `LOG_INFO -> "INFO"
| `LOG_DEBUG -> "DEBUG"
in
Printf.eprintf "[%s]: %s %s\n"
(Mutil.sprintf_date tm : Adef.safe_string :> string)
level msg
let wrap_output (conf : Config.config) (title : Adef.safe_string)
(content : unit -> unit) =
Output.print_sstring conf {|<!DOCTYPE html><head><title>|};
Output.print_string conf title;
Output.print_sstring conf {|</title>|};
Output.print_sstring conf {|<meta name="robots" content="none">|};
Output.print_sstring conf {|<meta charset="|};
Output.print_sstring conf conf.charset;
Output.print_sstring conf {|">|};
Output.print_sstring conf
{|<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">|};
Output.print_sstring conf {|</head>|};
Output.print_sstring conf "<body>";
content ();
Output.print_sstring conf {|</body></html>|}
end
let init = ref Default.init
let base_path = ref Default.base_path
let bpath = ref Default.bpath
let output_error = ref Default.output_error
let p_auth = ref Default.p_auth
let syslog = ref Default.syslog
(** [wrap_output conf title content]
Plugins defining a page content but not a complete UI
may want to wrap their page using [wrap_output].
*)
let wrap_output = ref Default.wrap_output