Handle hostnames with upper-case letters
[webmin.git] / apache / mod_proxy.pl
1 # mod_proxy.pl
2 # Editors for proxy directives
3
4 sub mod_proxy_directives
5 {
6 local $rv;
7 $rv = [ [ 'ProxyRequests', 0, 13, 'virtual', undef, 11 ],
8         [ 'ProxyRemote', 1, 13, 'virtual', undef, 7 ],
9         [ 'ProxyPass', 1, 10, 'virtual', undef, 0 ],
10         [ 'ProxyPassReverse', 1, 10, 'virtual', 1.306, 0 ],
11         [ 'ProxyBlock', 1, 13, 'virtual', 1.2, 9 ],
12         [ 'NoProxy', 1, 13, 'virtual', 1.3, 5 ],
13         [ 'ProxyDomain', 0, 13, 'virtual', 1.3, 4 ],
14         [ 'AllowCONNECT', 0, 13, 'virtual', 1.302, 2 ],
15         [ 'CacheRoot', 0, 13, 'virtual', -2.0, 10 ],
16         [ 'CacheSize', 0, 13, 'virtual', -2.0 ],
17         [ 'CacheGcInterval', 0, 13, 'virtual', -2.0 ],
18         [ 'CacheMaxExpire', 0, 13, 'virtual', -2.0 ],
19         [ 'CacheLastModifiedFactor', 0, 13, 'virtual', -2.0 ],
20         [ 'CacheDirLevels', 0, 13, 'virtual', -2.0 ],
21         [ 'CacheDirLength', 0, 13, 'virtual', -2.0 ],
22         [ 'CacheDefaultExpire', 0, 13, 'virtual', -2.0 ],
23         [ 'CacheForceCompletion', 0, 13, 'virtual', '1.301-2.0' ],
24         [ 'NoCache', 1, 13, 'virtual', -2.0, 3 ],
25         [ 'ProxyMaxForwards', 0, 13, 'virtual', 2.0 ],
26         [ 'ProxyPreserveHost', 0, 13, 'virtual', 2.031 ],
27         [ 'ProxyTimeout', 0, 13, 'virtual', 2.031 ],
28         [ 'ProxyVia', 0, 13, 'virtual', 2.0 ] ];
29 return &make_directives($rv, $_[0], "mod_proxy");
30 }
31
32 require 'cache.pl';
33
34 sub edit_ProxyRequests
35 {
36 return (1, $text{'mod_proxy_proxy'},
37         &choice_input($_[0]->{'value'}, "ProxyRequests", "off",
38                       "$text{'yes'},on", "$text{'no'},off"));
39 }
40 sub save_ProxyRequests
41 {
42 return &parse_choice("ProxyRequests", "off");
43 }
44
45 sub edit_ProxyRemote
46 {
47 local($rv, $i, $match, $proxy, $max);
48 $rv = "<table border>\n".
49       "<tr $tb> <td><b>$text{'mod_proxy_req'}</b></td> <td><b>$text{'mod_proxy_forw'}</b></td> </tr>\n";
50 $max = @{$_[0]}+1;
51 for($i=0; $i<$max; $i++) {
52         if ($_[0]->[$i]->{'value'} =~ /^(\S+)\s+(\S+)$/) {
53                 $match = $1; $proxy = $2;
54                 }
55         else {
56                 $match = "*"; $proxy = "";
57                 }
58         $rv .= "<tr $cb>\n";
59         $rv .= sprintf
60                 "<td><input type=radio name=ProxyRemote_match_all_$i value=1 %s> $text{'mod_proxy_all'}\n",
61                 $match eq "*" ? "checked" : "";
62         $rv .= sprintf
63                 "<input type=radio name=ProxyRemote_match_all_$i value=0 %s> $text{'mod_proxy_match'}\n",
64                 $match eq "*" ? "" : "checked";
65         $rv .= sprintf
66                 "<input name=ProxyRemote_match_$i size=20 value=\"%s\"></td>\n",
67                 $match eq "*" ? "" : $match;
68         $rv .= "<td><input name=ProxyRemote_proxy_$i size=20 ".
69                "value=\"$proxy\"></td>\n";
70         $rv .= "</tr>\n";
71         }
72 $rv .= "</table>\n";
73 return (2, $text{'mod_proxy_pass'}, $rv);
74 }
75 sub save_ProxyRemote
76 {
77 local($i, $match, $match_all, $proxy, @rv);
78 for($i=0; defined($proxy = $in{"ProxyRemote_proxy_$i"}); $i++) {
79         $match = $in{"ProxyRemote_match_$i"};
80         $match_all = $in{"ProxyRemote_match_all_$i"};
81         if ($match !~ /\S/ && $proxy !~ /\S/) { next; }
82         if ($match_all) { $match = "*"; }
83         elsif ($match !~ /^\S+$/) { &error(&text('mod_proxy_erequest', $match)); }
84         $proxy =~ /^http:\/\/\S+$/ || &error(&text('mod_proxy_epurl', $proxy));
85         push(@rv, "$match $proxy");
86         }
87 return ( \@rv );
88 }
89
90 sub edit_ProxyPass
91 {
92 return (2, $text{'mod_proxy_map'},
93         &proxy_pass_input($_[0], "ProxyPass", $_[1]));
94 }
95 sub save_ProxyPass
96 {
97 return &parse_proxy_pass("ProxyPass");
98 }
99
100 sub edit_ProxyPassReverse
101 {
102 return (2, $text{'mod_proxy_headers'},
103         &proxy_pass_input($_[0], "ProxyPassReverse", $_[1]));
104 }
105 sub save_ProxyPassReverse
106 {
107 return &parse_proxy_pass("ProxyPassReverse");
108 }
109
110 # proxy_pass_input(&directives, name, &config)
111 sub proxy_pass_input
112 {
113 local($rv, $i, $path, $url, $max);
114 $rv = "<table border>\n".
115       "<tr $tb> <td><b>$text{'mod_proxy_local'}</b></td> <td><b>$text{'mod_proxy_remote'}</b></td> </tr>\n";
116 $max = @{$_[0]} + 1;
117 for($i=0; $i<$max; $i++) {
118         if ($_[0]->[$i]->{'value'} =~ /^(\S+)\s+(\S+)$/) {
119                 $path = $1; $url = $2;
120                 }
121         else { $path = $url = ""; }
122         $rv .= "<tr $cb>\n";
123         $rv .= "<td>".&ui_textbox("$_[1]_path_$i", $path, 20)."</td>\n";
124         if ($_[2]->{'version'} >= 2.0) {
125                 $rv .= "<td>".&ui_opt_textbox("$_[1]_url_$i",
126                                 $url eq "!" ? undef : $url, 30,
127                                 $text{'mod_proxy_not'})."</td>\n";
128                 }
129         else {
130                 $rv .= "<td>".&ui_textbox("$_[1]_url_$i", $url, 30),"</td>";
131                 }
132         $rv .= "</tr>\n";
133         }
134 $rv .= "</table>\n";
135 return $rv;
136 }
137
138 # parse_proxy_pass(name)
139 sub parse_proxy_pass
140 {
141 local($i, $url, $path, @rv, @notrv);
142 for($i=0; defined($path = $in{"$_[0]_path_$i"}); $i++) {
143         $url = $in{"$_[0]_url_${i}_def"} ? "!" : $in{"$_[0]_url_$i"};
144         next if (!$path);
145         $path =~ /^\/\S*$/ || &error(&text('mod_proxy_elurl', $path));
146         $url =~ /^(http|https|balancer):\/\/(\S+)$/ || $url eq "!" ||
147                 &error(&text('mod_proxy_erurl', $url));
148         if ($url eq "!") {
149                 push(@notrv, "$path $url");
150                 }
151         else {
152                 push(@rv, "$path $url");
153                 }
154         }
155 return ( [ @notrv, @rv ] );
156 }
157
158 sub edit_ProxyBlock
159 {
160 local($b, @b);
161 foreach $b (@{$_[0]}) { push(@b, split(/\s+/, $b->{'value'})); }
162 return (2, $text{'mod_proxy_block'},
163         &opt_input(@b ? join(' ', @b) : undef, "ProxyBlock", $text{'mod_proxy_none3'}, 50));
164 }
165 sub save_ProxyBlock
166 {
167 return &parse_opt("ProxyBlock", '\S', $text{'mod_proxy_eblock'});
168 }
169
170 sub edit_NoProxy
171 {
172 local($n, @n, $i, $rv);
173 foreach $n (@{$_[0]}) { push(@n, split(/\s+/, $n->{'value'})); }
174 $rv = "<table border>\n".
175       "<tr $tb> <td><b>$text{'mod_proxy_type'}</b></td> <td><b>$text{'mod_proxy_noproxy'}</b></td> </tr>\n";
176 for($i=0; $i<=@n; $i++) {
177         $rv .= "<tr $cb>\n";
178         if ($i>=@n) { $type = 0; }
179         elsif ($n[$i] =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
180                 if ($4 == 0) { $type = 3; }
181                 else { $type = 0; }
182                 }
183         elsif ($n[$i] =~ /^([0-9\.]+)\/(\d+)$/) { $type = 4; }
184         elsif ($n[$i] =~ /^([0-9\.]+)$/) { $type = 3; }
185         elsif ($n[$i] =~ /^\.(\S+)$/) { $type = 2; }
186         else { $type = 1; }
187         $rv .= "<td>".&select_input($type, "NoProxy_type_$i", 0,
188                 "$text{'mod_proxy_ip'},0", "$text{'mod_proxy_host'},1",
189                 "$text{'mod_proxy_domain'},2", "$text{'mod_proxy_net'},3",
190                 "$text{'mod_proxy_netbit'},4")."</td>\n";
191         $rv .= "<td><input name=NoProxy_for_$i size=30 value=\"$n[$i]\"></td>\n";
192         $rv .= "</tr>\n";
193         }
194 $rv .= "</table>\n";
195 return (2, $text{'mod_proxy_nopass'}, $rv);
196 }
197 sub save_NoProxy
198 {
199 local($i, $type, $for, @rv);
200 for($i=0; defined($type = $in{"NoProxy_type_$i"}); $i++) {
201         $for = $in{"NoProxy_for_$i"};
202         if ($for !~ /\S/) { next; }
203         if ($type == 0) {
204                 &check_ipaddress($for) || 
205                     &check_ip6address($for) || 
206                         &error(&text('mod_proxy_eip', $for));
207                 }
208         elsif ($type == 1) {
209                 $for =~ /^[A-z0-9\-][A-z0-9\-\.]+[A-z0-9\-]$/ ||
210                         &error(&text('mod_proxy_ehost', $for));
211                 }
212         elsif ($type == 2) {
213                 $for =~ /^\.[A-z0-9\-\.]+[A-z0-9\-]$/ ||
214                         &error(&text('mod_proxy_edomain', $for));
215                 }
216         elsif ($type == 3) {
217                 if ($for =~ /^(\d+)$/) { $for .= ".0.0.0"; }
218                 elsif ($for =~ /^(\d+)\.(\d+)$/) { $for .= ".0.0"; }
219                 elsif ($for =~ /^(\d+)\.(\d+)\.(\d+)$/) { $for .= ".0"; }
220                 &check_ipaddress($for) || &error(&text('mod_proxy_enet', $for));
221                 }
222         elsif ($type == 4) {
223                 ($for =~ /^(\S+)\/(\d+)$/ &&
224                   (&check_ipaddress($1) || &check_ip6address($1)) && $2 < 32) ||
225                         &error(&text('mod_proxy_enetbit', $for));
226                 }
227         push(@rv, $for);
228         }
229 return @rv ? ( [ join(' ', @rv) ] ) : ( [ ] );
230 }
231
232 sub edit_ProxyDomain
233 {
234 return (1, $text{'mod_proxy_nodomain'},
235         &opt_input($_[0]->{'value'}, "ProxyDomain", $text{'mod_proxy_none'}, 20));
236 }
237 sub save_ProxyDomain
238 {
239 return &parse_opt("ProxyDomain", '^[A-z0-9\-]+$', $text{'mod_proxy_enodomain'});
240 }
241
242 sub edit_AllowCONNECT
243 {
244 return (1, $text{'mod_proxy_connect'},
245         &opt_input($_[0]->{'value'}, "AllowCONNECT", $text{'mod_proxy_default'}, 10));
246 }
247 sub save_AllowCONNECT
248 {
249 return &parse_opt("AllowCONNECT", '^[\d ]+$', $text{'mod_proxy_econnect'});
250 }
251
252 sub edit_ProxyMaxForwards
253 {
254 return (1, $text{'mod_proxy_maxfw'},
255         &opt_input($_[0]->{'value'}, "ProxyMaxForwards", $text{'default'}, 5));
256 }
257 sub save_ProxyMaxForwards
258 {
259 return &parse_opt("ProxyMaxForwards", '^\d+$', $text{'mod_proxy_emaxfw'});
260 }
261
262 sub edit_ProxyPreserveHost
263 {
264 return (1, $text{'mod_proxy_preserve'},
265         &choice_input($_[0]->{'value'}, "ProxyPreserveHost", "",
266               "$text{'yes'},on", "$text{'no'},off", "$text{'default'},"));
267 }
268 sub save_ProxyPreserveHost
269 {
270 return &parse_choice("ProxyPreserveHost", "");
271 }
272
273 sub edit_ProxyTimeout
274 {
275 return (1, $text{'mod_proxy_timeout'},
276         &opt_input($_[0]->{'value'}, "ProxyTimeout", $text{'default'}, 5));
277 }
278 sub save_ProxyTimeout
279 {
280 return &parse_opt("ProxyTimeout", '^\d+$', $text{'mod_proxy_etimeout'});
281 }
282
283 sub edit_ProxyVia
284 {
285 return (1, $text{'mod_proxy_via'},
286         &choice_input($_[0]->{'value'}, "ProxyVia", "",
287               "$text{'yes'},on", "$text{'no'},off", "$text{'default'},"));
288 }
289 sub save_ProxyVia
290 {
291 return &parse_choice("ProxyVia", "");
292 }
293
294
295
296 1;
297