Skip to content

Commit 8248a82

Browse files
author
Andre Malo
committed
nobody came up with another patch or objections and it should not get lost:
add mod_version and invoke it into *x (modules = all) and win32 builds git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@103345 13f79535-47bb-0310-9956-ffa450edef68
1 parent 286e652 commit 8248a82

7 files changed

Lines changed: 470 additions & 0 deletions

File tree

Apache.dsw

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ Package=<4>
198198
Project_Dep_Name mod_usertrack
199199
End Project Dependency
200200
Begin Project Dependency
201+
Project_Dep_Name mod_version
202+
End Project Dependency
203+
Begin Project Dependency
201204
Project_Dep_Name mod_vhost_alias
202205
End Project Dependency
203206
Begin Project Dependency
@@ -1758,6 +1761,27 @@ Package=<4>
17581761

17591762
###############################################################################
17601763

1764+
Project: "mod_version"=".\modules\metadata\mod_version.dsp" - Package Owner=<4>
1765+
1766+
Package=<5>
1767+
{{{
1768+
}}}
1769+
1770+
Package=<4>
1771+
{{{
1772+
Begin Project Dependency
1773+
Project_Dep_Name libapr
1774+
End Project Dependency
1775+
Begin Project Dependency
1776+
Project_Dep_Name libaprutil
1777+
End Project Dependency
1778+
Begin Project Dependency
1779+
Project_Dep_Name libhttpd
1780+
End Project Dependency
1781+
}}}
1782+
1783+
###############################################################################
1784+
17611785
Project: "mod_vhost_alias"=".\modules\mappers\mod_vhost_alias.dsp" - Package Owner=<4>
17621786

17631787
Package=<5>

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ Changes with Apache 2.1.0-dev
22

33
[Remove entries to the current 2.0 section below, when backported]
44

5+
*) Added new module mod_version, which provides version dependent
6+
configuration containers. [Andr� Malo]
7+
58
*) Accept URLs for the ServerAdmin directive. If the supplied
69
argument is not recognized as an URL, assume it's a mail address.
710
PR 28174. [Andr� Malo]

Makefile.win

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ _build:
284284
$(MAKE) $(MAKEOPT) -f mod_setenvif.mak CFG="mod_setenvif - Win32 $(LONG)" RECURSE=0 $(CTARGET)
285285
$(MAKE) $(MAKEOPT) -f mod_unique_id.mak CFG="mod_unique_id - Win32 $(LONG)" RECURSE=0 $(CTARGET)
286286
$(MAKE) $(MAKEOPT) -f mod_usertrack.mak CFG="mod_usertrack - Win32 $(LONG)" RECURSE=0 $(CTARGET)
287+
$(MAKE) $(MAKEOPT) -f mod_version.mak CFG="mod_version - Win32 $(LONG)" RECURSE=0 $(CTARGET)
287288
cd ..\..
288289
cd modules\proxy
289290
$(MAKE) $(MAKEOPT) -f mod_proxy.mak CFG="mod_proxy - Win32 $(LONG)" RECURSE=0 $(CTARGET)
@@ -420,6 +421,7 @@ _copybin:
420421
copy modules\metadata\$(LONG)\mod_setenvif.$(src_so) "$(inst_so)" <.y
421422
copy modules\metadata\$(LONG)\mod_unique_id.$(src_so) "$(inst_so)" <.y
422423
copy modules\metadata\$(LONG)\mod_usertrack.$(src_so) "$(inst_so)" <.y
424+
copy modules\metadata\$(LONG)\mod_version.$(src_so) "$(inst_so)" <.y
423425
copy modules\proxy\$(LONG)\mod_proxy.$(src_so) "$(inst_so)" <.y
424426
copy modules\proxy\$(LONG)\mod_proxy_connect.$(src_so) "$(inst_so)" <.y
425427
copy modules\proxy\$(LONG)\mod_proxy_ftp.$(src_so) "$(inst_so)" <.y

