Bump to 1.14.1
[platform/upstream/augeas.git] / lenses / httpd.aug
1 (* Apache HTTPD lens for Augeas
2
3 Authors:
4   David Lutterkort <lutter@redhat.com>
5   Francis Giraldeau <francis.giraldeau@usherbrooke.ca>
6   Raphael Pinson <raphink@gmail.com>
7
8 About: Reference
9   Online Apache configuration manual: http://httpd.apache.org/docs/trunk/
10
11 About: License
12     This file is licensed under the LGPL v2+.
13
14 About: Lens Usage
15   Sample usage of this lens in augtool
16
17   Apache configuration is represented by two main structures, nested sections
18   and directives. Sections are used as labels, while directives are kept as a
19   value. Sections and directives can have positional arguments inside values
20   of "arg" nodes. Arguments of sections must be the firsts child of the
21   section node.
22
23   This lens doesn't support automatic string quoting. Hence, the string must
24   be quoted when containing a space.
25
26   Create a new VirtualHost section with one directive:
27   > clear /files/etc/apache2/sites-available/foo/VirtualHost
28   > set /files/etc/apache2/sites-available/foo/VirtualHost/arg "172.16.0.1:80"
29   > set /files/etc/apache2/sites-available/foo/VirtualHost/directive "ServerAdmin"
30   > set /files/etc/apache2/sites-available/foo/VirtualHost/*[self::directive="ServerAdmin"]/arg "admin@example.com"
31
32 About: Configuration files
33   This lens applies to files in /etc/httpd and /etc/apache2. See <filter>.
34
35 *)
36
37
38 module Httpd =
39
40 autoload xfm
41
42 (******************************************************************
43  *                           Utilities lens
44  *****************************************************************)
45 let dels (s:string)     = del s s
46
47 (* The continuation sequence that indicates that we should consider the
48  * next line part of the current line *)
49 let cont = /\\\\\r?\n/
50
51 (* Whitespace within a line: space, tab, and the continuation sequence *)
52 let ws = /[ \t]/ | cont
53
54 (* Any possible character - '.' does not match \n *)
55 let any = /(.|\n)/
56
57 (* Any character preceded by a backslash *)
58 let esc_any = /\\\\(.|\n)/
59
60 (* Newline sequence - both for Unix and DOS newlines *)
61 let nl = /\r?\n/
62
63 (* Whitespace at the end of a line *)
64 let eol = del (ws* . nl) "\n"
65
66 (* deal with continuation lines *)
67 let sep_spc             = del ws+ " "
68 let sep_osp             = del ws* ""
69 let sep_eq              = del (ws* . "=" . ws*) "="
70
71 let nmtoken             = /[a-zA-Z:_][a-zA-Z0-9:_.-]*/
72 let word                = /[a-z][a-z0-9._-]*/i
73
74 (* A complete line that is either just whitespace or a comment that only
75  * contains whitespace *)
76 let empty = [ del (ws* . /#?/ . ws* . nl) "\n" ]
77
78 let indent              = Util.indent
79
80 (* A comment that is not just whitespace. We define it in terms of the
81  * things that are not allowed as part of such a comment:
82  *   1) Starts with whitespace
83  *   2) Ends with whitespace, a backslash or \r
84  *   3) Unescaped newlines
85  *)
86 let comment =
87   let comment_start = del (ws* . "#" . ws* ) "# " in
88   let unesc_eol = /[^\]?/ . nl in
89   let w = /[^\t\n\r \\]/ in
90   let r = /[\r\\]/ in
91   let s = /[\t\r ]/ in
92   (*
93    * we'd like to write
94    * let b = /\\\\/ in
95    * let t = /[\t\n\r ]/ in
96    * let x = b . (t? . (s|w)* ) in
97    * but the definition of b depends on commit 244c0edd in 1.9.0 and
98    * would make the lens unusable with versions before 1.9.0. So we write
99    * x out which works in older versions, too
100    *)
101   let x = /\\\\[\t\n\r ]?[^\n\\]*/ in
102   let line = ((r . s* . w|w|r) . (s|w)* . x*|(r.s* )?).w.(s*.w)* in
103   [ label "#comment" . comment_start . store line . eol ]
104
105 (* borrowed from shellvars.aug *)
106 let char_arg_sec  = /([^\\ '"\t\r\n>]|[^ '"\t\r\n>]+[^\\ \t\r\n>])|\\\\"|\\\\'|\\\\ /
107 let char_arg_wl   = /([^\\ '"},\t\r\n]|[^ '"},\t\r\n]+[^\\ '"},\t\r\n])/
108
109 let dquot =
110      let no_dquot = /[^"\\\r\n]/
111   in /"/ . (no_dquot|esc_any)* . /"/
112 let dquot_msg =
113      let no_dquot = /([^ \t"\\\r\n]|[^"\\\r\n]+[^ \t"\\\r\n])/
114   in /"/ . (no_dquot|esc_any)* . no_dquot
115
116 let squot =
117      let no_squot = /[^'\\\r\n]/
118   in /'/ . (no_squot|esc_any)* . /'/
119 let comp = /[<>=]?=/
120
121 (******************************************************************
122  *                            Attributes
123  *****************************************************************)
124
125 (* The arguments for a directive come in two flavors: quoted with single or
126  * double quotes, or bare. Bare arguments may not start with a single or
127  * double quote; since we also treat "word lists" special, i.e. lists
128  * enclosed in curly braces, bare arguments may not start with those,
129  * either.
130  *
131  * Bare arguments may not contain unescaped spaces, but we allow escaping
132  * with '\\'. Quoted arguments can contain anything, though the quote must
133  * be escaped with '\\'.
134  *)
135 let bare = /([^{"' \t\n\r]|\\\\.)([^ \t\n\r]|\\\\.)*[^ \t\n\r\\]|[^{"' \t\n\r\\]/
136
137 let arg_quoted = [ label "arg" . store (dquot|squot) ]
138 let arg_bare = [ label "arg" . store bare ]
139
140 (* message argument starts with " but ends at EOL *)
141 let arg_dir_msg = [ label "arg" . store dquot_msg ]
142 let arg_wl  = [ label "arg" . store (char_arg_wl+|dquot|squot) ]
143
144 (* comma-separated wordlist as permitted in the SSLRequire directive *)
145 let arg_wordlist =
146      let wl_start = dels "{" in
147      let wl_end   = dels "}" in
148      let wl_sep   = del /[ \t]*,[ \t]*/ ", "
149   in [ label "wordlist" . wl_start . arg_wl . (wl_sep . arg_wl)* . wl_end ]
150
151 let argv (l:lens) = l . (sep_spc . l)*
152
153 (* the arguments of a directive. We use this once we have parsed the name
154  * of the directive, and the space right after it. When dir_args is used,
155  * we also know that we have at least one argument. We need to be careful
156  * with the spacing between arguments: quoted arguments and word lists do
157  * not need to have space between them, but bare arguments do.
158  *
159  * Apache apparently is also happy if the last argument starts with a double
160  * quote, but has no corresponding closing duoble quote, which is what
161  * arg_dir_msg handles
162  *)
163 let dir_args =
164   let arg_nospc = arg_quoted|arg_wordlist in
165   (arg_bare . sep_spc | arg_nospc . sep_osp)* . (arg_bare|arg_nospc|arg_dir_msg)
166
167 let directive =
168   [ indent . label "directive" . store word .  (sep_spc . dir_args)? . eol ]
169
170 let arg_sec = [ label "arg" . store (char_arg_sec+|comp|dquot|squot) ]
171
172 let section (body:lens) =
173     (* opt_eol includes empty lines *)
174     let opt_eol = del /([ \t]*#?[ \t]*\r?\n)*/ "\n" in
175     let inner = (sep_spc . argv arg_sec)? . sep_osp .
176              dels ">" . opt_eol . ((body|comment) . (body|empty|comment)*)? .
177              indent . dels "</" in
178     let kword = key (word - /perl/i) in
179     let dword = del (word - /perl/i) "a" in
180         [ indent . dels "<" . square kword inner dword . del />[ \t\n\r]*/ ">\n" ]
181
182 let perl_section = [ indent . label "Perl" . del /<perl>/i "<Perl>"
183                    . store /[^<]*/
184                    . del /<\/perl>/i "</Perl>" . eol ]
185
186
187 let rec content = section (content|directive)
188                 | perl_section
189
190 let lns = (content|directive|comment|empty)*
191
192 let filter = (incl "/etc/apache2/apache2.conf") .
193              (incl "/etc/apache2/httpd.conf") .
194              (incl "/etc/apache2/ports.conf") .
195              (incl "/etc/apache2/conf.d/*") .
196              (incl "/etc/apache2/conf-available/*.conf") .
197              (incl "/etc/apache2/mods-available/*") .
198              (incl "/etc/apache2/sites-available/*") .
199              (incl "/etc/apache2/vhosts.d/*.conf") .
200              (incl "/etc/httpd/conf.d/*.conf") .
201              (incl "/etc/httpd/httpd.conf") .
202              (incl "/etc/httpd/conf/httpd.conf") .
203              (incl "/etc/httpd/conf.modules.d/*.conf") .
204              Util.stdexcl
205
206 let xfm = transform lns filter