No more catch-all aliases, and default aliases go to a separate file
[hcoop/domtool2.git] / src / plugins / alias.sml
... / ...
CommitLineData
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(* Configuring e-mail aliases *)
20
21structure Alias :> ALIAS = struct
22
23open Ast
24
25structure SM = DataStructures.StringMap
26
27val aliases : Domain.files SM.map ref = ref SM.empty
28fun aliasesF node = valOf (SM.find (!aliases, node))
29
30val aliasesD : Domain.files SM.map ref = ref SM.empty
31fun aliasesDF node = valOf (SM.find (!aliasesD, node))
32
33fun write nodes =
34 let
35 val files = map (fn node => aliasesF node) nodes
36 in
37 (fn s => app (fn file => #write file s) files,
38 fn () => app (fn file => #writeDom file ()) files)
39 end
40
41fun writeD nodes =
42 let
43 val files = map (fn node => aliasesDF node) nodes
44 in
45 (fn s => app (fn file => #write file s) files,
46 fn () => app (fn file => #writeDom file ()) files)
47 end
48
49fun openInAll base = foldl (fn (node, r) =>
50 SM.insert (r,
51 node,
52 Domain.domainsFile {node = node, name = base}))
53 SM.empty Domain.nodes
54
55val _ = Domain.registerBefore
56 (fn _ => (aliases := openInAll "aliases";
57 aliasesD := openInAll "aliases.default"))
58
59val _ = Domain.registerAfter
60 (fn _ => (SM.app (fn file => #close file ()) (!aliases);
61 SM.app (fn file => #close file ()) (!aliasesD)))
62
63fun validEmailUser s =
64 size s > 0 andalso size s < 50
65 andalso CharVector.all (fn ch => Char.isAlphaNum ch
66 orelse ch = #"."
67 orelse ch = #"_"
68 orelse ch = #"-"
69 orelse ch = #"+") s
70
71val _ = Env.type_one "emailUser"
72 Env.string
73 validEmailUser
74
75fun validEmail s =
76 case String.fields (fn ch => ch = #"@") s of
77 [user] => validEmailUser user
78 | [user, host] => validEmailUser user andalso Domain.validDomain host
79 | _ => false
80
81val _ = Env.type_one "email"
82 Env.string
83 validEmail
84
85datatype aliasSource =
86 User of string
87 | Default
88
89val source = fn (EApp ((EVar "userSource", _), e), _) =>
90 Option.map User (Env.string e)
91 | (EVar "defaultSource", _) => SOME Default
92 | _ => NONE
93
94datatype aliasTarget =
95 Address of string
96 | Addresses of string list
97 | Drop
98
99val target = fn (EApp ((EVar "addressTarget", _), e), _) =>
100 Option.map Address (Env.string e)
101 | (EApp ((EVar "addressesTarget", _), e), _) =>
102 Option.map Addresses (Env.list Env.string e)
103 | (EVar "dropTarget", _) => SOME Drop
104 | _ => NONE
105
106fun localhostify s =
107 let
108 val (prefix, suffix) = Substring.splitl (fn ch => ch <> #"@") (Substring.full s)
109 in
110 if Substring.size suffix = 0 then
111 s ^ "@localhost"
112 else
113 s
114 end
115
116fun writeSource (env, s, t) =
117 let
118 val nodes = Env.env (Env.list Env.string) (env, "MailNodes")
119
120 val (write, writeDom) = write nodes
121 val (writeD, writeDomD) = writeD nodes
122
123 fun writeTarget (writer, t) =
124 case t of
125 Address s => writer (localhostify s)
126 | Addresses [] => writer "!"
127 | Addresses ss => writer (String.concatWith "," (map localhostify ss))
128 | Drop => writer "!"
129 in
130 case s of
131 User s => (write s;
132 write "@";
133 writeDom ();
134 write ": ";
135 writeTarget (write, t);
136 write "\n")
137 | Default => (writeD "*@";
138 writeDomD ();
139 writeD ": ";
140 writeTarget (writeD, t);
141 writeD "\n")
142 end
143
144val _ = Env.actionV_two "aliasPrim"
145 ("from", source, "to", target)
146 writeSource
147
148end