Added machine-parsable links database, per-page links and page source.
authorrich <rich>
Wed, 27 Oct 2004 21:14:05 +0000 (21:14 +0000)
committerrich <rich>
Wed, 27 Oct 2004 21:14:05 +0000 (21:14 +0000)
Updated MANIFEST.
Updated deps.

MANIFEST
conf/cocanwiki.conf
scripts/.depend
scripts/links.ml [new file with mode: 0644]
scripts/source.ml [new file with mode: 0644]
templates/links.txt [new file with mode: 0644]

index 7f1643b..b806e63 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -147,6 +147,7 @@ scripts/lib/cocanwiki_template.mli
 scripts/lib/cocanwiki_version.ml.in
 scripts/lib/wikilib.ml
 scripts/lib/wikilib.mli
+scripts/links.ml
 scripts/login.ml
 scripts/login_form.ml
 scripts/logout.ml
@@ -179,6 +180,7 @@ scripts/set_password.ml
 scripts/set_password_form.ml
 scripts/signup.ml
 scripts/sitemap.ml
+scripts/source.ml
 scripts/stats.ml
 scripts/stats_top.ml
 scripts/undelete_file.ml
@@ -240,6 +242,7 @@ templates/invite_user_confirm_form.html
 templates/invite_user_exists.txt
 templates/invite_user_form.html
 templates/largest_pages.html
+templates/links.txt
 templates/login_form.html
 templates/mail_import_form.html
 templates/mail_import_header.txt
index a46300a..69ac832 100644 (file)
@@ -1,5 +1,5 @@
 # Apache configuration for COCANWIKI.
-# $Id: cocanwiki.conf,v 1.16 2004/10/23 15:00:14 rich Exp $
+# $Id: cocanwiki.conf,v 1.17 2004/10/27 21:14:05 rich Exp $
 
 # Uncomment the following lines if necessary.  You will probably need
 # to adjust the paths to reflect where cocanwiki is really installed.
@@ -59,6 +59,7 @@ RewriteRule ^/_files$ /_bin/files.cmo [PT,L,QSA]
 RewriteRule ^/_global.css$ /_bin/hoststyle.cmo [PT,L,QSA]
 RewriteRule ^/_images$ /_bin/images.cmo [PT,L,QSA]
 RewriteRule ^/_invite$ /_bin/invite_user_confirm_form.cmo [PT,L,QSA]
+RewriteRule ^/_links$ /_bin/links.cmo [PT,L,QSA]
 RewriteRule ^/_login$ /_bin/login_form.cmo [PT,L,QSA]
 RewriteRule ^/_logout$ /_bin/logout.cmo [PT,L,QSA]
 RewriteRule ^/_mailing_list.csv$ /_bin/mailing_list_view.cmo?csv=1 [PT,L]
@@ -85,6 +86,8 @@ RewriteRule ^/([^_].*)/editcss$ /_bin/edit_page_css_form.cmo?page=$1 [PT,L,QSA]
 RewriteRule ^/([^_].*)/edittitle$ /_bin/edit_page_title_form.cmo?page=$1 [PT,L,QSA]
 RewriteRule ^/([^_].*)/history$ /_bin/history.cmo?page=$1 [PT,L,QSA]
 RewriteRule ^/([^_].*)/index.rss$ /_bin/rss.cmo?page=$1 [PT,L,QSA]
+RewriteRule ^/([^_].*)/links$ /_bin/links.cmo?page=$1 [PT,L,QSA]
+RewriteRule ^/([^_].*)/source$ /_bin/source.cmo?page=$1 [PT,L,QSA]
 RewriteRule ^/([^_].*)/stats$ /_bin/stats.cmo?page=$1 [PT,L,QSA]
 RewriteRule ^/([^_].*)/styles.css$ /_bin/pagestyle.cmo?page=$1 [PT,L,QSA]
 
index 6eff1f2..81b3d7a 100644 (file)
@@ -182,6 +182,8 @@ invite_user_form.cmo: lib/cocanwiki.cmo lib/cocanwiki_template.cmi
 invite_user_form.cmx: lib/cocanwiki.cmx lib/cocanwiki_template.cmx 
 largest_pages.cmo: lib/cocanwiki.cmo lib/cocanwiki_template.cmi 
 largest_pages.cmx: lib/cocanwiki.cmx lib/cocanwiki_template.cmx 
