diff -rNU 20 ../httpd-2.2.12-o/docs/conf/httpd.conf.in ./docs/conf/httpd.conf.in
--- ../httpd-2.2.12-o/docs/conf/httpd.conf.in	2007-12-21 12:43:00.000000000 +0100
+++ ./docs/conf/httpd.conf.in	2011-09-16 15:21:48.000000000 +0200
@@ -332,40 +332,46 @@
 </IfModule>
 
 #
 # The mod_mime_magic module allows the server to use various hints from the
 # contents of the file itself to determine its type.  The MIMEMagicFile
 # directive tells the module where the hint definitions are located.
 #
 #MIMEMagicFile @rel_sysconfdir@/magic
 
 #
 # Customizable error responses come in three flavors:
 # 1) plain text 2) local redirects 3) external redirects
 #
 # Some examples:
 #ErrorDocument 500 "The server made a boo boo."
 #ErrorDocument 404 /missing.html
 #ErrorDocument 404 "/cgi-bin/missing_handler.pl"
 #ErrorDocument 402 http://www.example.com/subscription_info.html
 #
 
+# MaxRanges: Maximum number of Ranges in a request before
+# returning the entire resource, or 0 for unlimited
+# Default setting is to accept 200 Ranges
+#MaxRanges 0
+#
+
 #
 # EnableMMAP and EnableSendfile: On systems that support it, 
 # memory-mapping or the sendfile syscall is used to deliver
 # files.  This usually improves server performance, but must
 # be turned off when serving from networked-mounted 
 # filesystems or if support for these functions is otherwise
 # broken on your system.
 #
 #EnableMMAP off
 #EnableSendfile off
 
 # Supplemental configuration
 #
 # The configuration files in the @rel_sysconfdir@/extra/ directory can be 
 # included to add extra features or to modify the default configuration of 
 # the server, or you may simply copy their contents here and change as 
 # necessary.
 
 # Server-pool management (MPM specific)
 #Include @rel_sysconfdir@/extra/httpd-mpm.conf
diff -rNU 20 ../httpd-2.2.12-o/docs/manual/mod/core.html.en ./docs/manual/mod/core.html.en
--- ../httpd-2.2.12-o/docs/manual/mod/core.html.en	2009-06-24 11:46:30.000000000 +0200
+++ ./docs/manual/mod/core.html.en	2011-09-16 15:23:25.000000000 +0200
@@ -56,40 +56,41 @@
 <li><img alt="" src="../images/down.gif" /> <a href="#filesmatch">&lt;FilesMatch&gt;</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#forcetype">ForceType</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#hostnamelookups">HostnameLookups</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#ifdefine">&lt;IfDefine&gt;</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#ifmodule">&lt;IfModule&gt;</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#include">Include</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#keepalive">KeepAlive</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#keepalivetimeout">KeepAliveTimeout</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#limit">&lt;Limit&gt;</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#limitexcept">&lt;LimitExcept&gt;</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#limitinternalrecursion">LimitInternalRecursion</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#limitrequestbody">LimitRequestBody</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#limitrequestfields">LimitRequestFields</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#limitrequestfieldsize">LimitRequestFieldSize</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#limitrequestline">LimitRequestLine</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#limitxmlrequestbody">LimitXMLRequestBody</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#location">&lt;Location&gt;</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#locationmatch">&lt;LocationMatch&gt;</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#loglevel">LogLevel</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#maxkeepaliverequests">MaxKeepAliveRequests</a></li>
+<li><img alt="" src="../images/down.gif" /> <a href="#maxranges">MaxRanges</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#namevirtualhost">NameVirtualHost</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#options">Options</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#require">Require</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#rlimitcpu">RLimitCPU</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#rlimitmem">RLimitMEM</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#rlimitnproc">RLimitNPROC</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#satisfy">Satisfy</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#scriptinterpretersource">ScriptInterpreterSource</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#serveradmin">ServerAdmin</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#serveralias">ServerAlias</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#servername">ServerName</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#serverpath">ServerPath</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#serverroot">ServerRoot</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#serversignature">ServerSignature</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#servertokens">ServerTokens</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#sethandler">SetHandler</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#setinputfilter">SetInputFilter</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#setoutputfilter">SetOutputFilter</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#timeout">TimeOut</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#traceenable">TraceEnable</a></li>
@@ -2186,40 +2187,75 @@
 <tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>MaxKeepAliveRequests 100</code></td></tr>
 <tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host</td></tr>
 <tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Core</td></tr>
 <tr><th><a href="directive-dict.html#Module">Module:</a></th><td>core</td></tr>
 </table>
     <p>The <code class="directive">MaxKeepAliveRequests</code> directive
     limits the number of requests allowed per connection when
     <code class="directive"><a href="#keepalive">KeepAlive</a></code> is on. If it is
     set to <code>0</code>, unlimited requests will be allowed. We
     recommend that this setting be kept to a high value for maximum
     server performance.</p>
 
     <p>For example:</p>
 
     <div class="example"><p><code>
       MaxKeepAliveRequests 500
     </code></p></div>
 
 </div>
 <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
+<div class="directive-section"><h2><a name="MaxRanges" id="MaxRanges">MaxRanges</a> <a name="maxranges" id="maxranges">Directive</a></h2>
+<table class="directive">
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Number of ranges allowed before returning the complete
+resource </td></tr>
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>MaxRanges default | unlimited | none | <var>number-of-ranges</var></code></td></tr>
+<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>MaxRanges 200</code></td></tr>
+<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host, directory</td></tr>
+<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Core</td></tr>
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>core</td></tr>
+<tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>Available in Apache HTTP Server 2.2.21 and later</td></tr>
+</table>
+    <p>The <code class="directive">MaxRanges</code> 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>
+
+</div>
+<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
+
 <div class="directive-section"><h2><a name="NameVirtualHost" id="NameVirtualHost">NameVirtualHost</a> <a name="namevirtualhost" id="namevirtualhost">Directive</a></h2>
 <table class="directive">
 <tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Designates an IP address for name-virtual
 hosting</td></tr>
 <tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>NameVirtualHost <var>addr</var>[:<var>port</var>]</code></td></tr>
 <tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config</td></tr>
 <tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Core</td></tr>
 <tr><th><a href="directive-dict.html#Module">Module:</a></th><td>core</td></tr>
 </table>
     <p>The <code class="directive">NameVirtualHost</code> directive is a
     required directive if you want to configure <a href="../vhosts/">name-based virtual hosts</a>.</p>
 
     <p>Although <var>addr</var> can be hostname it is recommended
     that you always use an IP address, e.g.</p>
 
     <div class="example"><p><code>
       NameVirtualHost 111.22.33.44
     </code></p></div>
 
     <p>With the <code class="directive">NameVirtualHost</code> directive you
@@ -3443,21 +3479,21 @@
 <ul>
 <li><a href="../vhosts/">Apache Virtual Host documentation</a></li>
 <li><a href="../dns-caveats.html">Issues Regarding DNS and
     Apache</a></li>
 <li><a href="../bind.html">Setting
     which addresses and ports Apache uses</a></li>
 <li><a href="../sections.html">How &lt;Directory&gt;, &lt;Location&gt;
     and &lt;Files&gt; sections work</a> for an explanation of how these
     different sections are combined when a request is received</li>
 </ul>
 </div>
 </div>
 <div class="bottomlang">
 <p><span>Available Languages: </span><a href="../de/mod/core.html" hreflang="de" rel="alternate" title="Deutsch">&nbsp;de&nbsp;</a> |
 <a href="../en/mod/core.html" title="English">&nbsp;en&nbsp;</a> |
 <a href="../ja/mod/core.html" hreflang="ja" rel="alternate" title="Japanese">&nbsp;ja&nbsp;</a> |
 <a href="../tr/mod/core.html" hreflang="tr" rel="alternate" title="Türkçe">&nbsp;tr&nbsp;</a></p>
 </div><div id="footer">
 <p class="apache">Copyright 2009 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
 <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div>
