(* camlp4r ./pa_html.cmo *)
(* $Id: updateIndOk.ml,v 4.18.2.1 2006/01/03 12:04:10 ddr Exp $ *)
(* Copyright (c) 1998-2005 INRIA *)
open Config;
open Def;
open Gutil;
open Util;
value raw_get conf key =
match p_getenv conf.env key with
[ Some v -> v
| None -> failwith (key ^ " unbound") ]
;
value get conf key =
match p_getenv conf.env key with
[ Some v -> v
| None -> failwith (key ^ " unbound") ]
;
value get_nth conf key cnt = p_getenv conf.env (key ^ string_of_int cnt);
value getn conf var key =
match p_getenv conf.env (var ^ "_" ^ key) with
[ Some v -> v
| None -> failwith (var ^ "_" ^ key ^ " unbound") ]
;
value rec reconstitute_string_list conf var ext cnt =
match get_nth conf var cnt with
[ Some s ->
let s = only_printable s in
let (sl, ext) = reconstitute_string_list conf var ext (cnt + 1) in
match get_nth conf ("add_" ^ var) cnt with
[ Some "on" -> ([s; "" :: sl], True)
| _ -> ([s :: sl], ext) ]
| _ -> ([], ext) ]
;
value reconstitute_insert_title conf ext cnt tl =
let var = "ins_title" ^ string_of_int cnt in
let n =
match (p_getenv conf.env var, p_getint conf.env (var ^ "_n")) with
[ (_, Some n) when n > 1 -> n
| (Some "on", _) -> 1
| _ -> 0 ]
in
if n > 0 then
let tl =
loop tl n where rec loop tl n =
if n > 0 then
let t1 =
{t_name = Tnone; t_ident = ""; t_place = "";
t_date_start = Adef.codate_None; t_date_end = Adef.codate_None;
t_nth = 0}
in
loop [t1 :: tl] (n - 1)
else tl
in
(tl, True)
else (tl, ext)
;
value rec reconstitute_titles conf ext cnt =
match
(get_nth conf "t_ident" cnt, get_nth conf "t_place" cnt,
get_nth conf "t_name" cnt)
with
[ (Some t_ident, Some t_place, Some t_name) ->
let t_name =
match (get_nth conf "t_main_title" cnt, t_name) with
[ (Some "on", _) -> Tmain
| (_, "") -> Tnone
| (_, _) -> Tname (only_printable t_name) ]
in
let t_date_start =
Update.reconstitute_date conf ("t_date_start" ^ string_of_int cnt)
in
let t_date_end =
Update.reconstitute_date conf ("t_date_end" ^ string_of_int cnt)
in
let t_nth =
match get_nth conf "t_nth" cnt with
[ Some s -> try int_of_string s with [ Failure _ -> 0 ]
| _ -> 0 ]
in
let t =
{t_name = t_name; t_ident = only_printable t_ident;
t_place = only_printable t_place;
t_date_start = Adef.codate_of_od t_date_start;
t_date_end = Adef.codate_of_od t_date_end; t_nth = t_nth}
in
let (tl, ext) = reconstitute_titles conf ext (cnt + 1) in
let (tl, ext) = reconstitute_insert_title conf ext cnt tl in
([t :: tl], ext)
| _ -> ([], ext) ]
;
value reconstitute_add_relation conf ext cnt rl =
match get_nth conf "add_relation" cnt with
[ Some "on" ->
let r =
{r_type = Adoption; r_fath = None; r_moth = None; r_sources = ""}
in
([r :: rl], True)
| _ -> (rl, ext) ]
;
value reconstitute_relation_parent conf var key sex =
match (getn conf var (key ^ "_fn"), getn conf var (key ^ "_sn")) with
[ ("", _) | ("?", _) | (_, "?") -> None
| (fn, sn) ->
let occ =
try int_of_string (getn conf var (key ^ "_occ")) with
[ Failure _ -> 0 ]
in
let create =
match getn conf var (key ^ "_p") with
[ "create" -> Update.Create sex None
| _ -> Update.Link ]
in
Some (fn, sn, occ, create, var ^ "_" ^ key) ]
;
value reconstitute_relation conf var =
try
let r_fath = reconstitute_relation_parent conf var "fath" Male in
let r_moth = reconstitute_relation_parent conf var "moth" Female in
let r_type =
match getn conf var "type" with
[ "Adoption" -> Adoption
| "Recognition" -> Recognition
| "CandidateParent" -> CandidateParent
| "GodParent" -> GodParent
| "FosterParent" -> FosterParent
| _ -> Adoption ]
in
Some {r_type = r_type; r_fath = r_fath; r_moth = r_moth; r_sources = ""}
with
[ Failure _ -> None ]
;
value rec reconstitute_relations conf ext cnt =
match reconstitute_relation conf ("r" ^ string_of_int cnt) with
[ Some r ->
let (rl, ext) = reconstitute_relations conf ext (cnt + 1) in
let (rl, ext) = reconstitute_add_relation conf ext cnt rl in
([r :: rl], ext)
| _ -> ([], ext) ]
;
value reconstitute_death conf birth death_place burial burial_place =
let d = Update.reconstitute_date conf "death" in
let dr =
match p_getenv conf.env "death_reason" with
[ Some "Killed" -> Killed
| Some "Murdered" -> Murdered
| Some "Executed" -> Executed
| Some "Disappeared" -> Disappeared
| Some "Unspecified" | None -> Unspecified
| Some x -> failwith ("bad death reason type " ^ x) ]
in
match get conf "death" with
[ "Auto" when d = None ->
if death_place <> "" || burial <> UnknownBurial || burial_place <> "" ||
dr <> Unspecified then
DeadDontKnowWhen
else Update.infer_death conf birth
| "DeadYoung" when d = None -> DeadYoung
| "DontKnowIfDead" when d = None -> DontKnowIfDead
| "NotDead" -> NotDead
| _ ->
match d with
[ Some d -> Death dr (Adef.cdate_of_date d)
| _ -> DeadDontKnowWhen ] ]
;
value reconstitute_burial conf burial_place =
let d = Update.reconstitute_date conf "burial" in
match p_getenv conf.env "burial" with
[ Some "UnknownBurial" | None ->
match (d, burial_place) with
[ (None, "") -> UnknownBurial
| _ -> Buried (Adef.codate_of_od d) ]
| Some "Buried" -> Buried (Adef.codate_of_od d)
| Some "Cremated" -> Cremated (Adef.codate_of_od d)
| Some x -> failwith ("bad burial type " ^ x) ]
;
value only_printable_or_nl s =
let s = strip_spaces s in
let s' = String.create (String.length s) in
do {
for i = 0 to String.length s - 1 do {
s'.[i] :=
match s.[i] with
[ ' '..'~' | '\160'..'\255' | '\n' -> s.[i]
| _ -> ' ' ]
};
s'
}
;
value reconstitute_person conf =
let ext = False in
let cle_index =
match p_getenv conf.env "i" with
[ Some s -> try int_of_string (strip_spaces s) with [ Failure _ -> -1 ]
| _ -> -1 ]
in
let first_name = only_printable (get conf "first_name") in
let surname = only_printable (get conf "surname") in
let occ =
try int_of_string (strip_spaces (get conf "occ")) with [ Failure _ -> 0 ]
in
let image = only_printable (get conf "image") in
let (first_names_aliases, ext) =
reconstitute_string_list conf "first_name_alias" ext 0
in
let (surnames_aliases, ext) =
reconstitute_string_list conf "surname_alias" ext 0
in
let public_name = only_printable (get conf "public_name") in
let (qualifiers, ext) = reconstitute_string_list conf "qualifier" ext 0 in
let (aliases, ext) = reconstitute_string_list conf "alias" ext 0 in
let (titles, ext) = reconstitute_titles conf ext 1 in
let (titles, ext) = reconstitute_insert_title conf ext 0 titles in
let (rparents, ext) = reconstitute_relations conf ext 1 in
let (rparents, ext) = reconstitute_add_relation conf ext 0 rparents in
let access =
match p_getenv conf.env "access" with
[ Some "Public" -> Public
| Some "Private" -> Private
| _ -> IfTitles ]
in
let occupation = only_printable (get conf "occu") in
let sex =
match p_getenv conf.env "sex" with
[ Some "M" -> Male
| Some "F" -> Female
| _ -> Neuter ]
in
let birth = Update.reconstitute_date conf "birth" in
let birth_place = only_printable (get conf "birth_place") in
let bapt = Adef.codate_of_od (Update.reconstitute_date conf "bapt") in
let bapt_place = only_printable (get conf "bapt_place") in
let burial_place = only_printable (get conf "burial_place") in
let burial = reconstitute_burial conf burial_place in
let death_place = only_printable (get conf "death_place") in
let death = reconstitute_death conf birth death_place burial burial_place in
let death_place =
match death with
[ Death _ _ | DeadYoung | DeadDontKnowWhen -> death_place
| _ -> "" ]
in
let death =
match (death, burial) with
[ (NotDead | DontKnowIfDead, Buried _ | Cremated _) -> DeadDontKnowWhen
| _ -> death ]
in
let notes =
if first_name = "?" || surname = "?" then ""
else only_printable_or_nl (strip_all_trailing_spaces (get conf "notes"))
in
let psources = only_printable (get conf "src") in
let p =
{first_name = first_name; surname = surname; occ = occ; image = image;
first_names_aliases = first_names_aliases;
surnames_aliases = surnames_aliases; public_name = public_name;
qualifiers = qualifiers; aliases = aliases; titles = titles;
rparents = rparents; occupation = occupation; related = []; sex = sex;
access = access; birth = Adef.codate_of_od birth;
birth_place = birth_place;
birth_src = only_printable (get conf "birth_src"); baptism = bapt;
baptism_place = bapt_place;
baptism_src = only_printable (get conf "bapt_src"); death = death;
death_place = death_place;
death_src = only_printable (get conf "death_src"); burial = burial;
burial_place = burial_place;
burial_src = only_printable (get conf "burial_src");
notes = notes; psources = psources;
cle_index = Adef.iper_of_int cle_index}
in
(p, ext)
;
value check_person conf base p =
if p.first_name = "" || p.first_name = "?" then
Some (transl conf "first name missing")
else if p.surname = "" || p.surname = "?" then
Some (transl conf "surname missing")
else None
;
value error_person conf base p err =
let title _ = Wserver.wprint "%s" (capitale (transl conf "error")) in
do {
rheader conf title; Wserver.wprint "%s\n" (capitale err); trailer conf;
}
;
value strip_list = List.filter (fun s -> s <> "");
value strip_person p =
do {
p.first_names_aliases := strip_list p.first_names_aliases;
p.surnames_aliases := strip_list p.surnames_aliases;
p.qualifiers := strip_list p.qualifiers;
p.aliases := strip_list p.aliases;
p.titles := List.filter (fun t -> t.t_ident <> "") p.titles;
p.rparents :=
List.filter (fun r -> r.r_fath <> None || r.r_moth <> None) p.rparents;
}
;
value print_conflict conf base p =
let title _ = Wserver.wprint "%s" (capitale (transl conf "error")) in
do {
rheader conf title;
Update.print_error conf base (AlreadyDefined p);
html_p conf;
let free_n =
Gutil.find_free_occ base (p_first_name base p) (p_surname base p) 0
in
tag "ul" begin
html_li conf;
Wserver.wprint "%s: %d.\n" (capitale (transl conf "first free number"))
free_n;
Wserver.wprint (fcapitale (ftransl conf "click on \"%s\""))
(transl conf "create");
Wserver.wprint "%s.\n" (transl conf " to try again with this number");
html_li conf;
Wserver.wprint "%s " (capitale (transl conf "or"));
Wserver.wprint (ftransl conf "click on \"%s\"") (transl conf "back");
Wserver.wprint " %s %s." (transl_nth conf "and" 0)
(transl conf "change it (the number) yourself");
end;
html_p conf;
tag "form" "method=POST action=\"%s\"" conf.command begin
List.iter
(fun (x, v) ->
Wserver.wprint "\n" x
(quote_escaped (decode_varenv v)))
(conf.henv @ conf.env);
Wserver.wprint "\n"
free_n;
Wserver.wprint "\n"
(capitale (transl conf "create"));
Wserver.wprint "\n"
(capitale (transl conf "back"));
end;
Update.print_same_name conf base p;
trailer conf;
raise Update.ModErr
}
;
value print_cannot_change_sex conf base p =
let title _ = Wserver.wprint "%s" (capitale (transl conf "error")) in
do {
rheader conf title;
Update.print_error conf base (BadSexOfMarriedPerson p);
tag "ul" begin
html_li conf;
Wserver.wprint "\n%s" (referenced_person_text conf base p);
Wserver.wprint "\n";
end;
Update.print_return conf;
trailer conf;
raise Update.ModErr
}
;
value check_conflict conf base sp ipl =
let name = Name.lower (sp.first_name ^ " " ^ sp.surname) in
List.iter
(fun ip ->
let p1 = poi base ip in
if p1.cle_index <> sp.cle_index &&
Name.lower (p_first_name base p1 ^ " " ^ p_surname base p1) =
name &&
p1.occ = sp.occ then
print_conflict conf base p1
else ())
ipl
;
value check_sex_married conf base sp op =
if sp.sex <> op.sex then
let u = uoi base op.cle_index in
let no_check =
List.for_all (fun ifam -> (foi base ifam).relation = NoSexesCheck)
(Array.to_list u.family)
in
if no_check then () else print_cannot_change_sex conf base op
else ()
;
value rename_image_file conf base op sp =
match auto_image_file conf base op with
[ Some old_f ->
let s = default_image_name_of_key sp.first_name sp.surname sp.occ in
let f = Filename.concat (Util.base_path ["images"] conf.bname) s in
let new_f =
if Filename.check_suffix old_f ".gif" then f ^ ".gif" else f ^ ".jpg"
in
try Sys.rename old_f new_f with [ Sys_error _ -> () ]
| _ -> () ]
;
value rparents_of p =
List.fold_left
(fun ipl r ->
match (r.r_fath, r.r_moth) with
[ (Some ip1, Some ip2) -> [ip1; ip2 :: ipl]
| (Some ip, _) -> [ip :: ipl]
| (_, Some ip) -> [ip :: ipl]
| _ -> ipl ])
[] p.rparents
;
value is_witness_at_marriage base ip p =
let u = uoi base ip in
List.exists
(fun ifam -> let fam = foi base ifam in array_memq ip fam.witnesses)
(Array.to_list u.family)
;
value update_relation_parents base op np =
let op_rparents = rparents_of op in
let np_rparents = rparents_of np in
let pi = np.cle_index in
let mod_ippl = [] in
let mod_ippl =
List.fold_left
(fun ippl ip ->
if List.mem ip op_rparents then ippl
else
let p = poi base ip in
if not (List.mem pi p.related) then do {
p.related := [pi :: p.related];
if List.mem_assoc ip ippl then ippl else [(ip, p) :: ippl]
}
else ippl)
mod_ippl np_rparents
in
let mod_ippl =
List.fold_left
(fun ippl ip ->
let p = poi base ip in
if List.mem ip np_rparents ||
np.sex = Male && is_witness_at_marriage base ip np then
ippl
else if List.mem pi p.related then do {
p.related := List.filter ( \<> pi) p.related;
if List.mem_assoc ip ippl then ippl else [(ip, p) :: ippl]
}
else ippl)
mod_ippl op_rparents
in
List.iter (fun (ip, p) -> base.func.patch_person ip p) mod_ippl
;
value effective_mod conf base sp =
let pi = sp.cle_index in
let op = poi base pi in
let key = sp.first_name ^ " " ^ sp.surname in
let ofn = p_first_name base op in
let osn = p_surname base op in
do {
if ofn = sp.first_name && osn = sp.surname && op.occ == sp.occ then ()
else do {
let ipl = person_ht_find_all base key in
check_conflict conf base sp ipl;
rename_image_file conf base op sp;
};
if Name.crush_lower (ofn ^ " " ^ osn) <> Name.crush_lower key ||
(ofn = "?" || osn = "?") && sp.first_name <> "?" &&
sp.surname <> "?" then
person_ht_add base key pi
else ();
check_sex_married conf base sp op;
let created_p = ref [] in
let np =
map_person_ps (Update.insert_person conf base sp.psources created_p)
(Update.insert_string base) sp
in
np.related := op.related;
let op_misc_names = person_misc_names base op in
let np_misc_names = person_misc_names base np in
List.iter
(fun key ->
if List.mem key op_misc_names then () else person_ht_add base key pi)
np_misc_names;
update_relation_parents base op np;
np
}
;
value effective_add conf base sp =
let pi = Adef.iper_of_int base.data.persons.len in
let key = nominative (sp.first_name ^ " " ^ sp.surname) in
let ipl = person_ht_find_all base key in
do {
check_conflict conf base sp ipl;
person_ht_add base key pi;
let created_p = ref [] in
let np =
map_person_ps (Update.insert_person conf base sp.psources created_p)
(Update.insert_string base) sp
in
let na = no_ascend () in
let nu = {family = [| |]} in
np.cle_index := pi;
base.func.patch_person pi np;
base.func.patch_ascend pi na;
base.func.patch_union pi nu;
let np_misc_names = person_misc_names base np in
List.iter (fun key -> person_ht_add base key pi) np_misc_names;
(np, na)
}
;
value array_except v a =
loop 0 where rec loop i =
if i == Array.length a then a
else if a.(i) = v then
Array.append (Array.sub a 0 i)
(Array.sub a (i + 1) (Array.length a - i - 1))
else loop (i + 1)
;
value effective_del conf base p =
let none = Update.insert_string base "?" in
let empty = Update.insert_string base "" in
let asc = aoi base p.cle_index in
do {
match parents asc with
[ Some ifam ->
let des = doi base ifam in
do {
des.children := array_except p.cle_index des.children;
set_parents asc None;
set_consang asc (Adef.fix (-1));
base.func.patch_descend ifam des;
base.func.patch_ascend p.cle_index asc;
()
}
| None -> () ];
p.first_name := none;
p.surname := none;
p.occ := 0;
p.image := empty;
p.public_name := empty;
p.qualifiers := [];
p.aliases := [];
p.first_names_aliases := [];
p.surnames_aliases := [];
p.titles := [];
p.rparents := [];
p.related := [];
p.occupation := empty;
p.access := IfTitles;
p.birth := Adef.codate_None;
p.birth_place := empty;
p.birth_src := empty;
p.baptism := Adef.codate_None;
p.baptism_place := empty;
p.baptism_src := empty;
p.death := DontKnowIfDead;
p.death_place := empty;
p.death_src := empty;
p.burial := UnknownBurial;
p.burial_place := empty;
p.burial_src := empty;
p.notes := empty;
p.psources := empty;
}
;
value print_mod_ok conf base wl p =
let title _ =
Wserver.wprint "%s" (capitale (transl conf "person modified"))
in
do {
header conf title;
print_link_to_welcome conf True;
Wserver.wprint "\n%s" (referenced_person_text conf base p);
Wserver.wprint "\n";
Update.print_warnings conf base wl;
trailer conf;
}
;
(*
value print_mod_ok conf base wl p =
if wl = [] then Perso.print conf base p
else print_mod_ok_aux conf base wl p
;
*)
value relation_sex_is_coherent base warning p =
List.iter
(fun r ->
do {
match r.r_fath with
[ Some ip ->
let p = poi base ip in
if p.sex <> Male then warning (IncoherentSex p 0 0) else ()
| None -> () ];
match r.r_moth with
[ Some ip ->
let p = poi base ip in
if p.sex <> Female then warning (IncoherentSex p 0 0) else ()
| None -> () ];
})
p.rparents
;
value all_checks_person conf base p a u =
let wl = ref [] in
let error = Update.error conf base in
let warning w = wl.val := [w :: wl.val] in
do {
Gutil.check_person base error warning p;
relation_sex_is_coherent base warning p;
match parents a with
[ Some ifam ->
Gutil.check_family base error warning (foi base ifam) (coi base ifam)
(doi base ifam)
| _ -> () ];
Array.iter
(fun ifam ->
Gutil.check_family base error warning (foi base ifam) (coi base ifam)
(doi base ifam))
u.family;
List.iter
(fun
[ ChangedOrderOfChildren ifam des _ -> base.func.patch_descend ifam des
| _ -> () ])
wl.val;
List.rev wl.val
}
;
value print_add_ok conf base wl p =
let title _ = Wserver.wprint "%s" (capitale (transl conf "person added")) in
do {
header conf title;
print_link_to_welcome conf True;
Wserver.wprint "\n%s" (referenced_person_text conf base p);
Wserver.wprint "\n";
Update.print_warnings conf base wl;
trailer conf;
}
;
(*
value print_add_ok conf base wl p =
if wl = [] then Perso.print conf base p
else print_add_ok_aux conf base wl p
;
*)
value print_del_ok conf base wl =
let title _ =
Wserver.wprint "%s" (capitale (transl conf "person deleted"))
in
do {
header conf title;
print_link_to_welcome conf False;
Update.print_warnings conf base wl;
trailer conf;
}
;
value print_add o_conf base =
let conf = Update.update_conf o_conf in
try
let (sp, ext) = reconstitute_person conf in
let redisp =
match p_getenv conf.env "return" with
[ Some _ -> True
| _ -> False ]
in
if ext || redisp then UpdateInd.print_update_ind conf base sp ""
else do {
strip_person sp;
match check_person conf base sp with
[ Some err -> error_person conf base sp err
| None ->
let (p, a) = effective_add conf base sp in
let u = uoi base p.cle_index in
let wl = all_checks_person conf base p a u in
let k = (sp.first_name, sp.surname, sp.occ) in
do {
Util.commit_patches conf base;
History.record conf base k "ap";
print_add_ok conf base wl p;
} ]
}
with
[ Update.ModErr -> () ]
;
value print_del conf base =
match p_getint conf.env "i" with
[ Some i ->
let p = base.data.persons.get i in
let k = (sou base p.first_name, sou base p.surname, p.occ) in
do {
effective_del conf base p;
base.func.patch_person p.cle_index p;
Util.commit_patches conf base;
History.record conf base k "dp";
print_del_ok conf base [];
}
| _ -> incorrect_request conf ]
;
value print_mod_aux conf base callback =
try
let (p, ext) = reconstitute_person conf in
let redisp =
match p_getenv conf.env "return" with
[ Some _ -> True
| _ -> False ]
in
let digest = Update.digest_person (poi base p.cle_index) in
if digest = raw_get conf "digest" then
if ext || redisp then UpdateInd.print_update_ind conf base p digest
else do {
strip_person p;
match check_person conf base p with
[ Some err -> error_person conf base p err
| None -> callback p ]
}
else Update.error_digest conf base
with
[ Update.ModErr -> () ]
;
value print_mod o_conf base =
let conf = Update.update_conf o_conf in
let callback sp =
let p = effective_mod conf base sp in
let u = uoi base p.cle_index in
do {
base.func.patch_person p.cle_index p;
Update.update_misc_names_of_family base p u;
let wl = all_checks_person conf base p (aoi base p.cle_index) u in
let k = (sp.first_name, sp.surname, sp.occ) in
Util.commit_patches conf base;
History.record conf base k "mp";
let quest_string = Adef.istr_of_int 1 in
if p.surname <> quest_string && p.first_name <> quest_string
&& not (is_old_person conf p) then
Update.delete_topological_sort_v conf base
else ();
print_mod_ok conf base wl p;
}
in
print_mod_aux conf base callback
;