+links.cmo: lib/cocanwiki.cmo lib/cocanwiki_template.cmi 
+links.cmx: lib/cocanwiki.cmx lib/cocanwiki_template.cmx 
 login.cmo: lib/cocanwiki.cmo lib/cocanwiki_ok.cmo 
 login.cmx: lib/cocanwiki.cmx lib/cocanwiki_ok.cmx 
 login_form.cmo: lib/cocanwiki.cmo lib/cocanwiki_strings.cmo \
@@ -278,6 +280,8 @@ sitemap.cmo: lib/cocanwiki.cmo lib/cocanwiki_date.cmo \
     lib/cocanwiki_strings.cmo lib/cocanwiki_template.cmi lib/wikilib.cmi 
 sitemap.cmx: lib/cocanwiki.cmx lib/cocanwiki_date.cmx \
     lib/cocanwiki_strings.cmx lib/cocanwiki_template.cmx lib/wikilib.cmx 
+source.cmo: lib/cocanwiki.cmo lib/cocanwiki_template.cmi 
+source.cmx: lib/cocanwiki.cmx lib/cocanwiki_template.cmx 
 stats.cmo: lib/cocanwiki.cmo lib/cocanwiki_server_settings.cmo \
     lib/cocanwiki_template.cmi 
 stats.cmx: lib/cocanwiki.cmx lib/cocanwiki_server_settings.cmx \