-</body></html>
\ No newline at end of file
+</body></html>
diff -rNU 20 ../httpd-2.2.12-o/docs/manual/mod/directives.html.en ./docs/manual/mod/directives.html.en
--- ../httpd-2.2.12-o/docs/manual/mod/directives.html.en	2009-05-19 13:46:27.000000000 +0200
+++ ./docs/manual/mod/directives.html.en	2011-09-16 15:28:58.000000000 +0200
@@ -247,40 +247,41 @@
 <li><a href="core.html#limit">&lt;Limit&gt;</a></li>
 <li><a href="core.html#limitexcept">&lt;LimitExcept&gt;</a></li>
 <li><a href="core.html#limitinternalrecursion">LimitInternalRecursion</a></li>
 <li><a href="core.html#limitrequestbody">LimitRequestBody</a></li>
 <li><a href="core.html#limitrequestfields">LimitRequestFields</a></li>
 <li><a href="core.html#limitrequestfieldsize">LimitRequestFieldSize</a></li>
 <li><a href="core.html#limitrequestline">LimitRequestLine</a></li>
 <li><a href="core.html#limitxmlrequestbody">LimitXMLRequestBody</a></li>
 <li><a href="mpm_common.html#listen">Listen</a></li>
 <li><a href="mpm_common.html#listenbacklog">ListenBackLog</a></li>
 <li><a href="mod_so.html#loadfile">LoadFile</a></li>
 <li><a href="mod_so.html#loadmodule">LoadModule</a></li>
 <li><a href="core.html#location">&lt;Location&gt;</a></li>
 <li><a href="core.html#locationmatch">&lt;LocationMatch&gt;</a></li>
 <li><a href="mpm_common.html#lockfile">LockFile</a></li>
 <li><a href="mod_log_config.html#logformat">LogFormat</a></li>
 <li><a href="core.html#loglevel">LogLevel</a></li>
 <li><a href="mpm_common.html#maxclients" id="M" name="M">MaxClients</a></li>
 <li><a href="core.html#maxkeepaliverequests">MaxKeepAliveRequests</a></li>
 <li><a href="mpm_common.html#maxmemfree">MaxMemFree</a></li>
+<li><a href="core.html#maxranges">MaxRanges</a></li>
 <li><a href="mpm_common.html#maxrequestsperchild">MaxRequestsPerChild</a></li>
 <li><a href="beos.html#maxrequestsperthread">MaxRequestsPerThread</a></li>
 <li><a href="prefork.html#maxspareservers">MaxSpareServers</a></li>
 <li><a href="mpm_common.html#maxsparethreads">MaxSpareThreads</a></li>
 <li><a href="mpm_netware.html#maxthreads">MaxThreads</a></li>
 <li><a href="mod_mem_cache.html#mcachemaxobjectcount">MCacheMaxObjectCount</a></li>
 <li><a href="mod_mem_cache.html#mcachemaxobjectsize">MCacheMaxObjectSize</a></li>
 <li><a href="mod_mem_cache.html#mcachemaxstreamingbuffer">MCacheMaxStreamingBuffer</a></li>
 <li><a href="mod_mem_cache.html#mcacheminobjectsize">MCacheMinObjectSize</a></li>
 <li><a href="mod_mem_cache.html#mcacheremovalalgorithm">MCacheRemovalAlgorithm</a></li>
 <li><a href="mod_mem_cache.html#mcachesize">MCacheSize</a></li>
 <li><a href="mod_cern_meta.html#metadir">MetaDir</a></li>
 <li><a href="mod_cern_meta.html#metafiles">MetaFiles</a></li>
 <li><a href="mod_cern_meta.html#metasuffix">MetaSuffix</a></li>
 <li><a href="mod_mime_magic.html#mimemagicfile">MimeMagicFile</a></li>
 <li><a href="prefork.html#minspareservers">MinSpareServers</a></li>
 <li><a href="mpm_common.html#minsparethreads">MinSpareThreads</a></li>
 <li><a href="mod_file_cache.html#mmapfile">MMapFile</a></li>
 <li><a href="mod_mime.html#modmimeusepathinfo">ModMimeUsePathInfo</a></li>
 <li><a href="mod_mime.html#multiviewsmatch">MultiviewsMatch</a></li>
@@ -435,21 +436,21 @@
 <li><a href="mod_userdir.html#userdir">UserDir</a></li>
 <li><a href="mod_vhost_alias.html#virtualdocumentroot" id="V" name="V">VirtualDocumentRoot</a></li>
 <li><a href="mod_vhost_alias.html#virtualdocumentrootip">VirtualDocumentRootIP</a></li>
 <li><a href="core.html#virtualhost">&lt;VirtualHost&gt;</a></li>
 <li><a href="mod_vhost_alias.html#virtualscriptalias">VirtualScriptAlias</a></li>
 <li><a href="mod_vhost_alias.html#virtualscriptaliasip">VirtualScriptAliasIP</a></li>
 <li><a href="mpm_winnt.html#win32disableacceptex" id="W" name="W">Win32DisableAcceptEx</a></li>
 <li><a href="mod_include.html#xbithack" id="X" name="X">XBitHack</a></li>
 </ul></div>
 <div class="bottomlang">
 <p><span>Available Languages: </span><a href="../de/mod/directives.html" hreflang="de" rel="alternate" title="Deutsch">&nbsp;de&nbsp;</a> |
 <a href="../en/mod/directives.html" title="English">&nbsp;en&nbsp;</a> |
 <a href="../es/mod/directives.html" hreflang="es" rel="alternate" title="Español">&nbsp;es&nbsp;</a> |
 <a href="../ja/mod/directives.html" hreflang="ja" rel="alternate" title="Japanese">&nbsp;ja&nbsp;</a> |
 <a href="../ko/mod/directives.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a> |
 <a href="../ru/mod/directives.html" hreflang="ru" rel="alternate" title="Russian">&nbsp;ru&nbsp;</a> |
 <a href="../tr/mod/directives.html" hreflang="tr" rel="alternate" title="Türkçe">&nbsp;tr&nbsp;</a></p>
 </div><div id="footer">
 <p class="apache">Copyright 2009 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
 <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div>
-</body></html>
\ No newline at end of file
+</body></html>
diff -rNU 20 ../httpd-2.2.12-o/docs/manual/mod/quickreference.html.en ./docs/manual/mod/quickreference.html.en
--- ../httpd-2.2.12-o/docs/manual/mod/quickreference.html.en	2009-05-19 13:46:27.000000000 +0200
+++ ./docs/manual/mod/quickreference.html.en	2011-09-16 15:32:23.000000000 +0200
@@ -432,40 +432,42 @@
 <tr><td><a href="mod_so.html#loadmodule">LoadModule <em>module filename</em></a></td><td></td><td>s</td><td>E</td></tr><tr><td class="descr" colspan="4">Links in the object file or library, and adds to the list
 of active modules</td></tr>
 <tr class="odd"><td><a href="core.html#location">&lt;Location
     <var>URL-path</var>|<var>URL</var>&gt; ... &lt;/Location&gt;</a></td><td></td><td>sv</td><td>C</td></tr><tr class="odd"><td class="descr" colspan="4">Applies the enclosed directives only to matching
 URLs</td></tr>
 <tr><td><a href="core.html#locationmatch">&lt;LocationMatch
     <var>regex</var>&gt; ... &lt;/LocationMatch&gt;</a></td><td></td><td>sv</td><td>C</td></tr><tr><td class="descr" colspan="4">Applies the enclosed directives only to regular-expression
 matching URLs</td></tr>
 <tr class="odd"><td><a href="mpm_common.html#lockfile">LockFile <var>filename</var></a></td><td> logs/accept.lock </td><td>s</td><td>M</td></tr><tr class="odd"><td class="descr" colspan="4">Location of the accept serialization lock file</td></tr>
 <tr><td><a href="mod_log_config.html#logformat">LogFormat <var>format</var>|<var>nickname</var>
 [<var>nickname</var>]</a></td><td> "%h %l %u %t \"%r\" +</td><td>sv</td><td>B</td></tr><tr><td class="descr" colspan="4">Describes a format for use in a log file</td></tr>
 <tr class="odd"><td><a href="core.html#loglevel">LogLevel <var>level</var></a></td><td> warn </td><td>sv</td><td>C</td></tr><tr class="odd"><td class="descr" colspan="4">Controls the verbosity of the ErrorLog</td></tr>
 <tr><td><a href="mpm_common.html#maxclients" id="M" name="M">MaxClients <var>number</var></a></td><td></td><td>s</td><td>M</td></tr><tr><td class="descr" colspan="4">Maximum number of connections that will be processed
 simultaneously</td></tr>
 <tr class="odd"><td><a href="core.html#maxkeepaliverequests">MaxKeepAliveRequests <var>number</var></a></td><td> 100 </td><td>sv</td><td>C</td></tr><tr class="odd"><td class="descr" colspan="4">Number of requests allowed on a persistent
 connection</td></tr>
 <tr><td><a href="mpm_common.html#maxmemfree">MaxMemFree <var>KBytes</var></a></td><td> 0 </td><td>s</td><td>M</td></tr><tr><td class="descr" colspan="4">Maximum amount of memory that the main allocator is allowed
 to hold without calling <code>free()</code></td></tr>
 <tr class="odd"><td><a href="mpm_common.html#maxrequestsperchild">MaxRequestsPerChild <var>number</var></a></td><td> 10000 </td><td>s</td><td>M</td></tr><tr class="odd"><td class="descr" colspan="4">Limit on the number of requests that an individual child server
 will handle during its life</td></tr>
