]> granicus.if.org Git - apache/commitdiff
mod_mime: Add `MimeOptions`
authorEric Covener <covener@apache.org>
Wed, 13 Mar 2019 18:41:30 +0000 (18:41 +0000)
committerEric Covener <covener@apache.org>
Wed, 13 Mar 2019 18:41:30 +0000 (18:41 +0000)
mod_mime: Add `MimeOptions` directive to allow Content-Type or all metadata
detection to use only the last (right-most) file extension.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1855449 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/manual/mod/mod_mime.xml
modules/http/mod_mime.c

diff --git a/CHANGES b/CHANGES
index 55ebc0f548c54a431e2c385e2dbd6b93ff173536..f5f14f7ec70a82a65d79141fbb9e84c7cc841d7a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.1
 
+  *) mod_mime: Add `MimeOptions` directive to allow Content-Type or all metadata
+     detection to use only the last (right-most) file extension. [Eric Covener]
+
   *) MPMs unix: bind the bucket number of each child to its slot number, for a
      more efficient per bucket maintenance. [Yann Ylavic]
 
index 422b00808028f337a3417a8e02419530ceda3bb8..f50ed8f814bbb46bf91bb57d5db5cb00942c1386 100644 (file)
@@ -1051,4 +1051,38 @@ RemoveType .cgi
 <seealso><module>mod_mime_magic</module></seealso>
 </directivesynopsis>
 
+<directivesynopsis>
+<name>MimeOptions</name>
+<description>Configures mod_mime behavior</description>
+<syntax>MimeOptions<var>option</var> [<var>option</var>] ...</syntax>
+<contextlist><context>server config</context>
+<context>virtual host</context><context>directory</context>
+<context>.htaccess</context>
+<compatibility>IBM HTTP Server 9.0.0.12 and later</compatibility>
+</contextlist>
+<override>FileInfo</override>
+
+<usage>
+    <p>The <directive>MimeOptions</directive> directive configures certain
+    behaviors of <module>mod_mime</module>. <var>Option</var> can
+    be one of</p>
+
+    <dl>
+      <dt><code>TypesLastExtension</code></dt>
+      <dd>This option only consider the last (right-most) filename extension
+      when determining a files Content-Type.</dd>
+      <dt><code>NoTypesLastExtension</code></dt>
+      <dd>This option can be used to revert to the default behavior of testing
+      every filename extension when determining a files Content-Type.</dd>
+      <dt><code>AllLastExtension</code></dt>
+      <dd>This option only consider the last (right-most) filename extension
+      when determining any response metadata (Content-Type, language, encoding,
+      etc.) .</dd>
+      <dt><code>NoAllLastExtension</code></dt>
+      <dd>This option can be used to revert to the default behavior of testing
+      every filename extension when determining any response metadata
+      (Content-Type, language, encoding, etc.) .</dd>
+    </dl>
+</usage>
+</directivesynopsis>
 </modulesynopsis>
index 03d1c4110b66d367efdf8ae198ec20474b76f559..249f64e8c29f4bf8d252edd07bddc562657b1cdb 100644 (file)
@@ -91,6 +91,10 @@ typedef struct {
                            * If set to 2, this value is unset and is
                            *   effectively 0.
                            */
+    /* Only use the final extension for Content-Type */
+    enum {CT_LAST_INIT, CT_LAST_ON, CT_LAST_OFF} ct_last_ext;
+    /* Only use the final extension for anything */
+    enum {ALL_LAST_INIT, ALL_LAST_ON, ALL_LAST_OFF} all_last_ext;
 } mime_dir_config;
 
 typedef struct param_s {
@@ -127,6 +131,8 @@ static void *create_mime_dir_config(apr_pool_t *p, char *dummy)
     new->multimatch = MULTIMATCH_UNSET;
 
     new->use_path_info = 2;
+    new->ct_last_ext = CT_LAST_INIT;
+    new->all_last_ext = ALL_LAST_INIT;
 
     return new;
 }
