]> matita.cs.unibo.it Git - helm.git/commitdiff
added http_getter OCaml implementation
authorStefano Zacchiroli <zack@upsilon.cc>
Wed, 25 Dec 2002 20:48:30 +0000 (20:48 +0000)
committerStefano Zacchiroli <zack@upsilon.cc>
Wed, 25 Dec 2002 20:48:30 +0000 (20:48 +0000)
19 files changed:
helm/http_getter/.cvsignore
helm/http_getter/.depend [new file with mode: 0644]
helm/http_getter/Makefile.in [deleted file]
helm/http_getter/http_getter.ml [new file with mode: 0644]
helm/http_getter/http_getter_cache.ml [new file with mode: 0644]
helm/http_getter/http_getter_cache.mli [new file with mode: 0644]
helm/http_getter/http_getter_common.ml [new file with mode: 0644]
helm/http_getter/http_getter_common.mli [new file with mode: 0644]
helm/http_getter/http_getter_const.ml [new file with mode: 0644]
helm/http_getter/http_getter_const.mli [new file with mode: 0644]
helm/http_getter/http_getter_env.ml [new file with mode: 0644]
helm/http_getter/http_getter_env.mli [new file with mode: 0644]
helm/http_getter/http_getter_map.ml [new file with mode: 0644]
helm/http_getter/http_getter_map.mli [new file with mode: 0644]
helm/http_getter/http_getter_misc.ml [new file with mode: 0644]
helm/http_getter/http_getter_misc.mli [new file with mode: 0644]
helm/http_getter/http_getter_types.ml [new file with mode: 0644]
helm/http_getter/threadSafe.ml [new file with mode: 0644]
helm/http_getter/threadSafe.mli [new file with mode: 0644]

index a29a8a1574a6409e11c27e1f31be3f5f6ab7f868..060f87336122af44562ecc7422fbac98ce69443e 100644 (file)
@@ -1 +1,9 @@
 Makefile configure config.log config.cache config.status http_getter.pl helm_http_getter.spec
+*.cmi
+*.cmo
+*.cma
+*.cmx
+*.o
+*.a
+http_getter
+http_getter.opt
diff --git a/helm/http_getter/.depend b/helm/http_getter/.depend
new file mode 100644 (file)
index 0000000..72e0220
--- /dev/null
@@ -0,0 +1,29 @@
+http_getter.cmo: http_getter_cache.cmi http_getter_common.cmi \
+    http_getter_const.cmi http_getter_env.cmi http_getter_map.cmi \
+    http_getter_misc.cmi http_getter_types.cmo 
+http_getter.cmx: http_getter_cache.cmx http_getter_common.cmx \
+    http_getter_const.cmx http_getter_env.cmx http_getter_map.cmx \
+    http_getter_misc.cmx http_getter_types.cmx 
+http_getter_cache.cmo: http_getter_common.cmi http_getter_env.cmi \
+    http_getter_types.cmo http_getter_cache.cmi 
+http_getter_cache.cmx: http_getter_common.cmx http_getter_env.cmx \
+    http_getter_types.cmx http_getter_cache.cmi 
+http_getter_common.cmo: http_getter_env.cmi http_getter_misc.cmi \
+    http_getter_types.cmo http_getter_common.cmi 
+http_getter_common.cmx: http_getter_env.cmx http_getter_misc.cmx \
+    http_getter_types.cmx http_getter_common.cmi 
+http_getter_const.cmo: http_getter_const.cmi 
+http_getter_const.cmx: http_getter_const.cmi 
+http_getter_env.cmo: http_getter_misc.cmi http_getter_types.cmo \
+    http_getter_env.cmi 
+http_getter_env.cmx: http_getter_misc.cmx http_getter_types.cmx \
+    http_getter_env.cmi 
+http_getter_map.cmo: threadSafe.cmi http_getter_map.cmi 
+http_getter_map.cmx: threadSafe.cmx http_getter_map.cmi 
+http_getter_misc.cmo: http_getter_misc.cmi 
+http_getter_misc.cmx: http_getter_misc.cmi 
+threadSafe.cmo: threadSafe.cmi 
+threadSafe.cmx: threadSafe.cmi 
+http_getter_cache.cmi: http_getter_types.cmo 
+http_getter_common.cmi: http_getter_types.cmo 
+http_getter_env.cmi: http_getter_types.cmo 
diff --git a/helm/http_getter/Makefile.in b/helm/http_getter/Makefile.in
deleted file mode 100644 (file)
index f4e6b59..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-INSTALL_DIR=@RESOLVED_EXEC_PREFIX@/bin
-CGI_DIR=@HELM_CGI_DIR@
-
-all:
-
-install: installgetter installcgi
-
-uninstall: uninstallcgi uninstallgetter
-
-installgetter:
-       cp http_getter.pl $(INSTALL_DIR)/
-
-installcgi:
-       for f in *.cgi; do \
-  if [ -f $$f ]; then \
-   cp -f $$f $(CGI_DIR)/; \
-  fi; \
- done
-
-uninstallgetter:
-       rm $(INSTALL_DIR)/http_getter.pl
-
-uninstallcgi:
-       for f in *.cgi; do \
-  rm -f $(CGI_DIR)/$$f; \
- done
-
-clean:
-
-distclean: clean
-       rm -f Makefile configure config.log config.cache config.status \
-         http_getter.pl *.spec
-
-dist:   clean
-       rm -rf ../@PACKAGE@-@VERSION@
-       mkdir ../@PACKAGE@-@VERSION@
-       cp -r * ../@PACKAGE@-@VERSION@
-       (cd .. ; tar cvfz @PACKAGE@-@VERSION@.tar.gz @PACKAGE@-@VERSION@ ; rm -rf @PACKAGE@-@VERSION@)
-
-.PHONY: all install distclean
-
diff --git a/helm/http_getter/http_getter.ml b/helm/http_getter/http_getter.ml
new file mode 100644 (file)
index 0000000..bb9c78e
--- /dev/null
@@ -0,0 +1,356 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+(* TODO optimization: precompile almost all regexp *)
+
+open Http_getter_common;;
+open Http_getter_types;;
+open Printf;;
+
+ (* debugging settings *)
+let debug = true;;
+let debug_print s = if debug then prerr_endline ("[HTTP-Getter] " ^ s);;
+let http_debug = false;;
+Http_common.debug := http_debug;;
+
+let http_get url =
+  debug_print ("Downloading URL: " ^ url);
+  try
+    Some (Http_client.Convenience.http_get url)
+  with Http_client.Http_error (code, _) ->
+    (debug_print
+      (sprintf "Failed to download %s, HTTP response was %d" url code);
+    None)
+;;
+
+let parse_format (req: Http_types.request) =
+  try
+    (match req#param "format" with
+    | "normal" -> Enc_normal
+    | "gz" -> Enc_gzipped
+    | s -> raise (Http_getter_bad_request ("Invalid format: " ^ s)))
+  with Http_types.Param_not_found _ -> Enc_normal
+;;
+let parse_patch_dtd (req: Http_types.request) =
+  try
+    (match req#param "patch_dtd" with
+    | s when String.lowercase s = "yes" -> true
+    | s when String.lowercase s = "no" -> false
+    | s -> raise (Http_getter_bad_request ("Invalid patch_dtd value: " ^ s)))
+  with Http_types.Param_not_found _ -> true
+;;
+let parse_ls_format (req: Http_types.request) =
+  match req#param "format" with
+  | s when String.lowercase s = "txt" -> Fmt_text
+  | s when String.lowercase s = "xml" -> Fmt_xml
+  | s -> raise (Http_getter_bad_request ("Invalid /ls format: " ^ s))
+;;
+let parse_ls_uri (req: Http_types.request) =
+  let baseuri = req#param "baseuri" in
+  let subs =
+    Pcre.extract ~pat:"^(\\w+):(.*)$" (Pcre.replace ~pat:"/+$"  baseuri)
+  in
+  match (subs.(1), subs.(2)) with
+  | "cic", uri -> Cic uri
+  | "theory", uri -> Theory uri
+  | _ -> raise (Http_getter_bad_request ("Invalid /ls baseuri: " ^ baseuri))
+;;
+
+let xml_map = new Http_getter_map.map Http_getter_env.xml_dbm in
+let rdf_map = new Http_getter_map.map Http_getter_env.rdf_dbm in
+let xsl_map = new Http_getter_map.map Http_getter_env.xsl_dbm in
+
+let resolve uri = (* use global maps *)
+  let map =
+    match uri with
+    | uri when is_xml_uri uri -> xml_map
+    | uri when is_rdf_uri uri -> rdf_map
+    | uri when is_xsl_uri uri -> xsl_map
+    | uri -> raise (Http_getter_unresolvable_URI uri)
+  in
+  map#resolve uri
+in
+let return_all_foo_uris map doctype filter outchan =
+  Http_daemon.send_basic_headers outchan;
+  Http_daemon.send_header "Content-Type" "text/xml" outchan;
+  Http_daemon.send_CRLF outchan;
+  output_string
+    outchan
+    (sprintf
+"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>
+<!DOCTYPE %s SYSTEM \"%s/getdtd?uri=%s.dtd\">;
+
+<%s>
+"
+      doctype
+      Http_getter_env.my_own_url
+      doctype
+      doctype);
+  map#iter
+    (fun uri _ ->
+      if filter uri then
+        output_string outchan (sprintf "\t<uri value=\"%s\" />\n" uri));
+  output_string outchan (sprintf "</%s>\n" doctype)
+in
+let return_all_uris = return_all_foo_uris xml_map "alluris" in
+let return_all_rdf_uris = return_all_foo_uris rdf_map "allrdfuris" in
+let return_ls =
+  let (++) (oldann, oldtypes, oldbody) (newann, newtypes, newbody) =
+    ((if newann   > oldann    then newann   else oldann),
+     (if newtypes > oldtypes  then newtypes else oldtypes),
+     (if newbody > oldbody    then newbody  else oldbody))
+   in
+  let basepartRE =
+    Pcre.regexp "^([^.]*\\.[^.]*)((\\.body)|(\\.types))?(\\.ann)?"
+  in
+  fun lsuri format outchan ->
+  let pat =
+    "^" ^ (match lsuri with Cic p -> ("cic:" ^ p) | Theory p -> ("theory:" ^ p))
+  in
+  let dirs = ref [] in
+  let objs = Hashtbl.create 17 in
+  xml_map#iter  (* BLEARGH Dbm module lacks support for fold-like functions *)
+    (fun _ -> function
+      | uri when Pcre.pmatch ~pat:(pat ^ "/") uri ->  (* directory hit *)
+          let dir =
+            List.hd (Pcre.split ~pat:"/" (Pcre.replace ~pat:(pat ^ "/") uri))
+          in
+          dirs := dir :: !dirs
+      | uri when Pcre.pmatch ~pat:(pat ^ "(\\.|$)") uri ->  (* object hit *)
+          let localpart = Pcre.replace ~pat:"^.*/" uri in
+          let basepart = Pcre.replace ~rex:basepartRE ~templ:"$1" localpart in
+          let oldflags =
+            try
+              Hashtbl.find objs basepart
+            with Not_found -> (false, No, No) (* no ann, no types no body *)
+          in
+          let newflags =
+            match localpart with
+            | s when Pcre.pmatch ~pat:"\\.types" s     -> (false, Yes, No)
+            | s when Pcre.pmatch ~pat:"\\.types.ann" s -> (true,  Ann, No)
+            | s when Pcre.pmatch ~pat:"\\.body" s      -> (false, No,  Yes)
+            | s when Pcre.pmatch ~pat:"\\.body.ann" s  -> (true,  No,  Ann)
+            | s ->
+                raise
+                  (Http_getter_internal_error ("Invalid /ls localpart: " ^ s))
+          in
+          Hashtbl.replace objs basepart (oldflags ++ newflags)
+      | _ -> () (* miss *));
+  match format with
+  | Fmt_text ->
+      let body =
+        "dir, " ^ (String.concat "\ndir, " (List.sort compare !dirs)) ^ "\n" ^
+        (Http_getter_misc.hashtbl_sorted_fold
+          (fun uri (annflag, typesflag, bodyflag) cont ->
+            sprintf
+              "%sobject, %s, <%s,%s,%s>\n"
+              cont uri (if annflag then "YES" else "NO")
+              (string_of_ls_flag typesflag) (string_of_ls_flag bodyflag))
+          objs "")
+      in Http_daemon.respond ~headers:["Content-Type", "text/txt"] ~body outchan
+  | Fmt_xml ->
+      let body =
+        sprintf
+"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>
+<!DOCTYPE ls SYSTEM \"%s/getdtd?uri=ls.dtd\"
+
+<ls>
+%s
+</ls>
+"
+          Http_getter_env.my_own_url
+          ("\n" ^
+          (String.concat
+            "\n"
+            (List.map
+              (fun d -> "<section>" ^ d ^ "</section>")
+              (List.sort compare !dirs))) ^ "\n" ^
+          (Http_getter_misc.hashtbl_sorted_fold
+            (fun uri (annflag, typesflag, bodyflag) cont ->
+              sprintf
+"%s<object name=\"%s\">
+\t<ann value=\"%s\">
+\t<types value=\"%s\">
+\t<body value=\"%s\">
+</object>
+"
+                cont uri (if annflag then "YES" else "NO")
+                (string_of_ls_flag typesflag)
+                (string_of_ls_flag bodyflag))
+            objs ""))
+      in Http_daemon.respond ~headers:["Content-Type", "text/xml"] ~body outchan
+in
+let update_from_server logmsg server_url = (* use global maps *)
+  let xml_url_of_uri = function
+      (* TODO missing sanity checks on server_url, e.g. it can contains $1 *)
+    | uri when (Pcre.pmatch ~pat:"^cic://" uri) ->
+        Pcre.replace ~pat:"^cic://" ~templ:server_url uri
+    | uri when (Pcre.pmatch ~pat:"^theory://" uri) ->
+        Pcre.replace ~pat:"^theory://" ~templ:server_url uri
+    | uri -> raise (Http_getter_invalid_URI uri)
+  in
+  let rdf_url_of_uri = function (* TODO as above *)
+    | uri when (Pcre.pmatch ~pat:"^helm:rdf.*//cic:" uri) ->
+        Pcre.replace ~pat:"^helm:rdf.*//cic:" ~templ:server_url uri
+    | uri when (Pcre.pmatch ~pat:"^helm:rdf.*//theory:" uri) ->
+        Pcre.replace ~pat:"^helm:rdf.*//theory:" ~templ:server_url uri
+    | uri -> raise (Http_getter_invalid_URI uri)
+  in
+  let log = ref ("Processing server: " ^ server_url ^ "<br />\n") in
+  let (xml_index, rdf_index, xsl_index) =
+    (* TODO keeps index in memory, is better to keep them on temp files? *)
+    (http_get (server_url ^ "/" ^ Http_getter_env.xml_index),
+     http_get (server_url ^ "/" ^ Http_getter_env.rdf_index),
+     http_get (server_url ^ "/" ^ Http_getter_env.xsl_index))
+  in
+  if (xml_index = None && rdf_index = None && xsl_index = None) then
+    debug_print (sprintf "Warning: useless server %s" server_url);
+  (match xml_index with
+  | Some xml_index ->
+      (log := !log ^ "Updating XML db ...<br />\n";
+      List.iter
+        (fun l ->
+          try
+            (match Pcre.split ~pat:"[ \\t]+" l with
+            | [uri; "gz"] -> xml_map#add uri ((xml_url_of_uri uri) ^ ".xml.gz")
+            | [uri] -> xml_map#add uri ((xml_url_of_uri uri) ^ ".xml")
+            | _ -> log := !log ^ "Ignoring invalid line: " ^ l ^ "<br />\n")
+          with Http_getter_invalid_URI uri ->
+            log := !log ^ "Ignoring invalid XML URI: " ^ uri)
+        (Pcre.split ~pat:"\n+" xml_index)) (* xml_index lines *)
+  | None -> ());
+  (match rdf_index with
+  | Some rdf_index ->
+      (log := !log ^ "Updating RDF db ...<br />\n";
+      List.iter
+        (fun l ->
+          try
+            (match Pcre.split ~pat:"[ \\t]+" l with
+            | [uri; "gz"] -> rdf_map#add uri ((rdf_url_of_uri uri) ^ ".xml.gz")
+            | [uri] -> rdf_map#add uri ((rdf_url_of_uri uri) ^ ".xml")
+            | _ -> log := !log ^ "Ignoring invalid line: " ^ l ^ "<br />\n")
+          with Http_getter_invalid_URI uri ->
+            log := !log ^ "Ignoring invalid RDF URI: " ^ uri)
+        (Pcre.split ~pat:"\n+" rdf_index)) (* rdf_index lines *)
+  | None -> ());
+  (match xsl_index with
+  | Some xsl_index ->
+      (log := !log ^ "Updating XSLT db ...<br />\n";
+      List.iter
+        (fun l -> xsl_map#add l (server_url ^ "/" ^ l))
+        (Pcre.split ~pat:"\n+" xsl_index);
+      log := !log ^ "All done!<br />\n")
+  | None -> ());
+  !log
+in
+
+  (* thread action *)
+let callback (req: Http_types.request) outchan =
+  try
+    debug_print ("Connection from " ^ req#clientAddr);
+    debug_print ("Received request: " ^ req#path);
+    (match req#path with
+    | "/help" -> return_html_msg Http_getter_const.usage_string outchan
+    | "/getxml" | "/getxslt" | "/getdtd" | "/resolve" | "/register" ->
+        (let uri = req#param "uri" in  (* common parameter *)
+        match req#path with
+        | "/getxml" ->
+            let enc = parse_format req in
+            let patch_dtd = parse_patch_dtd req in
+            Http_getter_cache.respond_xml
+              ~url:(resolve uri) ~uri ~enc ~patch_dtd outchan
+        | "/getxslt" ->
+(*             let patch_dtd = parse_patch_dtd req in *)
+            (* TODO add support and default value for patch_dtd *)
+            Http_getter_cache.respond_xsl ~url:(resolve uri) outchan
+        | "/getdtd" ->
+            let patch_dtd = parse_patch_dtd req in
+            Http_getter_cache.respond_dtd
+              ~patch_dtd ~url:(Http_getter_env.dtd_dir ^ "/" ^ uri) outchan
+        | "/resolve" ->
+            (try
+              return_xml_msg
+                (sprintf "<url value=\"%s\" />\n" (resolve uri))
+                outchan
+            with Http_getter_unresolvable_URI uri ->
+              return_xml_msg "<unresolved />\n" outchan)
+        | "/register" ->
+            let url = req#param "url" in
+            xml_map#add uri url;
+            return_html_msg "Register done" outchan
+        | _ -> assert false)
+    | "/update" ->
+        (xml_map#clear; rdf_map#clear; xsl_map#clear;
+        let log =
+          List.fold_left
+            update_from_server
+            ""  (* initial logmsg: empty *)
+              (* reverse order: 1st server is the most important one *)
+            (List.rev Http_getter_env.servers)
+        in
+        return_html_msg log outchan)
+    | "/getalluris" ->
+        return_all_uris
+          (fun uri ->
+            (Pcre.pmatch ~pat:"^cic:" uri) &&
+            not (Pcre.pmatch ~pat:"\\.types$" uri))
+          outchan
+    | "/getallrdfuris" ->
+        (let classs = req#param "class" in
+        try
+          let filter =
+            let base = "^helm:rdf:www\\.cs\\.unibo\\.it/helm/rdf/" in
+            match classs with
+            | ("forward" as c) | ("backward" as c) ->
+                (fun uri -> Pcre.pmatch ~pat:(base ^ c) uri)
+            | c -> raise (Http_getter_invalid_RDF_class c)
+          in
+          return_all_rdf_uris filter outchan
+        with Http_getter_invalid_RDF_class c ->
+          raise (Http_getter_bad_request ("Invalid RDF class: " ^ c)))
+    | "/ls" -> return_ls (parse_ls_uri req) (parse_ls_format req) outchan
+    | "/getempty" ->
+        Http_daemon.respond ~body:Http_getter_const.empty_xml outchan
+    | invalid_request ->
+        Http_daemon.respond_error ~status:(`Client_error `Bad_request) outchan)
+  with
+  | Http_types.Param_not_found attr_name ->
+      return_400 (sprintf "Parameter '%s' is missing" attr_name) outchan
+  | Http_getter_bad_request msg -> return_html_error msg outchan
+  | Http_getter_internal_error msg -> return_html_internal_error msg outchan
+  | exc ->
+      return_html_error
+        ("Uncaught exception: " ^ (Printexc.to_string exc))
+        outchan
+in
+
+  (* daemon initialization *)
+Http_getter_env.dump_env ();
+flush stdout;
+Unix.putenv "http_proxy" "";
+Http_daemon.start'
+  ~timeout:None ~port:Http_getter_env.port ~mode:`Thread callback
+
diff --git a/helm/http_getter/http_getter_cache.ml b/helm/http_getter/http_getter_cache.ml
new file mode 100644 (file)
index 0000000..6d2fe6e
--- /dev/null
@@ -0,0 +1,118 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+open Http_getter_common;;
+open Http_getter_types;;
+open Printf;;
+
+let resource_type_of_url = function
+  | url when Pcre.pmatch ~pat:"\\.xml\\.gz$" url -> Enc_gzipped
+  | url when Pcre.pmatch ~pat:"\\.xml$" url -> Enc_normal
+  | url -> raise (Http_getter_invalid_URL url)
+let extension_of_resource_type = function
+  | Enc_normal -> "xml"
+  | Enc_gzipped -> "xml.gz"
+
+  (* basename = resource name without trailing ".gz", if any *)
+let is_in_cache basename =
+  Sys.file_exists
+    (match Http_getter_env.cache_mode with
+    | Enc_normal -> basename
+    | Enc_gzipped -> basename ^ ".gz")
+
+let respond_xml ?(enc = Enc_normal) ?(patch_dtd = true) ~url ~uri outchan =
+  let resource_type = resource_type_of_url url in
+  let extension = extension_of_resource_type resource_type in
+  let downloadname =
+    match http_getter_uri_of_string uri with
+    | Xml_uri (Cic baseuri) | Xml_uri (Theory baseuri) ->
+          (* assumption: baseuri starts with "/" *)
+        sprintf "%s%s.%s" Http_getter_env.xml_dir baseuri extension
+    | Rdf_uri (prefix, ((Cic baseuri) as qbaseuri))
+    | Rdf_uri (prefix, ((Theory baseuri) as qbaseuri)) ->
+        let escaped_prefix =
+          (Pcre.replace ~pat:"/" ~templ:"_"
+            (Pcre.replace ~pat:"_" ~templ:"__"
+              (prefix ^
+              (match qbaseuri with
+              | Cic _ -> "//cic:"
+              | Theory _ -> "//theory:"))))
+        in
+        sprintf "%s/%s%s.%s"
+          Http_getter_env.rdf_dir escaped_prefix baseuri extension
+  in
+  let patch_fun =
+    if patch_dtd then Http_getter_common.patch_xml else (fun x -> x)
+  in
+  let basename = Pcre.replace ~pat:"\\.gz$" downloadname in
+  if not (is_in_cache basename) then begin (* download and fill cache *)
+    wget ~output:downloadname url;
+    match (resource_type, Http_getter_env.cache_mode) with
+    | Enc_normal, Enc_normal ->
+        (if enc = Enc_gzipped then gzip ~keep:true downloadname)
+    | Enc_gzipped, Enc_gzipped ->
+        (if enc = Enc_normal then gunzip ~keep:true downloadname)
+    | Enc_normal, Enc_gzipped -> gzip ~keep:(enc = Enc_normal) downloadname
+    | Enc_gzipped, Enc_normal -> gunzip ~keep:(enc = Enc_gzipped) downloadname
+  end else begin  (* resource already in cache *)
+    match (enc, Http_getter_env.cache_mode) with
+    | Enc_normal, Enc_normal | Enc_gzipped, Enc_gzipped -> ()
+    | Enc_normal, Enc_gzipped -> gunzip ~keep:true (basename ^ ".gz")
+    | Enc_gzipped, Enc_normal -> gzip ~keep:true basename
+  end;  (* now resource is in cache *)
+  (* invariant: file to be sent back to client is available on disk in the
+  format the client likes *)
+  (match enc with  (* send file to client *)
+  | Enc_normal ->
+      return_file ~fname:basename ~contype:"text/xml" ~patch_fun outchan
+  | Enc_gzipped ->
+      return_file
+        ~fname:(basename ^ ".gz") ~contype:"text/xml"  ~contenc:"x-gzip"
+        ~patch_fun outchan);
+  match (enc, Http_getter_env.cache_mode) with  (* remove temp files *)
+  | Enc_normal, Enc_normal | Enc_gzipped, Enc_gzipped -> ()
+  | Enc_normal, Enc_gzipped -> Sys.remove basename
+  | Enc_gzipped, Enc_normal -> Sys.remove (basename ^ ".gz")
+
+  (* TODO enc is not yet supported *)
+let respond_xsl ?(enc = Enc_normal) ?(patch_dtd = true) ~url outchan =
+  let patch_fun =
+    if patch_dtd then Http_getter_common.patch_xsl else (fun x -> x)
+  in
+  let fname = tempfile () in
+  wget ~output:fname url;
+  return_file ~fname ~contype:"text/xml" ~patch_fun outchan;
+  Sys.remove fname
+
+  (* TODO patch_dtd and format are fooish, implement them! *)
+let respond_dtd ?(enc = Enc_normal) ?(patch_dtd = true) ~url outchan =
+    if Sys.file_exists url then
+      return_file
+        ~fname:url ~contype:"text/xml" ~patch_fun:Http_getter_common.patch_dtd
+        outchan
+    else
+      return_html_error ("Can't find DTD: " ^ url) outchan
+
diff --git a/helm/http_getter/http_getter_cache.mli b/helm/http_getter/http_getter_cache.mli
new file mode 100644 (file)
index 0000000..d4deb67
--- /dev/null
@@ -0,0 +1,43 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+open Http_getter_types;;
+
+val respond_xml:
+  ?enc:http_getter_encoding -> ?patch_dtd:bool -> url:string -> uri:string ->
+  out_channel ->
+    unit
+
+val respond_xsl:
+  ?enc:http_getter_encoding -> ?patch_dtd:bool -> url:string ->
+  out_channel ->
+    unit
+
+val respond_dtd:
+  ?enc:http_getter_encoding -> ?patch_dtd:bool -> url:string ->
+  out_channel ->
+    unit
+
diff --git a/helm/http_getter/http_getter_common.ml b/helm/http_getter/http_getter_common.ml
new file mode 100644 (file)
index 0000000..67d72f4
--- /dev/null
@@ -0,0 +1,158 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+open Http_getter_types;;
+open Printf;;
+
+let string_of_ls_flag = function No -> "NO" | Yes -> "YES" | Ann -> "ANN"
+let string_of_encoding = function
+  | Enc_normal -> "Normal"
+  | Enc_gzipped -> "GZipped"
+
+let is_cic_uri uri = Pcre.pmatch ~pat:"^cic:" uri
+let is_theory_uri uri = Pcre.pmatch ~pat:"^theory:" uri
+let is_xml_uri uri = is_cic_uri uri || is_theory_uri uri
+let is_rdf_uri uri = Pcre.pmatch ~pat:"^helm:rdf(.*):(.*)//(.*)" uri
+let is_xsl_uri uri = Pcre.pmatch ~pat:"^\\w+\\.xsl" uri
+
+let rec http_getter_uri_of_string = function
+  | uri when is_rdf_uri uri ->
+      (match Pcre.split ~pat:"//" uri with
+      | [ prefix; uri ] ->
+          let rest =
+            match http_getter_uri_of_string uri with
+            | Xml_uri xmluri -> xmluri
+            | _ -> raise (Http_getter_invalid_URI uri)
+          in
+          Rdf_uri (prefix, rest)
+      | _ -> raise (Http_getter_invalid_URI uri))
+  | uri when is_cic_uri uri -> Xml_uri (Cic (Pcre.replace ~pat:"^cic:" uri))
+  | uri when is_theory_uri uri ->
+      Xml_uri (Theory (Pcre.replace ~pat:"^theory:" uri))
+  | uri -> raise (Http_getter_invalid_URI uri)
+
+let patch_xml line =
+  Pcre.replace
+    ~pat:(sprintf "DOCTYPE (.*) SYSTEM\\s+\"%s/" Http_getter_env.dtd_base_url)
+    ~templ:(
+      sprintf "DOCTYPE $1 SYSTEM \"%s/getdtd?uri=" Http_getter_env.my_own_url)
+    line
+let patch_xsl =
+  let mk_patch_fun tag line =
+    Pcre.replace
+      ~pat:(sprintf "%s\\s+href=\"" tag)
+      ~templ:(
+        sprintf "%s href=\"%s/getxslt?uri=" Http_getter_env.my_own_url tag)
+      line
+  in
+  let (patch_import, patch_include) =
+    (mk_patch_fun "xsl:import", mk_patch_fun "xsl:include")
+  in
+  fun line -> patch_include (patch_import line)
+let patch_dtd line =
+  Pcre.replace
+    ~pat:"ENTITY (.*) SYSTEM\\s+\""
+    ~templ:(
+      sprintf "ENTITY $1 SYSTEM \"%s/getdtd?uri=" Http_getter_env.my_own_url)
+    line
+
+let pp_error =
+  sprintf "<html><body><h1>Http Getter error: %s</h1></body></html>"
+let pp_internal_error =
+  sprintf "<html><body><h1>Http Getter Internal error: %s</h1></body></html>"
+let pp_msg = sprintf "<html><body><h1>%s</h1></body></html>"
+
+let mk_return_fun pp_fun contype msg outchan =
+  Http_daemon.respond
+    ~body:(pp_fun msg)
+    ~headers:["Content-Type", contype]
+    outchan
+
+let return_html_error = mk_return_fun pp_error "text/html"
+let return_html_internal_error = mk_return_fun pp_internal_error "text/html"
+let return_html_msg = mk_return_fun pp_msg "text/html"
+let return_xml_msg = mk_return_fun pp_msg "text/xml"
+  (**
+  @param fname name of the file to be sent
+  @param contype Content-Type header value
+  @param contenc Content-Enconding header value
+  @param patch_fun function used to patch file contents
+  @param outchan output channel over which sent file fname *)
+let return_file ~fname ?contype ?contenc ?(patch_fun = fun x -> x) outchan =
+  let headers =
+    match (contype, contenc) with
+    | (Some t, Some e) -> [ "Content-Type", t; "Content-Enconding", e ]
+    | (Some t, None) -> [ "Content-Type" , t ]
+    | (None, Some e) -> [ "Content-Enconding", e ]
+    | (None, None) -> []
+  in
+  Http_daemon.send_basic_headers outchan;
+  Http_daemon.send_headers headers outchan;
+  Http_daemon.send_CRLF outchan;
+  Http_getter_misc.iter_file
+    (fun line -> output_string outchan (patch_fun line ^ "\n"))
+    fname
+ (* return a bad request http response *)
+let return_400 body outchan = Http_daemon.respond_error ~code:400 ~body outchan
+
+let wget ?output url =
+  let flags =
+    (match output with Some file -> ["-O " ^ file] | None -> []) @ [url]
+  in
+  Shell.call
+    ~stdout:Shell.to_dev_null ~stderr:Shell.to_dev_null [Shell.cmd "wget" flags]
+
+  (* TODO gzip and gunzip create executables file, but umask seems to be
+  correctly inherited from the shell .... boh *)
+
+  (* stderr shown as usual *)
+let gzip ?(keep = false) fname =
+  if keep then  (* keep original file *)
+    Shell.call
+      ~stdout:(Shell.to_file (fname ^ ".gz"))
+      [Shell.cmd "gzip" ["-f"; "-c"; fname]]
+  else  (* don't keep original file *)
+    Shell.call [Shell.cmd "gzip" ["-f"; fname]]
+
+  (* stderr shown as usual *)
+let gunzip ?(keep = false) fname =
+  if not (Pcre.pmatch ~pat:"\\.gz$" fname) then
+    failwith "gunzip: source file doesn't end with '.gz'";
+  let basename = Pcre.replace ~pat:"\\.gz$" fname in
+  if keep then  (* keep original file *)
+    Shell.call
+      ~stdout:(Shell.to_file basename)
+      [Shell.cmd "gunzip" ["-f"; "-c"; fname]]
+  else  (* don't keep original file *)
+    Shell.call [Shell.cmd "gunzip" ["-f"; fname]]
+
+let tempfile () =
+  let buf = Buffer.create 28 in (* strlen("/tmp/fileSzb3Mw_http_getter") *)
+  Shell.call
+    ~stdout:(Shell.to_buffer buf)
+    [Shell.cmd "tempfile" ["--suffix=_http_getter"]];
+  Pcre.replace ~pat:"\n" (Buffer.contents buf)
+
diff --git a/helm/http_getter/http_getter_common.mli b/helm/http_getter/http_getter_common.mli
new file mode 100644 (file)
index 0000000..323c71d
--- /dev/null
@@ -0,0 +1,57 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+open Http_getter_types;;
+
+val string_of_ls_flag: http_getter_ls_flag -> string
+val string_of_encoding: http_getter_encoding -> string
+
+val is_xml_uri: string -> bool
+val is_rdf_uri: string -> bool
+val is_xsl_uri: string -> bool
+
+val http_getter_uri_of_string: string -> http_getter_uri
+
+val patch_xml : string -> string
+val patch_xsl : string -> string
+val patch_dtd : string -> string
+
+val return_html_error: string -> out_channel -> unit
+val return_html_internal_error: string -> out_channel -> unit
+val return_html_msg: string -> out_channel -> unit
+val return_xml_msg: string -> out_channel -> unit
+val return_400: string -> out_channel -> unit
+val return_file:
+  fname:string ->
+  ?contype:string -> ?contenc:string -> ?patch_fun:(string -> string) ->
+  out_channel ->
+    unit
+
+val wget: ?output: string -> string -> unit
+val gzip: ?keep: bool -> string -> unit
+val gunzip: ?keep: bool -> string -> unit
+val tempfile: unit -> string
+
diff --git a/helm/http_getter/http_getter_const.ml b/helm/http_getter/http_getter_const.ml
new file mode 100644 (file)
index 0000000..93c2d5d
--- /dev/null
@@ -0,0 +1,86 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+  (* TODO *)
+let usage_string =
+"
+<html>
+  <head>
+    <title>HTTP Getter's help message</title>
+  </head>
+  <body>
+    <p>
+    Usage: <kbd>http://hostname:getterport/</kbd><em>command</em>
+    </p>
+    <p>
+    Available commands:
+    </p>
+    <p>
+      <b><kbd>help</kbd></b><br />
+      display this help message
+    </p>
+    <p>
+      <b><kbd>getxml?uri=URI[&format=(normal|gz)][&patch_dtd=(yes|no)]</kbd></b><br />
+    </p>
+    <p>
+      <b><kbd>register?uri=URI&url=URL</kbd></b><br />
+    </p>
+    <p>
+      <b><kbd>resolve?uri=URI</kbd></b><br />
+    </p>
+    <p>
+      <b><kbd>getdtd?uri=URI[&patch_dtd=(yes|no)]</kbd></b><br />
+    </p>
+    <p>
+      <b><kbd>getxslt?uri=URI[&patch_dtd=(yes|no)]</kbd></b><br />
+    </p>
+    <p>
+      <b><kbd>update</kbd></b><br />
+    </p>
+    <p>
+      <b><kbd>getalluris</kbd></b><br />
+    </p>
+    <p>
+      <b><kbd>getallrdfuris</kbd></b><br />
+    </p>
+    <p>
+      <b><kbd>ls?baseuri=URI&format=(txt|xml)</kbd></b><br />
+    </p>
+    <p>
+      <b><kbd>getempty</kbd></b><br />
+    </p>
+  </body>
+</html>
+"
+
+let empty_xml =
+"<?xml version=\"1.0\"?>
+<!DOCTYPE empty [
+  <!ELEMENT empty EMPTY>
+]>
+<empty />
+"
+
diff --git a/helm/http_getter/http_getter_const.mli b/helm/http_getter/http_getter_const.mli
new file mode 100644 (file)
index 0000000..7f75002
--- /dev/null
@@ -0,0 +1,28 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+val usage_string: string
+val empty_xml: string
diff --git a/helm/http_getter/http_getter_env.ml b/helm/http_getter/http_getter_env.ml
new file mode 100644 (file)
index 0000000..377d305
--- /dev/null
@@ -0,0 +1,143 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+open Http_getter_types;;
+open Printf;;
+open Pxp_document;;
+open Pxp_types;;
+open Pxp_yacc;;
+
+type setting_src =
+  | Environment (* read setting from environment variables *)
+  | Conffile    (* read setting from configuration file *)
+  | Both        (* read setting from both; environment override config file *)
+
+let conf_file_tree = ref None
+
+let (conf_file, conf_dir) =
+  try
+    let conf_dir =
+      Pcre.replace ~pat:"/$" (Sys.getenv "HELM_CONFIGURATION_DIR")
+    in
+    (conf_dir ^ "/configuration.xml", conf_dir)
+  with Not_found -> failwith "HELM_CONFIGURATION_DIR undefined"
+
+let safe_getenv ?(from = Both) var =
+  (let rec read_from_file () =
+    (match !conf_file_tree with
+    | None ->
+        conf_file_tree :=
+          Some
+            (parse_wfcontent_entity
+              default_config (from_file conf_file) default_spec);
+        read_from_file ()
+    | Some t ->
+        (try
+          Some (find_element (String.lowercase var) t)#data
+        with Not_found -> None))
+  in
+  let read_from_env () = try Some (Sys.getenv var) with Not_found -> None in
+  let return_value name = function
+    | Some v -> v
+    | None -> failwith ("Setting " ^ name ^ " is not defined")
+  in
+  (match from with
+  | Environment -> return_value var (read_from_env ())
+  | Conffile -> return_value var (read_from_file ())
+  | Both ->
+      (match read_from_env () with
+      | None -> return_value var (read_from_file ())
+      | v -> return_value var v)))
+
+let servers_file = safe_getenv "HTTP_GETTER_SERVERS_FILE"
+let servers =
+  let cons hd tl = hd @ [ tl ] in
+  Http_getter_misc.fold_file cons [] servers_file
+
+let xml_dbm = safe_getenv "HTTP_GETTER_XML_DBM"
+let rdf_dbm = safe_getenv "HTTP_GETTER_RDF_DBM"
+let xsl_dbm = safe_getenv "HTTP_GETTER_XSL_DBM"
+let xml_index = safe_getenv "HTTP_GETTER_XML_INDEXNAME"
+let rdf_index = safe_getenv "HTTP_GETTER_RDF_INDEXNAME"
+let xsl_index = safe_getenv "HTTP_GETTER_XSL_INDEXNAME"
+let xml_dir = safe_getenv "HTTP_GETTER_XML_DIR"
+let rdf_dir = safe_getenv "HTTP_GETTER_RDF_DIR"
+let xsl_dir = safe_getenv "HTTP_GETTER_XSL_DIR"
+let dtd_dir = safe_getenv "HTTP_GETTER_DTD_DIR"
+
+let port =
+  let port = safe_getenv "HTTP_GETTER_PORT" in
+  try
+    int_of_string port
+  with Failure "int_of_string" ->
+    failwith ("Invalid port value: " ^ port)
+let host =
+  let buf = Buffer.create 20 in
+  Shell.call ~stdout:(Shell.to_buffer buf) [Shell.cmd "hostname" ["-f"]];
+  Pcre.replace ~pat:"\n+$" (Buffer.contents buf)
+let my_own_url =
+  sprintf
+    "http://%s%s/"
+    host
+    (if port = 80 then "" else (sprintf ":%d" port))
+let dtd_base_url = safe_getenv "HTTP_GETTER_DTD_BASE_URL"
+
+let cache_mode =
+  match String.lowercase (safe_getenv "HTTP_GETTER_CACHE_MODE") with
+  | "normal" -> Enc_normal
+  | "gz" -> Enc_gzipped
+  | mode -> failwith ("Invalid cache mode: " ^ mode)
+
+let dump_env () =
+  printf
+"xml_dbm:\t%s
+rdf_dbm:\t%s
+xsl_dbm:\t%s
+xml_index:\t%s
+rdf_index:\t%s
+xsl_index:\t%s
+xml_dir:\t%s
+rdf_dir:\t%s
+xsl_dir:\t%s
+dtd_dir:\t%s
+servers_file:\t%s
+host:\t\t%s
+port:\t\t%d
+my_own_url:\t%s
+dtd_base_url:\t%s
+cache_mode:\t%s
+conf_file:\t%s
+conf_dir:\t%s
+servers:
+\t%s
+"
+    xml_dbm rdf_dbm xsl_dbm xml_index rdf_index xsl_index
+    xml_dir rdf_dir xsl_dir dtd_dir servers_file host port
+    my_own_url dtd_base_url
+    (match cache_mode with Enc_normal -> "Normal" | Enc_gzipped -> "GZipped")
+    conf_file conf_dir (String.concat "\n\t" servers);
+  flush stdout
+
diff --git a/helm/http_getter/http_getter_env.mli b/helm/http_getter/http_getter_env.mli
new file mode 100644 (file)
index 0000000..e47cc3d
--- /dev/null
@@ -0,0 +1,58 @@
+(*
+  *  Copyright (C) 2000, HELM Team.
+  *
+  *  This file is part of HELM, an Hypertextual, Electronic
+  *  Library of Mathematics, developed at the Computer Science
+  *  Department, University of Bologna, Italy.
+  *
+  *  HELM is free software; you can redistribute it and/or
+  *  modify it under the terms of the GNU General Public License
+  *  as published by the Free Software Foundation; either version 2
+  *  of the License, or (at your option) any later version.
+  *
+  *  HELM is distributed in the hope that it will be useful,
+  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  *  GNU General Public License for more details.
+  *
+  *  You should have received a copy of the GNU General Public License
+  *  along with HELM; if not, write to the Free Software
+  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+  *  MA  02111-1307, USA.
+  *
+  *  For details, see the HELM World-Wide-Web page,
+  *  http://cs.unibo.it/helm/.
+  *)
+
+  open Http_getter_types;;
+
+  (* environment gathered data *)
+
+  val xml_dbm       : string        (* XML map DBM file *)
+  val rdf_dbm       : string        (* RDF map DBM file *)
+  val xsl_dbm       : string        (* XSL map DBM file *)
+  val xml_index     : string        (* XMLs' index *)
+  val rdf_index     : string        (* RDFs' index *)
+  val xsl_index     : string        (* XSLTs' index *)
+  val xml_dir       : string        (* XMLs' directory *)
+  val rdf_dir       : string        (* RDFs' directory *)
+  val xsl_dir       : string        (* XSLs' directory *)
+  val dtd_dir       : string        (* DTDs' root directory *)
+  val servers_file  : string        (* servers.txt file *)
+  val port          : int           (* port on which getter listens *)
+  val dtd_base_url  : string        (* base URL for DTD downloading *)
+
+  (* derived data *)
+
+  val host          : string        (* host on which getter listens *)
+  val my_own_url    : string        (* URL at which contact getter *)
+  val servers       : string list   (* servers list (i.e. servers_file lines) *)
+  val cache_mode    : http_getter_encoding  (* cached files encoding *)
+  val conf_file     : string        (* configuration file's full path *)
+  val conf_dir      : string        (* directory where conf_file resides *)
+
+  (* misc *)
+
+val dump_env : unit -> unit       (* dump a textual representation of the
+                                  current http_getter settings *)
+
diff --git a/helm/http_getter/http_getter_map.ml b/helm/http_getter/http_getter_map.ml
new file mode 100644 (file)
index 0000000..9ee8761
--- /dev/null
@@ -0,0 +1,69 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+exception Key_already_in of string;;
+exception Key_not_found of string;;
+
+class map dbname =
+  let perm = 420 in (* permission 644 in decimal notation *)
+  let db = Dbm.opendbm dbname [ Dbm.Dbm_rdwr; Dbm.Dbm_create ] perm in
+  object (self)
+
+    inherit ThreadSafe.threadSafe
+
+    initializer Gc.finalise Dbm.close db  (* close db on GC *)
+
+    method add key value =
+      self#doWriter (lazy (
+        try
+          Dbm.add db key value
+        with Dbm.Dbm_error "Entry already exists" -> raise (Key_already_in key)
+      ))
+
+    method remove key =
+      self#doWriter (lazy (
+        try
+          Dbm.remove db key
+        with Dbm.Dbm_error "dbm_delete" -> raise (Key_not_found key)
+      ))
+
+    method resolve key =
+      self#doReader (lazy (
+        try Dbm.find db key with Not_found -> raise (Key_not_found key)
+      ))
+
+    method iter (f: string -> string -> unit) =
+      self#doReader (lazy (
+        Dbm.iter f db
+      ))
+
+    method clear =
+      self#doWriter (lazy (
+        Dbm.iter (fun k _ -> Dbm.remove db k) db
+      ))
+
+  end
+
diff --git a/helm/http_getter/http_getter_map.mli b/helm/http_getter/http_getter_map.mli
new file mode 100644 (file)
index 0000000..d3402ee
--- /dev/null
@@ -0,0 +1,38 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+exception Key_already_in of string
+exception Key_not_found of string
+
+class map:
+  string ->
+    object
+      method add: string -> string -> unit
+      method remove: string -> unit
+      method resolve: string -> string
+      method iter: (string -> string -> unit) -> unit
+      method clear: unit
+    end
diff --git a/helm/http_getter/http_getter_misc.ml b/helm/http_getter/http_getter_misc.ml
new file mode 100644 (file)
index 0000000..d40fbf4
--- /dev/null
@@ -0,0 +1,45 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+let fold_file f init fname =
+  let inchan = open_in fname in
+  let rec fold_lines' value =
+    try 
+      let line = input_line inchan in 
+      fold_lines' (f value line)
+    with End_of_file -> value
+  in
+  let res = (try fold_lines' init with e -> (close_in inchan; raise e)) in
+  close_in inchan;
+  res
+let iter_file f = fold_file (fun _ line -> f line) ()
+
+let hashtbl_sorted_fold f tbl init =
+  let sorted_keys =
+    List.sort compare (Hashtbl.fold (fun key _ keys -> key::keys) tbl [])
+  in
+  List.fold_left (fun acc k -> f k (Hashtbl.find tbl k) acc) init sorted_keys
+
diff --git a/helm/http_getter/http_getter_misc.mli b/helm/http_getter/http_getter_misc.mli
new file mode 100644 (file)
index 0000000..c1afb19
--- /dev/null
@@ -0,0 +1,33 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+val fold_file : ('a -> string -> 'a) -> 'a -> string -> 'a
+val iter_file : (string -> unit) -> string -> unit
+
+  (** like Hashtbl.fold but keys are processed ordered *)
+val hashtbl_sorted_fold :
+  ('a -> 'b -> 'c -> 'c) -> ('a, 'b) Hashtbl.t -> 'c -> 'c
+
diff --git a/helm/http_getter/http_getter_types.ml b/helm/http_getter/http_getter_types.ml
new file mode 100644 (file)
index 0000000..96977b6
--- /dev/null
@@ -0,0 +1,45 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+exception Http_getter_bad_request of string
+exception Http_getter_unresolvable_URI of string
+exception Http_getter_invalid_URI of string
+exception Http_getter_invalid_URL of string
+exception Http_getter_invalid_RDF_class of string
+exception Http_getter_internal_error of string
+
+type http_getter_encoding = Enc_normal | Enc_gzipped
+type http_getter_answer_format = Fmt_text | Fmt_xml
+type http_getter_ls_flag = No | Yes | Ann
+
+type http_getter_xml_uri =
+  | Cic of string
+  | Theory of string
+type http_getter_rdf_uri = string * http_getter_xml_uri
+type http_getter_uri =
+  | Xml_uri of http_getter_xml_uri
+  | Rdf_uri of http_getter_rdf_uri
+
diff --git a/helm/http_getter/threadSafe.ml b/helm/http_getter/threadSafe.ml
new file mode 100644 (file)
index 0000000..72494ef
--- /dev/null
@@ -0,0 +1,96 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+let debug = false
+let debug_print msg = if debug then prerr_endline msg
+
+class threadSafe =
+  object (self)
+
+    val mutex = Mutex.create ()
+
+      (** condition variable: 'no readers is currently reading' *)
+    val noReaders = Condition.create ()
+
+      (** readers count *)
+    val mutable readersCount = 0
+
+    method private incrReadersCount = (* internal, not exported *)
+      self#doCritical (lazy (
+        readersCount <- readersCount + 1
+      ))
+
+    method private decrReadersCount = (* internal, not exported *)
+      self#doCritical (lazy (
+        if readersCount > 0 then readersCount <- readersCount - 1;
+      ))
+
+    method private signalNoReaders =  (* internal, not exported *)
+      self#doCritical (lazy (
+        if readersCount = 0 then Condition.signal noReaders
+      ))
+
+    method private doCritical: 'a. 'a lazy_t -> 'a =
+      fun action ->
+        debug_print "<doCritical>";
+        (try
+          Mutex.lock mutex;
+          let res = Lazy.force action in
+          Mutex.unlock mutex;
+          debug_print "</doCritical>";
+          res
+        with e ->
+          Mutex.unlock mutex;
+          raise e);
+
+    method private doReader: 'a. 'a lazy_t -> 'a =
+      fun action ->
+        debug_print "<doReader>";
+        let cleanup () =
+          self#decrReadersCount;
+          self#signalNoReaders
+        in
+        self#incrReadersCount;
+        let res = (try Lazy.force action with e -> (cleanup (); raise e)) in
+        cleanup ();
+        debug_print "</doReader>";
+        res
+
+      (* TODO may starve!!!! is what we want or not? *)
+    method private doWriter: 'a. 'a lazy_t -> 'a =
+      fun action ->
+        debug_print "<doWriter>";
+        self#doCritical (lazy (
+          while readersCount > 0 do
+            Condition.wait noReaders mutex
+          done;
+          let res = Lazy.force action in
+          debug_print "</doWriter>";
+          res
+        ))
+
+  end
+
diff --git a/helm/http_getter/threadSafe.mli b/helm/http_getter/threadSafe.mli
new file mode 100644 (file)
index 0000000..6f6d047
--- /dev/null
@@ -0,0 +1,42 @@
+(*
+ *  Copyright (C) 2000, HELM Team.
+ *
+ *  This file is part of HELM, an Hypertextual, Electronic
+ *  Library of Mathematics, developed at the Computer Science
+ *  Department, University of Bologna, Italy.
+ *
+ *  HELM is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version 2
+ *  of the License, or (at your option) any later version.
+ *
+ *  HELM is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with HELM; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ *  MA  02111-1307, USA.
+ *
+ *  For details, see the HELM World-Wide-Web page,
+ *  http://cs.unibo.it/helm/.
+ *)
+
+class threadSafe:
+  object
+
+      (** execute 'action' in mutual exclusion between all other threads *)
+    method private doCritical: 'a lazy_t -> 'a
+
+      (** execute 'action' acting as a 'reader' i.e.: multiple readers can act
+      at the same time but no writer can act until no readers are acting *)
+    method private doReader: 'a lazy_t -> 'a
+
+      (** execute 'action' acting as a 'writer' i.e.: when a writer is acting,
+      no readers or writer can act, beware that writers can starve *)
+    method private doWriter: 'a lazy_t -> 'a
+
+  end
+