Add default DNS mappings
[hcoop/domtool2.git] / src / plugins / alias.sml
CommitLineData
629a34f6
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(* Configuring e-mail aliases *)
20
21structure Alias :> ALIAS = struct
22
23open Ast
24
e0b0abd2 25structure SM = DataStructures.StringMap
629a34f6 26
a6b60abf 27val aliases : Domain.files SM.map ref = ref SM.empty
e0b0abd2 28fun aliasesF node = valOf (SM.find (!aliases, node))
629a34f6 29
a6b60abf 30val aliasesD : Domain.files SM.map ref = ref SM.empty
e0b0abd2
AC
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
a6b60abf
AC
37 (fn s => app (fn file => #write file s) files,
38 fn () => app (fn file => #writeDom file ()) files)
e0b0abd2
AC
39 end
40
41fun writeD nodes =
42 let
43 val files = map (fn node => aliasesDF node) nodes
44 in
a6b60abf
AC
45 (fn s => app (fn file => #write file s) files,
46 fn () => app (fn file => #writeDom file ()) files)
e0b0abd2
AC
47 end
48
49fun openInAll base = foldl (fn (node, r) =>
50 SM.insert (r,
51 node,
a6b60abf 52 Domain.domainsFile {node = node, name = base}))
2ed6d0e5 53 SM.empty Domain.nodes
629a34f6
AC
54
55val _ = Domain.registerBefore
e0b0abd2
AC
56 (fn _ => (aliases := openInAll "aliases";
57 aliasesD := openInAll "aliases.default"))
629a34f6
AC
58
59val _ = Domain.registerAfter
a6b60abf
AC
60 (fn _ => (SM.app (fn file => #close file ()) (!aliases);
61 SM.app (fn file => #close file ()) (!aliasesD)))
629a34f6
AC
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 | CatchAll
89
90val source = fn (EApp ((EVar "userSource", _), e), _) =>
91 Option.map User (Env.string e)
92 | (EVar "defaultSource", _) => SOME Default
93 | (EVar "catchAllSource", _) => SOME CatchAll
94 | _ => NONE
95
96datatype aliasTarget =
97 Address of string
98 | Addresses of string list
99 | Drop
100
101val target = fn (EApp ((EVar "addressTarget", _), e), _) =>
102 Option.map Address (Env.string e)
103 | (EApp ((EVar "addressesTarget", _), e), _) =>
104 Option.map Addresses (Env.list Env.string e)
105 | (EVar "dropTarget", _) => SOME Drop
106 | _ => NONE
107
108fun localhostify s =
109 let
110 val (prefix, suffix) = Substring.splitl (fn ch => ch <> #"@") (Substring.full s)
111 in
112 if Substring.size suffix = 0 then
113 s ^ "@localhost"
114 else
115 s
116 end
117
e0b0abd2
AC
118fun writeSource (env, s, t) =
119 let
120 val nodes = Env.env (Env.list Env.string) (env, "MailNodes")
121
a6b60abf
AC
122 val (write, writeDom) = write nodes
123 val (writeD, writeDomD) = writeD nodes
e0b0abd2
AC
124
125 fun writeTarget (writer, t) =
126 case t of
127 Address s => writer (localhostify s)
128 | Addresses [] => writer "!"
129 | Addresses ss => writer (String.concatWith "," (map localhostify ss))
130 | Drop => writer "!"
131 in
132 case s of
133 User s => (write s;
134 write "@";
a6b60abf 135 writeDom ();
e0b0abd2
AC
136 write ": ";
137 writeTarget (write, t);
138 write "\n")
139 | Default => (write "*@";
a6b60abf 140 writeDom ();
e0b0abd2
AC
141 write ": ";
142 writeTarget (write, t);
143 write "\n")
144 | CatchAll => (writeD "*@";
a6b60abf 145 writeDomD ();
e0b0abd2
AC
146 writeD ": ";
147 writeTarget (writeD, t);
148 writeD "\n")
149 end
150
151val _ = Env.actionV_two "aliasPrim"
152 ("from", source, "to", target)
153 writeSource
629a34f6
AC
154
155end