From: Rainer Jung Date: Wed, 5 Jun 2013 15:30:40 +0000 (+0000) Subject: core: Add MaxRanges directive to control the number of ranges permitted X-Git-Tag: 2.0.65~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=39c454deea91edb578d5d2b7238adf4d69279d38;p=thirdparty%2Fapache%2Fhttpd.git core: Add MaxRanges directive to control the number of ranges permitted before returning the entire resource, with a default limit of 200. Set 'Accept-Ranges: none' in the case Ranges are being ignored with MaxRanges none. Backport of r1162584, r1162587, r1166282, r1166663 and r1166667 from trunk resp. r1164894, r1164896, r1166612 and r1166772 from 2.2.x. Proposed/Backported by: rjung Reviewed by: wrowe, covener git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.0.x@1489917 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 986fd141643..686c1a87a11 100644 --- a/CHANGES +++ b/CHANGES @@ -28,6 +28,13 @@ Changes with Apache 2.0.65 is enabled, could allow local users to gain privileges via a .htaccess file. [Stefan Fritsch, Greg Ames] + *) core: Add MaxRanges directive to control the number of ranges permitted + before returning the entire resource, with a default limit of 200. + [Eric Covener, Rainer Jung] + + *) Set 'Accept-Ranges: none' in the case Ranges are being ignored with + MaxRanges none. [Eric Covener, Rainer Jung] + *) mod_rewrite: Allow merging RewriteBase down to subdirectories if new option 'RewriteOptions MergeBase' is configured. [Eric Covener] diff --git a/STATUS b/STATUS index efb976df0ab..1deb146e48c 100644 --- a/STATUS +++ b/STATUS @@ -164,21 +164,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - * byterange: Backport MaxRanges configuration directive and - ap_set_accept_ranges() utility function. - Trunk patch: http://svn.apache.org/viewvc?view=revision&revision=1162584 - http://svn.apache.org/viewvc?view=revision&revision=1162584 - http://svn.apache.org/viewvc?view=revision&revision=1162587 - http://svn.apache.org/viewvc?view=revision&revision=1166282 - http://svn.apache.org/viewvc?view=revision&revision=1166663 - http://svn.apache.org/viewvc?view=revision&revision=1166667 - 2.2.x patch: http://svn.apache.org/viewvc?view=revision&revision=1164894 - http://svn.apache.org/viewvc?view=revision&revision=1164896 - http://svn.apache.org/viewvc?view=revision&revision=1166612 - http://svn.apache.org/viewvc?view=revision&revision=1166772 - 2.0.x patch: http://people.apache.org/~rjung/patches/max-ranges-2.0.patch - +1: rjung, wrowe, covener - PATCHES PROPOSED TO BACKPORT FROM TRUNK: [ please place SVN revisions from trunk here, so it is easy to diff --git a/docs/conf/httpd-std.conf.in b/docs/conf/httpd-std.conf.in index d0b6e34847c..0ea194e72b2 100644 --- a/docs/conf/httpd-std.conf.in +++ b/docs/conf/httpd-std.conf.in @@ -446,6 +446,13 @@ DefaultType text/plain # HostnameLookups Off +# +# MaxRanges: Maximum number of Ranges in a request before +# returning the entire resource, or one of the special +# values 'default', 'none' or 'unlimited'. +# Default setting is to accept 200 Ranges. +#MaxRanges unlimited + # # EnableMMAP: Control whether memory-mapping is used to deliver # files (assuming that the underlying OS supports it). diff --git a/docs/conf/httpd-win.conf b/docs/conf/httpd-win.conf index 6fa2a4eb997..6bc548c14fa 100644 --- a/docs/conf/httpd-win.conf +++ b/docs/conf/httpd-win.conf @@ -372,6 +372,13 @@ DefaultType text/plain # HostnameLookups Off +# +# MaxRanges: Maximum number of Ranges in a request before +# returning the entire resource, or one of the special +# values 'default', 'none' or 'unlimited'. +# Default setting is to accept 200 Ranges. +#MaxRanges unlimited + # # EnableMMAP: Control whether memory-mapping is used to deliver # files (assuming that the underlying OS supports it). diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml index 91fdb330bd9..ec6b45e9553 100644 --- a/docs/manual/mod/core.xml +++ b/docs/manual/mod/core.xml @@ -2112,6 +2112,41 @@ connection + +MaxRanges +Number of ranges allowed before returning the complete +resource +MaxRanges default | unlimited | none | number-of-ranges +MaxRanges 200 +server configvirtual host +directory + +Available in Apache HTTP Server 2.0.65 and later + + +