+<tr><td><a href="core.html#maxranges">MaxRanges <var>number</var> (0 = no limit)</a></td><td> 200 </td><td>svd</td><td>C</td></tr><tr><td class="descr" colspan="4">Number of ranges allowed before returning the complete
+resource </td></tr>
 <tr><td><a href="beos.html#maxrequestsperthread">MaxRequestsPerThread <var>number</var></a></td><td> 0 </td><td>s</td><td>M</td></tr><tr><td class="descr" colspan="4">Limit on the number of requests that an individual thread
 will handle during its life</td></tr>
 <tr class="odd"><td><a href="prefork.html#maxspareservers">MaxSpareServers <var>number</var></a></td><td> 10 </td><td>s</td><td>M</td></tr><tr class="odd"><td class="descr" colspan="4">Maximum number of idle child server processes</td></tr>
 <tr><td><a href="mpm_common.html#maxsparethreads">MaxSpareThreads <var>number</var></a></td><td></td><td>s</td><td>M</td></tr><tr><td class="descr" colspan="4">Maximum number of idle threads</td></tr>
 <tr class="odd"><td><a href="mpm_netware.html#maxthreads">MaxThreads <var>number</var></a></td><td> 2048 </td><td>s</td><td>M</td></tr><tr class="odd"><td class="descr" colspan="4">Set the maximum number of worker threads</td></tr>
 <tr><td><a href="mod_mem_cache.html#mcachemaxobjectcount">MCacheMaxObjectCount <var>value</var></a></td><td> 1009 </td><td>s</td><td>E</td></tr><tr><td class="descr" colspan="4">The maximum number of objects allowed to be placed in the
 cache</td></tr>
 <tr class="odd"><td><a href="mod_mem_cache.html#mcachemaxobjectsize">MCacheMaxObjectSize <var>bytes</var></a></td><td> 10000 </td><td>s</td><td>E</td></tr><tr class="odd"><td class="descr" colspan="4">The maximum size (in bytes) of a document allowed in the
 cache</td></tr>
 <tr><td><a href="mod_mem_cache.html#mcachemaxstreamingbuffer">MCacheMaxStreamingBuffer <var>size_in_bytes</var></a></td><td> the smaller of 1000 +</td><td>s</td><td>E</td></tr><tr><td class="descr" colspan="4">Maximum amount of a streamed response to buffer in memory
 before declaring the response uncacheable</td></tr>
 <tr class="odd"><td><a href="mod_mem_cache.html#mcacheminobjectsize">MCacheMinObjectSize <var>bytes</var></a></td><td> 1 </td><td>s</td><td>E</td></tr><tr class="odd"><td class="descr" colspan="4">The minimum size (in bytes) of a document to be allowed in the
 cache</td></tr>
 <tr><td><a href="mod_mem_cache.html#mcacheremovalalgorithm">MCacheRemovalAlgorithm LRU|GDSF</a></td><td> GDSF </td><td>s</td><td>E</td></tr><tr><td class="descr" colspan="4">The algorithm used to select documents for removal from the
 cache</td></tr>
 <tr class="odd"><td><a href="mod_mem_cache.html#mcachesize">MCacheSize <var>KBytes</var></a></td><td> 100 </td><td>s</td><td>E</td></tr><tr class="odd"><td class="descr" colspan="4">The maximum amount of memory used by the cache in
 KBytes</td></tr>
 <tr><td><a href="mod_cern_meta.html#metadir">MetaDir <var>directory</var></a></td><td> .web </td><td>svdh</td><td>E</td></tr><tr><td class="descr" colspan="4">Name of the directory to find CERN-style meta information
 files</td></tr>
 <tr class="odd"><td><a href="mod_cern_meta.html#metafiles">MetaFiles on|off</a></td><td> off </td><td>svdh</td><td>E</td></tr><tr class="odd"><td class="descr" colspan="4">Activates CERN meta-file processing</td></tr>
@@ -763,21 +765,21 @@
 hostname or IP address</td></tr>
 <tr class="odd"><td><a href="mod_vhost_alias.html#virtualscriptalias">VirtualScriptAlias <em>interpolated-directory</em>|none</a></td><td> none </td><td>sv</td><td>E</td></tr><tr class="odd"><td class="descr" colspan="4">Dynamically configure the location of the CGI directory for
 a given virtual host</td></tr>
 <tr><td><a href="mod_vhost_alias.html#virtualscriptaliasip">VirtualScriptAliasIP <em>interpolated-directory</em>|none</a></td><td> none </td><td>sv</td><td>E</td></tr><tr><td class="descr" colspan="4">Dynamically configure the location of the cgi directory for
 a given virtual host</td></tr>
 <tr class="odd"><td><a href="mpm_winnt.html#win32disableacceptex" id="W" name="W">Win32DisableAcceptEx</a></td><td></td><td>s</td><td>M</td></tr><tr class="odd"><td class="descr" colspan="4">Use accept() rather than AcceptEx() to accept network connections</td></tr>
 <tr><td><a href="mod_include.html#xbithack" id="X" name="X">XBitHack on|off|full</a></td><td> off </td><td>svdh</td><td>B</td></tr><tr><td class="descr" colspan="4">Parse SSI directives in files with the execute bit
 set</td></tr>
 </table></div>
 <div class="bottomlang">
 <p><span>Available Languages: </span><a href="../de/mod/quickreference.html" hreflang="de" rel="alternate" title="Deutsch">&nbsp;de&nbsp;</a> |
 <a href="../en/mod/quickreference.html" title="English">&nbsp;en&nbsp;</a> |
 <a href="../es/mod/quickreference.html" hreflang="es" rel="alternate" title="Español">&nbsp;es&nbsp;</a> |
 <a href="../ja/mod/quickreference.html" hreflang="ja" rel="alternate" title="Japanese">&nbsp;ja&nbsp;</a> |
 <a href="../ko/mod/quickreference.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a> |
 <a href="../ru/mod/quickreference.html" hreflang="ru" rel="alternate" title="Russian">&nbsp;ru&nbsp;</a> |
 <a href="../tr/mod/quickreference.html" hreflang="tr" rel="alternate" title="Türkçe">&nbsp;tr&nbsp;</a></p>
 </div><div id="footer">
 <p class="apache">Copyright 2009 The Apache Software Foundation.<br />Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.</p>
 <p class="menu"><a href="../mod/">Modules</a> | <a href="../mod/directives.html">Directives</a> | <a href="../faq/">FAQ</a> | <a href="../glossary.html">Glossary</a> | <a href="../sitemap.html">Sitemap</a></p></div>
