]> granicus.if.org Git - apache/blob - modules/metadata/mod_headers.c
Update to Apache Software License version 1.1
[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 "httpd.h"
106 #include "http_config.h"
107 #include "http_request.h"
108
109 typedef enum {
110     hdr_add = 'a',              /* add header (could mean multiple hdrs) */
111     hdr_set = 's',              /* set (replace old value) */
112     hdr_append = 'm',           /* append (merge into any old value) */
113     hdr_unset = 'u'             /* unset header */
114 } hdr_actions;
115
116 typedef struct {
117     hdr_actions action;
118     char *header;
119     char *value;
120 } header_entry;
121
122 /*
123  * headers_conf is our per-module configuration. This is used as both
124  * a per-dir and per-server config
125  */
126 typedef struct {
127     ap_array_header_t *headers;
128 } headers_conf;
129
130 module MODULE_VAR_EXPORT headers_module;
131
132 static void *create_headers_config(ap_context_t *p, server_rec *s)
133 {
134     headers_conf *a =
135     (headers_conf *) ap_pcalloc(p, sizeof(headers_conf));
136
137     a->headers = ap_make_array(p, 2, sizeof(header_entry));
138     return a;
139 }
140
141 static void *create_headers_dir_config(ap_context_t *p, char *d)
142 {
143     return (headers_conf *) create_headers_config(p, NULL);
144 }
145
146 static void *merge_headers_config(ap_context_t *p, void *basev, void *overridesv)
147 {
148     headers_conf *a =
149     (headers_conf *) ap_pcalloc(p, sizeof(headers_conf));
150     headers_conf *base = (headers_conf *) basev, *overrides = (headers_conf *) overridesv;
151
152     a->headers = ap_append_arrays(p, base->headers, overrides->headers);
153
154     return a;
155 }
156
157
158 static const char *header_cmd(cmd_parms *cmd, headers_conf * dirconf, char *action, char *hdr, char *value)
159 {
160     header_entry *new;
161     server_rec *s = cmd->server;
162     headers_conf *serverconf =
163     (headers_conf *) ap_get_module_config(s->module_config, &headers_module);
164     char *colon;
165
166     if (cmd->path) {
167         new = (header_entry *) ap_push_array(dirconf->headers);
168     }
169     else {
170         new = (header_entry *) ap_push_array(serverconf->headers);
171     }
172
173     if (!strcasecmp(action, "set"))
174         new->action = hdr_set;
175     else if (!strcasecmp(action, "add"))
176         new->action = hdr_add;
177     else if (!strcasecmp(action, "append"))
178         new->action = hdr_append;
179     else if (!strcasecmp(action, "unset"))
180         new->action = hdr_unset;
181     else
182         return "first argument must be add, set, append or unset.";
183
184     if (new->action == hdr_unset) {
185         if (value)
186             return "Header unset takes two arguments";
187     }
188     else if (!value)
189         return "Header requires three arguments";
190
191     if ((colon = strchr(hdr, ':')))
192         *colon = '\0';
193
194     new->header = hdr;
195     new->value = value;
196
197     return NULL;
198 }
199
200 static const command_rec headers_cmds[] =
201 {
202     {"Header", header_cmd, NULL, OR_FILEINFO, TAKE23,
203      "an action, header and value"},
204     {NULL}
205 };
206
207 static void do_headers_fixup(request_rec *r, ap_array_header_t *headers)
208 {
209     int i;
210
211     for (i = 0; i < headers->nelts; ++i) {
212         header_entry *hdr = &((header_entry *) (headers->elts))[i];
213         switch (hdr->action) {
214         case hdr_add:
215             ap_table_addn(r->headers_out, hdr->header, hdr->value);
216             break;
217         case hdr_append:
218             ap_table_mergen(r->headers_out, hdr->header, hdr->value);
219             break;
220         case hdr_set:
221             ap_table_setn(r->headers_out, hdr->header, hdr->value);
222             break;
223         case hdr_unset:
224             ap_table_unset(r->headers_out, hdr->header);
225             break;
226         }
227     }
228
229 }
230
231 static int fixup_headers(request_rec *r)
232 {
233     void *sconf = r->server->module_config;
234     headers_conf *serverconf =
235     (headers_conf *) ap_get_module_config(sconf, &headers_module);
236     void *dconf = r->per_dir_config;
237     headers_conf *dirconf =
238     (headers_conf *) ap_get_module_config(dconf, &headers_module);
239
240     do_headers_fixup(r, serverconf->headers);
241     do_headers_fixup(r, dirconf->headers);
242
243     return DECLINED;
244 }
245 static void register_hooks(void)
246 {
247     ap_hook_fixups(fixup_headers,NULL,NULL,HOOK_MIDDLE);
248
249 module MODULE_VAR_EXPORT headers_module =
250 {
251     STANDARD20_MODULE_STUFF,
252     create_headers_dir_config,  /* dir config creater */
253     merge_headers_config,       /* dir merger --- default is to override */
254     create_headers_config,      /* server config */
255     merge_headers_config,       /* merge server configs */
256     headers_cmds,               /* command ap_table_t */
257     NULL,                       /* handlers */
258     register_hooks              /* register hooks */
259 };