]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
core: Add MaxRanges directive to control the number of ranges permitted
authorRainer Jung <rjung@apache.org>
Wed, 5 Jun 2013 15:30:40 +0000 (15:30 +0000)
committerRainer Jung <rjung@apache.org>
Wed, 5 Jun 2013 15:30:40 +0000 (15:30 +0000)
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

12 files changed:
CHANGES
STATUS
docs/conf/httpd-std.conf.in
docs/conf/httpd-win.conf
docs/manual/mod/core.xml
include/ap_mmn.h
include/http_core.h
include/http_protocol.h
modules/dav/fs/repos.c
modules/http/http_protocol.c
modules/mappers/mod_negotiation.c
server/core.c

diff --git a/CHANGES b/CHANGES
index 986fd1416430dd530ca4a7542bdfb34934e762dd..686c1a87a11722692086cbdb662e69e4b2d854f8 100644 (file)
--- 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 efb976df0ab6bfecb80b241f3390bab21d5bfc58..1deb146e48c43bfad37653a0cbd36c27b6d11ede 100644 (file)
--- 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
index d0b6e34847cba3cc7ba9534da541bc736b0203a4..0ea194e72b215b6d28f2b6ef60efe2aae596e22f 100644 (file)
@@ -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).
index 6fa2a4eb9975ecb77504efe07a9b5da3bcf8e6fe..6bc548c14fa50d9ed450d74296af0aeb60564136 100644 (file)
@@ -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).
index 91fdb330bd9cc74b1357716c0043a66375815ebf..ec6b45e9553d3cbe082bb364c70f6806f83f7bd5 100644 (file)
@@ -2112,6 +2112,41 @@ connection</description>
 </usage>
 </directivesynopsis>
 
+<directivesynopsis>
+<name>MaxRanges</name>
+<description>Number of ranges allowed before returning the complete
+resource </description>
+<syntax>MaxRanges default | unlimited | none | <var>number-of-ranges</var></syntax>
+<default>MaxRanges 200</default>
+<contextlist><context>server config</context><context>virtual host</context>
+<context>directory</context>
+</contextlist>
+<compatibility>Available in Apache HTTP Server 2.0.65 and later</compatibility>
+
+<usage>
+    <p>The <directive>MaxRanges</directive> 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.</p>
+
+    <dl>
+      <dt><strong>default</strong></dt>
+      <dd>Limits the number of ranges to a compile-time default of 200.</dd>
+
+      <dt><strong>none</strong></dt>
+      <dd>Range headers are ignored.</dd>
+
+      <dt><strong>unlimited</strong></dt>
+      <dd>The server does not limit the number of ranges it is
+          willing to satisfy.</dd>
+
+      <dt><var>number-of-ranges</var></dt>
+      <dd>A positive number representing the maximum number of ranges the
+      server is willing to satisfy.</dd>
+    </dl>
+</usage>
+</directivesynopsis>
+
 <directivesynopsis>
 <name>NameVirtualHost</name>
 <description>Designates an IP address for name-virtual
index 6d8458f65dc64e48acac5369db4211034513d247..869c8ce1e6319e4830a807f4b5add1addac7eb0b 100644 (file)
@@ -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
index 99b17a909f93c2c7911f65acbce6ca92b90d1b5d..27cf473ac0ba6de2a1149d462f2978f5e608f2a3 100644 (file)
@@ -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 */
index 356188effb82a9a772fd0514c4bc953f677a18c5..e0d1d80cf68d3fba301c13facf8c1fe3ca9701a3 100644 (file)
@@ -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.
  */
index bf8da8d021454c8c9a2faabdacda08d81873bca5..1e6d44dc790745bea87d09439b2e331e4450a4b9 100644 (file)
@@ -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);
index 6ba9adb78fdf210e13b0abebb269da513a2731cc..3d0603299af8ace97ca8bfd4fc213b5b2f3f7d5d 100644 (file)
@@ -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);
index f8214cb40073cdbddd68ec854eda8960789ca998..ec89a93762cfa264e155e898916f662394922992 100644 (file)
@@ -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 */
index a6b1b4e6fc769c97ed7df44786cfdf3a6cc60056..0c94aef4006c9edbdf97b3f07492ec57e7c0e06f 100644 (file)
@@ -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);