-</body></html>
\ No newline at end of file
+</body></html>
diff -rNU 20 ../httpd-2.2.12-o/include/http_core.h ./include/http_core.h
--- ../httpd-2.2.12-o/include/http_core.h	2009-05-28 10:04:03.000000000 +0200
+++ ./include/http_core.h	2011-09-16 15:19:20.000000000 +0200
@@ -551,40 +551,49 @@
     /*
      * Run-time performance tuning
      */
 #define ENABLE_MMAP_OFF    (0)
 #define ENABLE_MMAP_ON     (1)
 #define ENABLE_MMAP_UNSET  (2)
     unsigned int enable_mmap : 2;  /* whether files in this dir can be mmap'ed */
 
 #define ENABLE_SENDFILE_OFF    (0)
 #define ENABLE_SENDFILE_ON     (1)
 #define ENABLE_SENDFILE_UNSET  (2)
     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 USE_CANONICAL_PHYS_PORT_OFF   (0)
 #define USE_CANONICAL_PHYS_PORT_ON    (1)
 #define USE_CANONICAL_PHYS_PORT_UNSET (2)
     unsigned use_canonical_phys_port : 2;
 
+#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 */
 
 typedef struct {
   
 #ifdef GPROF
     char *gprof_dir;
 #endif
 
     /* Name translations --- we want the core to be able to do *something*
      * so it's at least a minimally functional web server on its own (and
      * can be tested that way).  But let's keep it to the bare minimum:
      */
     const char *ap_document_root;
   
     /* Access control */
 
     char *access_name;
     apr_array_header_t *sec_dir;
diff -rNU 20 ../httpd-2.2.12-o/include/http_protocol.h ./include/http_protocol.h
--- ../httpd-2.2.12-o/include/http_protocol.h	2007-12-08 15:01:47.000000000 +0100
+++ ./include/http_protocol.h	2011-09-16 15:20:15.000000000 +0200
@@ -292,40 +292,48 @@
 AP_DECLARE(void) ap_method_list_remove(ap_method_list_t *l,
 				       const char *method);
 
 /**
  * Reset a method list to be completely empty.
  *
  * @param   l       Pointer to a method list, such as cmd->methods_limited.
  * @return  None.
  */
 AP_DECLARE(void) ap_clear_method_list(ap_method_list_t *l);
     
 /**
  * Set the content type for this request (r->content_type). 
  * @param r The current request
  * @param ct The new content type
  * @warning This function must be called to set r->content_type in order 
  * for the AddOutputFilterByType directive to work correctly.
  */
 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.
  */
 
 /**
  * Output one character for this request
  * @param c the character to output
  * @param r the current request
  * @return The number of bytes sent
  */
 AP_DECLARE(int) ap_rputc(int c, request_rec *r);
 
 /**
  * Output a string for the current request
  * @param str The string to output
  * @param r The current request
  * @return The number of bytes sent
  */
 AP_DECLARE(int) ap_rputs(const char *str, request_rec *r);
 
diff -rNU 20 ../httpd-2.2.12-o/modules/dav/fs/repos.c ./modules/dav/fs/repos.c
--- ../httpd-2.2.12-o/modules/dav/fs/repos.c	2008-08-16 00:12:47.000000000 +0200
+++ ./modules/dav/fs/repos.c	2011-09-16 15:33:11.000000000 +0200
@@ -931,41 +931,41 @@
 #if DEBUG_GET_HANDLER
 
 /* only define set_headers() and deliver() for debug purposes */
 
 
 static dav_error * dav_fs_set_headers(request_rec *r,
                                       const dav_resource *resource)
 {
     /* ### this function isn't really used since we have a get_pathname */
     if (!resource->exists)
         return NULL;
 
     /* make sure the proper mtime is in the request record */
     ap_update_mtime(r, resource->info->finfo.mtime);
 
     /* ### note that these use r->filename rather than <resource> */
     ap_set_last_modified(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);
 
     /* ### how to set the content type? */
     /* ### until this is resolved, the Content-Type header is busted */
 
     return NULL;
 }
 
 static dav_error * dav_fs_deliver(const dav_resource *resource,
                                   ap_filter_t *output)
 {
     apr_pool_t *pool = resource->pool;
     apr_bucket_brigade *bb;
     apr_file_t *fd;
     apr_status_t status;
     apr_bucket *bkt;
 
     /* Check resource type */
diff -rNU 20 ../httpd-2.2.12-o/modules/filters/mod_filter.c ./modules/filters/mod_filter.c
--- ../httpd-2.2.12-o/modules/filters/mod_filter.c	2007-12-08 15:07:25.000000000 +0100
+++ ./modules/filters/mod_filter.c	2011-09-16 15:35:01.000000000 +0200
@@ -301,41 +301,41 @@
                                                 r->hostname));
                 }
             }
 
             /* things that are invalidated if the filter transforms content */
             if (proto_flags & AP_FILTER_PROTO_CHANGE) {
                 apr_table_unset(r->headers_out, "Content-MD5");
                 apr_table_unset(r->headers_out, "ETag");
                 if (proto_flags & AP_FILTER_PROTO_CHANGE_LENGTH) {
                     apr_table_unset(r->headers_out, "Content-Length");
                 }
             }
 
             /* no-cache is for a filter that has different effect per-hit */
             if (proto_flags & AP_FILTER_PROTO_NO_CACHE) {
                 apr_table_unset(r->headers_out, "Last-Modified");
                 apr_table_addn(r->headers_out, "Cache-Control", "no-cache");
             }
 
             if (proto_flags & AP_FILTER_PROTO_NO_BYTERANGE) {
-                apr_table_unset(r->headers_out, "Accept-Ranges");
+                apr_table_setn(r->headers_out, "Accept-Ranges", "none");
             }
             else if (rctx && rctx->range) {
                 /* restore range header we saved earlier */
                 apr_table_setn(r->headers_in, "Range", rctx->range);
                 rctx->range = NULL;
             }
 #endif
             for (pctx = ctx->init_ctx; pctx; pctx = pctx->next) {
                 if (pctx->provider == provider) {
                     ctx->fctx = pctx->ctx ;
                 }
             }
             ctx->func = provider->frec->filter_func.out_func;
             return 1;
         }
     }
 
     /* No provider matched */
     return 0;
 }
diff -rNU 20 ../httpd-2.2.12-o/modules/http/byterange_filter.c ./modules/http/byterange_filter.c
--- ../httpd-2.2.12-o/modules/http/byterange_filter.c	2011-09-16 14:52:15.000000000 +0200
+++ ./modules/http/byterange_filter.c	2011-09-08 12:41:15.000000000 +0200
@@ -38,352 +38,502 @@
 #include "http_protocol.h"
 #include "http_main.h"
 #include "http_request.h"
 #include "http_vhost.h"
 #include "http_log.h"           /* For errors detected in basic auth common
                                  * support code... */
 #include "apr_date.h"           /* For apr_date_parse_http and APR_DATE_BAD */
 #include "util_charset.h"
 #include "util_ebcdic.h"
 #include "util_time.h"
 
 #include "mod_core.h"
 
 #if APR_HAVE_STDARG_H
 #include <stdarg.h>
 #endif
 #if APR_HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
