diff --git a/modules/http/mod_mime.c b/modules/http/mod_mime.c index c16bd92c25..6d0e73ebea 100644 --- a/modules/http/mod_mime.c +++ b/modules/http/mod_mime.c @@ -787,6 +787,7 @@ static int find_ct(request_rec *r) char *ext; const char *type; const char *charset = NULL; + int found_any = 0; apr_array_header_t *exception_list = apr_array_make(r->pool, 2, sizeof(char *)); @@ -869,15 +870,18 @@ static int find_ct(request_rec *r) /* Not good... nobody claims it. */ - if (!found) + if (found) + found_any = 1; + else *((const char **) apr_array_push(exception_list)) = ext; } /* * Need to set a notes entry on r for unrecognized elements. - * Somebody better claim them! + * Somebody better claim them! If we did absolutely nothing, + * skip the notes to alert mod_negotiation we are clueless. */ - if (exception_list->nelts) { + if (found_any) { apr_table_setn(r->notes, "ap-mime-exceptions-list", (void *)exception_list); } diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c index 4d972b6935..30392adc82 100644 --- a/modules/mappers/mod_negotiation.c +++ b/modules/mappers/mod_negotiation.c @@ -962,36 +962,54 @@ static int read_types_multi(negotiation_state *neg) sub_req->content_type = CGI_MAGIC_TYPE; } + /* + * mod_mime will _always_ provide us the base name in the + * ap-mime-exception-list, if it processed anything. If + * this list is empty, give up immediately, there was + * nothing interesting. For example, looking at the files + * readme.txt and readme.foo, we will throw away .foo if + * it's an insignificant file (e.g. did not identify a + * language, charset, encoding, content type or handler,) + */ exception_list = (apr_array_header_t *)apr_table_get(sub_req->notes, "ap-mime-exceptions-list"); - if (exception_list) { - /* Every last missing bit danged well better be in our table! - * Simple enough for now, every unregonized bit better match - * our base name. When we break up our base name and allow - * index.en to match index.html.en, this gets tricker. - */ - char *base = apr_array_pstrcat(sub_req->pool, exception_list, '.'); - int base_len = strlen(base); - if (base_len > prefix_len -#ifdef CASE_BLIND_FILESYSTEM - || strncasecmp(base, filp, base_len) -#else - || strncmp(base, filp, base_len) -#endif - || (prefix_len > base_len && filp[base_len] != '.')) { - /* - * Something you don't know is, something you don't know... - */ - ap_destroy_sub_req(sub_req); - continue; - } + + if (!exception_list) { + ap_destroy_sub_req(sub_req); + continue; } - /* XXX If we successfully negotate ANYTHING, continue + /* + * Simple enough for now, every unregonized bit better match + * our base name. When we break up our base name and allow + * index.en to match index.html.en, this gets tricker. + * XXX: index.html.foo won't be caught by testing index.html + * since the exceptions result is index.foo - this should be + * fixed as part of a new match-parts logic here. */ - if (sub_req->status != HTTP_OK || - (!sub_req->content_type && !exception_list)) { + char *base = apr_array_pstrcat(sub_req->pool, exception_list, '.'); + int base_len = strlen(base); + if (base_len > prefix_len +#ifdef CASE_BLIND_FILESYSTEM + || strncasecmp(base, filp, base_len) +#else + || strncmp(base, filp, base_len) +#endif + || (prefix_len > base_len && filp[base_len] != '.')) { + /* + * Something you don't know is, something you don't know... + */ + ap_destroy_sub_req(sub_req); + continue; + } + + /* + * ###: be warned, the _default_ content type is already + * picked up here! If we failed the subrequest, or don't + * know what we are serving, then continue. + */ + if (sub_req->status != HTTP_OK || (!sub_req->content_type) { ap_destroy_sub_req(sub_req); continue; } @@ -999,7 +1017,6 @@ static int read_types_multi(negotiation_state *neg) /* If it's a map file, we use that instead of the map * we're building... */ - if (((sub_req->content_type) && !strcmp(sub_req->content_type, MAP_FILE_MAGIC_TYPE)) || ((sub_req->handler) &&