join: use generic sendmail instead of exim4
[hcoop/portal.git] / static / gen.sml
index 272e785..2059f92 100644 (file)
@@ -10,25 +10,35 @@ end
 
 structure NM = BinaryMapFn(IntKey)
 
-val outputDir = "/var/www/dyn/"
+val outputDir = "/home/hcoop/public_html/"
 
 fun generate () =
     let
-       val db = C.conn "dbname='hcoop_hcoop'"
+       val db = C.conn "dbname='hcoop_hcoop' host='postgres'"
+
+       fun procOutput (outf, cmdline) =
+           let
+               val proc = Unix.execute cmdline
+               val ins = Unix.textInstreamOf proc
+                          
+               fun loop () =
+                   case TextIO.inputLine ins of
+                       NONE => ()
+                     | SOME s => (TextIO.output (outf, s); loop ())
+           in
+               loop ();
+               ignore (Unix.reap proc)
+           end
 
        fun header (outf, title) =
-           (TextIO.output (outf, "<html><head>\n<title>");
-            TextIO.output (outf, title);
-            TextIO.output (outf, "</title></head>\n<body>\n<h2><b>");
-            TextIO.output (outf, title);
-            TextIO.output (outf, "</b></h2>\n"))
+           (TextIO.output (outf, "<!--#include file=\"header.html\" -->\n<div id=\"main\">");
+            TextIO.output (outf, "<h2>" ^ title ^ "</h2>\n"))
 
-       fun footer outf =
-           TextIO.output (outf, "\n</body></html>")
+       fun footer outf = TextIO.output (outf, "</div>\n<!--#include file=\"footer.html\" -->\n");
 
        fun genMemberList () =
            let
-               val outf = TextIO.openOut (outputDir ^ "members.html")
+               val outf = TextIO.openOut (outputDir ^ "members.shtml")
 
                fun printOne ([name, rname, usr], (total, anon)) =
                    let