-static int parse_byterange(char *range, apr_off_t clength,
-                           apr_off_t *start, apr_off_t *end)
-{
-    char *dash = strchr(range, '-');
-    char *errp;
-    apr_off_t number;
-
-    if (!dash) {
-        return 0;
-    }
-
-    if ((dash == range)) {
-        /* In the form "-5" */
-        if (apr_strtoff(&number, dash+1, &errp, 10) || *errp) {
-            return 0;
-        }
-        *start = clength - number;
-        *end = clength - 1;
-    }
-    else {
-        *dash++ = '\0';
-        if (apr_strtoff(&number, range, &errp, 10) || *errp) {
-            return 0;
-        }
-        *start = number;
-        if (*dash) {
-            if (apr_strtoff(&number, dash, &errp, 10) || *errp) {
-                return 0;
-            }
-            *end = number;
-        }
-        else {                  /* "5-" */
-            *end = clength - 1;
-        }
-    }
-
-    if (*start < 0) {
-        *start = 0;
-    }
-
-    if (*end >= clength) {
-        *end = clength - 1;
-    }
-
-    if (*start > *end) {
-        return -1;
-    }
-
-    return (*start > 0 || *end < clength);
-}
+#ifndef AP_DEFAULT_MAX_RANGES
+#define AP_DEFAULT_MAX_RANGES 200
+#endif
 
-static int ap_set_byterange(request_rec *r);
-
-typedef struct byterange_ctx {
-    apr_bucket_brigade *bb;
-    int num_ranges;
-    char *boundary;
-    char *bound_head;
-} byterange_ctx;
+static int ap_set_byterange(request_rec *r, apr_off_t clength,
+                            apr_array_header_t **indexes);
 
 /*
  * Here we try to be compatible with clients that want multipart/x-byteranges
  * instead of multipart/byteranges (also see above), as per HTTP/1.1. We
  * look for the Request-Range header (e.g. Netscape 2 and 3) as an indication
  * that the browser supports an older protocol. We also check User-Agent
  * for Microsoft Internet Explorer 3, which needs this as well.
  */
 static int use_range_x(request_rec *r)
 {
     const char *ua;
     return (apr_table_get(r->headers_in, "Request-Range")
             || ((ua = apr_table_get(r->headers_in, "User-Agent"))
                 && ap_strstr_c(ua, "MSIE 3")));
 }
 
 #define BYTERANGE_FMT "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT "/%" APR_OFF_T_FMT
-#define PARTITION_ERR_FMT "apr_brigade_partition() failed " \
-                          "[%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT "]"
+
+static apr_status_t copy_brigade_range(apr_bucket_brigade *bb,
+                                       apr_bucket_brigade *bbout,
+                                       apr_off_t start,
+                                       apr_off_t end)
+{
+    apr_bucket *first = NULL, *last = NULL, *out_first = NULL, *e;
+    apr_uint64_t pos = 0, off_first = 0, off_last = 0;
+    apr_status_t rv;
+    apr_uint64_t start64, end64;
+    apr_off_t pofft = 0;
+
+    /*
+     * Once we know that start and end are >= 0 convert everything to apr_uint64_t.
+     * See the comments in apr_brigade_partition why.
+     * In short apr_off_t (for values >= 0)and apr_size_t fit into apr_uint64_t.
+     */
+    start64 = (apr_uint64_t)start;
+    end64 = (apr_uint64_t)end;
+
+    if (start < 0 || end < 0 || start64 > end64)
+        return APR_EINVAL;
+
+    for (e = APR_BRIGADE_FIRST(bb);
+         e != APR_BRIGADE_SENTINEL(bb);
+         e = APR_BUCKET_NEXT(e))
+    {
+        apr_uint64_t elen64;
+        /* we know that no bucket has undefined length (-1) */
+        AP_DEBUG_ASSERT(e->length != (apr_size_t)(-1));
+        elen64 = (apr_uint64_t)e->length;
+        if (!first && (elen64 + pos > start64)) {
+            first = e;
+            off_first = pos;
+        }
+        if (elen64 + pos > end64) {
+            last = e;
+            off_last = pos;
+            break;
+        }
+        pos += elen64;
+    }
+    if (!first || !last)
+        return APR_EINVAL;
+
+    e = first;
+    while (1)
+    {
+        apr_bucket *copy;
+        AP_DEBUG_ASSERT(e != APR_BRIGADE_SENTINEL(bb));
+        rv = apr_bucket_copy(e, &copy);
+        if (rv != APR_SUCCESS) {
+            apr_brigade_cleanup(bbout);
+            return rv;
+        }
+
+        APR_BRIGADE_INSERT_TAIL(bbout, copy);
+        if (e == first) {
+            if (off_first != start64) {
+                rv = apr_bucket_split(copy, (apr_size_t)(start64 - off_first));
+                if (rv != APR_SUCCESS) {
+                    apr_brigade_cleanup(bbout);
+                    return rv;
+                }
+                out_first = APR_BUCKET_NEXT(copy);
+                APR_BUCKET_REMOVE(copy);
+                apr_bucket_destroy(copy);
+            }
+            else {
+                out_first = copy;
+            }
+        }
+        if (e == last) {
+            if (e == first) {
+                off_last += start64 - off_first;
+                copy = out_first;
+            }
+            if (end64 - off_last != (apr_uint64_t)e->length) {
+                rv = apr_bucket_split(copy, (apr_size_t)(end64 + 1 - off_last));
+                if (rv != APR_SUCCESS) {
+                    apr_brigade_cleanup(bbout);
+                    return rv;
+                }
+                copy = APR_BUCKET_NEXT(copy);
+                if (copy != APR_BRIGADE_SENTINEL(bbout)) {
+                    APR_BUCKET_REMOVE(copy);
+                    apr_bucket_destroy(copy);
+                }
+            }
+            break;
+        }
+        e = APR_BUCKET_NEXT(e);
+    }
+
+    AP_DEBUG_ASSERT(APR_SUCCESS == apr_brigade_length(bbout, 1, &pofft));
+    pos = (apr_uint64_t)pofft;
+    AP_DEBUG_ASSERT(pos == end64 - start64 + 1);
+    return APR_SUCCESS;
+}
+
+typedef struct indexes_t {
+    apr_off_t start;
+    apr_off_t end;
+} indexes_t;
+
+static int get_max_ranges(request_rec *r) { 
+    core_dir_config *core_conf = 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;
+    conn_rec *c = f->r->connection;
+    ap_remove_output_filter(f);
+    f->r->status = HTTP_OK;
+    e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL,
+                               f->r->pool, c->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(tmpbb, e);
+    e = apr_bucket_eos_create(c->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(tmpbb, e);
+    return ap_pass_brigade(f->next, tmpbb);
+}
 
 AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(ap_filter_t *f,
                                                          apr_bucket_brigade *bb)
 {
-#define MIN_LENGTH(len1, len2) ((len1 > len2) ? len2 : len1)
     request_rec *r = f->r;
     conn_rec *c = r->connection;
-    byterange_ctx *ctx;
     apr_bucket *e;
     apr_bucket_brigade *bsend;
+    apr_bucket_brigade *tmpbb;
     apr_off_t range_start;
     apr_off_t range_end;
-    char *current;
     apr_off_t clength = 0;
     apr_status_t rv;
     int found = 0;
     int num_ranges;
-
-    /* Iterate through the brigade until reaching EOS or a bucket with
-     * unknown length. */
+    char *boundary = NULL;
+    char *bound_head = NULL;
+    apr_array_header_t *indexes;
+    indexes_t *idx;
+    int i;
+    int original_status;
+    int max_ranges = get_max_ranges(r);
+
+    /*
+     * Iterate through the brigade until reaching EOS or a bucket with
+     * unknown length.
+     */
     for (e = APR_BRIGADE_FIRST(bb);
          (e != APR_BRIGADE_SENTINEL(bb) && !APR_BUCKET_IS_EOS(e)
           && e->length != (apr_size_t)-1);
          e = APR_BUCKET_NEXT(e)) {
         clength += e->length;
     }
 
-    /* Don't attempt to do byte range work if this brigade doesn't
+    /*
+     * Don't attempt to do byte range work if this brigade doesn't
      * contain an EOS, or if any of the buckets has an unknown length;
      * this avoids the cases where it is expensive to perform
-     * byteranging (i.e. may require arbitrary amounts of memory). */
+     * byteranging (i.e. may require arbitrary amounts of memory).
+     */
     if (!APR_BUCKET_IS_EOS(e) || clength <= 0) {
         ap_remove_output_filter(f);
         return ap_pass_brigade(f->next, bb);
     }
 
-    num_ranges = ap_set_byterange(r);
+    original_status = r->status;
+    num_ranges = ap_set_byterange(r, clength, &indexes);
 
     /* We have nothing to do, get out of the way. */
-    if (num_ranges == 0) {
+    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);
     }
 
-    ctx = apr_pcalloc(r->pool, sizeof(*ctx));
-    ctx->num_ranges = num_ranges;
-    /* create a brigade in case we never call ap_save_brigade() */
-    ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc);
+    /* this brigade holds what we will be sending */
+    bsend = apr_brigade_create(r->pool, c->bucket_alloc);
 
