Fixed a bug triggered when the user typed search terms in quotes.
[cocanwiki.git] / scripts / mail_import.ml
index bd6f965..9e30fc9 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: mail_import.ml,v 1.2 2004/10/11 15:21:49 rich Exp $
+ * $Id: mail_import.ml,v 1.6 2004/10/20 15:17:18 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,6 +36,7 @@ open Cocanwiki_template
 open Cocanwiki_date
 open Cocanwiki_strings
 open Cocanwiki_pages
+open Cocanwiki_mail
 
 let irt_re = Pcre.regexp "<.*?>"
 let ws_re = Pcre.regexp "\\s+"
@@ -57,8 +58,6 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ user =
       upload.upload_value
     with
        Not_found ->
-         (* Force an error status which a script can detect. *)
-         Request.set_status r cHTTP_BAD_REQUEST;
          error ~back_button:true ~title:"No message"
            q "No message was uploaded.";
          return () in
@@ -86,12 +85,15 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ user =
    * cannot thread it, so give up.
    *)
   if date = "" || inet_message_id = "" then (
-    Request.set_status r cHTTP_BAD_REQUEST;
     error ~back_button:true ~title:"Headers missing"
       q "Date or Message-ID header missing.  Cannot handle this message. ";
     return ()
   );
 
+  (* Can't handle funny characters in subject lines - remove them. *)
+  let subject = String.map (fun c ->
+                             if Char.code c < 32 then ' ' else c) subject in
+
   (* Parse the date field. *)
   let date, time =
     try
@@ -190,7 +192,10 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ user =
           *)
          msgid in
 
-  (* The message is referred to by a unique title: *)
+  (* The message is referred to by a unique title.
+   * NB. Do not change this unique title - it is also used during thread
+   * indexing.
+   *)
   let title = sprintf "Mail/%s (%d)" subject msgid in
 
   (* Choose a suitable URL. *)
@@ -264,13 +269,67 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ user =
       | (_, `Parts []) -> raise Not_found (* should never happen *)
       | (_, `Parts (m :: _)) ->
          find_body m in
+
+    (* Markup a plain text body. *)
+    let markup_body text =
+      (* Get all the titles from the database! We're going to exclude
+       * mail messages from this.
+       *)
+      let sth =
+       dbh#prepare_cached
+         "select lower (title) from pages where hostid = ?
+              and url is not null and title not like 'Mail/%'" in
+      sth#execute [`Int hostid];
+      let links = sth#map (function [`String s] -> s | _ -> assert false) in
+
+      (* This code cannot find titles which are split across multiple lines.
+       * XXX
+       *)
+      let lines = Pcre.split ~rex:lines_re text in
+
+      (* We don't want to mark up the same link twice, so keep track of the
+       * titles we've already used.
+       *)
+      let used = ref [] in
+      let lines =
+       List.map
+         (fun line ->
+            let find str sub_lc =
+              try
+                String.find (String.lowercase str) sub_lc
+              with
+                  String.Invalid_string -> -1
+            in
+            let rec loop line = function
+                [] -> line
+              | link :: links ->
+                  let i = find line link in
+                  if i >= 0 && not (List.mem link !used) then (
+                    used := link :: !used;
+                    let n = String.length link in
+                    let n' = String.length line in
+                    let line =
+                      String.sub line 0 i ^
+                      "[[" ^ String.sub line i n ^
+                      "]]" ^ loop (String.sub line (i+n) (n' - (i+n))) links
+                    in
+                    line
+                  ) else
+                    loop line links
+            in
+            loop line links) lines in
+
+      let lines = List.map trim lines in
+      let lines = List.map (fun line -> line ^ "<br>") lines in
+
+      String.concat "\n" lines
+    in
+
     let content =
       try
        let text = find_body msg in
-       let lines = Pcre.split ~rex:lines_re text in
-       let lines = List.map trim lines in
-       let lines = List.map (fun str -> str ^ "<br>") lines in
-       String.concat "\n" lines
+       let content = markup_body text in
+       content
       with
          Not_found ->
            "No plain text message body found" in
@@ -295,6 +354,10 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ user =
    *)
   save_page dbh hostid ~user ~r model;
 
+  (* Rebuild threads? *)
+  if rebuild then
+    thread_mail dbh hostid ~user ~r date.Dbi.year date.Dbi.month;
+
   (* Commit to the database. *)
   dbh#commit ();