@@ -39,7 +49,7 @@ fun generate () =
                        if not isAnon then
                            (TextIO.output (outf, "<tr> <td><a href=\"member/");
                             TextIO.output (outf, name);
-                            TextIO.output (outf, ".html\">");
+                            TextIO.output (outf, "\">");
                             TextIO.output (outf, name);
                             TextIO.output (outf, "</a></td> <td>");
                             TextIO.output (outf, rname);
@@ -50,10 +60,10 @@ fun generate () =
                    end
                  | printOne _ = raise Fail "Bad printOne line"
 
-               val _ = header (outf, "Member list")
+               val _ = header (outf, "HCoop Member List")
                val _ = TextIO.output (outf, "<table>\n")
                val (total, anon) = C.fold db printOne (0, 0)
-                                          "SELECT name, rname, usr FROM WebUser LEFT OUTER JOIN DirectoryPref ON id = usr ORDER BY name"
+                                          "SELECT name, rname, usr FROM WebUserPaying LEFT OUTER JOIN DirectoryPref ON id = usr ORDER BY name"
            in
                TextIO.output (outf, "</table><br><br>\n\nUnlisted members: ");
                TextIO.output (outf, Int.toString anon);
@@ -78,15 +88,17 @@ fun generate () =
                            ()
                        else
                            let
-                               val outf = TextIO.openOut (String.concat [outputDir, "member/", name, ".html"])
+                               val outf = TextIO.openOut (String.concat [outputDir, "member/", name, ".shtml"])
 
-                               val _ = header (outf, "Hcoop member: " ^ name)
+                               val _ = header (outf, "HCoop Member: " ^ name)
+                               val _ = TextIO.output (outf, "<p><a href=\"/members\">Return to members directory</a></p>\n\n");
                                val _ = TextIO.output (outf, "<table>\n<tr> <td align=\"right\"><b>Member</b>:</td> <td>")
                                val _ = TextIO.output (outf, name)
                                val _ = TextIO.output (outf, "</td> </tr>\n<tr> <td align=\"right\"><b>Name</b>:</td> <td>")
                                val _ = TextIO.output (outf, rname)
                                val _ = TextIO.output (outf, "</td> </tr>\n<tr> <td align=\"right\"><b>Joined</b>:</td> <td>")
                                val _ = TextIO.output (outf, Date.toString (Date.fromTimeLocal joined))
+                               val _ = TextIO.output (outf, "</td></tr>\n\n");
 
                                fun doLocation [id] = C.intFromSql id
                                  | doLocation _ = raise Fail "Bad location row"
@@ -120,7 +132,7 @@ fun generate () =
                                val _ = case locations of
                                            [] => ()
                                          | _ =>
-                                           (TextIO.output (outf, "<tr> </tr>\n\n<tr> <td align=\"right\"><b>Locations</b>:</td> <td>");
+                                           (TextIO.output (outf, "<tr> <td align=\"right\"><b>Locations</b>:</td> <td>");
                                             app appLocation locations;
                                             TextIO.output (outf, "</td> </tr>\n"))
 
@@ -147,7 +159,7 @@ fun generate () =
                                val _ = case links of
                                            [] => ()
                                          | _ =>
-                                           (TextIO.output (outf, "<tr> </tr>\n\n<tr> <td><b>Hosted sites</b></td> </tr>\n");
+                                           (TextIO.output (outf, "<tr> <td><b>Hosted sites</b></td> </tr>\n");
                                             app appLink links)
 
                                fun doContact [v, name, url, urlPrefix, urlPostfix] =
@@ -179,7 +191,7 @@ fun generate () =
                                val _ = case contacts of
                                            [] => ()
                                          | _ =>
-                                           (TextIO.output (outf, "<tr> </tr>\n\n<tr> <td><b>Contact information</b></td> </tr>\n");
+                                           (TextIO.output (outf, "<tr> <td><b>Contact information</b></td> </tr>\n");
                                             app appContact contacts)
                            in
                                TextIO.output (outf, "</table>\n");
@@ -189,15 +201,15 @@ fun generate () =
                    end
                  | doOne _ = raise Fail "Bad member row"
            in
-               ignore (OS.Process.system ("/bin/rm " ^ outputDir ^ "member/*.html"));
-               C.app db doOne "SELECT id, name, rname, joined, usr FROM WebUser LEFT OUTER JOIN DirectoryPref ON usr = id"
+               ignore (OS.Process.system ("/bin/rm " ^ outputDir ^ "member/*.shtml"));
+               C.app db doOne "SELECT id, name, rname, joined, usr FROM WebUserPaying LEFT OUTER JOIN DirectoryPref ON usr = id"
            end
 
        fun genLocations () =
            let
                val outf = TextIO.openOut (outputDir ^ "locs.html")
 
-               val _ = header (outf, "Where members live")
+               val _ = header (outf, "HCoop: Where members live")
 
                fun countResidents () =
                    let
@@ -226,7 +238,7 @@ fun generate () =
                                addToParents (#loc lives, count)
                            end
                    in
-                       C.fold db folder NM.empty "SELECT loc, usr FROM Lives"
+                       C.fold db folder NM.empty "SELECT loc, usr FROM Lives JOIN WebUserActive ON id = usr"
                    end
 
                val res = countResidents ()
@@ -238,16 +250,17 @@ fun generate () =
                                val id = C.intFromSql id
                                val name = C.stringFromSql name
                            in
-                               TextIO.output (outf, "<li> ");
-                               TextIO.output (outf, Web.html name);
                                case NM.find (res, id) of
                                    NONE => ()
-                                 | SOME n => (TextIO.output (outf, " (");
-                                              TextIO.output (outf, Int.toString n);
-                                              TextIO.output (outf, ")"));
-                               TextIO.output (outf, "</li>\n<ul>\n");
-                               locationTree (SOME id);
-                               TextIO.output (outf, "</ul>\n")
+                                 | SOME n =>
+                                   (TextIO.output (outf, "<li> ");
+                                    TextIO.output (outf, Web.html name);
+                                    TextIO.output (outf, " (");
+                                    TextIO.output (outf, Int.toString n);
+                                    TextIO.output (outf, ")");
+                                    TextIO.output (outf, "</li>\n<ul>\n");
+                                    locationTree (SOME id);
+                                    TextIO.output (outf, "</ul>\n"))
                            end
                          | doOne _ = raise Fail "Bad locationTree row"
                    in
@@ -265,32 +278,32 @@ fun generate () =
            let
                val outf = TextIO.openOut (outputDir ^ "sites.html")
 
-               val _ = header (outf, "Hosted sites")
+               (* val _ = header (outf, "HCoop: Hosted sites") *)
 
                fun doLink [url, title, descr, name] = (C.stringFromSql url, C.stringFromSql title, C.stringFromSql descr, C.stringFromSql name)
                  | doLink _ = raise Fail "Bad link' row"
 
                val links = C.map db doLink (String.concat ["SELECT url, title, descr, name FROM Link",
-                                                           " JOIN WebUser ON WebUser.id = usr",
-                                                           " JOIN DirectoryPref ON WebUser.id = DirectoryPref.usr",
+                                                           " JOIN WebUserPaying ON WebUserPaying.id = usr",
+                                                           " JOIN DirectoryPref ON WebUserPaying.id = DirectoryPref.usr",
                                                            " ORDER BY title"])
 
                fun appLink (url, title, descr, name) = 
-                   (TextIO.output (outf, "<tr> <td><b><a href=\"");
+                   (TextIO.output (outf, "<tr> <td><a href=\"");
                     TextIO.output (outf, Web.html url);
                     TextIO.output (outf, "\">");
                     TextIO.output (outf, Web.html title);
-                    TextIO.output (outf, "</a></b></td> <td>");
+                    TextIO.output (outf, "</a></td> <td>");
                     TextIO.output (outf, Web.html descr);
                     TextIO.output (outf, "</td> <td><a href=\"member/");
                     TextIO.output (outf, name);
-                    TextIO.output (outf, ".html\">");
+                    TextIO.output (outf, "\">");
                     TextIO.output (outf, name);
                     TextIO.output (outf, "</a></td> </tr>\n"))
            in
-               TextIO.output (outf, "<table>\n");
+               (* TextIO.output (outf, "<table>\n"); *)
                app appLink links;
-               footer outf;
+               (* footer outf; *)
                TextIO.closeOut outf
            end
     in
@@ -305,10 +318,18 @@ fun main _ = (generate ())
     handle
     C.Sql s => (print "SQL exception: \n";
                print s;
+               print "\n";
                OS.Process.failure)
   | Fail s => (print "Fail: ";
               print s;
+              print "\n";
               OS.Process.failure)
+  | IO.Io {name, function, ...} => (print "IO exception ";
+                                   print function;
+                                   print ": ";
+                                   print name;
+                                   print "\n";
+                                   OS.Process.failure)
   | ex => (print "Exception!\n";
                  List.app (fn s => print (s ^ "\n")) (SMLofNJ.exnHistory ex);
                  OS.Process.failure)