-    if (ctx->num_ranges > 1) {
+    if (num_ranges < 0)
+        return send_416(f, bsend);
+
+    if (num_ranges > 1) {
         /* Is ap_make_content_type required here? */
         const char *orig_ct = ap_make_content_type(r, r->content_type);
-        ctx->boundary = apr_psprintf(r->pool, "%" APR_UINT64_T_HEX_FMT "%lx",
-                                     (apr_uint64_t)r->request_time, (long) getpid());
+        boundary = apr_psprintf(r->pool, "%" APR_UINT64_T_HEX_FMT "%lx",
+                                (apr_uint64_t)r->request_time, c->id);
 
         ap_set_content_type(r, apr_pstrcat(r->pool, "multipart",
                                            use_range_x(r) ? "/x-" : "/",
                                            "byteranges; boundary=",
-                                           ctx->boundary, NULL));
+                                           boundary, NULL));
 
         if (strcasecmp(orig_ct, NO_CONTENT_TYPE)) {
-            ctx->bound_head = apr_pstrcat(r->pool,
-                                          CRLF "--", ctx->boundary,
-                                          CRLF "Content-type: ",
-                                          orig_ct,
-                                          CRLF "Content-range: bytes ",
-                                          NULL);
+            bound_head = apr_pstrcat(r->pool,
+                                     CRLF "--", boundary,
+                                     CRLF "Content-type: ",
+                                     orig_ct,
+                                     CRLF "Content-range: bytes ",
+                                     NULL);
         }
         else {
             /* if we have no type for the content, do our best */
-            ctx->bound_head = apr_pstrcat(r->pool,
-                                          CRLF "--", ctx->boundary,
-                                          CRLF "Content-range: bytes ",
-                                          NULL);
+            bound_head = apr_pstrcat(r->pool,
+                                     CRLF "--", boundary,
+                                     CRLF "Content-range: bytes ",
+                                     NULL);
         }
-        ap_xlate_proto_to_ascii(ctx->bound_head, strlen(ctx->bound_head));
+        ap_xlate_proto_to_ascii(bound_head, strlen(bound_head));
     }
 
-    /* this brigade holds what we will be sending */
-    bsend = apr_brigade_create(r->pool, c->bucket_alloc);
-
-    while ((current = ap_getword(r->pool, &r->range, ','))
-           && (rv = parse_byterange(current, clength, &range_start,
-                                    &range_end))) {
-        apr_bucket *e2;
-        apr_bucket *ec;
+    tmpbb = apr_brigade_create(r->pool, c->bucket_alloc);
 
-        if (rv == -1) {
-            continue;
-        }
+    idx = (indexes_t *)indexes->elts;
+    for (i = 0; i < indexes->nelts; i++, idx++) {
+        range_start = idx->start;
+        range_end = idx->end;
 
-        /* These calls to apr_brigage_partition should only fail in
-         * pathological cases, e.g. a file being truncated whilst
-         * being served. */
-        if ((rv = apr_brigade_partition(bb, range_start, &ec)) != APR_SUCCESS) {
+        rv = copy_brigade_range(bb, tmpbb, range_start, range_end);
+        if (rv != APR_SUCCESS ) {
             ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-                          PARTITION_ERR_FMT, range_start, clength);
+                          "copy_brigade_range() failed [%" APR_OFF_T_FMT
+                          "-%" APR_OFF_T_FMT ",%" APR_OFF_T_FMT "]",
+                          range_start, range_end, clength);
             continue;
         }
-        if ((rv = apr_brigade_partition(bb, range_end+1, &e2)) != APR_SUCCESS) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
-                          PARTITION_ERR_FMT, range_end+1, clength);
-            continue;
-        }
-
         found = 1;
 
-        /* For single range requests, we must produce Content-Range header.
+        /*
+         * For single range requests, we must produce Content-Range header.
          * Otherwise, we need to produce the multipart boundaries.
          */
-        if (ctx->num_ranges == 1) {
+        if (num_ranges == 1) {
             apr_table_setn(r->headers_out, "Content-Range",
                            apr_psprintf(r->pool, "bytes " BYTERANGE_FMT,
                                         range_start, range_end, clength));
         }
         else {
             char *ts;
 
-            e = apr_bucket_pool_create(ctx->bound_head, strlen(ctx->bound_head),
+            e = apr_bucket_pool_create(bound_head, strlen(bound_head),
                                        r->pool, c->bucket_alloc);
             APR_BRIGADE_INSERT_TAIL(bsend, e);
 
             ts = apr_psprintf(r->pool, BYTERANGE_FMT CRLF CRLF,
                               range_start, range_end, clength);
             ap_xlate_proto_to_ascii(ts, strlen(ts));
             e = apr_bucket_pool_create(ts, strlen(ts), r->pool,
                                        c->bucket_alloc);
             APR_BRIGADE_INSERT_TAIL(bsend, e);
         }
 
-        do {
-            apr_bucket *foo;
-            const char *str;
-            apr_size_t len;
-
-            if (apr_bucket_copy(ec, &foo) != APR_SUCCESS) {
-                /* As above; this should not fail since the bucket has
-                 * a known length, but just to be sure, this takes
-                 * care of uncopyable buckets that do somehow manage
-                 * to slip through.  */
-                /* XXX: check for failure? */
-                apr_bucket_read(ec, &str, &len, APR_BLOCK_READ);
-                apr_bucket_copy(ec, &foo);
-            }
-            APR_BRIGADE_INSERT_TAIL(bsend, foo);
-            ec = APR_BUCKET_NEXT(ec);
-        } while (ec != e2);
+        APR_BRIGADE_CONCAT(bsend, tmpbb);
+        if (i && !(i & 0x1F)) {
+            /*
+             * Every now and then, pass what we have down the filter chain.
+             * In this case, the content-length filter cannot calculate and
+             * set the content length and we must remove any Content-Length
+             * header already present.
+             */
+            apr_table_unset(r->headers_out, "Content-Length");
+            if ((rv = ap_pass_brigade(f->next, bsend)) != APR_SUCCESS)
+                return rv;
+            apr_brigade_cleanup(bsend);
+        }
     }
 
     if (found == 0) {
-        ap_remove_output_filter(f);
-        r->status = HTTP_OK;
         /* bsend is assumed to be empty if we get here. */
-        e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL,
-                                   r->pool, c->bucket_alloc);
-        APR_BRIGADE_INSERT_TAIL(bsend, e);
-        e = apr_bucket_eos_create(c->bucket_alloc);
-        APR_BRIGADE_INSERT_TAIL(bsend, e);
-        return ap_pass_brigade(f->next, bsend);
+        return send_416(f, bsend);
     }
 
