Added a "side-by-side" mode using ''diff -y''. Disabled by default,
authorrich <rich>
Sat, 30 Oct 2004 10:16:09 +0000 (10:16 +0000)
committerrich <rich>
Sat, 30 Oct 2004 10:16:09 +0000 (10:16 +0000)
can be selected through user preferences.

User object now contains extra preferences field, which contains the
preferences from the database.

27 files changed:
MANIFEST
cocanwiki.sql
scripts/.depend
scripts/change_password.ml
scripts/contact.ml
scripts/delete_user.ml
scripts/delete_user_form.ml
scripts/diff.ml
scripts/edit.ml
scripts/edit_page_css.ml
scripts/edit_page_title.ml
scripts/edit_user.ml
scripts/invite_user.ml
scripts/lib/cocanwiki.ml
scripts/lib/cocanwiki_diff.ml
scripts/lib/cocanwiki_diff.mli [new file with mode: 0644]
scripts/lib/cocanwiki_emailnotify.ml
scripts/lib/cocanwiki_pages.ml
scripts/logout.ml
scripts/page.ml
scripts/recently_visited.ml
scripts/restore.ml
scripts/restore_form.ml
scripts/send_feedback.ml
scripts/user_prefs.ml
scripts/user_prefs_form.ml
templates/user_prefs_form.html

index b806e63..cc8a3cf 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -128,6 +128,7 @@ scripts/lib/cocanwiki_create_host.ml
 scripts/lib/cocanwiki_create_host.mli
 scripts/lib/cocanwiki_date.ml
 scripts/lib/cocanwiki_diff.ml
+scripts/lib/cocanwiki_diff.mli
 scripts/lib/cocanwiki_emailnotify.ml
 scripts/lib/cocanwiki_ext_calendar.ml
 scripts/lib/cocanwiki_files.ml
index 8d20a39..7f5b718 100644 (file)
@@ -248,7 +248,8 @@ CREATE TABLE users (
     force_password_change boolean DEFAULT false NOT NULL,
     can_import_mail boolean DEFAULT false NOT NULL,
     email_notify boolean DEFAULT true NOT NULL,
-    invite text
+    invite text,
+    diff_sidebyside boolean DEFAULT false NOT NULL
 );
 
 
index 8bfd481..b2533d2 100644 (file)
@@ -2,8 +2,8 @@ lib/cocanwiki.cmo: lib/cocanwiki_ok.cmo lib/cocanwiki_strings.cmo
 lib/cocanwiki.cmx: lib/cocanwiki_ok.cmx lib/cocanwiki_strings.cmx 
 lib/cocanwiki_create_host.cmo: lib/cocanwiki_create_host.cmi 
 lib/cocanwiki_create_host.cmx: lib/cocanwiki_create_host.cmi 
-lib/cocanwiki_diff.cmo: lib/cocanwiki_files.cmo 
-lib/cocanwiki_diff.cmx: lib/cocanwiki_files.cmx 
+lib/cocanwiki_diff.cmo: lib/cocanwiki.cmo lib/cocanwiki_files.cmo 
+lib/cocanwiki_diff.cmx: lib/cocanwiki.cmx lib/cocanwiki_files.cmx 
 lib/cocanwiki_emailnotify.cmo: lib/cocanwiki.cmo 
 lib/cocanwiki_emailnotify.cmx: lib/cocanwiki.cmx 
 lib/cocanwiki_ext_calendar.cmo: lib/cocanwiki.cmo lib/cocanwiki_date.cmo \
@@ -29,9 +29,9 @@ lib/cocanwiki_pages.cmo: lib/cocanwiki.cmo lib/cocanwiki_links.cmi \
 lib/cocanwiki_pages.cmx: lib/cocanwiki.cmx lib/cocanwiki_links.cmx \
     lib/cocanwiki_strings.cmx lib/wikilib.cmx lib/cocanwiki_pages.cmi 
 lib/cocanwiki_template.cmo: lib/cocanwiki_files.cmo lib/cocanwiki_strings.cmo \
-    lib/cocanwiki_version.cmo lib/cocanwiki_template.cmi 
+    lib/cocanwiki_template.cmi 
 lib/cocanwiki_template.cmx: lib/cocanwiki_files.cmx lib/cocanwiki_strings.cmx \
