Commit 5417be45 authored by William A. Rowe Jr's avatar William A. Rowe Jr
Browse files

  Close the mod_mime file extension matching issue by (as Ken Coar suggests)
  allowing users to continue to rely on the old 1.3 behavior of matching Any
  extensions, the strict behavior of matching NegotiatedOnly arguments, or
  including Handlers and Filters with the MultiviewsMatch directive for
  mod_negotiation control.  Unfortunately, the component matching occurs
  in mod_mime, so that's where this option must reside.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@91419 13f79535-47bb-0310-9956-ffa450edef68
parent ec8ba30f
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
Changes with Apache 2.0.26-dev

  *) Introduce the MultiviewsMatch directive, to allow the operator
     to be flexible in recognizing Handlers and Filters filename
     extensions as part of the Multiviews matching logic, strict with
     MultiviewsMatch NegotiatedOnly to accept only filename extentions 
     that designate negotiated parameters, (content type, charset, etc.)
     or MultiviewsAll for the 1.3 behavior of matching any files, even
     if they have unregistered extensions.  [William Rowe]

  *) Fixed the configure script to add a LoadModule directive to
     the default httpd.conf for any module that was compiled
     as a DSO.  [Aaron Bannert <aaron@clove.org>]
+59 −3
Original line number Diff line number Diff line
@@ -110,6 +110,12 @@ typedef struct extension_info {
    char *output_filters;             /* Added with AddOutputFilter... */
} extension_info;

#define MULTIMATCH_UNSET      0
#define MULTIMATCH_ANY        1
#define MULTIMATCH_NEGOTIATED 2
#define MULTIMATCH_HANDLERS   4
#define MULTIMATCH_FILTERS    8

typedef struct {
    apr_hash_t  *extension_mappings;  /* Map from extension name to
                                       * extension_info structure */
@@ -117,8 +123,10 @@ typedef struct {
    apr_array_header_t *remove_mappings; /* A simple list, walked once */

    char *default_language;     /* Language if no AddLanguage ext found */
	                        /* Due to the FUD about JS and charsets 
                                 * default_charset is actually in src/main */

    int multimatch;       /* Extensions to include in multiview matching
                           * for filenames, e.g. Filters and Handlers 
                           */
} mime_dir_config;

typedef struct param_s {
@@ -151,6 +159,8 @@ static void *create_mime_dir_config(apr_pool_t *p, char *dummy)

    new->default_language = NULL;

    new->multimatch = MULTIMATCH_UNSET;

    return new;
}
/*
@@ -267,6 +277,9 @@ static void *merge_mime_dir_configs(apr_pool_t *p, void *basev, void *addv)
    new->default_language = add->default_language ?
        add->default_language : base->default_language;

    new->multimatch = (add->multimatch != MULTIMATCH_UNSET) ?
        add->multimatch : base->multimatch;

    return new;
}

@@ -337,6 +350,41 @@ static const char *set_types_config(cmd_parms *cmd, void *dummy,
    return NULL;
}

static const char *multiviews_match(cmd_parms *cmd, void *m_, 
                                    const char *include)
{
    mime_dir_config *m = (mime_dir_config *) m_;

    if (strcasecmp(include, "Any") == 0) {
        if (m->multimatch && (m->multimatch & ~MULTIMATCH_ANY))
            return "Any is incompatible with NegotiatedOnly, "
                   "Filters and Handlers";
        m->multimatch |= MULTIMATCH_ANY;
    }
    else if (strcasecmp(include, "NegotiatedOnly") == 0) {
        if (m->multimatch && (m->multimatch & ~MULTIMATCH_NEGOTIATED))
            return "Any is incompatible with NegotiatedOnly, "
                   "Filters and Handlers";
        m->multimatch |= MULTIMATCH_NEGOTIATED;
    }
    else if (strcasecmp(include, "Filters") == 0) {
        if (m->multimatch && (m->multimatch & (MULTIMATCH_NEGOTIATED 
                                             | MULTIMATCH_ANY)))
            return "Filters is incompatible with Any and NegotiatedOnly";
        m->multimatch |= MULTIMATCH_FILTERS;
    }
    else if (strcasecmp(include, "Handlers") == 0) {
        if (m->multimatch && (m->multimatch & (MULTIMATCH_NEGOTIATED 
                                             | MULTIMATCH_ANY)))
            return "Handlers is incompatible with Any and NegotiatedOnly";
        m->multimatch |= MULTIMATCH_HANDLERS;
    }
    else 
        return "Unrecognized option";

    return NULL;
}

static const command_rec mime_cmds[] =
{
AP_INIT_ITERATE2("AddCharset", add_extension_info, 
@@ -363,6 +411,8 @@ AP_INIT_ITERATE2("AddType", add_extension_info,
AP_INIT_TAKE1("DefaultLanguage", ap_set_string_slot,
       (void*)APR_XtOffsetOf(mime_dir_config, default_language), OR_FILEINFO,
     "language to use for documents with no other language file extension"),
AP_INIT_ITERATE("MultiviewsMatch", multiviews_match, NULL, OR_FILEINFO,
     "Handlers and/or Filters, or NegotiatedOnly (neither)"),
AP_INIT_ITERATE("RemoveCharset", remove_extension_info, 
        (void *)APR_XtOffsetOf(extension_info, charset_type), OR_FILEINFO,
     "one or more file extensions"),
@@ -780,6 +830,8 @@ static int find_ct(request_rec *r)
             */
            if (exinfo->handler && r->proxyreq == PROXYREQ_NONE) {
                r->handler = exinfo->handler;
                if (conf->multimatch & MULTIMATCH_HANDLERS)
                    found = 1;
            }
            /* XXX Two significant problems; 1, we don't check to see if we are
             * setting redundant filters.    2, we insert these in the types config
@@ -791,6 +843,8 @@ static int find_ct(request_rec *r)
                    && (filter = ap_getword(r->pool, &filters, ';'))) {
                    ap_add_input_filter(filter, NULL, r, r->connection);
                }
                if (conf->multimatch & MULTIMATCH_FILTERS)
                    found = 1;
            }
            if (exinfo->output_filters && r->proxyreq == PROXYREQ_NONE) {
                const char *filter, *filters = exinfo->output_filters;
@@ -798,10 +852,12 @@ static int find_ct(request_rec *r)
                    && (filter = ap_getword(r->pool, &filters, ';'))) {
                    ap_add_output_filter(filter, NULL, r, r->connection);
                }
                if (conf->multimatch & MULTIMATCH_FILTERS)
                    found = 1;
            }
        }

        if (found)
        if (found || (conf->multimatch & MULTIMATCH_ANY))
            found_metadata = 1;
        else
            *((const char **) apr_array_push(exception_list)) = ext;