(* camlp4r ./pa_lock.cmo *) (* $Id: util.ml,v 4.95.2.1 2006/01/03 12:04:10 ddr Exp $ *) (* Copyright (c) 1998-2005 INRIA *) open Def; open Config; open Gutil; value sharelib = List.fold_right Filename.concat [Gwlib.prefix; "share"] "geneweb" ; value add_lang_path = Secure.add_lang_path; value add_doc_path = Secure.add_doc_path; value set_base_dir = Secure.set_base_dir; add_lang_path sharelib; add_lang_path Filename.current_dir_name; value cnt_dir = ref ""; value images_url = ref ""; value search_in_path p s = loop (p ()) where rec loop = fun [ [d :: dl] -> let f = Filename.concat d s in if Sys.file_exists f then f else loop dl | [] -> s ] ; value search_in_lang_path = search_in_path Secure.lang_path; value search_in_doc_path = search_in_path Secure.doc_path; (* Internationalization *) value start_with_vowel s = if String.length s > 0 then match Char.lowercase s.[0] with [ 'a' | 'e' | 'i' | 'o' | 'u' | 'y' | 'h' | 'à' | 'á' | 'â' | 'ã' | 'ä' | 'å' | 'æ' | 'è' | 'é' | 'ê' | 'ë' | 'ì' | 'í' | 'î' | 'ï' | 'ò' | 'ó' | 'ô' | 'õ' | 'ö' | 'ù' | 'ú' | 'û' | 'ü' | 'ý' | 'ÿ' -> True | _ -> False ] else False ; value match_begin s t = loop 0 0 where rec loop i j = if i >= String.length s || j >= String.length t then True else if s.[i] = t.[j] then loop (i + 1) (j + 1) else False ; value rec capitale s = if String.length s == 0 then "" else match s.[0] with [ 'a'..'z' | 'à'..'ö' | 'ø'..'ý' -> String.make 1 (Char.chr (Char.code s.[0] - Char.code 'a' + Char.code 'A')) ^ String.sub s 1 (String.length s - 1) | '&' -> if String.length s == 1 then s else if match_begin s "¡" then "¡" ^ capitale (String.sub s 7 (String.length s - 7)) else if match_begin s "æ" then "Æ" ^ String.sub s 7 (String.length s - 7) else match s.[1] with [ 'a'..'z' -> "&" ^ String.make 1 (Char.chr (Char.code s.[1] - Char.code 'a' + Char.code 'A')) ^ String.sub s 2 (String.length s - 2) | _ -> s ] | _ -> s ] ; value fcapitale (a : format 'a 'b 'c) : format 'a 'b 'c = Obj.magic capitale a ; value nth_field_abs w n = let rec start i n = if n == 0 then i else if i < String.length w then match w.[i] with [ '<' -> start (i + 2) n | '/' -> start (i + 1) (n - 1) | _ -> start (i + 1) n ] else i in let rec stop i = if i < String.length w then match w.[i] with [ '<' -> stop (i + 2) | '/' -> i | _ -> stop (i + 1) ] else i in let i1 = start 0 n in let i2 = stop i1 in (i1, i2) ; value nth_field w n = let (i1, i2) = nth_field_abs w n in let (i1, i2) = if i2 == i1 then nth_field_abs w 0 else (i1, i2) in String.sub w i1 (i2 - i1) ; value transl conf w = try Hashtbl.find conf.lexicon w with [ Not_found -> "[" ^ w ^ "]" ] ; value transl_nth conf w n = try nth_field (Hashtbl.find conf.lexicon w) n with [ Not_found -> "[" ^ nth_field w n ^ "]" ] ; value transl_nth_def conf w n def_n = try let w = Hashtbl.find conf.lexicon w in let (i1, i2) = nth_field_abs w n in if i2 == i1 then nth_field w def_n else String.sub w i1 (i2 - i1) with [ Not_found -> "[" ^ nth_field w def_n ^ "]" ] ; value plus_decl s = match rindex s '+' with [ Some i -> if i > 0 && s.[i - 1] == ' ' then let start = String.sub s 0 (i - 1) in let decl = String.sub s (i - 1) (String.length s - (i - 1)) in Some (start, decl) else None | None -> None ] ; value gen_decline wt s = let s1 = if s = "" then "" else " " ^ s in let len = String.length wt in if rindex wt '/' <> None then match rindex wt '/' with [ Some i -> if String.length s > 0 && start_with_vowel s then nth_field wt 1 ^ decline 'n' s else nth_field wt 0 ^ decline 'n' s1 | None -> wt ^ decline 'n' s1 ] else if len >= 3 && wt.[len - 3] == ':' && wt.[len - 1] == ':' then let start = String.sub wt 0 (len - 3) in start ^ decline wt.[len - 2] s else match plus_decl wt with [ Some (start, " +before") -> if s = "" then start else s ^ " " ^ start | _ -> wt ^ decline 'n' s1 ] ; value transl_decline conf w s = gen_decline (transl conf w) s; value gen_decline2 wt s1 s2 = let string_of = fun [ '1' -> Some s1 | '2' -> Some s2 | _ -> None ] in let len = String.length wt in let rec loop i = if i = len then "" else let (s, i) = match wt.[i] with [ '%' when i + 1 < len -> match string_of wt.[i + 1] with [ Some s -> (nominative s, i + 1) | None -> ("%", i) ] | ':' when i + 4 < len && wt.[i + 2] = ':' && wt.[i + 3] = '%' -> let c = wt.[i + 1] in match string_of wt.[i + 4] with [ Some s -> (decline c s, i + 4) | None -> (":", i) ] | '[' -> try let j = String.index_from wt i ']' in if j + 2 < len && wt.[j + 1] = '%' then match string_of wt.[j + 2] with [ Some s -> let s = nominative s in let s = if start_with_vowel s then String.make 1 wt.[j - 1] ^ s else String.sub wt (i + 1) (j - i - 2) ^ " " ^ s in (s, j + 2) | None -> raise Not_found ] else raise Not_found with [ Not_found -> ("[", i) ] | c -> (String.make 1 c, i) ] in s ^ loop (i + 1) in loop 0 ; value transl_a_of_b conf = gen_decline2 (transl_nth conf "%1 of %2" 0); value transl_a_of_gr_eq_gen_lev conf = gen_decline2 (transl_nth conf "%1 of %2" 1) ; value failed_format s : format 'a 'b 'c = Obj.magic ("[" ^ s ^ "]"); value valid_format ini_fmt (r : string) = let s : string = Obj.magic (ini_fmt : format 'a 'b 'c) in let rec loop i j = if i < String.length s - 1 && j < String.length r - 1 then match (s.[i], s.[i + 1], r.[j], r.[j + 1]) with [ ('%', x, '%', y) -> if x = y then loop (i + 2) (j + 2) else failed_format s | ('%', _, _, _) -> loop i (j + 1) | (_, _, '%', _) -> loop (i + 1) j | _ -> loop (i + 1) (j + 1) ] else if i < String.length s - 1 then if s.[i] == '%' then failed_format s else loop (i + 1) j else if j < String.length r - 1 then if r.[j] == '%' then failed_format s else loop i (j + 1) else (Obj.magic r : format 'a 'b 'c) in loop 0 0 ; value cftransl conf fmt = let fmt = transl conf fmt in let rec loop i = fun [ [] -> String.sub fmt i (String.length fmt - i) | [a :: al] as gal -> if i + 4 < String.length fmt && fmt.[i] == ':' && fmt.[i + 2] == ':' && fmt.[i + 3] == '%' && fmt.[i + 4] == 's' then decline fmt.[i + 1] a ^ loop (i + 5) al else if i + 1 < String.length fmt && fmt.[i] == '%' && fmt.[i + 1] == 's' then nominative a ^ loop (i + 2) al else if i < String.length fmt then String.make 1 fmt.[i] ^ loop (i + 1) gal else "" ] in loop 0 ; value ftransl conf s = valid_format s (transl conf (Obj.magic s : string)); value ftransl_nth conf s p = valid_format s (transl_nth conf (Obj.magic s : string) p) ; value fdecline conf w s = valid_format w (gen_decline (Obj.magic w : string) s) ; (* *) value secure s = let rec need_code i = if i < String.length s then match s.[i] with [ '<' | '>' -> True | _ -> need_code (i + 1) ] else False in if need_code 0 then let rec loop i len = if i = String.length s then Buff.get len else let (len, next_i) = match s.[i] with [ '<' -> (Buff.mstore len "<", i + 1) | '>' -> (Buff.mstore len ">", i + 1) | c -> (Buff.store len c, i + 1) ] in loop next_i len in loop 0 0 else s ; value html_br conf = do { Wserver.wprint "
"; Wserver.wprint "\n"; }; value html_p conf = do { Wserver.wprint "

"; Wserver.wprint "\n"; }; value html_li conf = do { Wserver.wprint "

  • "; Wserver.wprint "\n"; }; value nl () = Wserver.wprint "\013\010"; value week_day_txt = let txt = [| "Sun"; "Mon"; "Tue"; "Wed"; "Thu"; "Fri"; "Sat" |] in fun i -> let i = if i < 0 || i >= Array.length txt then 0 else i in txt.(i) ; value month_txt = let txt = [| "Jan"; "Feb"; "Mar"; "Apr"; "May"; "Jun"; "Jul"; "Aug"; "Sep"; "Oct"; "Nov"; "Dec" |] in fun i -> let i = if i < 0 || i >= Array.length txt then 0 else i in txt.(i) ; value string_of_ctime conf = let lt = Unix.gmtime conf.ctime in Printf.sprintf "%s, %d %s %d %02d:%02d:%02d GMT" (week_day_txt lt.Unix.tm_wday) lt.Unix.tm_mday (month_txt lt.Unix.tm_mon) (1900 + lt.Unix.tm_year) lt.Unix.tm_hour lt.Unix.tm_min lt.Unix.tm_sec ; value html conf = let charset = if conf.charset = "" then "iso-8859-1" else conf.charset in do { if not conf.cgi then do { Wserver.http ""; Wserver.wprint "Server: GeneWeb/%s" Version.txt; nl (); } else (); Wserver.wprint "Date: %s" (string_of_ctime conf); nl (); Wserver.wprint "Connection: close"; nl (); Wserver.wprint "Content-type: text/html; charset=%s" charset; nl (); } ; value html1 conf = do { html conf; nl (); } ; value unauthorized conf auth_type = do { if not conf.cgi then do { Wserver.http "401 Unauthorized"; Wserver.wprint "WWW-Authenticate: Basic realm=\"%s\"" auth_type; nl () } else (); Wserver.wprint "Content-type: text/html; charset=%s" conf.charset; nl (); nl (); Wserver.wprint "Access failed\n"; Wserver.wprint "

    Access failed

    \n"; Wserver.wprint "\n" auth_type; Wserver.wprint "\n"; } ; value commd conf = let c = conf.command ^ "?" in List.fold_left (fun c (k, v) -> c ^ k ^ "=" ^ v ^ ";") c (conf.henv @ conf.senv) ; value commd_no_params conf = conf.command ^ "?" ^ List.fold_left (fun c (k, v) -> c ^ (if c = "" then "" else ";") ^ k ^ (if v = "" then "" else "=" ^ v)) "" conf.henv ; value code_varenv = Wserver.encode; value decode_varenv = Wserver.decode; value quote_escaped s = let rec need_code i = if i < String.length s then match s.[i] with [ '"' | '&' | '<' | '>' -> True | x -> need_code (succ i) ] else False in let rec compute_len i i1 = if i < String.length s then let i1 = match s.[i] with [ '"' -> i1 + 6 | '&' -> i1 + 5 | '<' | '>' -> i1 + 4 | _ -> succ i1 ] in compute_len (succ i) i1 else i1 in let rec copy_code_in s1 i i1 = if i < String.length s then let i1 = match s.[i] with [ '"' -> do { String.blit """ 0 s1 i1 6; i1 + 6 } | '&' -> do { String.blit "&" 0 s1 i1 5; i1 + 5 } | '<' -> do { String.blit "<" 0 s1 i1 4; i1 + 4 } | '>' -> do { String.blit ">" 0 s1 i1 4; i1 + 4 } | c -> do { s1.[i1] := c; succ i1 } ] in copy_code_in s1 (succ i) i1 else s1 in if need_code 0 then let len = compute_len 0 0 in copy_code_in (String.create len) 0 0 else s ; value hidden_env conf = List.iter (fun (k, v) -> Wserver.wprint "\n" k (quote_escaped (decode_varenv v))) (conf.henv @ conf.senv) ; value p_getenv env label = try Some (decode_varenv (List.assoc (decode_varenv label) env)) with [ Not_found -> None ] ; value p_getint env label = match p_getenv env label with [ Some s -> try Some (int_of_string (strip_spaces s)) with [ Failure _ -> None ] | None -> None ] ; value parent_has_title base p = let a = aoi base p.cle_index in match parents a with [ Some ifam -> let cpl = coi base ifam in let fath = poi base (father cpl) in let moth = poi base (mother cpl) in fath.access <> Private && fath.titles <> [] || moth.access <> Private && moth.titles <> [] | _ -> False ] ; value authorized_age conf base p = if p.access = Public || conf.friend || conf.wizard then True else if conf.public_if_titles && p.access = IfTitles && (p.titles <> [] || parent_has_title base p) then True else match (Adef.od_of_codate p.birth, Adef.od_of_codate p.baptism, p.death, date_of_death p.death) with [ (_, _, NotDead, _) when conf.private_years > 0 -> False | (Some (Dgreg d _), _, _, _) -> let a = time_gone_by d conf.today in a.year > conf.private_years | (_, Some (Dgreg d _), _, _) -> let a = time_gone_by d conf.today in a.year > conf.private_years | (_, _, _, Some (Dgreg d _)) -> let a = time_gone_by d conf.today in a.year > conf.private_years | (None, None, DontKnowIfDead, None) -> p.access <> Private && conf.public_if_no_date | _ -> let u = uoi base p.cle_index in let rec loop i = if i >= Array.length u.family then False else let fam = foi base u.family.(i) in match Adef.od_of_codate fam.marriage with [ Some (Dgreg d _) -> let a = time_gone_by d conf.today in a.year > conf.private_years | _ -> loop (i + 1) ] in loop 0 ] ; value is_old_person conf p = match (Adef.od_of_codate p.birth, Adef.od_of_codate p.baptism, p.death, date_of_death p.death) with [ (_, _, NotDead, _) when conf.private_years > 0 -> False | (Some (Dgreg d _), _, _, _) -> let a = time_gone_by d conf.today in a.year > conf.private_years | (_, Some (Dgreg d _), _, _) -> let a = time_gone_by d conf.today in a.year > conf.private_years | (_, _, _, Some (Dgreg d _)) -> let a = time_gone_by d conf.today in a.year > conf.private_years | (None, None, DontKnowIfDead, None) -> p.access <> Private && conf.public_if_no_date | _ -> False ] ; value fast_auth_age conf p = if conf.friend || conf.wizard || p.access = Public then True else if conf.public_if_titles && p.access = IfTitles && p.titles <> [] then True else is_old_person conf p ; value is_restricted (conf : config) base ip = let quest_string = Adef.istr_of_int 1 in let fct p = p.surname <> quest_string && p.first_name <> quest_string && not (fast_auth_age conf p) in if conf.use_restrict then base.data.visible.v_get fct (Adef.int_of_iper ip) else False ; value empty_string = Adef.istr_of_int 0; value is_hidden p = p.surname = empty_string ; value pget (conf : config) base ip = if is_restricted conf base ip then { first_name = empty_string; surname = empty_string; occ = 0; image = empty_string; first_names_aliases = []; surnames_aliases = []; public_name = empty_string; qualifiers = []; titles = []; rparents = []; related = []; aliases = []; occupation = empty_string; sex = Neuter; access = Private; birth = Adef.codate_None; birth_place = empty_string; birth_src = empty_string; baptism = Adef.codate_None; baptism_place = empty_string; baptism_src = empty_string; death = DontKnowIfDead; death_place = empty_string; death_src = empty_string; burial = UnknownBurial; burial_place = empty_string; burial_src = empty_string; notes = empty_string; psources = empty_string; cle_index = ip } else base.data.persons.get (Adef.int_of_iper ip) ; value aget (conf : config) base ip = if is_restricted conf base ip then no_ascend () else base.data.ascends.get (Adef.int_of_iper ip) ; value uget (conf : config) base ip = if is_restricted conf base ip then { family = [| |] } else base.data.unions.get (Adef.int_of_iper ip) ; (* value nobr_level = ref 0; value enter_nobr () = do { if nobr_level.val == 0 then Wserver.wprint "" else (); incr nobr_level; } ; value exit_nobr () = do { decr nobr_level; if nobr_level.val == 0 then Wserver.wprint "" else (); } ; *) value know base p = sou base p.first_name <> "?" || sou base p.surname <> "?" ; value is_public conf base p = p.access = Public || conf.public_if_titles && p.access = IfTitles && p.titles <> [] || is_old_person conf p ; value acces_n conf base n x = let first_name = p_first_name base x in let surname = p_surname base x in if surname = "" then "" else if (conf.wizard && conf.friend || conf.access_by_key) && not (first_name = "?" || surname = "?") && (not conf.hide_names || is_public conf base x) then "p" ^ n ^ "=" ^ code_varenv (Name.lower first_name) ^ ";n" ^ n ^ "=" ^ code_varenv (Name.lower surname) ^ (if x.occ > 0 then ";oc" ^ n ^ "=" ^ string_of_int x.occ else "") else "i" ^ n ^ "=" ^ string_of_int (Adef.int_of_iper x.cle_index) ^ (if conf.wizard && x.occ > 0 then ";oc" ^ n ^ "=" ^ string_of_int x.occ else "") ; value acces conf base x = acces_n conf base "" x; type p_access = (base -> person -> string * base -> person -> string); value std_access = (p_first_name, p_surname); value raw_access = (fun base p -> sou base p.first_name, fun base p -> sou base p.surname) ; value restricted_txt conf = "....."; value gen_person_text (p_first_name, p_surname) conf base p = if is_hidden p then restricted_txt conf else if conf.hide_names && not (fast_auth_age conf p) then "x x" else let beg = match (sou base p.public_name, p.qualifiers) with [ ("", [nn :: _]) -> p_first_name base p ^ " " ^ sou base nn ^ "" | ("", []) -> p_first_name base p | (n, [nn :: _]) -> n ^ " " ^ sou base nn ^ "" | (n, []) -> n ] in let ali = match p.aliases with [ [alias :: _] -> " (" ^ sou base alias ^ ")" | _ -> "" ] in beg ^ " " ^ p_surname base p ^ ali ; value gen_person_text_no_html (p_first_name, p_surname) conf base p = if is_hidden p then restricted_txt conf else if conf.hide_names && not (fast_auth_age conf p) then "x x" else let beg = match (sou base p.public_name, p.qualifiers) with [ ("", [nn :: _]) -> p_first_name base p ^ " " ^ sou base nn | ("", []) -> p_first_name base p | (n, [nn :: _]) -> n ^ " " ^ sou base nn | (n, []) -> n ] in beg ^ " " ^ p_surname base p ; value gen_person_text_without_surname (p_first_name, p_surname) conf base p = if is_hidden p then restricted_txt conf else if conf.hide_names && not (fast_auth_age conf p) then "x x" else let s = match (sou base p.public_name, p.qualifiers) with [ (n, [nn :: _]) when n <> "" -> n ^ " " ^ sou base nn ^ "" | (n, []) when n <> "" -> n | (_, [nn :: _]) -> p_first_name base p ^ " " ^ sou base nn ^ "" | (_, []) -> p_first_name base p ] in let ali = match p.aliases with [ [alias :: _] -> " (" ^ sou base alias ^ ")" | _ -> "" ] in s ^ ali ; value person_text = gen_person_text std_access; value person_text_no_html = gen_person_text_no_html std_access; value person_text_without_surname = gen_person_text_without_surname std_access ; value main_title base p = let rec find_main = fun [ [] -> None | [x :: l] -> if x.t_name == Tmain then Some x else find_main l ] in match find_main p.titles with [ None -> match p.titles with [ [x :: _] -> Some x | _ -> None ] | x -> x ] ; value titled_person_text conf base p t = let estate = sou base t.t_place in let surname = p_surname base p in let elen = String.length estate in let slen = String.length surname in if Name.strip_lower estate = Name.strip_lower surname then match (t.t_name, p.qualifiers) with [ (Tname n, []) -> sou base n | (Tname n, [nn :: _]) -> sou base n ^ " " ^ sou base nn ^ "" | _ -> person_text_without_surname conf base p ] else if elen < slen && String.sub surname (slen - elen) elen = estate then match (t.t_name, p.qualifiers) with [ (Tname n, []) -> sou base n | (Tname n, [nn :: _]) -> sou base n ^ " " ^ sou base nn ^ "" | _ -> let trunc_surname _ _ = strip_spaces (String.sub surname 0 (slen - elen)) in let trunc_access = (p_first_name, trunc_surname) in gen_person_text trunc_access conf base p ] else match t.t_name with [ Tname s -> let s = sou base s in match p.qualifiers with [ [] -> s | [nn :: _] -> s ^ " " ^ sou base nn ^ "" ] | _ -> person_text conf base p ] ; value one_title_text conf base p t = let place = sou base t.t_place in let s = sou base t.t_ident in let s = if place = "" then s else s ^ " " ^ place in ", " ^ s ^ "" ; value geneweb_link conf href s = if conf.cancel_links then s else "" ^ s ^ "" ; value wprint_geneweb_link conf href s = Wserver.wprint "%s" (geneweb_link conf href s) ; value reference conf base p s = if conf.cancel_links || is_hidden p then s else "" ^ s ^ "" ; value no_reference conf base p s = s; value gen_person_title_text reference p_access conf base p = if authorized_age conf base p then match main_title base p with [ Some t -> reference conf base p (titled_person_text conf base p t) ^ one_title_text conf base p t | None -> reference conf base p (gen_person_text p_access conf base p) ] else reference conf base p (gen_person_text p_access conf base p) ; value referenced_person_title_text = gen_person_title_text reference std_access ; value person_title_text = gen_person_title_text no_reference std_access; value referenced_person_text conf base p = reference conf base p (person_text conf base p) ; value referenced_person_text_without_surname conf base p = reference conf base p (person_text_without_surname conf base p) ; value gen_person_text_without_title p_access conf base p = match main_title base p with [ Some t -> if t.t_place == p.surname then gen_person_text_without_surname p_access conf base p else match (t.t_name, p.qualifiers) with [ (Tname s, [nn :: _]) -> sou base s ^ " " ^ sou base nn ^ "" | (Tname s, _) -> sou base s | _ -> gen_person_text p_access conf base p ] | None -> gen_person_text p_access conf base p ] ; value person_text_without_title = gen_person_text_without_title std_access; value person_title conf base p = if authorized_age conf base p then match main_title base p with [ Some t -> one_title_text conf base p t | None -> "" ] else "" ; value surname_begin n = let i = initial n in if i == 0 then "" else let i = strip_spaces i where rec strip_spaces i = if i >= 1 && n.[i - 1] == ' ' then strip_spaces (pred i) else i in " (" ^ String.sub n 0 i ^ ")" ; value surname_end n = let i = initial n in if i == 0 then n else String.sub n i (String.length n - i) ; value rec skip_spaces s i = if i < String.length s && s.[i] == ' ' then skip_spaces s (i + 1) else i ; value create_env s = let rec get_assoc beg i = if i == String.length s then if i == beg then [] else [String.sub s beg (i - beg)] else if s.[i] == ';' || s.[i] == '&' then let next_i = skip_spaces s (succ i) in [String.sub s beg (i - beg) :: get_assoc next_i next_i] else get_assoc beg (succ i) in let rec separate i s = if i = String.length s then (s, "") else if s.[i] == '=' then (String.sub s 0 i, String.sub s (succ i) (String.length s - succ i)) else separate (succ i) s in List.map (separate 0) (get_assoc 0 0) ; value red_color = "red"; value std_color conf s = "" ^ s ^ "" ; value index_of_sex = fun [ Male -> 0 | Female -> 1 | Neuter -> 2 ] ; value input_to_semi ic = loop 0 where rec loop len = let c = input_char ic in if c = ';' then Buff.get len else loop (Buff.store len c) ; value base_path pref bname = let pref = [Secure.base_dir () :: pref] in let bfile = List.fold_right Filename.concat pref bname in ifdef WIN95 then bfile else if Sys.file_exists bfile then bfile else if String.length bname >= 6 then let dirs = pref @ [String.make 1 bname.[0]; String.make 1 bname.[1]] in List.fold_right Filename.concat dirs bname else bfile ; value base_len n = let n = base_path [] (n ^ ".gwb") in match try Some (Iobase.input n) with [ Sys_error _ -> None ] with [ Some base -> let len = base.data.persons.len in do { base.func.cleanup (); string_of_int len } | _ -> "?" ] ; value open_etc_file fname = let fname1 = base_path ["etc"] (Filename.basename fname ^ ".txt") in let fname2 = search_in_lang_path (Filename.concat "etc" (Filename.basename fname ^ ".txt")) in try Some (Secure.open_in fname1) with [ Sys_error _ -> try Some (Secure.open_in fname2) with [ Sys_error _ -> None ] ] ; value macro_etc env imcom c = try List.assoc c env () with [ Not_found -> match c with [ '%' -> "%" | 'k' -> imcom | 'o' -> if images_url.val <> "" then images_url.val else imcom ^ "m=IM;v=" | 'v' -> Version.txt | c -> "%" ^ String.make 1 c ] ] ; value rec copy_from_etc env lang imcom ic = let cnt = ref 0 in try while True do { match input_char ic with [ '%' -> let c = input_char ic in match c with [ '+' -> incr cnt | '#' -> Wserver.wprint "%d" cnt.val | 'n' -> Wserver.wprint "%s" (base_len (input_to_semi ic)) | 'r' -> let name = input_line ic in match open_etc_file name with [ Some ic -> copy_from_etc env lang imcom ic | None -> Wserver.wprint "... file not found: \"%s.txt\"
    " name ] | c -> Wserver.wprint "%s" (macro_etc env imcom c) ] | '[' -> let c = input_char ic in if c = '\n' then let s = loop 0 (input_char ic) where rec loop len c = if c = ']' then Buff.get len else loop (Buff.store len c) (input_char ic) in let (s, alt) = Translate.inline lang '%' (macro_etc env imcom) s in let s = if alt then "[" ^ s ^ "]" else s in Wserver.wprint "%s" s else Wserver.wprint "[%c" c | c -> Wserver.wprint "%c" c ] } with exc -> do { close_in ic; match exc with [ End_of_file -> () | exc -> raise exc ] } ; value image_prefix conf = if images_url.val <> "" then images_url.val else if conf.cgi then conf.command ^ "?m=IM;v=" else "images" ; value default_body_prop conf = " background=\"" ^ image_prefix conf ^ "/gwback.jpg\"" ; value body_prop conf = try match List.assoc "body_prop" conf.base_env with [ "" -> default_body_prop conf | s -> " " ^ s ] with [ Not_found -> default_body_prop conf ] ; value get_server_string_aux cgi request = if not cgi then Wserver.extract_param "host: " '\r' request else let server_name = try Sys.getenv "SERVER_NAME" with [ Not_found -> "" ] in let server_port = try Sys.getenv "SERVER_PORT" with [ Not_found | Failure _ -> "80" ] in if server_port = "80" then server_name else server_name ^ ":" ^ server_port ; value get_request_string_aux cgi request = if not cgi then Wserver.extract_param "GET " ' ' request else let script_name = try Sys.getenv "SCRIPT_NAME" with [ Not_found -> "" ] in let query_string = try Sys.getenv "QUERY_STRING" with [ Not_found -> "" ] in script_name ^ "?" ^ query_string ; value get_server_string conf = get_server_string_aux conf.cgi conf.request; value get_request_string conf = get_request_string_aux conf.cgi conf.request; value url_no_index conf base = let scratch s = code_varenv (Name.lower (sou base s)) in let get_person v = match try Some (int_of_string v) with [ Failure _ -> None ] with [ Some i -> if i >= 0 && i < base.data.persons.len then let p = pget conf base (Adef.iper_of_int i) in if (conf.hide_names && not (fast_auth_age conf p)) || is_hidden p then None else let f = scratch p.first_name in let s = scratch p.surname in let oc = string_of_int p.occ in Some (f, s, oc) else None | None -> None ] in let get_family v = match try Some (int_of_string v) with [ Failure _ -> None ] with [ Some i -> if i >= 0 && i < base.data.families.len then if is_deleted_family (base.data.families.get i) then None else let cpl = base.data.couples.get i in let p = pget conf base (father cpl) in let f = scratch p.first_name in let s = scratch p.surname in if f = "" || s = "" then None else let oc = string_of_int p.occ in let u = uget conf base (father cpl) in let n = loop 0 where rec loop k = if u.family.(k) == Adef.ifam_of_int i then string_of_int k else loop (k + 1) in Some (f, s, oc, n) else None | None -> None ] in let env = let rec loop = fun [ [] -> [] | [("opt", "no_index") :: l] -> loop l | [("escache", _) :: l] -> loop l | [("dsrc", _) :: l] -> loop l | [("templ", _) :: l] -> loop l | [("i", v) :: l] -> new_env "i" v (fun x -> x) l | [("ei", v) :: l] -> new_env "ei" v (fun x -> "e" ^ x) l | [(k, v) :: l] when String.length k == 2 && k.[0] == 'i' -> let c = String.make 1 k.[1] in new_env k v (fun x -> x ^ c) l | [(k, v) :: l] when String.length k > 2 && k.[0] == 'e' && k.[1] == 'f' -> new_fam_env k v (fun x -> x ^ k) l | [kv :: l] -> [kv :: loop l] ] and new_env k v c l = match get_person v with [ Some (f, s, oc) -> if oc = "0" then [(c "p", f); (c "n", s) :: loop l] else [(c "p", f); (c "n", s); (c "oc", oc) :: loop l] | None -> [(k, v) :: loop l] ] and new_fam_env k v c l = match get_family v with [ Some (f, s, oc, n) -> let l = loop l in let l = if n = "0" then l else [(c "f", n) :: l] in if oc = "0" then [(c "p", f); (c "n", s) :: l] else [(c "p", f); (c "n", s); (c "oc", oc) :: l] | None -> [(k, v) :: loop l] ] in loop conf.env in let addr = let pref = let s = get_request_string conf in match rindex s '?' with [ Some i -> String.sub s 0 i | None -> s ] in get_server_string conf ^ pref in let suff = List.fold_right (fun (x, v) s -> let sep = if s = "" then "" else ";" in x ^ "=" ^ v ^ sep ^ s) [("lang", conf.lang) :: env] "" in let suff = if conf.cgi then "b=" ^ conf.bname ^ ";" ^ suff else suff in addr ^ "?" ^ suff ; value include_hed_trl conf base_opt suff = let hed_fname = let fname = base_path ["lang"; conf.lang] (conf.bname ^ suff) in if Sys.file_exists fname then fname else base_path ["lang"] (conf.bname ^ suff) in match try Some (Secure.open_in hed_fname) with [ Sys_error _ -> None ] with [ Some ic -> let url () = match base_opt with [ Some base -> url_no_index conf base | None -> get_server_string conf ^ get_request_string conf ] in let pref () = let s = url () in match rindex s '?' with [ Some i -> String.sub s 0 (i + 1) | None -> s ] in let suff () = let s = url () in match rindex s '?' with [ Some i -> String.sub s (i + 1) (String.length s - i - 1) | None -> "" ] in copy_from_etc [('p', pref); ('s', suff); ('t', fun _ -> commd conf)] conf.lang conf.indep_command ic | None -> () ] ; value message_to_wizard conf = if conf.wizard || conf.just_friend_wizard then let print_file fname = let fname = base_path ["etc"; conf.bname] (fname ^ ".txt") in match try Some (Secure.open_in fname) with [ Sys_error _ -> None ] with [ Some ic -> try while True do { Wserver.wprint "%c" (input_char ic); } with [ End_of_file -> close_in ic ] | None -> () ] in do { print_file "mess_wizard"; if conf.user <> "" then print_file ("mess_wizard_" ^ conf.user) else (); } else () ; value header_without_page_title conf title = do { html1 conf; Wserver.wprint "\ "; Wserver.wprint "\n\n"; Wserver.wprint " \n"; Wserver.wprint " "; title True; Wserver.wprint "\n"; include_hed_trl conf None ".hed"; Wserver.wprint "\n"; let s = try " dir=" ^ Hashtbl.find conf.lexicon " !dir" with [ Not_found -> "" ] in let s = s ^ body_prop conf in Wserver.wprint "" s; Wserver.wprint "\n"; message_to_wizard conf; } ; value header conf title = do { header_without_page_title conf title; Wserver.wprint "

    " conf.highlight; title False; Wserver.wprint "

    \n"; } ; value rheader conf title = do { header_without_page_title conf title; Wserver.wprint "

    " red_color; title False; Wserver.wprint "

    \n"; } ; value header_no_page_title conf title = do { header_without_page_title conf title; match p_getenv conf.env "title" with [ None | Some "" -> () | Some x -> do { Wserver.wprint "

    " conf.highlight; Wserver.wprint "%s" x; Wserver.wprint "

    \n" } ]; } ; value start_with s i p = i + String.length p <= String.length s && String.lowercase (String.sub s i (String.length p)) = p ; value http_string s i = if start_with s i "http://" then let j = loop (i + String.length "http://") where rec loop j = if j < String.length s then match s.[j] with [ 'a'..'z' | 'A'..'Z' | 'à'..'ÿ' | 'À'..'Ý' | '0'..'9' | '/' | ':' | '?' | '%' | ';' | '=' | '_' | '-' | '&' | '.' | '~' | '#' | '+' -> loop (j + 1) | _ -> j ] else j in match s.[j - 1] with [ ':' | ';' | '.' -> Some (j - 1) | _ -> Some j ] else None ; value email_addr s i = let rec before_at empty i = if i = String.length s then None else match s.[i] with [ 'a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_' | '.' -> before_at False (i + 1) | '@' -> if empty then None else after_at True (i + 1) | _ -> None ] and after_at empty i = if i = String.length s then None else match s.[i] with [ 'a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_' -> after_at False (i + 1) | '.' -> if empty then None else after_dot 0 (i + 1) | _ -> None ] and after_dot len i = if i = String.length s then Some (len, i) else match s.[i] with [ 'a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_' | '.' -> after_dot (len + 1) (i + 1) | _ -> Some (len, i) ] in match before_at True i with [ Some (len, i) -> let (len, i) = if len > 0 && s.[i - 1] = '.' then (len - 1, i - 1) else (len, i) in if len = 0 then None else Some i | None -> None ] ; value tag_id s i = loop i 0 where rec loop i len = if i = String.length s then Buff.get len else match s.[i] with [ 'a'..'z' | 'A'..'Z' | '0'..'9' -> loop (i + 1) (Buff.store len (Char.lowercase s.[i])) | _ -> if len = 0 then loop (i + 1) 0 else Buff.get len ] ; value good_tags_list = ["a"; "b"; "br"; "dd"; "div"; "dl"; "dt"; "em"; "font"; "hr"; "h1"; "h2"; "h3"; "h4"; "i"; "img"; "li"; "ol"; "p"; "pre"; "strong"; "sup"; "table"; "td"; "tr"; "u"; "ul"] ; value bad_tags_list = ["applet"; "embed"; "form"; "input"; "object"; "script"] ; value good_tag s i = List.mem (tag_id s i) good_tags_list; value bad_tag s i = List.mem (tag_id s i) bad_tags_list; value get_variable s i = loop 0 i where rec loop len i = if i == String.length s then (Buff.get len, i) else match s.[i] with [ 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' as c -> loop (Buff.store len c) (i + 1) | ';' -> (Buff.get len, i + 1) | _ -> (Buff.get len, i) ] ; type tag_type = [ In_a_href | In_norm | Out ]; value expand_env = let buff = Buffer.create 30 in fun conf s -> match p_getenv conf.base_env "expand_env" with [ Some "yes" -> let _ : unit = Buffer.clear buff in loop 0 where rec loop i = if i = String.length s then Buffer.contents buff else if i + 1 < String.length s && s.[i] = '$' && s.[i+1] = '{' then try let j = String.index_from s (i+1) '}' in let v = Sys.getenv (String.sub s (i + 2) (j - i - 2)) in do { Buffer.add_string buff v; loop (j + 1) } with [ Not_found -> do { Buffer.add_char buff s.[i]; loop (i + 1) } ] else do { Buffer.add_char buff s.[i]; loop (i + 1) } | _ -> s ] ; value string_with_macros conf positive_filtering env s = let buff = Buffer.create 1000 in loop Out 0 where rec loop tt i = if i < String.length s then if i + 1 < String.length s && s.[i] = '%' then let i = try do { Buffer.add_string buff (List.assoc s.[i + 1] env ()); i + 2 } with [ Not_found -> match s.[i + 1] with [ 's' -> do { Buffer.add_string buff (commd conf); i + 2 } | 'v' -> let (k, j) = get_variable s (i + 2) in let (v, i) = let v = try let v = List.assoc ("var_" ^ k) conf.base_env in Some (expand_env conf v) with [ Not_found -> None ] in match v with [ Some v -> (v, j) | None -> ("%", i + 1) ] in do { Buffer.add_string buff v; i } | '%' -> do { Buffer.add_string buff "%"; i + 2 } | _ -> do { Buffer.add_string buff "%"; i + 1 } ] ] in loop tt i else if s.[i] = '<' && i + 1 < String.length s && s.[i+1] = '%' then do { Buffer.add_string buff "<"; loop tt (i + 1) } else if s.[i] = '<' && (positive_filtering && not (good_tag s (i + 1)) || not positive_filtering && bad_tag s (i + 1)) then do { Buffer.add_string buff "<"; loop tt (i + 1) } else match tt with [ In_a_href -> let tt = if start_with s i "" then Out else In_a_href in do { Buffer.add_char buff s.[i]; loop tt (i + 1) } | In_norm -> let tt = if s.[i] = '>' then Out else In_norm in do { Buffer.add_char buff s.[i]; loop tt (i + 1) } | Out -> match http_string s i with [ Some j -> let x = String.sub s i (j - i) in do { Printf.bprintf buff "%s" x x; loop Out j } | None -> match email_addr s i with [ Some j -> let x = String.sub s i (j - i) in do { Printf.bprintf buff "%s" x x; loop Out j } | None -> let tt = if start_with s i "gwsetup" with [ Not_found -> "" ] ; value gen_trailer with_logo conf = let env = [('s', fun _ -> commd conf); ('d', fun _ -> let s = if conf.cancel_links then "" else " - DOC" in if not conf.setup_link then s else s ^ " - " ^ setup_link conf)] in do { if not with_logo then () else Wserver.wprint "\

    ...
    " (commd conf) (image_prefix conf); match open_etc_file "copyr" with [ Some ic -> copy_from_etc env conf.lang conf.indep_command ic | None -> do { html_p conf; Wserver.wprint "


    Copyright (c) 1998-2005 INRIA - GeneWeb %s" Version.txt; html_br conf; () } ]; include_hed_trl conf None ".trl"; Wserver.wprint "\n\n"; } ; value trailer = gen_trailer True; value menu_threshold = 20; value is_number t = match t.[0] with [ '1'..'9' -> True | _ -> False ] ; value print_alphab_list conf crit print_elem liste = let len = List.length liste in do { if len > menu_threshold then let _ = List.fold_left (fun last e -> let t = crit e in let same_than_last = match last with [ Some t1 -> t = t1 | _ -> False ] in do { if not same_than_last then Wserver.wprint "%s\n" t t else (); Some t }) None liste in () else (); Wserver.wprint "\n" else () | _ -> () ]; if not same_than_last then do { html_li conf; Wserver.wprint "%s\n" t t; Wserver.wprint " \n" else (); Wserver.wprint "\n"; } ; value parent conf base p a = match a.public_name with [ n when sou base n <> "" -> sou base n ^ person_title conf base a | _ -> if conf.hide_names && not (fast_auth_age conf a) then "x x" else p_first_name base a ^ (if p.surname <> a.surname then " " ^ p_surname base a else "") ] ; value print_parent conf base p fath moth = let s = match (fath, moth) with [ (Some fath, None) -> parent conf base p fath | (None, Some moth) -> parent conf base p moth | (Some fath, Some moth) -> parent conf base p fath ^ " " ^ transl_nth conf "and" 0 ^ " " ^ parent conf base p moth | _ -> "" ] in let is = index_of_sex p.sex in Wserver.wprint "%s" (transl_a_of_gr_eq_gen_lev conf (transl_nth conf "son/daughter/child" is) s) ; value specify_homonymous conf base p = let is = index_of_sex p.sex in match (p.public_name, p.qualifiers) with [ (n, [nn :: _]) when sou base n <> "" -> Wserver.wprint "%s %s" (sou base n) (sou base nn) | (_, [nn :: _]) -> Wserver.wprint "%s %s" (p_first_name base p) (sou base nn) | (n, []) when sou base n <> "" -> Wserver.wprint "%s" (sou base n) | (_, []) -> let a = aget conf base p.cle_index in let ifam = match parents a with [ Some ifam -> let cpl = coi base ifam in let fath = let fath = pget conf base (father cpl) in if p_first_name base fath = "?" then None else Some fath in let moth = let moth = pget conf base (mother cpl) in if p_first_name base moth = "?" then None else Some moth in Some (fath, moth) | None -> None ] in match ifam with [ Some (None, None) | None -> let u = uget conf base p.cle_index in let rec loop i = if i < Array.length u.family then let des = doi base u.family.(i) in let conjoint = spouse p.cle_index (coi base u.family.(i)) in let ct = des.children in if Array.length ct > 0 then let enfant = pget conf base ct.(0) in let (child_fn, child_sn) = if conf.hide_names && not (fast_auth_age conf enfant) then ("x", " x") else (p_first_name base enfant, if p.surname <> enfant.surname then " " ^ p_surname base enfant else "") in Wserver.wprint "%s" (transl_a_of_b conf (transl_nth conf "father/mother" is) (child_fn ^ child_sn)) else let conjoint = pget conf base conjoint in if p_first_name base conjoint <> "?" || p_surname base conjoint <> "?" then Wserver.wprint "%s" (transl_a_of_b conf (transl_nth conf "husband/wife" is) (p_first_name base conjoint ^ " " ^ p_surname base conjoint)) else loop (i + 1) else Wserver.wprint "..." in loop 0 | Some (fath, moth) -> print_parent conf base p fath moth ] ] ; (* fix system bug: string_of_float 17.97 = "17.969999999999" *) value my_string_of_float f = Printf.sprintf "%.6g" f ; value string_of_decimal_num conf f = let s = my_string_of_float f in let b = Buffer.create 20 in let rec loop i = if i == String.length s then Buffer.contents b else do { match s.[i] with [ '.' -> if i == String.length s - 1 then () else Buffer.add_string b (transl conf "(decimal separator)") | x -> Buffer.add_char b x ]; loop (i + 1) } in loop 0 ; value personal_image_file_name bname str = Filename.concat (base_path ["images"] bname) str ; value source_image_file_name bname str = let fname1 = List.fold_right Filename.concat [base_path ["src"] bname; "images"] str in let fname2 = List.fold_right Filename.concat [Secure.base_dir (); "src"; "images"] str in if Sys.file_exists fname1 then fname1 else fname2 ; value image_file_name str = let fname1 = List.fold_right Filename.concat [Secure.base_dir (); "images"] str in if Sys.file_exists fname1 then fname1 else search_in_lang_path (Filename.concat "images" str) ; value png_image_size ic = let magic = let s = String.create 4 in do { really_input ic s 0 4; s } in if magic = "\137PNG" then do { seek_in ic 16; let wid = input_binary_int ic in let hei = input_binary_int ic in Some (wid, hei) } else None ; value gif_image_size ic = let magic = let s = String.create 4 in do { really_input ic s 0 4; s } in if magic = "GIF8" then do { seek_in ic 6; let wid = let x = input_byte ic in input_byte ic * 256 + x in let hei = let x = input_byte ic in input_byte ic * 256 + x in Some (wid, hei) } else None ; value jpeg_image_size ic = let magic = let str = String.create 10 in do { really_input ic str 0 10; str } in if Char.code magic.[0] = 0xff && Char.code magic.[1] = 0xd8 && (let m = String.sub magic 6 4 in m = "JFIF" || m = "Exif") then let exif_type = String.sub magic 6 4 = "Exif" in let rec loop found = do { while Char.code (input_char ic) <> 0xFF do { () }; let ch = loop (input_char ic) where rec loop ch = if Char.code ch = 0xFF then loop (input_char ic) else ch in if Char.code ch = 0xC0 || Char.code ch = 0xC3 then if exif_type && not found then loop True else do { for i = 1 to 3 do { let _ = input_char ic in () }; let a = input_char ic in let b = input_char ic in let c = input_char ic in let d = input_char ic in let wid = Char.code c lsl 8 lor Char.code d in let hei = Char.code a lsl 8 lor Char.code b in Some (wid, hei) } else let a = input_char ic in let b = input_char ic in let len = Char.code a lsl 8 lor Char.code b in let len = if len >= 32768 then 0 else len in do { for i = 1 to len - 2 do { let _ = input_char ic in () }; if Char.code ch <> 0xDA then loop found else None } } in loop False else None ; value image_size fname = match try Some (Secure.open_in_bin fname) with [ Sys_error _ -> None ] with [ Some ic -> let r = try let sz = jpeg_image_size ic in let sz = if sz = None then do { seek_in ic 0; png_image_size ic } else sz in if sz = None then do { seek_in ic 0; gif_image_size ic } else sz with [ End_of_file -> None ] in do { close_in ic; r } | None -> None ] ; value limited_image_size max_wid max_hei fname size = match if fname = "" then size else image_size fname with [ Some (wid, hei) -> let (wid, hei) = if hei > max_hei then let wid = wid * max_hei / hei in let hei = max_hei in (wid, hei) else (wid, hei) in let (wid, hei) = if wid > max_wid then let hei = hei * max_wid / wid in let wid = max_wid in (wid, hei) else (wid, hei) in Some (wid, hei) | None -> None ] ; value up_fname conf = "up.jpg"; value link_to_referer conf = let referer = Wserver.extract_param "referer: " '\n' conf.request in if referer <> "" then let fname = "left.jpg" in let wid_hei = match image_size (image_file_name fname) with [ Some (wid, hei) -> " width=" ^ string_of_int wid ^ " height=" ^ string_of_int hei | None -> "" ] in "\"<<\"\n" else "" ; value print_link_to_welcome conf right_aligned = if conf.cancel_links then () else do { let fname = up_fname conf in let dir = if conf.is_rtl then "left" else "right" in let wid_hei = match image_size (image_file_name fname) with [ Some (wid, hei) -> " width=" ^ string_of_int wid ^ " height=" ^ string_of_int hei | None -> "" ] in if right_aligned then Wserver.wprint "
    \n" dir else (); let str = link_to_referer conf in if str = "" then () else Wserver.wprint "%s" str; Wserver.wprint "" (commd_no_params conf); Wserver.wprint "\"^^\"" (image_prefix conf) fname wid_hei; Wserver.wprint "\n"; if right_aligned then Wserver.wprint "
    \n" else (); } ; value incorrect_request conf = let title _ = Wserver.wprint "%s" (capitale (transl conf "incorrect request")) in do { header conf title; print_link_to_welcome conf False; trailer conf } ; value find_person_in_env conf base suff = match p_getint conf.env ("i" ^ suff) with [ Some i -> if i >= 0 && i < base.data.persons.len then let p = pget conf base (Adef.iper_of_int i) in if is_hidden p then None else Some p else None | None -> match (p_getenv conf.env ("p" ^ suff), p_getenv conf.env ("n" ^ suff)) with [ (Some p, Some n) -> let occ = match p_getint conf.env ("oc" ^ suff) with [ Some oc -> oc | None -> 0 ] in let k = p ^ " " ^ n in let xl = List.fold_left (fun l ip -> let p = pget conf base ip in if is_hidden p then l else [p :: l]) [] (person_ht_find_all base k) in try let r = List.find (fun x -> Name.lower (p_first_name base x) = Name.lower p && Name.lower (p_surname base x) = Name.lower n && x.occ == occ) xl in if not conf.hide_names || authorized_age conf base r then Some r else None with [ Not_found -> None ] | _ -> None ] ] ; value find_sosa_ref conf base = match find_person_in_env conf base "z" with [ Some p -> Some p | None -> match p_getenv conf.base_env "default_sosa_ref" with [ Some n -> if n = "" then None else match person_ht_find_all base n with [ [ip] -> let p = pget conf base ip in if is_hidden p then None else Some p | _ -> None ] | None -> None ] ] ; value create_topological_sort conf base = match p_getenv conf.env "opt" with [ Some "no_tsfile" -> let _ = base.data.ascends.array () in let _ = base.data.couples.array () in Consang.topological_sort base (aget conf) | Some "no_tstab" -> Array.create base.data.persons.len 0 | _ -> let bfile = base_path [] (conf.bname ^ ".gwb") in lock (Iobase.lock_file bfile) with [ Accept -> let tstab_file = if conf.use_restrict then Filename.concat bfile "tstab_visitor" else Filename.concat bfile "tstab" in let r = match try Some (Secure.open_in_bin tstab_file) with [ Sys_error _ -> None ] with [ Some ic -> let r = try Some (Marshal.from_channel ic) with [ End_of_file | Failure _ -> None ] in do { close_in ic; r } | None -> None ] in match r with [ Some tstab -> tstab | None -> let _ = base.data.ascends.array () in let _ = base.data.couples.array () in let tstab = Consang.topological_sort base (aget conf) in do { if conf.use_restrict then base.data.visible.v_write () else (); match try Some (Secure.open_out_bin tstab_file) with [ Sys_error _ -> None ] with [ Some oc -> do { Marshal.to_channel oc tstab [Marshal.No_sharing]; close_out oc; } | None -> () ]; tstab } ] | Refuse -> let _ = base.data.ascends.array () in let _ = base.data.couples.array () in Consang.topological_sort base (aget conf) ] ] ; value branch_of_sosa conf base ip n = do { if Num.eq n Num.zero then invalid_arg "branch_of_sosa" else (); let rec expand bl n = if Num.eq n Num.one then bl else expand [Num.even n :: bl] (Num.half n) in let rec loop ipl ip sp = fun [ [] -> Some [(ip, sp) :: ipl] | [goto_fath :: nl] -> match parents (aget conf base ip) with [ Some ifam -> let cpl = coi base ifam in if goto_fath then loop [(ip, sp) :: ipl] (father cpl) Male nl else loop [(ip, sp) :: ipl] (mother cpl) Female nl | _ -> None ] ] in loop [] ip (pget conf base ip).sex (expand [] n) } ; value sosa_of_branch ipl = do { if ipl = [] then failwith "sosa_of_branch" else (); let ipl = List.tl (List.rev ipl) in List.fold_left (fun b (ip, sp) -> let b = Num.twice b in match sp with [ Male -> b | Female -> Num.inc b 1 | Neuter -> assert False ]) Num.one ipl } ; value space_to_unders s = match rindex s ' ' with [ Some _ -> let s' = String.create (String.length s) in do { for i = 0 to String.length s - 1 do { s'.[i] := if s.[i] = ' ' then '_' else s.[i] }; s' } | None -> s ] ; value default_image_name_of_key fnam surn occ = let f = space_to_unders (Name.lower fnam) in let s = space_to_unders (Name.lower surn) in f ^ "." ^ string_of_int occ ^ "." ^ s ; value default_image_name base p = default_image_name_of_key (p_first_name base p) (p_surname base p) p.occ ; value auto_image_file conf base p = let s = default_image_name base p in let f = Filename.concat (base_path ["images"] conf.bname) s in if Sys.file_exists (f ^ ".gif") then Some (f ^ ".gif") else if Sys.file_exists (f ^ ".jpg") then Some (f ^ ".jpg") else if Sys.file_exists (f ^ ".png") then Some (f ^ ".png") else None ; value image_and_size conf base p image_size = if not conf.no_image && authorized_age conf base p then match sou base p.image with [ "" -> match auto_image_file conf base p with [ Some f -> Some (True, f, image_size f None) | None -> None ] | s -> let (s, size) = let l = String.length s - 1 in if s.[l] = ')' then try let pos1 = String.index s '(' in let pos2 = String.index_from s pos1 'x' in let wid = String.sub s (pos1+1) (pos2-pos1-1) in let hei = String.sub s (pos2+1) (l-pos2-1) in let size = Some (int_of_string wid, int_of_string hei) in (String.sub s 0 pos1, image_size "" size) with [ Not_found | Failure _ -> (s, None) ] else (s, None) in let http = "http://" in if String.length s > String.length http && String.sub s 0 (String.length http) = http then Some (False, s, size) else if Filename.is_implicit s then match try Some (List.assoc "images_path" conf.base_env) with [ Not_found -> None ] with [ Some p when p <> "" -> Some (False, p ^ s, size) | _ -> let fname = personal_image_file_name conf.bname s in if Sys.file_exists fname then Some (True, fname, image_size fname None) else None ] else None ] else None ; value has_image conf base p = if not conf.no_image && authorized_age conf base p then p.image <> Adef.istr_of_int 0 || auto_image_file conf base p <> None else False ; value only_printable 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' -> s.[i] | _ -> ' ' ] }; s' } ; value relation_type_text conf t n = match t with [ Adoption -> transl_nth conf "adoptive father/adoptive mother/adoptive parents" n | Recognition -> transl_nth conf "recognizing father/recognizing mother/recognizing parents" n | CandidateParent -> transl_nth conf "candidate father/candidate mother/candidate parents" n | GodParent -> transl_nth conf "godfather/godmother/godparents" n | FosterParent -> transl_nth conf "foster father/foster mother/foster parents" n ] ; value rchild_type_text conf t n = match t with [ Adoption -> transl_nth conf "adoptive son/adoptive daughter/adoptive child" n | Recognition -> transl_nth conf "recognized son/recognized daughter/recognized child" n | CandidateParent -> transl_nth conf "candidate son/candidate daughter/candidate child" n | GodParent -> transl_nth conf "godson/goddaughter/godchild" n | FosterParent -> transl_nth conf "foster son/foster daughter/foster child" n ] ; value wprint_hidden pref name valu = Wserver.wprint "\n" pref name (quote_escaped valu) ; value wprint_hidden_person conf base pref p = let first_name = p_first_name base p in let surname = p_surname base p in if (conf.wizard && conf.friend || conf.access_by_key) && not (first_name = "?" || surname = "?") then do { wprint_hidden pref "p" (Name.lower first_name); wprint_hidden pref "n" (Name.lower surname); if p.occ > 0 then wprint_hidden pref "oc" (string_of_int p.occ) else (); } else wprint_hidden pref "i" (string_of_int (Adef.int_of_iper p.cle_index)) ; exception Ok; value has_nephews_or_nieces conf base p = try let a = aget conf base p.cle_index in match parents a with [ Some ifam -> let des = doi base ifam in do { Array.iter (fun ip -> if ip == p.cle_index then () else Array.iter (fun ifam -> if Array.length (doi base ifam).children > 0 then raise Ok else ()) (uget conf base ip).family) des.children; False } | _ -> False ] with [ Ok -> True ] ; value browser_doesnt_have_tables conf = let user_agent = Wserver.extract_param "user-agent: " '/' conf.request in String.lowercase user_agent = "lynx" ; (* Printing for browsers without tables *) value pre_text_size txt = let rec normal len i = if i = String.length txt then len else if txt.[i] = '<' then in_tag len (i + 1) else if txt.[i] = '&' then in_char (len + 1) (i + 1) else normal (len + 1) (i + 1) and in_tag len i = if i = String.length txt then len else if txt.[i] = '>' then normal len (i + 1) else in_tag len (i + 1) and in_char len i = if i = String.length txt then len else if txt.[i] = ';' then normal len (i + 1) else in_char len (i + 1) in normal 0 0 ; value print_pre_center sz txt = do { for i = 1 to (sz - pre_text_size txt) / 2 do { Wserver.wprint " " }; Wserver.wprint "%s\n" txt; } ; value print_pre_left sz txt = let tsz = pre_text_size txt in do { if tsz < sz / 2 - 1 then for i = 2 to (sz / 2 - 1 - tsz) / 2 do { Wserver.wprint " " } else (); Wserver.wprint " %s\n" txt; } ; value print_pre_right sz txt = let tsz = pre_text_size txt in do { if tsz < sz / 2 - 1 then do { for i = 1 to sz / 2 do { Wserver.wprint " " }; for i = 1 to (sz / 2 - 1 - tsz) / 2 do { Wserver.wprint " " }; () } else for i = 1 to sz - pre_text_size txt - 1 do { Wserver.wprint " " }; Wserver.wprint " %s\n" txt; } ; value of_course_died conf p = match Adef.od_of_codate p.birth with [ Some (Dgreg d _) -> conf.today.year - d.year > 120 | _ -> False ] ; value relation_txt conf sex fam = let is = index_of_sex sex in match fam.relation with [ NotMarried -> ftransl_nth conf "relationship%t to" is | Married | NoSexesCheck -> ftransl_nth conf "married%t to" is | Engaged -> ftransl_nth conf "engaged%t to" is | NoMention -> let s = "%t " ^ transl conf "with" in valid_format "%t" s ] ; value escache_value conf = let bdir = base_path [] (conf.bname ^ ".gwb") in let s = try Unix.stat (Filename.concat bdir "patches") with [ Unix.Unix_error _ _ _ -> Unix.stat (Filename.concat bdir "base") ] in let v = int_of_float (mod_float s.Unix.st_mtime (float_of_int max_int)) in string_of_int v ; value adm_file f = List.fold_right Filename.concat [cnt_dir.val; "cnt"] f ; value std_date conf = let (hour, min, sec) = conf.time in Printf.sprintf "%04d-%02d-%02d %02d:%02d:%02d" conf.today.year conf.today.month conf.today.day hour min sec ; value read_wf_trace fname = match try Some (Secure.open_in fname) with [ Sys_error _ -> None ] with [ Some ic -> let r = ref [] in do { try while True do { r.val := [input_line ic :: r.val] } with [ End_of_file -> close_in ic ]; List.rev r.val } | None -> [] ] ; value write_wf_trace fname wt = let oc = Secure.open_out fname in do { List.iter (fun (dt, u) -> Printf.fprintf oc "%s %s\n" dt u) wt; close_out oc; } ; value update_wf_trace conf fname = let dt = std_date conf in let wt = let r = read_wf_trace fname in let dtlen = String.length dt in let rec loop found r = fun [ [x :: l] -> if String.length x > dtlen + 2 then let u = String.sub x (dtlen + 1) (String.length x - dtlen - 1) in if u = conf.user then loop True [(dt, u) :: r] l else loop found [(String.sub x 0 dtlen, u) :: r] l else loop found r l | [] -> if found then r else [(dt, conf.user) :: r] ] in loop False [] r in write_wf_trace fname (Sort.list \> wt) ; value commit_patches conf base = do { base.func.commit_patches (); conf.henv := List.map (fun (k, v) -> if k = "escache" then (k, escache_value conf) else (k, v)) conf.henv ; if conf.user <> "" then let wpf = try List.assoc "wizard_passwd_file" conf.base_env with [ Not_found -> "" ] in if wpf <> "" then let fname = adm_file (conf.bname ^ "_u.txt") in update_wf_trace conf fname else () else (); } ; (* List selection bullets *) value bullet_sel_txt = "o"; value bullet_unsel_txt = "+"; value bullet_nosel_txt = "o"; value print_selection_bullet conf = fun [ Some (txt, sel) -> let req = List.fold_left (fun req (k, v) -> if not sel && k = "u" && v = txt then req else let s = k ^ "=" ^ v in if req = "" then s else req ^ ";" ^ s) "" conf.env in do { Wserver.wprint "" txt; Wserver.wprint "" (commd conf) req (if sel then ";u=" ^ txt else "") (if sel || List.mem_assoc "u" conf.env then "#" ^ txt else ""); Wserver.wprint "%s" (if sel then bullet_sel_txt else bullet_unsel_txt); Wserver.wprint "\n"; } | None -> Wserver.wprint "%s\n" bullet_nosel_txt ] ; value unselected_bullets conf = List.fold_left (fun sl (k, v) -> try if k = "u" then [int_of_string v :: sl] else sl with [ Failure _ -> sl ]) [] conf.env ; value short_f_month m = match m with [ 1 -> "VD" | 2 -> "BR" | 3 -> "FM" | 4 -> "NI" | 5 -> "PL" | 6 -> "VT" | 7 -> "GE" | 8 -> "FL" | 9 -> "PR" | 10 -> "ME" | 11 -> "TH" | 12 -> "FT" | 13 -> "JC" | _ -> "" ] ;