The MaxRanges directive + limits the number of HTTP ranges the server is willing to + return to the client. If more ranges then permitted are requested, + the complete resource is returned instead.

+ +
+
default
+
Limits the number of ranges to a compile-time default of 200.
+ +
none
+
Range headers are ignored.
+ +
unlimited
+
The server does not limit the number of ranges it is + willing to satisfy.
+ +
number-of-ranges
+
A positive number representing the maximum number of ranges the + server is willing to satisfy.
+
+
+
+ NameVirtualHost Designates an IP address for name-virtual diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 6d8458f65dc..869c8ce1e63 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -90,6 +90,8 @@ * 20020903.14 (2.0.64-dev) added ap_vhost_iterate_given_conn * 20020903.15 (2.0.65-dev) added state_set, options_set, baseurl_set to * rewrite_server_conf and rewrite_perdir_conf + * 20020903.16 (2.0.65) add max_ranges to core_dir_config and add + * ap_set_accept_ranges() */ #define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */ @@ -97,7 +99,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20020903 #endif -#define MODULE_MAGIC_NUMBER_MINOR 15 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 16 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/http_core.h b/include/http_core.h index 99b17a909f9..27cf473ac0b 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -524,6 +524,13 @@ typedef struct { unsigned int enable_sendfile : 2; /* files in this dir can be mmap'ed */ unsigned int allow_encoded_slashes : 1; /* URLs may contain %2f w/o being * pitched indiscriminately */ +#define AP_MAXRANGES_UNSET -1 +#define AP_MAXRANGES_DEFAULT -2 +#define AP_MAXRANGES_UNLIMITED -3 +#define AP_MAXRANGES_NORANGES 0 + /** Number of Ranges before returning HTTP_OK. **/ + int max_ranges; + } core_dir_config; /* Per-server core configuration */ diff --git a/include/http_protocol.h b/include/http_protocol.h index 356188effb8..e0d1d80cf68 100644 --- a/include/http_protocol.h +++ b/include/http_protocol.h @@ -321,6 +321,13 @@ AP_DECLARE(void) ap_clear_method_list(ap_method_list_t *l); */ AP_DECLARE(void) ap_set_content_type(request_rec *r, const char *ct); +/** + * Set the Accept-Ranges header for this response + * @param r The current request + */ +AP_DECLARE(void) ap_set_accept_ranges(request_rec *r); + + /* Hmmm... could macrofy these for now, and maybe forever, though the * definitions of the macros would get a whole lot hairier. */ diff --git a/modules/dav/fs/repos.c b/modules/dav/fs/repos.c index bf8da8d0214..1e6d44dc790 100644 --- a/modules/dav/fs/repos.c +++ b/modules/dav/fs/repos.c @@ -915,7 +915,7 @@ static dav_error * dav_fs_set_headers(request_rec *r, ap_set_etag(r); /* we accept byte-ranges */ - apr_table_setn(r->headers_out, "Accept-Ranges", "bytes"); + ap_set_accept_ranges(r); /* set up the Content-Length header */ ap_set_content_length(r, resource->info->finfo.size); diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index 6ba9adb78fd..3d0603299af 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -2109,6 +2109,14 @@ AP_DECLARE(int) ap_discard_request_body(request_rec *r) return OK; } +AP_DECLARE(void) ap_set_accept_ranges(request_rec *r) +{ + core_dir_config *d = (core_dir_config *)ap_get_module_config(r->per_dir_config, + &core_module); + apr_table_setn(r->headers_out, "Accept-Ranges", + (d->max_ranges == AP_MAXRANGES_NORANGES) ? "none" + : "bytes"); +} static const char *add_optional_notes(request_rec *r, const char *prefix, const char *key, @@ -3021,6 +3029,17 @@ typedef struct indexes_t { apr_off_t end; } indexes_t; +static int get_max_ranges(request_rec *r) { + core_dir_config *core_conf = (core_dir_config *)ap_get_module_config(r->per_dir_config, + &core_module); + if (core_conf->max_ranges >= 0 || core_conf->max_ranges == AP_MAXRANGES_UNLIMITED) { + return core_conf->max_ranges; + } + + /* Any other negative val means the default */ + return AP_DEFAULT_MAX_RANGES; +} + static apr_status_t send_416(ap_filter_t *f, apr_bucket_brigade *tmpbb) { apr_bucket *e; @@ -3054,6 +3073,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f, apr_array_header_t *indexes; indexes_t *idx; int original_status; + int max_ranges = get_max_ranges(r); int i; /* @@ -3082,7 +3102,7 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f, num_ranges = ap_set_byterange(r, clength, &indexes); /* We have nothing to do, get out of the way. */ - if (num_ranges == 0 || (AP_DEFAULT_MAX_RANGES >= 0 && num_ranges > AP_DEFAULT_MAX_RANGES)) { + if (num_ranges == 0 || (max_ranges >= 0 && num_ranges > max_ranges)) { r->status = original_status; ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c index f8214cb4007..ec89a93762c 100644 --- a/modules/mappers/mod_negotiation.c +++ b/modules/mappers/mod_negotiation.c @@ -2882,7 +2882,7 @@ static int handle_map_file(request_rec *r) * ap_set_last_modified(r); * ap_set_etag(r); */ - apr_table_setn(r->headers_out, "Accept-Ranges", "bytes"); + ap_set_accept_ranges(r); ap_set_content_length(r, best->bytes); /* set MIME type and charset as negotiated */ diff --git a/server/core.c b/server/core.c index a6b1b4e6fc7..0c94aef4006 100644 --- a/server/core.c +++ b/server/core.c @@ -158,6 +158,8 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir) conf->enable_sendfile = ENABLE_SENDFILE_UNSET; conf->allow_encoded_slashes = 0; + conf->max_ranges = AP_MAXRANGES_UNSET; + return (void *)conf; } @@ -434,7 +436,9 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv) } conf->allow_encoded_slashes = new->allow_encoded_slashes; - + + conf->max_ranges = new->max_ranges != AP_MAXRANGES_UNSET ? new->max_ranges : base->max_ranges; + return (void*)conf; } @@ -2652,6 +2656,32 @@ static const char *set_limit_xml_req_body(cmd_parms *cmd, void *conf_, return NULL; } +static const char *set_max_ranges(cmd_parms *cmd, void *conf_, const char *arg) +{ + core_dir_config *conf = conf_; + int val = 0; + + if (!strcasecmp(arg, "none")) { + val = AP_MAXRANGES_NORANGES; + } + else if (!strcasecmp(arg, "default")) { + val = AP_MAXRANGES_DEFAULT; + } + else if (!strcasecmp(arg, "unlimited")) { + val = AP_MAXRANGES_UNLIMITED; + } + else { + val = atoi(arg); + if (val <= 0) + return "MaxRanges requires 'none', 'default', 'unlimited' or " + "a positive integer"; + } + + conf->max_ranges = val; + + return NULL; +} + AP_DECLARE(size_t) ap_get_limit_xml_body(const request_rec *r) { core_dir_config *conf; @@ -3289,6 +3319,10 @@ AP_INIT_TAKE1("LimitXMLRequestBody", set_limit_xml_req_body, NULL, OR_ALL, "Limit (in bytes) on maximum size of an XML-based request " "body"), +AP_INIT_TAKE1("MaxRanges", set_max_ranges, NULL, RSRC_CONF|ACCESS_CONF, + "Maximum number of Ranges in a request before returning the entire " + "resource, or 0 for unlimited"), + /* System Resource Controls */ #ifdef RLIMIT_CPU AP_INIT_TAKE12("RLimitCPU", set_limit_cpu, @@ -3600,7 +3634,7 @@ static int default_handler(request_rec *r) ap_update_mtime(r, r->finfo.mtime); ap_set_last_modified(r); ap_set_etag(r); - apr_table_setn(r->headers_out, "Accept-Ranges", "bytes"); + ap_set_accept_ranges(r); ap_set_content_length(r, r->finfo.size); if ((errstatus = ap_meets_conditions(r)) != OK) { apr_file_close(fd);