-    lib/cocanwiki_version.cmx lib/cocanwiki_template.cmi 
+    lib/cocanwiki_template.cmi 
 lib/wikilib.cmo: lib/cocanwiki_strings.cmo lib/wikilib.cmi 
 lib/wikilib.cmx: lib/cocanwiki_strings.cmx lib/wikilib.cmi 
 lib/cocanwiki_mail.cmi: lib/cocanwiki.cmo 
index 531e2e6..fcb561f 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: change_password.ml,v 1.2 2004/10/14 15:57:15 rich Exp $
+ * $Id: change_password.ml,v 1.3 2004/10/30 10:16:09 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
@@ -34,7 +34,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ user =
   let userid =
     match user with
        Anonymous -> assert false (* cannot happen *)
-      | User (userid, _, _) -> userid in
+      | User (userid, _, _, _) -> userid in
 
   let sth = dbh#prepare_cached "select 1 from users
                                  where hostid = ? and id = ?
index 584e3f3..16db870 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: contact.ml,v 1.6 2004/10/04 15:19:56 rich Exp $
+ * $Id: contact.ml,v 1.7 2004/10/30 10:16:09 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
@@ -117,7 +117,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
   let username =
     match user with
        Anonymous -> "anonymous"
-      | User (userid, username, _) ->
+      | User (userid, username, _, _) ->
          sprintf "%s (%d)" username userid in
 
   template#set "ip" ip;
