1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
#! /bin/sh /usr/share/dpatch/dpatch-run
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Bug #442266
## DP: r821333,r821538,r821539 from upstream svn
@DPATCH@
diff --git a/modules/cache/cache_util.c b/modules/cache/cache_util.c
index ec2d749..aec7b09 100644
--- a/modules/cache/cache_util.c
+++ b/modules/cache/cache_util.c
@@ -27,41 +27,78 @@ extern module AP_MODULE_DECLARE_DATA cache_module;
/* Determine if "url" matches the hostname, scheme and port and path
* in "filter". All but the path comparisons are case-insensitive.
*/
-static int uri_meets_conditions(apr_uri_t filter, int pathlen, apr_uri_t url)
-{
- /* Compare the hostnames */
- if(filter.hostname) {
- if (!url.hostname) {
- return 0;
- }
- else if (strcasecmp(filter.hostname, url.hostname)) {
- return 0;
- }
- }
+static int uri_meets_conditions(const apr_uri_t filter, const int pathlen,
+ const apr_uri_t url) {
+
+ /* Scheme, hostname port and local part. The filter URI and the
+ * URI we test may have the following shapes:
+ * /<path>
+ * <scheme>[:://<hostname>[:<port>][/<path>]]
+ * That is, if there is no scheme then there must be only the path,
+ * and we check only the path; if there is a scheme, we check the
+ * scheme for equality, and then if present we match the hostname,
+ * and then if present match the port, and finally the path if any.
+ *
+ * Note that this means that "/<path>" only matches local paths,
+ * and to match proxied paths one *must* specify the scheme.
+ */
- /* Compare the schemes */
- if(filter.scheme) {
- if (!url.scheme) {
- return 0;
- }
- else if (strcasecmp(filter.scheme, url.scheme)) {
+ /* Is the filter is just for a local path or a proxy URI? */
+ if (!filter.scheme) {
+ if (url.scheme || url.hostname) {
return 0;
}
}
-
- /* Compare the ports */
- if(filter.port_str) {
- if (url.port_str && filter.port != url.port) {
+ else {
+ /* The URI scheme must be present and identical except for case. */
+ if (!url.scheme || strcasecmp(filter.scheme, url.scheme)) {
return 0;
}
- /* NOTE: ap_port_of_scheme will return 0 if given NULL input */
- else if (filter.port != apr_uri_port_of_scheme(url.scheme)) {
- return 0;
+
+ /* If the filter hostname is null or empty it matches any hostname,
+ * if it begins with a "*" it matches the _end_ of the URI hostname
+ * excluding the "*", if it begins with a "." it matches the _end_
+ * of the URI * hostname including the ".", otherwise it must match
+ * the URI hostname exactly. */
+
+ if (filter.hostname && filter.hostname[0]) {
+ if (filter.hostname[0] == '.') {
+ const size_t fhostlen = strlen(filter.hostname);
+ const size_t uhostlen = url.hostname ? strlen(url.hostname) : 0;
+
+ if (fhostlen > uhostlen || strcasecmp(filter.hostname,
+ url.hostname + uhostlen - fhostlen)) {
+ return 0;
+ }
+ }
+ else if (filter.hostname[0] == '*') {
+ const size_t fhostlen = strlen(filter.hostname + 1);
+ const size_t uhostlen = url.hostname ? strlen(url.hostname) : 0;
+
+ if (fhostlen > uhostlen || strcasecmp(filter.hostname + 1,
+ url.hostname + uhostlen - fhostlen)) {
+ return 0;
+ }
+ }
+ else if (!url.hostname || strcasecmp(filter.hostname, url.hostname)) {
+ return 0;
+ }
}
- }
- else if(url.port_str && filter.scheme) {
- if (apr_uri_port_of_scheme(filter.scheme) == url.port) {
- return 0;
+
+ /* If the filter port is empty it matches any URL port.
+ * If the filter or URL port are missing, or the URL port is
+ * empty, they default to the port for their scheme. */
+
+ if (!(filter.port_str && !filter.port_str[0])) {
+ /* NOTE: ap_port_of_scheme will return 0 if given NULL input */
+ const unsigned fport = filter.port_str ? filter.port
+ : apr_uri_port_of_scheme(filter.scheme);
+ const unsigned uport = (url.port_str && url.port_str[0])
+ ? url.port : apr_uri_port_of_scheme(url.scheme);
+
+ if (fport != uport) {
+ return 0;
+ }
}
}
|