hcoop: move gibran and marsh to new ips
[hcoop/domtool2.git] / src / plugins / mailman.sml
CommitLineData
325285ab
AC
1(* HCoop Domtool (http://hcoop.sourceforge.net/)
2 * Copyright (c) 2006, Adam Chlipala
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *)
18
19(* Mailman mailing list handling *)
20
21structure Mailman :> MAILMAN = struct
22
de5351c7
AC
23open Ast
24
b5f2d506 25val () = Env.type_one "mailman_node"
de5351c7
AC
26 Env.string
27 (fn node => Apache.webNode node orelse node = Config.Mailman.node)
28
29val dl = ErrorMsg.dummyLoc
30
b5f2d506 31val () = Env.registerFunction ("mailman_node",
e9f528ab
AC
32 fn [] => SOME (EString Config.Mailman.node, dl)
33 | _ => NONE)
34
b5f2d506 35val () = Env.registerFunction ("mailman_node_to_node",
e9f528ab
AC
36 fn [e] => SOME e
37 | _ => NONE)
38
b5f2d506
AC
39fun mailmanPlace (EApp ((EVar "mailman_place_default", _), (EString node, _)), _) =
40 SOME (node, Domain.nodeIp node)
41 | mailmanPlace (EApp ((EApp ((EVar "mailman_place", _), (EString node, _)), _), (EString ip, _)), _) =
42 SOME (node, ip)
43 | mailmanPlace _ = NONE
44
b5f2d506
AC
45val _ = Env.registerFunction ("mailman_place_to_web_node",
46 fn [e] => Option.map (fn (node, _) => (EString node, dl)) (mailmanPlace e)
47 | _ => NONE)
48
49val _ = Env.registerFunction ("mailman_place_to_node",
50 fn [e] => Option.map (fn (node, _) => (EString node, dl)) (mailmanPlace e)
51 | _ => NONE)
52
53val _ = Env.registerFunction ("mailman_place_to_ip",
54 fn [e] => Option.map (fn (_, ip) => (EString ip, dl)) (mailmanPlace e)
55 | _ => NONE)
56
325285ab
AC
57val files = ref ([] : TextIO.outstream list)
58val write = ref (fn _ : string => ())
59
60val () = Env.action_one "mailmanWebHost"
61 ("hostname", Env.string)
62 (fn host =>
63 let
85095959 64 val {write, writeDom, close} = Domain.domainsFile {node = Config.Mailman.node,
3ae703b6 65 name = "mailman.conf"}
325285ab 66 in
85095959
AC
67 write "\t'";
68 write host;
69 write "' : '";
70 writeDom ();
71 write "',\n";
72 close ()
325285ab
AC
73 end)
74
1c9b5e20
AC
75val () = Env.actionV_one "mailmanVhost"
76 ("host", Env.string)
77 (fn (env, host) =>
78 let
b5f2d506 79 val places = Env.env (Env.list mailmanPlace) (env, "MailmanPlaces")
1c9b5e20
AC
80
81 val ssl = Env.env Apache.ssl (env, "SSL")
82 val user = Env.env Env.string (env, "User")
e322749a 83 val sadmin = Env.env Env.string (env, "ServerAdmin")
1c9b5e20
AC
84
85 val fullHost = host ^ "." ^ Domain.currentDomain ()
86 val vhostId = fullHost ^ (if Option.isSome ssl then ".ssl" else "")
87 val confFile = fullHost ^ (if Option.isSome ssl then ".vhost_ssl" else ".vhost")
88 in
b5f2d506 89 app (fn (node, ip) =>
1c9b5e20
AC
90 let
91 val file = Domain.domainFile {node = node,
92 name = confFile}
93 fun print s = TextIO.output (file, s)
94
95 val ld = Apache.logDir {user = user, node = node, vhostId = vhostId}
96 in
954e17ad
AC
97 print "# Owner: ";
98 print user;
99 print "\n";
1c9b5e20 100 print "<VirtualHost ";
b5f2d506 101 print ip;
1c9b5e20
AC
102 print ":";
103 print (case ssl of
104 SOME _ => "443"
105 | NONE => "80");
de5351c7 106 print ">\n";
3af11fe6
AC
107 print " ServerName ";
108 print host;
109 print ".";
110 print (Domain.currentDomain ());
111 print "\n";
1c9b5e20 112 print " ServerAdmin ";
e322749a
AC
113 print sadmin;
114 print "\n";
28b75d66
CE
115 (*
116 print " SuexecUserGroup list list\n";
1c9b5e20 117 print "\n";
28b75d66 118 *)
1c9b5e20
AC
119 print " ErrorLog ";
120 print ld;
121 print "/error.log\n";
122 print " CustomLog ";
123 print ld;
124 print "/access.log combined\n";
125 print "\n";
126 print " RewriteEngine on\n";
127 print "\n";
128 print " # Default to showing listinfo page\n";
4a824a5f
AC
129 print " RewriteRule ^/$ http";
130 case ssl of
131 NONE => ()
132 | SOME _ => print "s";
133 print "://";
1c9b5e20
AC
134 print fullHost;
135 print "/listinfo/\n";
136 print "\n";
137 print " Alias /images/mailman /usr/share/images/mailman\n";
138 print " Alias /pipermail /var/lib/mailman/archives/public\n";
139 print "\n";
140 print " DocumentRoot /usr/lib/cgi-bin/mailman\n";
141 print " <Directory /usr/lib/cgi-bin/mailman>\n";
142 print " AllowOverride None\n";
143 print " Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch\n";
144 print " ForceType cgi-script\n";
145 print " Order allow,deny\n";
146 print " Allow from all\n";
147 print " </Directory>\n";
148 print "\n";
149 print " <Directory /usr/share/doc/mailman>\n";
150 print " Order allow,deny\n";
151 print " Allow from all\n";
152 print " </Directory>\n";
28b75d66
CE
153 print "\n";
154 print " <Directory /var/lib/mailman/archives/public/>\n";
155 print " Options +SymlinksIfOwnerMatch -ExecCGI +Indexes\n";
156 print " Require all granted\n";
157 print " </Directory>\n";
e9f528ab 158
b5f2d506 159 Apache.doPre {user = user, nodes = map #1 places, id = vhostId, hostname = fullHost};
e9f528ab 160
1c9b5e20
AC
161 print "</VirtualHost>\n";
162
e9f528ab
AC
163 TextIO.closeOut file;
164
165 Apache.doPost ()
b5f2d506 166 end) places
1c9b5e20
AC
167 end)
168
325285ab
AC
169val mailmanChanged = ref false
170
171val () = Slave.registerPreHandler (fn () => mailmanChanged := false)
172
173val () = Slave.registerFileHandler (fn fs =>
174 let
175 val spl = OS.Path.splitDirFile (#file fs)
176 in
177 case #file spl of
3ae703b6 178 "mailman.conf" => mailmanChanged := true
325285ab
AC
179 | _ => ()
180 end)
181
182val () = Slave.registerPostHandler (fn () =>
183 if !mailmanChanged then
3ae703b6 184 (Slave.concatTo (fn s => s = "mailman.conf")
325285ab 185 Config.Mailman.mapFile;
3ae703b6 186 Slave.enumerateTo (fn s => s = "mailman.conf") ":"
5543e924
AC
187 Config.Mailman.handleDomains;
188 Slave.shellF ([Config.Mailman.reload],
325285ab
AC
189 fn cl => "Error reloading Mailman with " ^ cl))
190 else
191 ())
192
d300166d 193val () = Domain.registerDescriber (Domain.considerAll
3ae703b6 194 [Domain.Filename {filename = "mailman.conf",
d936cf4d 195 heading = "Mailman web host mapping:",
d300166d
AC
196 showEmpty = false}])
197
325285ab 198end