index 469e45c..bcb52c6 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: delete_user.ml,v 1.3 2004/10/23 15:00:14 rich Exp $
+ * $Id: delete_user.ml,v 1.4 2004/10/30 10:16:10 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
@@ -48,7 +48,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} self =
   (* Can't delete self! *)
   let () =
     match self with
-      | User (id, _, _) when id = userid ->
+      | User (id, _, _, _) when id = userid ->
          error ~back_button:true ~title:"Delete own account"
            q "You cannot delete your own user account.";
          return ()
index 382814a..7924d01 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: delete_user_form.ml,v 1.2 2004/09/23 11:56:47 rich Exp $
+ * $Id: delete_user_form.ml,v 1.3 2004/10/30 10:16:10 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
@@ -37,7 +37,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ self =
   (* Can't delete self! *)
   let () =
     match self with
-      | User (id, _, _) when id = userid ->
+      | User (id, _, _, _) when id = userid ->
          error ~back_button:true ~title:"Delete own account"
            q "You cannot delete your own user account.";
          return ()
index a199533..f81b9d4 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: diff.ml,v 1.7 2004/09/09 12:21:22 rich Exp $
+ * $Id: diff.ml,v 1.8 2004/10/30 10:16:10 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
@@ -28,7 +28,7 @@ open Cocanwiki
 open Cocanwiki_template
 open Cocanwiki_diff
 
-let run r (q : cgi) (dbh : Dbi.connection) hostid _ _ =
+let run r (q : cgi) (dbh : Dbi.connection) hostid _ user =
   let template = get_template dbh hostid "diff.html" in
 
   let page = q#param "page" in
@@ -49,10 +49,10 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ _ =
   let diff, old_version =
     try
       let old_version = int_of_string (q#param "old_version") in
-      get_diff dbh hostid page ~old_version ~version ()
+      get_diff dbh hostid ~user page ~old_version ~version ()
     with
        Not_found ->
-         get_diff dbh hostid page ~version () in
+         get_diff dbh hostid ~user page ~version () in
 
   template#set "version" (string_of_int version);
   template#set "old_version" (string_of_int old_version);
index abf8e3c..aa3daa6 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: edit.ml,v 1.22 2004/10/25 07:44:55 rich Exp $
+ * $Id: edit.ml,v 1.23 2004/10/30 10:16:10 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
@@ -359,7 +359,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
          | SaveConflict (new_version, old_version, url, css) ->
              (* Edited by someone else ...  Get the other's changes. *)
              let other_diff, _ =
-               get_diff dbh hostid url
+               get_diff dbh hostid ~user url
                  ~old_version ~version:new_version () in
 
              (* Synthesize our own changes. *)
@@ -367,7 +367,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
              let new_page =
                page_for_diff css (List.map (fun (sectionname, _, content) ->
                                sectionname, content) model.contents) in
-             let our_diff = diff_cmd old_page new_page in
+             let our_diff = diff_cmd ~user old_page new_page in
 
              (* Fill out the conflict template. *)
              template_conflict#set "other_diff" other_diff;
@@ -427,7 +427,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
 
       let body = fun () ->
        (* Prepare the diff between this version and the previous version. *)
-       let diff, _ = get_diff dbh hostid url ~version:pageid () in
+       let diff, _ = get_diff dbh hostid ~user url ~version:pageid () in
        "Page: http://" ^ hostname ^ "/" ^ url ^ "\n\n" ^
        diff in
 
index 22cab69..b9cb6ee 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: edit_page_css.ml,v 1.13 2004/10/21 19:54:29 rich Exp $
+ * $Id: edit_page_css.ml,v 1.14 2004/10/30 10:16:10 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
@@ -43,7 +43,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
 
   let logged_user =
     match user with
-      | User (id, _, _) -> `Int id
+      | User (id, _, _, _) -> `Int id
       | _ -> `Null in
 
   (* Changing the CSS creates a new version of the page.  This enables
@@ -95,7 +95,8 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
   let subject = "CSS for page " ^ page ^ " has been modified" in
   let body = fun () ->
     let diff, _ =
-      get_diff dbh hostid page ~version:pageid ~old_version:oldpageid () in
+      get_diff dbh hostid ~user page
+       ~version:pageid ~old_version:oldpageid () in
     "Page: http://" ^ hostname ^ "/" ^ page ^ "\n\n" ^
     diff in
 
index bc51f67..708e899 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: edit_page_title.ml,v 1.5 2004/10/21 19:54:29 rich Exp $
+ * $Id: edit_page_title.ml,v 1.6 2004/10/30 10:16:10 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
@@ -75,7 +75,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
 
   let logged_user =
     match user with
-      | User (id, _, _) -> `Int id
+      | User (id, _, _, _) -> `Int id
       | _ -> `Null in
 
   (* Changing the title creates a new version of the page.  This enables
index 234c5a6..b46b905 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: edit_user.ml,v 1.8 2004/10/23 15:00:14 rich Exp $
+ * $Id: edit_user.ml,v 1.9 2004/10/30 10:16:10 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
@@ -76,7 +76,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ self =
 
   (* Trying to remove manage users permission from self? *)
   (match can_manage_users, self with
-     | false, User (id, _, _) when id = userid ->
+     | false, User (id, _, _, _) when id = userid ->
         error ~back_button:true ~title:"Remove manage users from self"
           q ("You tried to remove 'Manage users' permission from yourself. "^
              "You can't do this.  You'll have to do it from another "^
index bca130f..2895d78 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: invite_user.ml,v 1.2 2004/10/23 15:00:15 rich Exp $
+ * $Id: invite_user.ml,v 1.3 2004/10/30 10:16:10 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
@@ -44,24 +44,17 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
     return ()
   );
 
-  let userid, username = match user with
-      User (userid, username, _) -> userid, username
+  let userid, username, email = match user with
+      User (userid, username, _, prefs) -> userid, username, prefs.email
     | _ -> assert false in
 
   let subject = username ^ " has invited you to join " ^ hostname in
 
-  (* Get user's own email address, which will be the return address
-   * for the email.
-   *)
-  let sth = dbh#prepare_cached "select email from users
-                                 where hostid = ? and id = ?" in
-  sth#execute [`Int hostid; `Int userid];
-
+  (* Get a suitable return address for the email. *)
   let from =
-    match sth#fetch1 () with
-       [ `String email ] -> email
-      | [ `Null ] -> "service@merjis.com"
-      | _ -> assert false in
+    match email with
+      | Some email -> email
+      | None -> "service@merjis.com" in
 
   (* Add user accounts for these new users.  For users who are already
    * registered, we'll send reminder emails.
index dfa44eb..553c03a 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: cocanwiki.ml,v 1.1 2004/10/21 11:42:05 rich Exp $
+ * $Id: cocanwiki.ml,v 1.2 2004/10/30 10:16:10 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
@@ -49,17 +49,24 @@ type host_t = { hostname : string;
 type permissions_t = CanView | CanEdit | CanManageUsers | CanManageContacts
                   | CanManageSite | CanEditGlobalCSS | CanImportMail
 
+(* User preferences and other settings (some cannot be changed by the user). *)
+type prefs_t = {
+  email : string option;               (* Email address. *)
+  email_notify : bool;                 (* Email notification. *)
+  diff_sidebyside : bool;              (* Shows diffs side-by-side. *)
+}
+
 (* The "user object". *)
 type user_t = Anonymous                        (* Not logged in. *)
-           | User of int * string * permissions_t list
-                                       (* Userid, name, permissions. *)
+           | User of int * string * permissions_t list * prefs_t
+                                       (* Userid, name, perms, prefs. *)
 
 let test_permission {edit_anon = edit_anon; view_anon = view_anon} perm user =
   if perm = CanEdit && edit_anon then true
   else if perm = CanView && view_anon then true
   else match user with
       Anonymous -> false
-    | User (_, _, perms) -> List.mem perm perms
+    | User (_, _, perms, _) -> List.mem perm perms
 
 let can_edit host = test_permission host CanEdit
 let can_manage_users host = test_permission host CanManageUsers
@@ -153,7 +160,8 @@ let register_script ?(restrict = []) ?(anonymous = true) run =
             dbh#prepare_cached
               "select u.id, u.name, u.can_edit, u.can_manage_users,
                        u.can_manage_contacts, u.can_manage_site,
-                       u.can_edit_global_css, u.can_import_mail
+                       u.can_edit_global_css, u.can_import_mail,
+                       u.email, u.email_notify, u.diff_sidebyside
                   from usercookies uc, users u
                  where uc.cookie = ? and uc.userid = u.id and u.hostid = ?" in
           sth#execute [`String cookie; `Int hostid];
@@ -161,7 +169,9 @@ let register_script ?(restrict = []) ?(anonymous = true) run =
                [ `Int userid; `String name;
                  `Bool can_edit; `Bool can_manage_users;
                  `Bool can_manage_contacts; `Bool can_manage_site;
-                 `Bool can_edit_global_css; `Bool can_import_mail ] ->
+                 `Bool can_edit_global_css; `Bool can_import_mail;
+                 (`Null | `String _) as email; `Bool email_notify;
+                 `Bool diff_sidebyside ] ->
                  (* Every logged in user can view. *)
                  let perms = [CanView] in
                  let perms =
@@ -182,7 +192,15 @@ let register_script ?(restrict = []) ?(anonymous = true) run =
                  let perms =
                    if can_import_mail then CanImportMail :: perms
                    else perms in
-                 User (userid, name, perms)
+                 (* Preferences. *)
+                 let email =
+                   match email with
+                       `Null -> None
+                     | `String email -> Some email in
+                 let prefs = { email = email;
+                               email_notify = email_notify;
+                               diff_sidebyside = diff_sidebyside } in
+                 User (userid, name, perms, prefs)
              | _ -> assert false)
         with
             Not_found -> Anonymous
index 849a818..ff143a2 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: cocanwiki_diff.ml,v 1.1 2004/10/21 11:42:05 rich Exp $
+ * $Id: cocanwiki_diff.ml,v 1.2 2004/10/30 10:16:10 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
@@ -25,6 +25,7 @@ open Cgi
 open Printf
 
 open Cocanwiki_files
+open Cocanwiki
 
 (* Convenience code for generating diffs between versions.  See diff.ml
  * and edit.ml which both use this code.
@@ -36,19 +37,46 @@ let page_for_diff css sections =
                  content ^ "\n\n") sections)) ^
   "CSS:\n\n" ^ css
 
-let diff_cmd old_page new_page =
+let le_re = Pcre.regexp "\r?\n"
+let le_subst = Pcre.subst "\n"
+
+let diff_cmd ~user old_page new_page =
+  (* Convert line-endings in the input files from \r\n to \n.  Diff
+   * can get confused by the \r characters, particularly in side-by-side
+   * mode when asked to expand tabs (-y -t).
+   *)
+  let f = Pcre.replace ~rex:le_re ~itempl:le_subst in
+  let new_page = f new_page in
+  let old_page = f old_page in
+
   let new_filename = output_tempfile new_page in
   let old_filename = output_tempfile old_page in
 
-  let cmd = sprintf "diff -u %s %s ||:" old_filename new_filename in
+  let diff_sidebyside =
+    match user with
+       Anonymous -> false
+      | User (_, _, _, prefs) -> prefs.diff_sidebyside in
+
+  let options =
+    if not diff_sidebyside then
+      "-u"
+    else
+      "-y --left-column" in
+  let options = options ^ " -t -b -B" in
+
+  let cmd = sprintf "diff %s %s %s ||:" options old_filename new_filename in
   let diff = pget cmd in
 
+  (* Remove the temporary files. *)
+  unlink new_filename; unlink old_filename;
+
   let diff =
-    match diff with
-       _ :: _ :: diff -> diff
-      | diff -> diff in
+    if not diff_sidebyside then
+      match diff with
+         _ :: _ :: diff -> diff
+       | diff -> diff
+    else diff in
 
-  unlink new_filename; unlink old_filename;
   String.concat "\n" diff
 
 let get_version_for_diff (dbh : Dbi.connection) version =
@@ -74,7 +102,7 @@ let get_version_for_diff (dbh : Dbi.connection) version =
     page
   )
 
-let get_diff (dbh : Dbi.connection) hostid page ?old_version ~version () =
+let get_diff (dbh : Dbi.connection) hostid ~user page ?old_version ~version ()=
   let old_version =
     match old_version with
       | Some version -> version
@@ -93,5 +121,5 @@ let get_diff (dbh : Dbi.connection) hostid page ?old_version ~version () =
   let old_page = get_version_for_diff dbh old_version in
 
   (* Compute the diff of the two versions. *)
-  let diff = diff_cmd old_page new_page in
+  let diff = diff_cmd ~user old_page new_page in
   diff, old_version
diff --git a/scripts/lib/cocanwiki_diff.mli b/scripts/lib/cocanwiki_diff.mli
new file mode 100644 (file)
index 0000000..543257d
--- /dev/null
@@ -0,0 +1,32 @@
+(* COCANWIKI - a wiki written in Objective CAML.
+ * Written by Richard W.M. Jones <rich@merjis.com>.
+ * Copyright (C) 2004 Merjis Ltd.
+ * $Id: cocanwiki_diff.mli,v 1.1 2004/10/30 10:16:10 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.
+ *)
+
+val page_for_diff : string -> (string * string) list -> string
+
+val diff_cmd : user:Cocanwiki.user_t -> string -> string -> string
+
+val get_version_for_diff : Dbi.connection -> int -> string
+
+val get_diff :
+  Dbi.connection ->
+  int ->
+  user:Cocanwiki.user_t ->
+  string -> ?old_version:int -> version:int -> unit -> string * int
index 07e7597..7d014c5 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: cocanwiki_emailnotify.ml,v 1.3 2004/10/23 15:00:16 rich Exp $
+ * $Id: cocanwiki_emailnotify.ml,v 1.4 2004/10/30 10:16:10 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
@@ -34,12 +34,14 @@ let email_notify ~subject ~body ?user (dbh : Dbi.connection) hostid =
    * notification back to the person who changed the page.  If
    * we don't have a userid, set it to 0, because no real user can
    * have userid = 0.
+   *
+   * Also get the user's email address.
    *)
-  let own_userid =
+  let own_userid, from =
     match user with
       | None
-      | Some Anonymous -> 0
-      | Some (User (userid, _, _)) -> userid in
+      | Some Anonymous -> 0, None
+      | Some (User (userid, _, _, prefs)) -> userid, prefs.email in
 
   (* Send a change email to everyone who hasn't opted out using
    * their preferences.  This behaviour replaces the old
@@ -58,21 +60,6 @@ let email_notify ~subject ~body ?user (dbh : Dbi.connection) hostid =
                           | _ -> assert false) in
 
   if to_addr <> [] then (
-    (* Get the from address of the user, if available. *)
-    let from =
-      match user with
-       | None
-       | Some Anonymous -> None
-       | Some (User (userid, _, _)) ->
-           let sth = dbh#prepare_cached "select email from users
-                                           where hostid = ? and id = ?" in
-           sth#execute [`Int hostid; `Int userid];
-
-           match sth#fetch1 () with
-             | [ `Null ] -> None
-             | [ `String email ] -> Some email
-             | _ -> assert false in
-
     (* Prepare the body of the message.  The assumption is that
      * this takes time and database access, so we defer the creation
      * of the body until we know that someone needs to be notified.
index 2530688..f6abd61 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: cocanwiki_pages.ml,v 1.1 2004/10/21 11:42:05 rich Exp $
+ * $Id: cocanwiki_pages.ml,v 1.2 2004/10/30 10:16:10 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
@@ -117,7 +117,7 @@ let save_page (dbh : Dbi.connection) hostid ?user ?r model =
        None -> `Null
       | Some user ->
          match user with
-           | User (id, _, _) -> `Int id
+           | User (id, _, _, _) -> `Int id
            | _ -> `Null in
 
   let logged_ip =
index eb32e85..eb1028e 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: logout.ml,v 1.3 2004/09/09 12:21:22 rich Exp $
+ * $Id: logout.ml,v 1.4 2004/10/30 10:16:10 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
@@ -36,7 +36,7 @@ let run r (q : cgi) (dbh : Dbi.connection) _ _ user =
    *)
   (match user with
        Anonymous -> ()
-     | User (userid, _, _) ->
+     | User (userid, _, _, _) ->
         let sth = dbh#prepare_cached "delete from usercookies
                                         where userid = ?" in
         sth#execute [`Int userid];
index bf3fd30..67ac47c 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: page.ml,v 1.36 2004/10/23 15:00:15 rich Exp $
+ * $Id: page.ml,v 1.37 2004/10/30 10:16:10 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
@@ -268,14 +268,14 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid
     (match user with
         Anonymous ->
           t#conditional "user_logged_in" false
-       | User (_, username, _) ->
+       | User (_, username, _, _) ->
           t#conditional "user_logged_in" true;
           t#set "username" username);
 
     (* If logged in, we want to update the recently_visited table. *)
     if pageid <> None then (
       match user with
-       | User (userid, _, _) ->
+       | User (userid, _, _, _) ->
            let sth = dbh#prepare_cached "delete from recently_visited
                                            where hostid = ? and userid = ?
                                              and url = ?" in
@@ -299,7 +299,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid
 
       let rv =
        match user with
-         | User (userid, _, _) ->
+         | User (userid, _, _, _) ->
              (* Recently visited URLs, but don't repeat any from the 'what
               * links here' section, and don't link to self.
               *)
index 6e689fc..2ef7904 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: recently_visited.ml,v 1.1 2004/10/10 16:14:43 rich Exp $
+ * $Id: recently_visited.ml,v 1.2 2004/10/30 10:16:10 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
@@ -32,7 +32,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ user =
 
   let userid =
     match user with
-       User (userid, _, _) -> userid
+       User (userid, _, _, _) -> userid
       | _ -> assert false in
 
   let sth = dbh#prepare_cached "select rv.url, p.title, rv.visit_time
index 97fae79..0e74693 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: restore.ml,v 1.14 2004/10/21 19:54:29 rich Exp $
+ * $Id: restore.ml,v 1.15 2004/10/30 10:16:10 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
@@ -41,7 +41,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
 
     let logged_user =
       match user with
-       | User (id, _, _) -> `Int id
+       | User (id, _, _, _) -> `Int id
        | _ -> `Null in
 
     (* Copy the old version of the page to be live. *)
@@ -96,7 +96,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
     let subject = "Page " ^ page ^ " has been restored." in
     let body = fun () ->
       (* Prepare the diff between this version and the previous version. *)
-      let diff, _ = get_diff dbh hostid page ~version:pageid () in
+      let diff, _ = get_diff dbh hostid ~user page ~version:pageid () in
       "Page: http://" ^ hostname ^ "/" ^ page ^ "\n\n" ^
       diff in
 
index 8e18f45..4e9552a 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: restore_form.ml,v 1.8 2004/09/23 11:56:47 rich Exp $
+ * $Id: restore_form.ml,v 1.9 2004/10/30 10:16:10 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
@@ -29,7 +29,7 @@ open Cocanwiki_template
 open Cocanwiki_ok
 open Cocanwiki_diff
 
-let run r (q : cgi) (dbh : Dbi.connection) hostid _ _ =
+let run r (q : cgi) (dbh : Dbi.connection) hostid _ user =
   let template = get_template dbh hostid "restore_form.html" in
 
   (* Parameters. *)
@@ -54,7 +54,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ _ =
     return ()
   );
 
-  let diff, _ = get_diff dbh hostid page ~old_version ~version () in
+  let diff, _ = get_diff dbh hostid ~user page ~old_version ~version () in
 
   (* Display the diff. *)
   template#set "diff" diff;
index 682b8f6..84e8a73 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: send_feedback.ml,v 1.3 2004/10/04 15:19:56 rich Exp $
+ * $Id: send_feedback.ml,v 1.4 2004/10/30 10:16:10 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
@@ -71,7 +71,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname = hostname} user =
   let username =
     match user with
        Anonymous -> "anonymous"
-      | User (userid, username, _) ->
+      | User (userid, username, _, _) ->
          sprintf "%s (%d)" username userid in
 
   template#set "ip" ip;
index 3c1f713..e603c19 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: user_prefs.ml,v 1.2 2004/10/23 15:05:07 rich Exp $
+ * $Id: user_prefs.ml,v 1.3 2004/10/30 10:16:10 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
@@ -35,17 +35,19 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid {hostname=hostname} user =
   (* Get the fields. *)
   let new_email = trim (q#param "email") in
   let email_notify = q#param_true "email_notify" in
+  let diff_sidebyside = q#param_true "diff_sidebyside" in
 
   let userid =
     match user with
        Anonymous -> assert false
-      | User (userid, _, _) -> userid in
+      | User (userid, _, _, _) -> userid in
 
-  (* Update the email notify field. *)
+  (* Update the preferences fields. *)
   let sth =
-    dbh#prepare_cached "update users set email_notify = ?
+    dbh#prepare_cached "update users set email_notify = ?, diff_sidebyside = ?
                          where hostid = ? and id = ?" in
-  sth#execute [`Bool email_notify; `Int hostid; `Int userid];
+  sth#execute [`Bool email_notify; `Bool diff_sidebyside;
+              `Int hostid; `Int userid];
 
   (* Have we changed the email address? *)
   let confirm_needed =
index c346f17..86d384a 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: user_prefs_form.ml,v 1.1 2004/10/23 15:00:16 rich Exp $
+ * $Id: user_prefs_form.ml,v 1.2 2004/10/30 10:16:10 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
@@ -28,39 +28,39 @@ open Cocanwiki
 open Cocanwiki_template
 open Cocanwiki_date
 
-let run r (q : cgi) (dbh : Dbi.connection) hostid _ user =
+let run r (q : cgi) (dbh : Dbi.connection) hostid host user =
   let template = get_template dbh hostid "user_prefs_form.html" in
 
-  let userid =
+  let userid, name, prefs =
     match user with
       | Anonymous -> assert false
-      | User (userid, _, _) -> userid in
+      | User (userid, name, _, prefs) -> userid, name, prefs in
 
-  (* Pull out the preferences. *)
+  let can_edit = can_edit host user in
+
+  (* Pull out the registration date - not stored in the user object. *)
   let sth =
     dbh#prepare_cached
-      "select name, email, registration_date, can_edit, email_notify
-         from users where hostid = ? and id = ?" in
+      "select registration_date from users where hostid = ? and id = ?" in
   sth#execute [`Int hostid; `Int userid];
 
-  let name, email, has_email, registration_date, can_edit, email_notify =
+  let registration_date =
     match sth#fetch1 () with
-       [ `String name; (`Null | `String _) as email;
-         `Date registration_date; `Bool can_edit; `Bool email_notify ] ->
-         let email, has_email =
-           match email with
-               `Null -> "", false
-             | `String email -> email, true in
-         name, email, has_email, registration_date,
-         can_edit, email_notify
+       [ `Date registration_date ] -> registration_date
       | _ -> assert false in
 
+  let email, has_email =
+    match prefs.email with
+       None -> "", false
+      | Some email -> email, true in
+
   template#set "name" name;
   template#set "email" email;
   template#conditional "has_email" has_email;
   template#set "registration_date" (printable_date' registration_date);
   template#conditional "can_edit" can_edit;
-  template#conditional "email_notify" email_notify;
+  template#conditional "email_notify" prefs.email_notify;
+  template#conditional "diff_sidebyside" prefs.diff_sidebyside;
 
   q#template template
 
index 8fcbbb7..9bd7fb4 100644 (file)
 </tr>
 <tr>
   <td></td>
-  <td> <input type="checkbox" id="email_notify" name="email_notify" value="1" ::if(email_notify)::checked="checked"::end::/> <label for="email_notify">Receive email notifications <small>when the site is edited</small></label> </td>
+  <td>
+    <input type="checkbox" id="email_notify" name="email_notify" value="1" ::if(email_notify)::checked="checked"::end::/> <label for="email_notify">Receive email notifications <small>when the site is edited</small></label> <br/>
+    <input type="checkbox" id="diff_sidebyside" name="diff_sidebyside" value="1" ::if(diff_sidebyside)::checked="checked"::end::/> <label for="diff_sidebyside">Diffs formatted side-by-side</label>
+  </td>
 </tr>
 <tr>
   <td></td>