]> granicus.if.org Git - apache/blob - modules/metadata/mod_headers.c
The big change. This is part 3 of the apr-util symbols rename, please
[apache] / modules / metadata / mod_headers.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
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
17  *    distribution.
18  *
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.
25  *
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.
30  *
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.
34  *
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
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
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/>.
53  *
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.
57  */
58
59 /*
60  * mod_headers.c: Add/append/remove HTTP response headers
61  *     Written by Paul Sutton, paul@ukweb.com, 1 Oct 1996
62  *
63  * New directive, Header, can be used to add/replace/remove HTTP headers.
64  * Valid in both per-server and per-dir configurations.
65  *
66  * Syntax is:
67  *
68  *   Header action header value
69  *
70  * Where action is one of:
71  *     set    - set this header, replacing any old value
72  *     add    - add this header, possible resulting in two or more
73  *              headers with the same name
74  *     append - append this text onto any existing header of this same
75  *     unset  - remove this header
76  *
77  * Where action is unset, the third argument (value) should not be given.
78  * The header name can include the colon, or not.
79  *
80  * The Header directive can only be used where allowed by the FileInfo 
81  * override.
82  *
83  * When the request is processed, the header directives are processed in
84  * this order: firstly, the main server, then the virtual server handling
85  * this request (if any), then any <Directory> sections (working downwards 
86  * from the root dir), then an <Location> sections (working down from 
87  * shortest URL component), the any <File> sections. This order is
88  * important if any 'set' or 'unset' actions are used. For example,
89  * the following two directives have different effect if applied in
90  * the reverse order:
91  *
92  *   Header append Author "John P. Doe"
93  *   Header unset Author
94  *
95  * Examples:
96  *
97  *  To set the "Author" header, use
98  *     Header add Author "John P. Doe"
99  *
100  *  To remove a header:
101  *     Header unset Author
102  *
103  */
104
105 #include "apr_strings.h"
106 #include "httpd.h"
107 #include "http_config.h"
108 #include "http_request.h"
109
110 #ifdef HAVE_STRINGS_H
111 #include <strings.h>
112 #endif
113
114 typedef enum {
115     hdr_add = 'a',              /* add header (could mean multiple hdrs) */
116     hdr_set = 's',              /* set (replace old value) */
117     hdr_append = 'm',           /* append (merge into any old value) */
118     hdr_unset = 'u'             /* unset header */
119 } hdr_actions;
120
121 typedef struct {
122     hdr_actions action;
123     char *header;
124     const char *value;
125 } header_entry;
126
127 /*
128  * headers_conf is our per-module configuration. This is used as both
129  * a per-dir and per-server config
130  */
131 typedef struct {
132     apr_array_header_t *headers;
133 } headers_conf;
134
135 module AP_MODULE_DECLARE_DATA headers_module;
136
137 static void *create_headers_config(apr_pool_t *p, server_rec *s)
138 {
139     headers_conf *a =
140     (headers_conf *) apr_pcalloc(p, sizeof(headers_conf));
141
142     a->headers = apr_make_array(p, 2, sizeof(header_entry));
143     return a;
144 }
145
146 static void *create_headers_dir_config(apr_pool_t *p, char *d)
147 {
148     return (headers_conf *) create_headers_config(p, NULL);
149 }
150
151 static void *merge_headers_config(apr_pool_t *p, void *basev, void *overridesv)
152 {
153     headers_conf *a =
154     (headers_conf *) apr_pcalloc(p, sizeof(headers_conf));
155     headers_conf *base = (headers_conf *) basev, *overrides = (headers_conf *) overridesv;
156
157     a->headers = apr_append_arrays(p, base->headers, overrides->headers);
158
159     return a;
160 }
161
162
163 static const char *header_cmd(cmd_parms *cmd, void *indirconf,
164                               const char *action, const char *inhdr, const char *value)
165 {
166     headers_conf *dirconf = indirconf;
167     char *hdr = apr_pstrdup(cmd->pool, inhdr);
168     header_entry *new;
169     server_rec *s = cmd->server;
170     headers_conf *serverconf =
171     (headers_conf *) ap_get_module_config(s->module_config, &headers_module);
172     char *colon;
173
174     if (cmd->path) {
175         new = (header_entry *) apr_push_array(dirconf->headers);
176     }
177     else {
178         new = (header_entry *) apr_push_array(serverconf->headers);
179     }
180
181     if (!strcasecmp(action, "set"))
182         new->action = hdr_set;
183     else if (!strcasecmp(action, "add"))
184         new->action = hdr_add;
185     else if (!strcasecmp(action, "append"))
186         new->action = hdr_append;
187     else if (!strcasecmp(action, "unset"))
188         new->action = hdr_unset;
189     else
190         return "first argument must be add, set, append or unset.";
191
192     if (new->action == hdr_unset) {
193         if (value)
194             return "Header unset takes two arguments";
195     }
196     else if (!value)
197         return "Header requires three arguments";
198
199     if ((colon = strchr(hdr, ':')))
200         *colon = '\0';
201
202     new->header = hdr;
203     new->value = value;
204
205     return NULL;
206 }
207
208 static const command_rec headers_cmds[] =
209 {
210     AP_INIT_TAKE23("Header", header_cmd, NULL, OR_FILEINFO,
211                    "an action, header and value"),
212     {NULL}
213 };
214
215 static void do_headers_fixup(request_rec *r, apr_array_header_t *headers)
216 {
217     int i;
218
219     for (i = 0; i < headers->nelts; ++i) {
220         header_entry *hdr = &((header_entry *) (headers->elts))[i];
221         switch (hdr->action) {
222         case hdr_add:
223             apr_table_addn(r->headers_out, hdr->header, hdr->value);
224             break;
225         case hdr_append:
226             apr_table_mergen(r->headers_out, hdr->header, hdr->value);
227             break;
228         case hdr_set:
229             apr_table_setn(r->headers_out, hdr->header, hdr->value);
230             break;
231         case hdr_unset:
232             apr_table_unset(r->headers_out, hdr->header);
233             break;
234         }
235     }
236
237 }
238
239 static int fixup_headers(request_rec *r)
240 {
241     void *sconf = r->server->module_config;
242     headers_conf *serverconf =
243     (headers_conf *) ap_get_module_config(sconf, &headers_module);
244     void *dconf = r->per_dir_config;
245     headers_conf *dirconf =
246     (headers_conf *) ap_get_module_config(dconf, &headers_module);
247
248     do_headers_fixup(r, serverconf->headers);
249     do_headers_fixup(r, dirconf->headers);
250
251     return DECLINED;
252 }
253
254 static void register_hooks(apr_pool_t *p)
255 {
256     ap_hook_fixups(fixup_headers,NULL,NULL,APR_HOOK_MIDDLE);
257
258
259 module AP_MODULE_DECLARE_DATA headers_module =
260 {
261     STANDARD20_MODULE_STUFF,
262     create_headers_dir_config,  /* dir config creater */
263     merge_headers_config,       /* dir merger --- default is to override */
264     create_headers_config,      /* server config */
265     merge_headers_config,       /* merge server configs */
266     headers_cmds,               /* command apr_table_t */
267     register_hooks              /* register hooks */
268 };