@@ -239,6 +245,13 @@ static void *merge_mime_dir_configs(apr_pool_t *p, void *basev, void *addv)
         new->use_path_info = base->use_path_info;
     }
 
+    new->ct_last_ext = (add->ct_last_ext != CT_LAST_INIT)
+                           ? add->ct_last_ext
+                           : base->ct_last_ext;
+    new->all_last_ext = (add->all_last_ext != ALL_LAST_INIT)
+                           ? add->all_last_ext
+                           : base->all_last_ext;
+
     return new;
 }
 
@@ -364,6 +377,33 @@ static const char *multiviews_match(cmd_parms *cmd, void *m_,
     return NULL;
 }
 
+static const char *add_mime_options(cmd_parms *cmd, void *in_dc,
+                                    const char *flag)
+{
+    mime_dir_config *dc = in_dc;
+
+    if (!strcasecmp(flag, "TypesLastExtension")) {
+        dc->ct_last_ext = CT_LAST_ON;
+    }
+    else if (!strcasecmp(flag, "NoTypesLastExtension")) {
+        dc->ct_last_ext = CT_LAST_OFF;
+    }
+    else if (!strcasecmp(flag, "AllLastExtension")) {
+        dc->all_last_ext = ALL_LAST_ON;
+    }
+    else if (!strcasecmp(flag, "AllLastExtension")) {
+        dc->all_last_ext = ALL_LAST_OFF;
+    }
+    else {
+        return apr_pstrcat(cmd->temp_pool,
+                           "Invalid MimeOptions option: ",
+                           flag,
+                           NULL);
+    }
+
+    return NULL;
+}
+
 static const command_rec mime_cmds[] =
 {
     AP_INIT_ITERATE2("AddCharset", add_extension_info,
@@ -421,6 +461,11 @@ static const command_rec mime_cmds[] =
     AP_INIT_FLAG("ModMimeUsePathInfo", ap_set_flag_slot,
         (void *)APR_OFFSETOF(mime_dir_config, use_path_info), ACCESS_CONF,
         "Set to 'yes' to allow mod_mime to use path info for type checking"),
+    AP_INIT_ITERATE("MimeOptions",
+                    add_mime_options,
+                    NULL,
+                    OR_FILEINFO,
+                    "valid options: [No]TypesLastExtension, [No]AllLastExtension"),
     {NULL}
 };
 
@@ -817,11 +862,17 @@ static int find_ct(request_rec *r)
         const extension_info *exinfo = NULL;
         int found;
         char *extcase;
+        int skipct = (conf->ct_last_ext == CT_LAST_ON) && (*fn);
+        int skipall = (conf->all_last_ext == ALL_LAST_ON) && (*fn);
 
         if (*ext == '\0') {  /* ignore empty extensions "bad..html" */
             continue;
         }
 
+        if (skipall) { 
+            continue; 
+        }
+
         found = 0;
 
         /* Save the ext in extcase before converting it to lower case.
@@ -834,7 +885,7 @@ static int find_ct(request_rec *r)
                                                    ext, APR_HASH_KEY_STRING);
         }
 
-        if (exinfo == NULL || !exinfo->forced_type) {
+        if ((exinfo == NULL || !exinfo->forced_type) && !skipct) {
             if ((type = apr_hash_get(mime_type_extensions, ext,
                                      APR_HASH_KEY_STRING)) != NULL) {
                 ap_set_content_type(r, (char*) type);
@@ -845,7 +896,7 @@ static int find_ct(request_rec *r)
         if (exinfo != NULL) {
 
             /* empty string is treated as special case for RemoveType */
-            if (exinfo->forced_type && *exinfo->forced_type) {
+            if ((exinfo->forced_type && *exinfo->forced_type) && !skipct) {
                 ap_set_content_type(r, exinfo->forced_type);
                 found = 1;
             }