diff --git a/scripts/links.ml b/scripts/links.ml
new file mode 100644 (file)
index 0000000..e84f49b
--- /dev/null
@@ -0,0 +1,141 @@
+(* COCANWIKI - a wiki written in Objective CAML.
+ * Written by Richard W.M. Jones <rich@merjis.com>.
+ * Copyright (C) 2004 Merjis Ltd.
+ * $Id: links.ml,v 1.1 2004/10/27 21:14:05 rich Exp $
+ *
+ * This program 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.
+ *
+ * This program 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 this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *)
+
+open Apache
+open Registry
+open Cgi
+open Printf
+
+open Cocanwiki
+open Cocanwiki_template
+open Cocanwiki_links
+
+(* This script produces the links database for the whole site (if
+ * called without the 'page' parameter), or else just for a particular
+ * page.  If called with 'page' and 'type' parameters together, then it
+ * can show inbound or outbound links only.  The format in all cases is a
+ * simple machine-parsable text file.
+ *)
+let run r (q : cgi) (dbh : Dbi.connection) hostid _ _ =
+  let template = get_template dbh hostid "links.txt" in
+
+  if q#param_exists "page" then (
+    let page = q#param "page" in
+    let page = if page = "" then "index" else page in
+
+    if q#param_exists "type" then (
+      let type_ = q#param "type" in
+
+      if type_ = "inbound" then (
+       (* This is "what links here".  We're interested in indirect
+        * links too, so use Cocanwiki_links.what_links_here function.
+        *)
+       let links = what_links_here dbh hostid page in
+       let links = List.map fst links in
+
+       q#header ~content_type:"text/plain" ();
+
+       List.iter (fun url -> ignore (print_endline r url)) links
+
+      ) else if type_ = "outbound" then (
+       (* Display a list of links outbound from this page. *)
+       let sth =
+         dbh#prepare_cached "select to_url from links
+                               where hostid = ? and from_url = ?" in
+
+       sth#execute [`Int hostid; `String page];
+
+       q#header ~content_type:"text/plain" ();
+
+       sth#iter (function [`String url] -> ignore (print_endline r url)
+                   | _ -> assert false)
+
+      ) else
+       failwith "'type' parameter should be 'inbound' or 'outbound'"
+
+    ) else (
+      (* Just return the single-row "links database" relating to this
+       * page.
+       *)
+      let sth = dbh#prepare_cached "select to_url from links
+                                     where hostid = ? and from_url = ?" in
+      sth#execute [`Int hostid; `String page];
+
+      let table =
+       sth#map (function [`String to_url] ->
+                  [ "to", Template.VarString to_url ]
+                  | _ -> assert false) in
+      let table =
+       [ [ "from", Template.VarString page;
+           "to", Template.VarTable table ] ] in
+      template#table "links" table;
+
+      q#template ~content_type:"text/plain" template
+    )
+  ) else (
+    (* Links database for whole site in the simple format required by
+     * the TouchGraph application.  We don't know anything about external
+     * links, so we don't include them.  However we do include links to
+     * non-existant internal pages.
+     *)
+    let h = Hashtbl.create 1024 in
+    let add_link from_url to_url =
+      let xs = try Hashtbl.find h from_url with Not_found -> [] in
+      let xs = to_url :: xs in
+      Hashtbl.replace h from_url xs
+    in
+
+    let sth = dbh#prepare_cached "select from_url, to_url from links
+                                   where hostid = ?" in
+    sth#execute [`Int hostid];
+
+    sth#iter (function [`String from_url; `String to_url] ->
+               add_link from_url to_url
+               | _ -> assert false);
+
+    (* Don't forget redirects!  They're kinda like links ... *)
+    let sth = dbh#prepare_cached "select url, redirect from pages
+                                   where hostid = ? and url is not null
+                                     and redirect is not null" in
+    sth#execute [`Int hostid];
+
+    sth#iter (function [`String url; `String redirect] ->
+               add_link url redirect
+               | _ -> assert false);
+
+    let keys h = Hashtbl.fold (fun key _ xs -> key :: xs) h [] in
+
+    let table =
+      List.map
+       (fun from ->
+          let xs = Hashtbl.find h from in
+          let table =
+            List.map (fun to_ -> [ "to", Template.VarString to_ ]) xs in
+          [ "from", Template.VarString from;
+            "to", Template.VarTable table ]
+       ) (keys h) in
+    template#table "links" table;
+
+    q#template ~content_type:"text/plain" template
+  )
+
+let () =
+  register_script run
diff --git a/scripts/source.ml b/scripts/source.ml
new file mode 100644 (file)
index 0000000..d724e01
--- /dev/null
@@ -0,0 +1,90 @@
+(* COCANWIKI - a wiki written in Objective CAML.
+ * Written by Richard W.M. Jones <rich@merjis.com>.
+ * Copyright (C) 2004 Merjis Ltd.
+ * $Id: source.ml,v 1.1 2004/10/27 21:14:05 rich Exp $
+ *
+ * This program 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.
+ *
+ * This program 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 this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *)
+
+open Apache
+open Registry
+open Cgi
+open Printf
+
+open Cocanwiki
+open Cocanwiki_pages
+open Cocanwiki_ok
+
+let rex = Pcre.regexp "\r?\n"
+let itempl = Pcre.subst "\r\n\t"
+
+(* This is a very simple script which just returns the source of a page
+ * in a format which is easily machine-parsable.
+ *)
+let run r (q : cgi) (dbh : Dbi.connection) hostid _ _ =
+  let url = q#param "page" in
+  let url = if url = "" then "index" else url in
+
+  let model =
+    try load_page dbh hostid ~url ()
+    with
+       Not_found ->
+         error ~title:"Page not found"
+           q "That page was not found";
+         return () in
+
+  (* XXX CSS - eventually both title and CSS fields should be returned in
+   * the Cocanwiki_pages.model_t structure.
+   *)
+
+  (* Get the title. *)
+  let sth = dbh#prepare_cached "select title from pages
+                                 where hostid = ? and id = ?" in
+  sth#execute [`Int hostid; `Int model.id];
+  let title = sth#fetch1string () in
+
+  (* Function to write out fields, with RFC822-like escaping. *)
+  let write key value =
+    print_string r key;
+    print_string r ": ";
+    print_string r (Pcre.replace ~rex ~itempl value);
+    ignore (print_newline r);
+  in
+
+  (* HTTP header. *)
+  q#header ~content_type:"text/plain" ();
+
+  (* Write out the standard fields. *)
+  write "Version" (string_of_int model.id);
+  write "Title" title;
+  write "Description" model.description;
+  if model.redirect <> "" then
+    write "Redirect" model.redirect
+  else
+    write "Section-Count" (string_of_int (List.length model.contents));
+  ignore (print_newline r);
+
+  (* Now write out the sections. *)
+  if model.redirect = "" then
+    List.iter
+      (fun (sectionname, divname, content) ->
+        write "Section-Header" sectionname;
+        write "Css-Id" divname;
+        write "Content" content;
+        ignore (print_newline r)) model.contents
+
+let () =
+  register_script run
diff --git a/templates/links.txt b/templates/links.txt
new file mode 100644 (file)
index 0000000..56bb676
--- /dev/null
@@ -0,0 +1,2 @@
+::table(links)::::from::::table(to):: ::to::::end::
+::end::
\ No newline at end of file