1 /* ====================================================================
2 * The Apache Software License, Version 1.1
4 * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The end-user documentation included with the redistribution,
20 * if any, must include the following acknowledgment:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowledgment may appear in the software itself,
24 * if and wherever such third-party acknowledgments normally appear.
26 * 4. The names "Apache" and "Apache Software Foundation" must
27 * not be used to endorse or promote products derived from this
28 * software without prior written permission. For written
29 * permission, please contact apache@apache.org.
31 * 5. Products derived from this software may not be called "Apache",
32 * nor may "Apache" appear in their name, without prior written
33 * permission of the Apache Software Foundation.
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * ====================================================================
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
54 * Portions of this software are based upon public domain software
55 * originally written at the National Center for Supercomputing Applications,
56 * University of Illinois, Urbana-Champaign.
61 #include "mod_cache.h"
65 /* -------------------------------------------------------------- */
67 /* return true if the request is conditional */
68 CACHE_DECLARE(int) ap_cache_request_is_conditional(request_rec *r)
70 if (apr_table_get(r->headers_in, "If-Match") ||
71 apr_table_get(r->headers_in, "If-None-Match") ||
72 apr_table_get(r->headers_in, "If-Modified-Since") ||
73 apr_table_get(r->headers_in, "If-Unmodified-Since")) {
81 /* remove other filters from filter stack */
82 CACHE_DECLARE(void) ap_cache_reset_output_filters(request_rec *r)
84 ap_filter_t *f = r->output_filters;
87 if (!strcasecmp(f->frec->name, "CORE") ||
88 !strcasecmp(f->frec->name, "CONTENT_LENGTH") ||
89 !strcasecmp(f->frec->name, "HTTP_HEADER")) {
94 ap_remove_output_filter(f);
100 CACHE_DECLARE(const char *)ap_cache_get_cachetype(request_rec *r,
101 cache_server_conf *conf,
104 const char *type = NULL;
107 /* loop through all the cacheenable entries */
108 for (i = 0; i < conf->cacheenable->nelts; i++) {
109 struct cache_enable *ent =
110 (struct cache_enable *)conf->cacheenable->elts;
111 const char *thisurl = ent[i].url;
112 const char *thistype = ent[i].type;
113 if ((thisurl) && !strncasecmp(thisurl, url, strlen(thisurl))) {
118 type = apr_pstrcat(r->pool, type, ",", thistype, NULL);
123 /* then loop through all the cachedisable entries */
124 for (i = 0; i < conf->cachedisable->nelts; i++) {
125 struct cache_disable *ent =
126 (struct cache_disable *)conf->cachedisable->elts;
127 const char *thisurl = ent[i].url;
128 if ((thisurl) && !strncasecmp(thisurl, url, strlen(thisurl))) {
137 * list is a comma-separated list of case-insensitive tokens, with
138 * optional whitespace around the tokens.
139 * The return returns 1 if the token val is found in the list, or 0
142 CACHE_DECLARE(int) ap_cache_liststr(const char *list, const char *key, char **val)
146 char valbuf[HUGE_STRING_LEN];
147 valbuf[sizeof(valbuf)-1] = 0; /* safety terminating zero */
151 while (list != NULL) {
152 p = strchr((char *) list, ',');
157 while (ap_isspace(*p));
162 while (i > 0 && ap_isspace(list[i - 1]))
164 if (i == len && strncasecmp(list, key, len) == 0) {
166 p = strchr((char *) list, ',');
167 while (ap_isspace(*list)) {
172 while (ap_isspace(*list)) {
175 strncpy(valbuf, list, MIN(p-list, sizeof(valbuf)-1));
185 /* return each comma separated token, one at a time */
186 CACHE_DECLARE(const char *)ap_cache_tokstr(apr_pool_t *p, const char *list, const char **str)
191 s = ap_strchr_c(list, ',');
196 while (apr_isspace(*s))
202 while (i > 0 && apr_isspace(list[i - 1]))
207 return apr_pstrndup(p, list, i);
214 * These functions were lifted from mod_proxy
215 * Consider putting them in APR or some other common accessable
219 * Converts apr_time_t hex digits to a time integer
221 CACHE_DECLARE(apr_time_t) ap_cache_hex2msec(const char *x)
225 for (i = 0, j = 0; i < sizeof(j) * 2; i++) {
230 else if (apr_isupper(ch))
231 j |= ch - ('A' - 10);
233 j |= ch - ('a' - 10);
239 * Converts a time integer to apr_time_t hex digits
241 CACHE_DECLARE(void) ap_cache_msec2hex(apr_time_t j, char *y)
245 for (i = (sizeof(j) * 2)-1; i >= 0; i--) {
249 y[i] = ch + ('A' - 10);
253 y[sizeof(j) * 2] = '\0';
256 static void cache_hash(const char *it, char *val, int ndepth, int nlength)
258 apr_md5_ctx_t context;
259 unsigned char digest[16];
263 static const char enc_table[64] =
264 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@";
266 apr_md5_init(&context);
267 apr_md5_update(&context, (const unsigned char *) it, strlen(it));
268 apr_md5_final(digest, &context);
270 /* encode 128 bits as 22 characters, using a modified uuencoding
271 * the encoding is 3 bytes -> 4 characters* i.e. 128 bits is
272 * 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters
274 for (i = 0, k = 0; i < 15; i += 3) {
275 x = (digest[i] << 16) | (digest[i + 1] << 8) | digest[i + 2];
276 tmp[k++] = enc_table[x >> 18];
277 tmp[k++] = enc_table[(x >> 12) & 0x3f];
278 tmp[k++] = enc_table[(x >> 6) & 0x3f];
279 tmp[k++] = enc_table[x & 0x3f];
284 tmp[k++] = enc_table[x >> 2]; /* use up 6 bits */
285 tmp[k++] = enc_table[(x << 4) & 0x3f];
287 /* now split into directory levels */
288 for (i = k = d = 0; d < ndepth; ++d) {
289 memcpy(&val[i], &tmp[k], nlength);
291 val[i + nlength] = '/';
294 memcpy(&val[i], &tmp[k], 22 - k);
295 val[i + 22 - k] = '\0';
298 CACHE_DECLARE(char *)generate_name(apr_pool_t *p, int dirlevels, int dirlength, const char *name)
301 cache_hash(name, hashfile, dirlevels, dirlength);
302 return apr_pstrdup(p, hashfile);