Commit 8296477a authored by Eric Covener's avatar Eric Covener
Browse files

mod_mime: Add `MimeOptions`

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
parent 87f16dd3
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
                                                         -*- 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]

+34 −0
Original line number Diff line number Diff line
@@ -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>
+53 −2
Original line number Diff line number Diff line
@@ -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;
            }