modules/metadata/config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ APACHE_MODULE(usertrack, user-session tracking, , , , [
1818

1919
APACHE_MODULE(unique_id, per-request unique ids)
2020
APACHE_MODULE(setenvif, basing ENV vars on headers, , , yes)
21+
APACHE_MODULE(version, determining httpd version in config files)
2122

2223
APACHE_MODPATH_FINISH

modules/metadata/mod_version.c

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
/* Copyright 2004 The Apache Software Foundation
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
/*
17+
* mod_version.c
18+
* Allow conditional configuration depending on the httpd version
19+
*
20+
* André Malo (nd/perlig.de), January 2004
21+
*
22+
* Some stuff coded here is heavily based on the core <IfModule>
23+
* containers.
24+
*
25+
* The module makes the following confgurations possible:
26+
*
27+
* <IfVersion op major.minor.patch>
28+
* # conditional config here ...
29+
*</IfVersion>
30+
*
31+
* where "op" is one of:
32+
* = / == equal
33+
* > greater than
34+
* >= greater or equal
35+
* < less than
36+
* <= less or equal
37+
*
38+
* If minor version and patch level are omitted they are assumed to be 0.
39+
*
40+
* Alternatively you can match the whole version (including some vendor-added
41+
* string of the CORE version, see ap_release.h) against a regular expression:
42+
*
43+
* <IfVersion op regex>
44+
* # conditional config here ...
45+
*</IfVersion>
46+
*
47+
* where "op" is one of:
48+
* = / == match; regex must be surrounded by slashes
49+
* ~ match; regex MAY NOT be surrounded by slashes
50+
*
51+
* Note that all operators may be preceeded by an exclamation mark
52+
* (without spaces) in order to reverse their meaning.
53+
*
54+
*/
55+
56+
#include "apr.h"
57+
#include "apr_strings.h"
58+
#include "apr_lib.h"
59+
60+
#include "httpd.h"
61+
#include "http_config.h"
62+
#include "http_log.h"
63+
64+
65+
/* module structure */
66+
module AP_MODULE_DECLARE_DATA version_module;
67+
68+
/* queried httpd version */
69+
static ap_version_t httpd_version;
70+
71+
72+
/*
73+
* compare the supplied version with the core one
74+
*/
75+
static int compare_version(char *version_string, const char **error)
76+
{
77+
char *p = version_string, *ep;
78+
int version[3] = {0, 0, 0};
79+
int c = 0;
80+
81+
*error = "Version appears to be invalid. It must have the format "
82+
"major[.minor[.patch]] where major, minor and patch are "
83+
"numbers.";
84+
85+
if (!apr_isdigit(*p)) {
86+
return 0;
87+
}
88+
89+
/* parse supplied version */
90+
ep = version_string + strlen(version_string);
91+
while (p <= ep && c < 3) {
92+
if (*p == '.') {
93+
*p = '\0';
94+
}
95+
96+
if (!*p) {
97+
version[c++] = atoi(version_string);
98+
version_string = ++p;
99+
continue;
100+
}
101+
102+
if (!apr_isdigit(*p)) {
103+
break;
104+
}
105+
106+
++p;
107+
}
108+
109+
if (p < ep) { /* syntax error */
110+
return 0;
111+
}
112+
113+
*error = NULL;
114+
115+
if (httpd_version.major > version[0]) {
116+
return 1;
117+
}
118+
else if (httpd_version.major < version[0]) {
119+
return -1;
120+
}
121+
else if (httpd_version.minor > version[1]) {
122+
return 1;
123+
}
124+
else if (httpd_version.minor < version[1]) {
125+
return -1;
126+
}
127+
else if (httpd_version.patch > version[2]) {
128+
return 1;
129+
}
130+
else if (httpd_version.patch < version[2]) {
131+
return -1;
132+
}
133+
134+
/* seems to be the same */
135+
return 0;
136+
}
137+
138+
/*
139+
* match version against a regular expression
140+
*/
141+
static int match_version(apr_pool_t *pool, char *version_string,
142+
const char **error)
143+
{
144+
regex_t *compiled;
145+
const char *to_match;
146+
int rc;
147+
148+
compiled = ap_pregcomp(pool, version_string, REG_EXTENDED);
149+
if (!compiled) {
150+
*error = "Unable to compile regular expression";
151+
return 0;
152+
}
153+
154+
*error = NULL;
155+
156+
to_match = apr_psprintf(pool, "%d.%d.%d%s",
157+
httpd_version.major,
158+
httpd_version.minor,
159+
httpd_version.patch,
160+
httpd_version.add_string);
161+
162+
rc = !ap_regexec(compiled, to_match, 0, NULL, 0);
163+
164+
ap_pregfree(pool, compiled);
165+
return rc;
166+
}
167+
168+
/*
169+
* Implements the <IfVersion> container
170+
*/
171+
static const char *start_ifversion(cmd_parms *cmd, void *mconfig,
172+
const char *arg1, const char *arg2,
173+
const char *arg3)
174+
{
175+
const char *endp;
176+
int reverse = 0, done = 0, match = 0, compare;
177+
const char *p, *error;
178+
char c;
179+
180+
/* supplying one argument is possible, we assume an equality check then */
181+
if (!arg2) {
182+
arg2 = arg1;
183+
arg1 = "=";
184+
}
185+
186+
/* surrounding quotes without operator */
187+
if (!arg3 && *arg2 == '>' && !arg2[1]) {
188+
arg3 = ">";
189+
arg2 = arg1;
190+
arg1 = "=";
191+
}
192+
193+
/* the third argument makes version surrounding quotes plus operator
194+
* possible.
195+
*/
196+
endp = arg2 + strlen(arg2);
197+
if ( endp == arg2
198+
|| (!(arg3 && *arg3 == '>' && !arg3[1]) && *--endp != '>')) {
199+
return apr_pstrcat(cmd->pool, cmd->cmd->name,
200+
"> directive missing closing '>'", NULL);
201+
}
202+
203+
p = arg1;
204+
if (*p == '!') {
205+
reverse = 1;
206+
if (p[1]) {
207+
++p;
208+
}
209+
}
210+
211+
c = *p++;
212+
if (!*p || (*p == '=' && !p[1] && c != '~')) {
213+
if (!httpd_version.major) {
214+
ap_get_server_revision(&httpd_version);
215+
}
216+
217+
done = 1;
218+
switch (c) {
219+
case '=':
220+
/* normal comparison */
221+
if (*arg2 != '/') {
222+
compare = compare_version(apr_pstrmemdup(cmd->pool, arg2,
223+
endp-arg2),
224+
&error);
225+
if (error) {
226+
return error;
227+
}
228+
229+
match = !compare;
230+
break;
231+
}
232+
233+
/* regexp otherwise */
234+
if (endp == ++arg2 || *--endp != '/') {
235+
return "Missing delimiting / of regular expression.";
236+
}
237+
238+
case '~':
239+
/* regular expression */
240+
match = match_version(cmd->pool, apr_pstrmemdup(cmd->pool, arg2,
241+
endp-arg2),
242+
&error);
243+
if (error) {
244+
return error;
245+
}
246+
break;
247+
248+
case '<':
249+
compare = compare_version(apr_pstrmemdup(cmd->pool, arg2,
250+
endp-arg2),
251+
&error);
252+
if (error) {
253+
return error;
254+
}
255+
256+
match = ((-1 == compare) || (*p && !compare));
257+
break;
258+
259+
case '>':
260+
compare = compare_version(apr_pstrmemdup(cmd->pool, arg2,
261+
endp-arg2),
262+
&error);
263+
if (error) {
264+
return error;
265+
}
266+
267+
match = ((1 == compare) || (*p && !compare));
268+
break;
269+
270+
default:
271+
done = 0;
272+
break;
273+
}
274+
}
275+
276+
if (!done) {
277+
return apr_pstrcat(cmd->pool, "unrecognized operator '", arg1, "'",
278+
NULL);
279+
}
280+
281+
if ((!reverse && match) || (reverse && !match)) {
282+
ap_directive_t *parent = NULL;
283+
ap_directive_t *current = NULL;
284+
const char *retval;
285+
286+
retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
287+
&current, &parent, "<IfVersion");
288+
*(ap_directive_t **)mconfig = current;
289+
return retval;
290+
}
291+
292+
*(ap_directive_t **)mconfig = NULL;
293+
return ap_soak_end_container(cmd, "<IfVersion");
294+
}
295+
296+
static const command_rec version_cmds[] = {
297+
AP_INIT_TAKE123("<IfVersion", start_ifversion, NULL, EXEC_ON_READ | OR_ALL,
298+
"a comparison operator, a version (and a delimiter)"),
299+
{ NULL }
300+
};
301+
302+
module AP_MODULE_DECLARE_DATA version_module =
303+
{
304+
STANDARD20_MODULE_STUFF,
305+
NULL, /* dir config creater */
306+
NULL, /* dir merger --- default is to override */
307+
NULL, /* server config */
308+
NULL, /* merge server configs */
309+
version_cmds, /* command apr_table_t */
310+
NULL, /* register hooks */
311+
};

0 commit comments

Comments
 (0)