-    if (ctx->num_ranges > 1) {
+    if (num_ranges > 1) {
         char *end;
 
         /* add the final boundary */
-        end = apr_pstrcat(r->pool, CRLF "--", ctx->boundary, "--" CRLF, NULL);
+        end = apr_pstrcat(r->pool, CRLF "--", boundary, "--" CRLF, NULL);
         ap_xlate_proto_to_ascii(end, strlen(end));
         e = apr_bucket_pool_create(end, strlen(end), r->pool, c->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(bsend, e);
     }
 
     e = apr_bucket_eos_create(c->bucket_alloc);
     APR_BRIGADE_INSERT_TAIL(bsend, e);
 
     /* we're done with the original content - all of our data is in bsend. */
-    apr_brigade_destroy(bb);
+    apr_brigade_cleanup(bb);
+    apr_brigade_destroy(tmpbb);
 
     /* send our multipart output */
     return ap_pass_brigade(f->next, bsend);
 }
 
-static int ap_set_byterange(request_rec *r)
+static int ap_set_byterange(request_rec *r, apr_off_t clength,
+                            apr_array_header_t **indexes)
 {
     const char *range;
     const char *if_range;
     const char *match;
     const char *ct;
-    int num_ranges;
+    char *cur;
+    int num_ranges = 0, unsatisfiable = 0;
+    apr_off_t sum_lengths = 0;
+    indexes_t *idx;
+    int ranges = 1;
+    const char *it;
 
     if (r->assbackwards) {
         return 0;
     }
 
-    /* Check for Range request-header (HTTP/1.1) or Request-Range for
+    /*
+     * Check for Range request-header (HTTP/1.1) or Request-Range for
      * backwards-compatibility with second-draft Luotonen/Franks
      * byte-ranges (e.g. Netscape Navigator 2-3).
      *
      * We support this form, with Request-Range, and (farther down) we
      * send multipart/x-byteranges instead of multipart/byteranges for
      * Request-Range based requests to work around a bug in Netscape
      * Navigator 2-3 and MSIE 3.
      */
 
     if (!(range = apr_table_get(r->headers_in, "Range"))) {
         range = apr_table_get(r->headers_in, "Request-Range");
     }
 
     if (!range || strncasecmp(range, "bytes=", 6) || r->status != HTTP_OK) {
         return 0;
     }
 
     /* is content already a single range? */
     if (apr_table_get(r->headers_out, "Content-Range")) {
        return 0;
     }
 
     /* is content already a multiple range? */
     if ((ct = apr_table_get(r->headers_out, "Content-Type"))
         && (!strncasecmp(ct, "multipart/byteranges", 20)
             || !strncasecmp(ct, "multipart/x-byteranges", 22))) {
        return 0;
     }
 
-    /* Check the If-Range header for Etag or Date.
+    /*
+     * Check the If-Range header for Etag or Date.
      * Note that this check will return false (as required) if either
      * of the two etags are weak.
      */
     if ((if_range = apr_table_get(r->headers_in, "If-Range"))) {
         if (if_range[0] == '"') {
             if (!(match = apr_table_get(r->headers_out, "Etag"))
                 || (strcmp(if_range, match) != 0)) {
                 return 0;
             }
         }
         else if (!(match = apr_table_get(r->headers_out, "Last-Modified"))
                  || (strcmp(if_range, match) != 0)) {
             return 0;
         }
     }
 
-    if (!ap_strchr_c(range, ',')) {
-        /* a single range */
-        num_ranges = 1;
-    }
-    else {
-        /* a multiple range */
-        num_ranges = 2;
+    range += 6;
+    it = range;
+    while (*it) {
+        if (*it++ == ',') {
+            ranges++;
+        }
+    }
+    it = range;
+    *indexes = apr_array_make(r->pool, ranges, sizeof(indexes_t));
+    while ((cur = ap_getword(r->pool, &range, ','))) {
+        char *dash;
+        char *errp;
+        apr_off_t number, start, end;
+
+        if (!*cur)
+            break;
+
+        /*
+         * Per RFC 2616 14.35.1: If there is at least one syntactically invalid
+         * byte-range-spec, we must ignore the whole header.
+         */
+
+        if (!(dash = strchr(cur, '-'))) {
+            return 0;
+        }
+
+        if (dash == cur) {
+            /* In the form "-5" */
+            if (apr_strtoff(&number, dash+1, &errp, 10) || *errp) {
+                return 0;
+            }
+            if (number < 1) {
+                return 0;
+            }
+            start = clength - number;
+            end = clength - 1;
+        }
+        else {
+            *dash++ = '\0';
+            if (apr_strtoff(&number, cur, &errp, 10) || *errp) {
+                return 0;
+            }
+            start = number;
+            if (*dash) {
+                if (apr_strtoff(&number, dash, &errp, 10) || *errp) {
+                    return 0;
+                }
+                end = number;
+                if (start > end) {
+                    return 0;
+                }
+            }
+            else {                  /* "5-" */
+                end = clength - 1;
+            }
+        }
+
+        if (start < 0) {
+            start = 0;
+        }
+        if (start >= clength) {
+            unsatisfiable = 1;
+            continue;
+        }
+        if (end >= clength) {
+            end = clength - 1;
+        }
+
+        idx = (indexes_t *)apr_array_push(*indexes);
+        idx->start = start;
+        idx->end = end;
+        sum_lengths += end - start + 1;
+        /* new set again */
+        num_ranges++;
+    }
+
+    if (num_ranges == 0 && unsatisfiable) {
+        /* If all ranges are unsatisfiable, we should return 416 */
+        return -1;
+    }
+    if (sum_lengths >= clength) {
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "Sum of ranges not smaller than file, ignoring.");
+        return 0;
     }
 
     r->status = HTTP_PARTIAL_CONTENT;
-    r->range = range + 6;
+    r->range = it;
 
     return num_ranges;
 }
diff -rNU 20 ../httpd-2.2.12-o/modules/http/http_protocol.c ./modules/http/http_protocol.c
--- ../httpd-2.2.12-o/modules/http/http_protocol.c	2009-01-12 14:59:56.000000000 +0100
+++ ./modules/http/http_protocol.c	2011-09-16 15:35:45.000000000 +0200
@@ -827,40 +827,49 @@
     return OK;
 }
 
 AP_DECLARE(void) ap_set_content_type(request_rec *r, const char *ct)
 {
     if (!ct) {
         r->content_type = NULL;
     }
     else if (!r->content_type || strcmp(r->content_type, ct)) {
         r->content_type = ct;
 
         /* Insert filters requested by the AddOutputFiltersByType
          * configuration directive. Content-type filters must be
          * inserted after the content handlers have run because
          * only then, do we reliably know the content-type.
          */
         ap_add_output_filters_by_type(r);
     }
 }
 
+AP_DECLARE(void) ap_set_accept_ranges(request_rec *r)
+{
+    core_dir_config *d = 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,
                                       const char *suffix)
 {
     const char *notes, *result;
 
     if ((notes = apr_table_get(r->notes, key)) == NULL) {
         result = apr_pstrcat(r->pool, prefix, suffix, NULL);
     }
     else {
         result = apr_pstrcat(r->pool, prefix, notes, suffix, NULL);
     }
 
     return result;
 }
 
 /* construct and return the default error message for a given
  * HTTP defined error code
  */
diff -rNU 20 ../httpd-2.2.12-o/modules/mappers/mod_negotiation.c ./modules/mappers/mod_negotiation.c
--- ../httpd-2.2.12-o/modules/mappers/mod_negotiation.c	2009-05-10 17:11:46.000000000 +0200
+++ ./modules/mappers/mod_negotiation.c	2011-09-16 15:36:33.000000000 +0200
@@ -2990,41 +2990,41 @@
         apr_bucket_brigade *bb;
         apr_bucket *e;
 
         ap_allow_standard_methods(r, REPLACE_ALLOW, M_GET, M_OPTIONS,
                                   M_POST, -1);
         /* XXX: ?
          * if (r->method_number == M_OPTIONS) {
          *    return ap_send_http_options(r);
          *}
          */
         if (r->method_number != M_GET && r->method_number != M_POST) {
             return HTTP_METHOD_NOT_ALLOWED;
         }
 
         /* ### These may be implemented by adding some 'extra' info
          *     of the file offset onto the etag
          * 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, best->bytes);
 
         /* set MIME type and charset as negotiated */
         if (best->mime_type && *best->mime_type) {
             if (best->content_charset && *best->content_charset) {
                 ap_set_content_type(r, apr_pstrcat(r->pool,
                                                    best->mime_type,
                                                    "; charset=",
                                                    best->content_charset,
                                                    NULL));
             }
             else {
                 ap_set_content_type(r, apr_pstrdup(r->pool, best->mime_type));
             }
         }
 
         /* set Content-language(s) as negotiated */
         if (best->content_languages && best->content_languages->nelts) {
             r->content_languages = apr_array_copy(r->pool,
                                                   best->content_languages);
diff -rNU 20 ../httpd-2.2.12-o/server/core.c ./server/core.c
--- ../httpd-2.2.12-o/server/core.c	2009-07-02 23:30:36.000000000 +0200
+++ ./server/core.c	2011-09-16 15:39:49.000000000 +0200
@@ -142,40 +142,42 @@
     conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME;
 
     /* Overriding all negotiation
      */
     conf->mime_type = NULL;
     conf->handler = NULL;
     conf->output_filters = NULL;
     conf->input_filters = NULL;
 
     /*
      * Flag for use of inodes in ETags.
      */
     conf->etag_bits = ETAG_UNSET;
     conf->etag_add = ETAG_UNSET;
     conf->etag_remove = ETAG_UNSET;
 
     conf->enable_mmap = ENABLE_MMAP_UNSET;
     conf->enable_sendfile = ENABLE_SENDFILE_UNSET;
     conf->allow_encoded_slashes = 0;
 
+    conf->max_ranges = AP_MAXRANGES_UNSET;
+
     return (void *)conf;
 }
 
 /*
  * Overlay one hash table of ct_output_filters onto another
  */
 static void *merge_ct_filters(apr_pool_t *p,
                               const void *key,
                               apr_ssize_t klen,
                               const void *overlay_val,
                               const void *base_val,
                               const void *data)
 {
     ap_filter_rec_t *cur;
     const ap_filter_rec_t *overlay_info = (const ap_filter_rec_t *)overlay_val;
     const ap_filter_rec_t *base_info = (const ap_filter_rec_t *)base_val;
 
     cur = NULL;
 
     while (overlay_info) {
@@ -428,40 +430,42 @@
     else {
         conf->etag_bits = new->etag_bits;
         conf->etag_add = new->etag_add;
         conf->etag_remove = new->etag_remove;
     }
 
     if (conf->etag_bits != ETAG_NONE) {
         conf->etag_bits &= (~ ETAG_NONE);
     }
 
     if (new->enable_mmap != ENABLE_MMAP_UNSET) {
         conf->enable_mmap = new->enable_mmap;
     }
 
     if (new->enable_sendfile != ENABLE_SENDFILE_UNSET) {
         conf->enable_sendfile = new->enable_sendfile;
     }
 
     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;
 }
 
 static void *create_core_server_config(apr_pool_t *a, server_rec *s)
 {
     core_server_config *conf;
     int is_virtual = s->is_virtual;
 
     conf = (core_server_config *)apr_pcalloc(a, sizeof(core_server_config));
 
 #ifdef GPROF
     conf->gprof_dir = NULL;
 #endif
 
     conf->access_name = is_virtual ? NULL : DEFAULT_ACCESS_FNAME;
     conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
     conf->sec_dir = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
     conf->sec_url = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
 
     /* recursion stopper */
@@ -2941,40 +2945,67 @@
     return NULL;
 }
 
 static const char *set_limit_xml_req_body(cmd_parms *cmd, void *conf_,
                                           const char *arg)
 {
     core_dir_config *conf = conf_;
     const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
     if (err != NULL) {
         return err;
     }
 
     conf->limit_xml_body = atol(arg);
     if (conf->limit_xml_body < 0)
         return "LimitXMLRequestBody requires a non-negative integer.";
 
     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;
 
     conf = ap_get_module_config(r->per_dir_config, &core_module);
     if (conf->limit_xml_body == AP_LIMIT_UNSET)
         return AP_DEFAULT_LIMIT_XML_BODY;
 
     return (size_t)conf->limit_xml_body;
 }
 
 #if !defined (RLIMIT_CPU) || !(defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)) || !defined (RLIMIT_NPROC)
 static const char *no_set_limit(cmd_parms *cmd, void *conf_,
                                 const char *arg, const char *arg2)
 {
     ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server,
                 "%s not supported on this platform", cmd->cmd->name);
 
     return NULL;
 }
@@ -3370,40 +3401,44 @@
 AP_INIT_TAKE1("LogLevel", set_loglevel, NULL, RSRC_CONF,
   "Level of verbosity in error logging"),
 AP_INIT_TAKE1("NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF,
   "A numeric IP address:port, or the name of a host"),
 AP_INIT_TAKE1("ServerTokens", set_serv_tokens, NULL, RSRC_CONF,
   "Determine tokens displayed in the Server: header - Min(imal), OS or Full"),
 AP_INIT_TAKE1("LimitRequestLine", set_limit_req_line, NULL, RSRC_CONF,
   "Limit on maximum size of an HTTP request line"),
 AP_INIT_TAKE1("LimitRequestFieldsize", set_limit_req_fieldsize, NULL,
   RSRC_CONF,
   "Limit on maximum size of an HTTP request header field"),
 AP_INIT_TAKE1("LimitRequestFields", set_limit_req_fields, NULL, RSRC_CONF,
   "Limit (0 = unlimited) on max number of header fields in a request message"),
 AP_INIT_TAKE1("LimitRequestBody", set_limit_req_body,
   (void*)APR_OFFSETOF(core_dir_config, limit_req_body), OR_ALL,
   "Limit (in bytes) on maximum size of request message body"),
 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,
   (void*)APR_OFFSETOF(core_dir_config, limit_cpu),
   OR_ALL, "Soft/hard limits for max CPU usage in seconds"),
 #else
 AP_INIT_TAKE12("RLimitCPU", no_set_limit, NULL,
   OR_ALL, "Soft/hard limits for max CPU usage in seconds"),
 #endif
 #if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined (RLIMIT_AS)
 AP_INIT_TAKE12("RLimitMEM", set_limit_mem,
   (void*)APR_OFFSETOF(core_dir_config, limit_mem),
   OR_ALL, "Soft/hard limits for max memory usage per process"),
 #else
 AP_INIT_TAKE12("RLimitMEM", no_set_limit, NULL,
   OR_ALL, "Soft/hard limits for max memory usage per process"),
 #endif
 #ifdef RLIMIT_NPROC
 AP_INIT_TAKE12("RLimitNPROC", set_limit_nproc,
   (void*)APR_OFFSETOF(core_dir_config, limit_nproc),
@@ -3688,41 +3723,41 @@
                               r->method);
                 return HTTP_METHOD_NOT_ALLOWED;
             }
         }
 
 
         if ((status = apr_file_open(&fd, r->filename, APR_READ | APR_BINARY
 #if APR_HAS_SENDFILE
                             | ((d->enable_sendfile == ENABLE_SENDFILE_OFF)
                                                 ? 0 : APR_SENDFILE_ENABLED)
 #endif
                                     , 0, r->pool)) != APR_SUCCESS) {
             ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
                           "file permissions deny server access: %s", r->filename);
             return HTTP_FORBIDDEN;
         }
 
         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);
 
         bb = apr_brigade_create(r->pool, c->bucket_alloc);
 
         if ((errstatus = ap_meets_conditions(r)) != OK) {
             apr_file_close(fd);
             r->status = errstatus;
         }
         else {
             if (bld_content_md5) {
                 apr_table_setn(r->headers_out, "Content-MD5",
                                ap_md5digest(r->pool, fd));
             }
 
             /* For platforms where the size of the file may be larger than
              * that which can be stored in a single bucket (where the
              * length field is an apr_size_t), split it into several
              * buckets: */
             if (sizeof(apr_off_t) > sizeof(apr_size_t)
                 && r->finfo.size > AP_MAX_SENDFILE) {
