Apache HTTPD
mod_mime.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * http_mime.c: Sends/gets MIME headers for requests
19 *
20 * Rob McCool
21 *
22 */
23
24#include "apr.h"
25#include "apr_strings.h"
26#include "apr_lib.h"
27#include "apr_hash.h"
28
29#define APR_WANT_STRFUNC
30#include "apr_want.h"
31
32#include "ap_config.h"
33#include "httpd.h"
34#include "http_config.h"
35#include "http_log.h"
36#include "http_request.h"
37#include "http_protocol.h"
38
39/* XXXX - fix me / EBCDIC
40 * there was a cludge here which would use its
41 * own version apr_isascii(). Indicating that
42 * on some platforms that might be needed.
43 *
44 * #define OS_ASC(c) (c) -- for mere mortals
45 * or
46 * #define OS_ASC(c) (ebcdic2ascii[c]) -- for dino's
47 *
48 * #define apr_isascii(c) ((OS_ASC(c) & 0x80) == 0)
49 */
50
51/* XXXXX - fix me - See note with NOT_PROXY
52 */
53
54typedef struct attrib_info {
55 char *name;
56 int offset;
58
59/* Information to which an extension can be mapped
60 */
61typedef struct extension_info {
62 char *forced_type; /* Additional AddTyped stuff */
63 char *encoding_type; /* Added with AddEncoding... */
64 char *language_type; /* Added with AddLanguage... */
65 char *handler; /* Added with AddHandler... */
66 char *charset_type; /* Added with AddCharset... */
67 char *input_filters; /* Added with AddInputFilter... */
68 char *output_filters; /* Added with AddOutputFilter... */
70
71#define MULTIMATCH_UNSET 0
72#define MULTIMATCH_ANY 1
73#define MULTIMATCH_NEGOTIATED 2
74#define MULTIMATCH_HANDLERS 4
75#define MULTIMATCH_FILTERS 8
76
77typedef struct {
78 apr_hash_t *extension_mappings; /* Map from extension name to
79 * extension_info structure */
80
81 apr_array_header_t *remove_mappings; /* A simple list, walked once */
82
83 char *default_language; /* Language if no AddLanguage ext found */
84
85 int multimatch; /* Extensions to include in multiview matching
86 * for filenames, e.g. Filters and Handlers
87 */
88 int use_path_info; /* If set to 0, only use filename.
89 * If set to 1, append PATH_INFO to filename for
90 * lookups.
91 * If set to 2, this value is unset and is
92 * effectively 0.
93 */
95
96typedef struct param_s {
97 char *attr;
98 char *val;
99 struct param_s *next;
101
109
110static char tspecial[] = {
111 '(', ')', '<', '>', '@', ',', ';', ':',
112 '\\', '"', '/', '[', ']', '?', '=',
113 '\0'
114};
115
116module AP_MODULE_DECLARE_DATA mime_module;
117
119{
121
122 new->extension_mappings = NULL;
123 new->remove_mappings = NULL;
124
125 new->default_language = NULL;
126
127 new->multimatch = MULTIMATCH_UNSET;
128
129 new->use_path_info = 2;
130
131 return new;
132}
133/*
134 * Overlay one hash table of extension_mappings onto another
135 */
137 const void *key,
139 const void *overlay_val,
140 const void *base_val,
141 const void *data)
142{
146
147 if (overlay_info->forced_type) {
148 new_info->forced_type = overlay_info->forced_type;
149 }
150 if (overlay_info->encoding_type) {
151 new_info->encoding_type = overlay_info->encoding_type;
152 }
153 if (overlay_info->language_type) {
154 new_info->language_type = overlay_info->language_type;
155 }
156 if (overlay_info->handler) {
157 new_info->handler = overlay_info->handler;
158 }
159 if (overlay_info->charset_type) {
160 new_info->charset_type = overlay_info->charset_type;
161 }
162 if (overlay_info->input_filters) {
163 new_info->input_filters = overlay_info->input_filters;
164 }
165 if (overlay_info->output_filters) {
166 new_info->output_filters = overlay_info->output_filters;
167 }
168
169 return new_info;
170}
171
172/* Member is the offset within an extension_info of the pointer to reset
173 */
176{
177 attrib_info *suffix = (attrib_info *) remove->elts;
178 int i;
179 for (i = 0; i < remove->nelts; i++) {
181 suffix[i].name,
183 if (exinfo && *(const char**)((char *)exinfo + suffix[i].offset)) {
185 exinfo = apr_pmemdup(p, copyinfo, sizeof(*exinfo));
188
189 *(const char**)((char *)exinfo + suffix[i].offset) = NULL;
190 }
191 }
192}
193
194static void *merge_mime_dir_configs(apr_pool_t *p, void *basev, void *addv)
195{
199
200 if (base->extension_mappings && add->extension_mappings) {
201 new->extension_mappings = apr_hash_merge(p, add->extension_mappings,
202 base->extension_mappings,
204 NULL);
205 }
206 else {
207 if (base->extension_mappings == NULL) {
208 new->extension_mappings = add->extension_mappings;
209 }
210 else {
211 new->extension_mappings = base->extension_mappings;
212 }
213 /* We may not be merging the tables, but if we potentially will change
214 * an exinfo member, then we are about to trounce it anyways.
215 * We must have a copy for safety.
216 */
217 if (new->extension_mappings && add->remove_mappings) {
218 new->extension_mappings =
219 apr_hash_copy(p, new->extension_mappings);
220 }
221 }
222
223 if (new->extension_mappings) {
224 if (add->remove_mappings)
225 remove_items(p, add->remove_mappings, new->extension_mappings);
226 }
227 new->remove_mappings = NULL;
228
229 new->default_language = add->default_language ?
230 add->default_language : base->default_language;
231
232 new->multimatch = (add->multimatch != MULTIMATCH_UNSET) ?
233 add->multimatch : base->multimatch;
234
235 if ((add->use_path_info & 2) == 0) {
236 new->use_path_info = add->use_path_info;
237 }
238 else {
239 new->use_path_info = base->use_path_info;
240 }
241
242 return new;
243}
244
245static const char *add_extension_info(cmd_parms *cmd, void *m_,
246 const char *value_, const char* ext)
247{
250 int offset = (int) (long) cmd->info;
251 char *key = apr_pstrdup(cmd->temp_pool, ext);
252 char *value = apr_pstrdup(cmd->pool, value_);
255
256 if (*key == '.') {
257 ++key;
258 }
259 if (!m->extension_mappings) {
260 m->extension_mappings = apr_hash_make(cmd->pool);
261 exinfo = NULL;
262 }
263 else {
264 exinfo = (extension_info*)apr_hash_get(m->extension_mappings, key,
266 }
267 if (!exinfo) {
268 exinfo = apr_pcalloc(cmd->pool, sizeof(extension_info));
269 key = apr_pstrdup(cmd->pool, key);
270 apr_hash_set(m->extension_mappings, key, APR_HASH_KEY_STRING, exinfo);
271 }
272 *(const char**)((char *)exinfo + offset) = value;
273 return NULL;
274}
275
276/*
277 * As RemoveType should also override the info from TypesConfig, we add an
278 * empty string as type instead of actually removing the type.
279 */
280static const char *remove_extension_type(cmd_parms *cmd, void *m_,
281 const char *ext)
282{
283 return add_extension_info(cmd, m_, "", ext);
284}
285
286/*
287 * Note handler names are un-added with each per_dir_config merge.
288 * This keeps the association from being inherited, but not
289 * from being re-added at a subordinate level.
290 */
291static const char *remove_extension_info(cmd_parms *cmd, void *m_,
292 const char *ext)
293{
296 if (*ext == '.') {
297 ++ext;
298 }
299 if (!m->remove_mappings) {
300 m->remove_mappings = apr_array_make(cmd->pool, 4, sizeof(*suffix));
301 }
302 suffix = (attrib_info *)apr_array_push(m->remove_mappings);
303 suffix->name = apr_pstrdup(cmd->pool, ext);
304 ap_str_tolower(suffix->name);
305 suffix->offset = (int) (long) cmd->info;
306 return NULL;
307}
308
309/* The sole bit of server configuration that the MIME module has is
310 * the name of its config file, so...
311 */
312
313static const char *set_types_config(cmd_parms *cmd, void *dummy,
314 const char *arg)
315{
316 ap_set_module_config(cmd->server->module_config, &mime_module,
317 (void *)arg);
318 return NULL;
319}
320
321static const char *multiviews_match(cmd_parms *cmd, void *m_,
322 const char *include)
323{
325 const char *errmsg;
326
328 if (errmsg != NULL) {
329 return errmsg;
330 }
331
332 if (strcasecmp(include, "Any") == 0) {
333 if (m->multimatch && (m->multimatch & ~MULTIMATCH_ANY)) {
334 return "Any is incompatible with NegotiatedOnly, "
335 "Filters and Handlers";
336 }
337 m->multimatch |= MULTIMATCH_ANY;
338 }
339 else if (strcasecmp(include, "NegotiatedOnly") == 0) {
340 if (m->multimatch && (m->multimatch & ~MULTIMATCH_NEGOTIATED)) {
341 return "NegotiatedOnly is incompatible with Any, "
342 "Filters and Handlers";
343 }
344 m->multimatch |= MULTIMATCH_NEGOTIATED;
345 }
346 else if (strcasecmp(include, "Filters") == 0) {
347 if (m->multimatch && (m->multimatch & (MULTIMATCH_NEGOTIATED
348 | MULTIMATCH_ANY))) {
349 return "Filters is incompatible with Any and NegotiatedOnly";
350 }
351 m->multimatch |= MULTIMATCH_FILTERS;
352 }
353 else if (strcasecmp(include, "Handlers") == 0) {
354 if (m->multimatch && (m->multimatch & (MULTIMATCH_NEGOTIATED
355 | MULTIMATCH_ANY))) {
356 return "Handlers is incompatible with Any and NegotiatedOnly";
357 }
358 m->multimatch |= MULTIMATCH_HANDLERS;
359 }
360 else {
361 return apr_psprintf(cmd->pool, "Unrecognized option '%s'", include);
362 }
363
364 return NULL;
365}
366
367static const command_rec mime_cmds[] =
368{
370 (void *)APR_OFFSETOF(extension_info, charset_type), OR_FILEINFO,
371 "a charset (e.g., iso-2022-jp), followed by one or more "
372 "file extensions"),
374 (void *)APR_OFFSETOF(extension_info, encoding_type), OR_FILEINFO,
375 "an encoding (e.g., gzip), followed by one or more file extensions"),
377 (void *)APR_OFFSETOF(extension_info, handler), OR_FILEINFO,
378 "a handler name followed by one or more file extensions"),
379 AP_INIT_ITERATE2("AddInputFilter", add_extension_info,
380 (void *)APR_OFFSETOF(extension_info, input_filters), OR_FILEINFO,
381 "input filter name (or ; delimited names) followed by one or "
382 "more file extensions"),
384 (void *)APR_OFFSETOF(extension_info, language_type), OR_FILEINFO,
385 "a language (e.g., fr), followed by one or more file extensions"),
386 AP_INIT_ITERATE2("AddOutputFilter", add_extension_info,
387 (void *)APR_OFFSETOF(extension_info, output_filters), OR_FILEINFO,
388 "output filter name (or ; delimited names) followed by one or "
389 "more file extensions"),
391 (void *)APR_OFFSETOF(extension_info, forced_type), OR_FILEINFO,
392 "a mime type followed by one or more file extensions"),
393 AP_INIT_TAKE1("DefaultLanguage", ap_set_string_slot,
394 (void*)APR_OFFSETOF(mime_dir_config, default_language), OR_FILEINFO,
395 "language to use for documents with no other language file extension"),
397 "NegotiatedOnly (default), Handlers and/or Filters, or Any"),
398 AP_INIT_ITERATE("RemoveCharset", remove_extension_info,
399 (void *)APR_OFFSETOF(extension_info, charset_type), OR_FILEINFO,
400 "one or more file extensions"),
401 AP_INIT_ITERATE("RemoveEncoding", remove_extension_info,
402 (void *)APR_OFFSETOF(extension_info, encoding_type), OR_FILEINFO,
403 "one or more file extensions"),
404 AP_INIT_ITERATE("RemoveHandler", remove_extension_info,
405 (void *)APR_OFFSETOF(extension_info, handler), OR_FILEINFO,
406 "one or more file extensions"),
407 AP_INIT_ITERATE("RemoveInputFilter", remove_extension_info,
408 (void *)APR_OFFSETOF(extension_info, input_filters), OR_FILEINFO,
409 "one or more file extensions"),
410 AP_INIT_ITERATE("RemoveLanguage", remove_extension_info,
411 (void *)APR_OFFSETOF(extension_info, language_type), OR_FILEINFO,
412 "one or more file extensions"),
413 AP_INIT_ITERATE("RemoveOutputFilter", remove_extension_info,
414 (void *)APR_OFFSETOF(extension_info, output_filters), OR_FILEINFO,
415 "one or more file extensions"),
417 (void *)APR_OFFSETOF(extension_info, forced_type), OR_FILEINFO,
418 "one or more file extensions"),
420 "the MIME types config file"),
421 AP_INIT_FLAG("ModMimeUsePathInfo", ap_set_flag_slot,
422 (void *)APR_OFFSETOF(mime_dir_config, use_path_info), ACCESS_CONF,
423 "Set to 'yes' to allow mod_mime to use path info for type checking"),
424 {NULL}
425};
426
428
430{
432 char l[MAX_STRING_LEN];
433 const char *types_confname = ap_get_module_config(s->module_config,
434 &mime_module);
436
437 if (!types_confname) {
439 }
440
442 if (!types_confname) {
444 "Invalid mime types config path %s",
445 (const char *)ap_get_module_config(s->module_config,
446 &mime_module));
448 }
449 if ((status = ap_pcfg_openfile(&f, ptemp, types_confname))
450 != APR_SUCCESS) {
452 "could not open mime types config file %s.",
455 }
456
458
459 while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
460 const char *ll = l, *ct;
461
462 if (l[0] == '#') {
463 continue;
464 }
465 ct = ap_getword_conf(p, &ll);
466
467 while (ll[0]) {
468 char *ext = ap_getword_conf(p, &ll);
471 }
472 }
474 return OK;
475}
476
477static const char *zap_sp(const char *s)
478{
479 if (s == NULL) {
480 return (NULL);
481 }
482 if (*s == '\0') {
483 return (s);
484 }
485
486 /* skip prefixed white space */
487 for (; *s == ' ' || *s == '\t' || *s == '\n'; s++)
488 ;
489
490 return (s);
491}
492
493static char *zap_sp_and_dup(apr_pool_t *p, const char *start,
494 const char *end, apr_size_t *len)
495{
496 while ((start < end) && apr_isspace(*start)) {
497 start++;
498 }
499 while ((end > start) && apr_isspace(*(end - 1))) {
500 end--;
501 }
502 if (len) {
503 *len = end - start;
504 }
505 return apr_pstrmemdup(p, start, end - start);
506}
507
508static int is_token(char c)
509{
510 int res;
511
513 && (strchr(tspecial, c) == NULL)) ? 1 : -1;
514 return res;
515}
516
517static int is_qtext(char c)
518{
519 int res;
520
521 res = (apr_isascii(c) && (c != '"') && (c != '\\') && (c != '\n'))
522 ? 1 : -1;
523 return res;
524}
525
526static int is_quoted_pair(const char *s)
527{
528 int res = -1;
529 int c;
530
531 if (*s == '\\') {
532 c = (int) *(s + 1);
533 if (c && apr_isascii(c)) {
534 res = 1;
535 }
536 }
537 return (res);
538}
539
540static content_type *analyze_ct(request_rec *r, const char *s)
541{
542 const char *cp, *mp;
543 char *attribute, *value;
544 int quoted = 0;
545 server_rec * ss = r->server;
546 apr_pool_t * p = r->pool;
547
549 param *pp, *npp;
550
551 /* initialize ctp */
553 ctp->type = NULL;
554 ctp->subtype = NULL;
555 ctp->param = NULL;
556
557 mp = s;
558
559 /* getting a type */
560 cp = mp;
561 while (apr_isspace(*cp)) {
562 cp++;
563 }
564 if (!*cp) {
566 "mod_mime: analyze_ct: cannot get media type from '%s'",
567 (const char *) mp);
568 return (NULL);
569 }
570 ctp->type = cp;
571 do {
572 cp++;
573 } while (*cp && (*cp != '/') && !apr_isspace(*cp) && (*cp != ';'));
574 if (!*cp || (*cp == ';')) {
576 "Cannot get media type from '%s'",
577 (const char *) mp);
578 return (NULL);
579 }
580 while (apr_isspace(*cp)) {
581 cp++;
582 }
583 if (*cp != '/') {
585 "mod_mime: analyze_ct: cannot get media type from '%s'",
586 (const char *) mp);
587 return (NULL);
588 }
589 ctp->type_len = cp - ctp->type;
590
591 cp++; /* skip the '/' */
592
593 /* getting a subtype */
594 while (apr_isspace(*cp)) {
595 cp++;
596 }
597 if (!*cp) {
599 "Cannot get media subtype.");
600 return (NULL);
601 }
602 ctp->subtype = cp;
603 do {
604 cp++;
605 } while (*cp && !apr_isspace(*cp) && (*cp != ';'));
606 ctp->subtype_len = cp - ctp->subtype;
607 while (apr_isspace(*cp)) {
608 cp++;
609 }
610
611 if (*cp == '\0') {
612 return (ctp);
613 }
614
615 /* getting parameters */
616 cp++; /* skip the ';' */
617 cp = zap_sp(cp);
618 if (cp == NULL || *cp == '\0') {
620 "Cannot get media parameter.");
621 return (NULL);
622 }
623 mp = cp;
624 attribute = NULL;
625 value = NULL;
626
627 while (cp != NULL && *cp != '\0') {
628 if (attribute == NULL) {
629 if (is_token(*cp) > 0) {
630 cp++;
631 continue;
632 }
633 else if (*cp == ' ' || *cp == '\t' || *cp == '\n') {
634 cp++;
635 continue;
636 }
637 else if (*cp == '=') {
638 attribute = zap_sp_and_dup(p, mp, cp, NULL);
639 if (attribute == NULL || *attribute == '\0') {
641 "Cannot get media parameter.");
642 return (NULL);
643 }
644 cp++;
645 cp = zap_sp(cp);
646 if (cp == NULL || *cp == '\0') {
648 "Cannot get media parameter.");
649 return (NULL);
650 }
651 mp = cp;
652 continue;
653 }
654 else {
656 "Cannot get media parameter.");
657 return (NULL);
658 }
659 }
660 else {
661 if (mp == cp) {
662 if (*cp == '"') {
663 quoted = 1;
664 cp++;
665 }
666 else {
667 quoted = 0;
668 }
669 }
670 if (quoted > 0) {
671 while (quoted && *cp != '\0') {
672 if (is_qtext(*cp) > 0) {
673 cp++;
674 }
675 else if (is_quoted_pair(cp) > 0) {
676 cp += 2;
677 }
678 else if (*cp == '"') {
679 cp++;
680 while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
681 cp++;
682 }
683 if (*cp != ';' && *cp != '\0') {
685 "Cannot get media parameter.");
686 return(NULL);
687 }
688 quoted = 0;
689 }
690 else {
692 "Cannot get media parameter.");
693 return (NULL);
694 }
695 }
696 }
697 else {
698 while (1) {
699 if (is_token(*cp) > 0) {
700 cp++;
701 }
702 else if (*cp == '\0' || *cp == ';') {
703 break;
704 }
705 else {
707 "Cannot get media parameter.");
708 return (NULL);
709 }
710 }
711 }
712 value = zap_sp_and_dup(p, mp, cp, NULL);
713 if (value == NULL || *value == '\0') {
715 "Cannot get media parameter.");
716 return (NULL);
717 }
718
719 pp = apr_palloc(p, sizeof(param));
720 pp->attr = attribute;
721 pp->val = value;
722 pp->next = NULL;
723
724 if (ctp->param == NULL) {
725 ctp->param = pp;
726 }
727 else {
728 npp = ctp->param;
729 while (npp->next) {
730 npp = npp->next;
731 }
732 npp->next = pp;
733 }
734 quoted = 0;
735 attribute = NULL;
736 value = NULL;
737 if (*cp == '\0') {
738 break;
739 }
740 cp++;
741 mp = cp;
742 }
743 }
744 return (ctp);
745}
746
747/*
748 * find_ct is the hook routine for determining content-type and other
749 * MIME-related metadata. It assumes that r->filename has already been
750 * set and stat has been called for r->finfo. It also assumes that the
751 * non-path base file name is not the empty string unless it is a dir.
752 */
754{
755 mime_dir_config *conf;
757 char *ext;
758 const char *fn, *fntmp, *type, *charset = NULL, *resource_name, *qm;
759 int found_metadata = 0;
760
761 if (r->finfo.filetype == APR_DIR) {
763 return OK;
764 }
765
766 if (!r->filename) {
767 return DECLINED;
768 }
769
771 &mime_module);
772 exception_list = apr_array_make(r->pool, 2, sizeof(char *));
773
774 /* If use_path_info is explicitly set to on (value & 1 == 1), append. */
775 if (conf->use_path_info & 1) {
777 }
778 /*
779 * In the reverse proxy case r->filename might contain a query string if
780 * the nocanon option was used with ProxyPass.
781 * If this is the case cut off the query string as the last parameter in
782 * this query string might end up on an extension we take care about, but
783 * we only want to match against path components not against query
784 * parameters.
785 */
786 else if ((r->proxyreq == PROXYREQ_REVERSE)
787 && (apr_table_get(r->notes, "proxy-nocanon"))
788 && ((qm = ap_strchr_c(r->filename, '?')) != NULL)) {
790 }
791 else {
793 }
794
795 /* Always drop the path leading up to the file name.
796 */
797 if ((fn = ap_strrchr_c(resource_name, '/')) == NULL) {
798 fn = resource_name;
799 }
800 else {
801 ++fn;
802 }
803
804
805 /* The exception list keeps track of those filename components that
806 * are not associated with extensions indicating metadata.
807 * The base name is always the first exception (i.e., "txt.html" has
808 * a basename of "txt" even though it might look like an extension).
809 * Leading dots are considered to be part of the base name (a file named
810 * ".png" is likely not a png file but just a hidden file called png).
811 */
812 fntmp = fn;
813 while (*fntmp == '.')
814 fntmp++;
815 fntmp = ap_strchr_c(fntmp, '.');
816 if (fntmp) {
817 ext = apr_pstrmemdup(r->pool, fn, fntmp - fn);
818 fn = fntmp + 1;
819 }
820 else {
821 ext = apr_pstrdup(r->pool, fn);
822 fn += strlen(fn);
823 }
824
825 *((const char **)apr_array_push(exception_list)) = ext;
826
827 /* Parse filename extensions which can be in any order
828 */
829 while (*fn && (ext = ap_getword(r->pool, &fn, '.'))) {
830 const extension_info *exinfo = NULL;
831 int found;
832 char *extcase;
833
834 if (*ext == '\0') { /* ignore empty extensions "bad..html" */
835 continue;
836 }
837
838 found = 0;
839
840 /* Save the ext in extcase before converting it to lower case.
841 */
844
845 if (conf->extension_mappings != NULL) {
848 }
849
850 if (exinfo == NULL || !exinfo->forced_type) {
853 ap_set_content_type_ex(r, (char*) type, 1);
854 found = 1;
855 }
856 }
857
858 if (exinfo != NULL) {
859
860 /* empty string is treated as special case for RemoveType */
861 if (exinfo->forced_type && *exinfo->forced_type) {
862 ap_set_content_type_ex(r, exinfo->forced_type, 1);
863 found = 1;
864 }
865
866 if (exinfo->charset_type) {
867 charset = exinfo->charset_type;
868 found = 1;
869 }
870 if (exinfo->language_type) {
871 if (!r->content_languages) {
873 sizeof(char *));
874 }
875 *((const char **)apr_array_push(r->content_languages))
876 = exinfo->language_type;
877 found = 1;
878 }
879 if (exinfo->encoding_type) {
880 if (!r->content_encoding) {
881 r->content_encoding = exinfo->encoding_type;
882 }
883 else {
884 /* XXX should eliminate duplicate entities
885 *
886 * ah no. Order is important and double encoding is neither
887 * forbidden nor impossible. -- nd
888 */
891 ", ",
892 exinfo->encoding_type,
893 NULL);
894 }
895 found = 1;
896 }
897 /* The following extensions are not 'Found'. That is, they don't
898 * make any contribution to metadata negotiation, so they must have
899 * been explicitly requested by name.
900 */
901 if (exinfo->handler && r->proxyreq == PROXYREQ_NONE) {
902 r->handler = exinfo->handler;
903 if (conf->multimatch & MULTIMATCH_HANDLERS) {
904 found = 1;
905 }
906 }
907 /* XXX Two significant problems; 1, we don't check to see if we are
908 * setting redundant filters. 2, we insert these in the types
909 * config hook, which may be too early (dunno.)
910 */
911 if (exinfo->input_filters) {
912 const char *filter, *filters = exinfo->input_filters;
913 while (*filters
914 && (filter = ap_getword(r->pool, &filters, ';'))) {
916 }
917 if (conf->multimatch & MULTIMATCH_FILTERS) {
918 found = 1;
919 }
920 }
921 if (exinfo->output_filters) {
922 const char *filter, *filters = exinfo->output_filters;
923 while (*filters
924 && (filter = ap_getword(r->pool, &filters, ';'))) {
926 }
927 if (conf->multimatch & MULTIMATCH_FILTERS) {
928 found = 1;
929 }
930 }
931 }
932
933 if (found || (conf->multimatch & MULTIMATCH_ANY)) {
934 found_metadata = 1;
935 }
936 else {
937 *((const char **) apr_array_push(exception_list)) = extcase;
938 }
939 }
940
941 /*
942 * Need to set a notes entry on r for unrecognized elements.
943 * Somebody better claim them! If we did absolutely nothing,
944 * skip the notes to alert mod_negotiation we are clueless.
945 */
946 if (found_metadata) {
947 apr_table_setn(r->notes, "ap-mime-exceptions-list",
948 (void *)exception_list);
949 }
950
951 if (r->content_type) {
953 int override = 0;
954
955 if ((ctp = analyze_ct(r, r->content_type))) {
956 param *pp = ctp->param;
957 char *base_content_type = apr_palloc(r->pool, ctp->type_len +
958 ctp->subtype_len +
959 sizeof("/"));
960 char *tmp = base_content_type;
961 memcpy(tmp, ctp->type, ctp->type_len);
962 tmp += ctp->type_len;
963 *tmp++ = '/';
964 memcpy(tmp, ctp->subtype, ctp->subtype_len);
965 tmp += ctp->subtype_len;
966 *tmp = 0;
968 while (pp != NULL) {
969 if (charset && !strcmp(pp->attr, "charset")) {
970 if (!override) {
974 "; charset=",
975 charset,
977 override = 1;
978 }
979 }
980 else {
984 "; ", pp->attr,
985 "=", pp->val,
987 }
988 pp = pp->next;
989 }
990 if (charset && !override) {
992 "; charset=", charset,
994 }
995 }
996 }
997
998 /* Set default language, if none was specified by the extensions
999 * and we have a DefaultLanguage setting in force
1000 */
1001
1002 if (!r->content_languages && conf->default_language) {
1003 const char **new;
1004
1005 r->content_languages = apr_array_make(r->pool, 2, sizeof(char *));
1006 new = (const char **)apr_array_push(r->content_languages);
1007 *new = conf->default_language;
1008 }
1009
1010 if (!r->content_type) {
1011 return DECLINED;
1012 }
1013
1014 return OK;
1015}
1016
1018{
1021 /*
1022 * this hook seems redundant ... is there any reason a type checker isn't
1023 * allowed to do this already? I'd think that fixups in general would be
1024 * the last opportunity to get the filters right.
1025 * ap_hook_insert_filter(mime_insert_filters,NULL,NULL,APR_HOOK_MIDDLE);
1026 */
1027}
1028
1031 create_mime_dir_config, /* create per-directory config structure */
1032 merge_mime_dir_configs, /* merge per-directory config structures */
1033 NULL, /* create per-server config structure */
1034 NULL, /* merge per-server config structures */
1035 mime_cmds, /* command apr_table_t */
1036 register_hooks /* register hooks */
1037};
Symbol export macros and hook functions.
const char apr_size_t len
Definition ap_regex.h:187
APR Hash Tables.
APR general purpose library routines.
APR Strings library.
APR Standard Headers Support.
return found
Definition core.c:2840
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
#define AP_INIT_ITERATE2(directive, func, mconfig, where, help)
int ap_cfg_closefile(ap_configfile_t *cfp)
Definition util.c:931
void ap_hook_post_config(ap_HOOK_post_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:105
apr_status_t ap_pcfg_openfile(ap_configfile_t **ret_cfg, apr_pool_t *p, const char *name)
Definition util.c:957
#define AP_DECLARE_MODULE(foo)
#define AP_INIT_FLAG(directive, func, mconfig, where, help)
ap_conf_vector_t * base
#define AP_INIT_ITERATE(directive, func, mconfig, where, help)
char * ap_server_root_relative(apr_pool_t *p, const char *fname)
Definition config.c:1594
const char * ap_set_string_slot(cmd_parms *cmd, void *struct_ptr, const char *arg)
Definition config.c:1469
#define ap_set_module_config(v, m, val)
const char * ap_set_flag_slot(cmd_parms *cmd, void *struct_ptr, int arg)
Definition config.c:1512
request_rec * r
apr_status_t ap_cfg_getline(char *buf, apr_size_t bufsize, ap_configfile_t *cfp)
Definition util.c:1198
#define MAX_STRING_LEN
Definition httpd.h:300
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#define AP_TYPES_CONFIG_FILE
Definition httpd.h:228
ap_filter_t * ap_add_input_filter(const char *name, void *ctx, request_rec *r, conn_rec *c)
ap_filter_t * ap_add_output_filter(const char *name, void *ctx, request_rec *r, conn_rec *c)
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_ERR
Definition http_log.h:67
#define ap_log_error
Definition http_log.h:370
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_WARNING
Definition http_log.h:68
void ap_set_content_type_ex(request_rec *r, const char *ct, int trusted)
void ap_hook_type_checker(ap_HOOK_type_checker_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition request.c:89
void * dummy
Definition http_vhost.h:62
void const char * arg
Definition http_vhost.h:63
#define AP_REQUEST_IS_TRUSTED_CT(r)
Definition httpd.h:696
#define APR_EBADPATH
Definition apr_errno.h:332
apr_file_t * f
apr_file_t apr_off_t start
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
Definition apr_dbd.h:287
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
#define ACCESS_CONF
#define RSRC_CONF
#define OR_FILEINFO
#define HTTP_INTERNAL_SERVER_ERROR
Definition httpd.h:535
#define STANDARD20_MODULE_STUFF
char * ap_getword(apr_pool_t *p, const char **line, char stop)
Definition util.c:723
#define ap_strrchr_c(s, c)
Definition httpd.h:2357
#define ap_strchr_c(s, c)
Definition httpd.h:2353
#define PROXYREQ_NONE
Definition httpd.h:1133
void ap_str_tolower(char *s)
Definition util.c:2410
#define PROXYREQ_REVERSE
Definition httpd.h:1135
char * ap_getword_conf(apr_pool_t *p, const char **line)
Definition util.c:833
const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
Definition core.c:1301
#define NOT_IN_LOCATION
apr_size_t size
#define apr_isspace(c)
Definition apr_lib.h:225
#define apr_isgraph(c)
Definition apr_lib.h:211
#define apr_isascii(c)
Definition apr_lib.h:218
const char * value
Definition apr_env.h:51
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
@ APR_DIR
const char * key
apr_seek_where_t apr_off_t * offset
void * data
int type
int strcasecmp(const char *a, const char *b)
apr_ssize_t * klen
Definition apr_hash.h:71
#define APR_HASH_KEY_STRING
Definition apr_hash.h:47
apr_vformatter_buff_t * c
Definition apr_lib.h:175
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char char ** end
const char * s
Definition apr_strings.h:95
const void * m
apr_cmdtype_e cmd
int int status
#define DIR_MAGIC_TYPE
Definition httpd.h:711
Apache Configuration.
Apache Logging library.
HTTP protocol handling.
Apache Request library.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
static void remove_items(apr_pool_t *p, apr_array_header_t *remove, apr_hash_t *mappings)
Definition mod_mime.c:174
static const char * multiviews_match(cmd_parms *cmd, void *m_, const char *include)
Definition mod_mime.c:321
static int mime_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
Definition mod_mime.c:429
static const char * remove_extension_type(cmd_parms *cmd, void *m_, const char *ext)
Definition mod_mime.c:280
static char * zap_sp_and_dup(apr_pool_t *p, const char *start, const char *end, apr_size_t *len)
Definition mod_mime.c:493
static void * overlay_extension_mappings(apr_pool_t *p, const void *key, apr_ssize_t klen, const void *overlay_val, const void *base_val, const void *data)
Definition mod_mime.c:136
struct param_s param
#define MULTIMATCH_HANDLERS
Definition mod_mime.c:74
#define MULTIMATCH_FILTERS
Definition mod_mime.c:75
static content_type * analyze_ct(request_rec *r, const char *s)
Definition mod_mime.c:540
static const char * zap_sp(const char *s)
Definition mod_mime.c:477
static const char * add_extension_info(cmd_parms *cmd, void *m_, const char *value_, const char *ext)
Definition mod_mime.c:245
static apr_hash_t * mime_type_extensions
Definition mod_mime.c:427
static void register_hooks(apr_pool_t *p)
Definition mod_mime.c:1017
#define MULTIMATCH_NEGOTIATED
Definition mod_mime.c:73
static char tspecial[]
Definition mod_mime.c:110
static const char * remove_extension_info(cmd_parms *cmd, void *m_, const char *ext)
Definition mod_mime.c:291
static void * create_mime_dir_config(apr_pool_t *p, char *dummy)
Definition mod_mime.c:118
static const char * set_types_config(cmd_parms *cmd, void *dummy, const char *arg)
Definition mod_mime.c:313
#define MULTIMATCH_ANY
Definition mod_mime.c:72
static int is_token(char c)
Definition mod_mime.c:508
static int is_qtext(char c)
Definition mod_mime.c:517
#define MULTIMATCH_UNSET
Definition mod_mime.c:71
static int is_quoted_pair(const char *s)
Definition mod_mime.c:526
static int find_ct(request_rec *r)
Definition mod_mime.c:753
static void * merge_mime_dir_configs(apr_pool_t *p, void *basev, void *addv)
Definition mod_mime.c:194
static const command_rec mime_cmds[]
Definition mod_mime.c:367
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
char * name
apr_filetype_e filetype
char * name
Definition mod_mime.c:55
const char * subtype
Definition mod_mime.c:105
const char * type
Definition mod_mime.c:103
param * param
Definition mod_mime.c:107
apr_size_t subtype_len
Definition mod_mime.c:106
apr_size_t type_len
Definition mod_mime.c:104
char * input_filters
Definition mod_mime.c:67
char * forced_type
Definition mod_mime.c:62
char * charset_type
Definition mod_mime.c:66
char * output_filters
Definition mod_mime.c:68
char * language_type
Definition mod_mime.c:64
char * encoding_type
Definition mod_mime.c:63
char * handler
Definition mod_mime.c:65
apr_hash_t * extension_mappings
Definition mod_mime.c:78
apr_array_header_t * remove_mappings
Definition mod_mime.c:81
char * default_language
Definition mod_mime.c:83
char * val
Definition mod_mime.c:98
char * attr
Definition mod_mime.c:97
struct param_s * next
Definition mod_mime.c:99
A structure that represents the current request.
Definition httpd.h:845
apr_array_header_t * content_languages
Definition httpd.h:999
const char * content_type
Definition httpd.h:992
const char * handler
Definition httpd.h:994
apr_table_t * notes
Definition httpd.h:985
apr_pool_t * pool
Definition httpd.h:847
char * filename
Definition httpd.h:1018
int proxyreq
Definition httpd.h:873
conn_rec * connection
Definition httpd.h:849
apr_finfo_t finfo
Definition httpd.h:1094
server_rec * server
Definition httpd.h:851
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047
char * path_info
Definition httpd.h:1024
const char * content_encoding
Definition httpd.h:997
A structure to store information for each virtual server.
Definition httpd.h:1322
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray