[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1034329: unblock: apache2/2.4.57-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
X-Debbugs-Cc: apache2@packages.debian.org
Control: affects -1 + src:apache2

Please unblock package apache2

[ Reason ]
The security fixes provided by version 2.4.56 includes some regressions
(#1033408 and #1033284)

[ Impact ]
Major bugs

[ Tests ]
Test updated, passes

[ Risks ]
Low risk here, the version 2.4.57 contains only bug fixes

[ Checklist ]
  [X] all changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in testing

[ Other info ]
The diff contains also a debian/NEWS entry (added also in bullseye after
#1018718 fix)

unblock apache2/2.4.57-1
diff --git a/CHANGES b/CHANGES
index 16f8f55d..b0e8b117 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,58 @@
                                                          -*- coding: utf-8 -*-
+Changes with Apache 2.4.57
+
+  *) mod_proxy: Check before forwarding that a nocanon path has not been
+     rewritten with spaces during processing.  [Yann Ylavic]
+
+  *) mod_proxy: In case that AllowEncodedSlashes is set to NoDecode do not
+     double encode encoded slashes in the URL sent by the reverse proxy to the
+     backend. [Ruediger Pluem]
+
+  *) mod_http2: fixed a crash during connection termination. See PR 66539.
+     [Stefan Eissing]
+
+  *) mod_rewrite: Fix a 2.4.56 regression for substitutions ending
+     in a question mark. PR66547. [Eric Covener]
+
+  *) mod_rewrite: Add "BCTLS" and "BNE" RewriteRule flags. Re-allow encoded
+     characters on redirections without the "NE" flag. 
+     [Yann Ylavic, Eric Covener]
+
+  *) mod_proxy: Fix double encoding of the uri-path of the request forwarded
+     to the origin server, when using mapping=encoded|servlet.  [Yann Ylavic]
+
+  *) mod_mime: Do not match the extention against possible query string
+     parameters in case ProxyPass was used with the nocanon option.
+     [Ruediger Pluem]
+
 Changes with Apache 2.4.56
 
+  *) SECURITY: CVE-2023-27522: Apache HTTP Server: mod_proxy_uwsgi
+     HTTP response splitting (cve.mitre.org)
+     HTTP Response Smuggling vulnerability in Apache HTTP Server via
+     mod_proxy_uwsgi. This issue affects Apache HTTP Server: from
+     2.4.30 through 2.4.55.
+     Special characters in the origin response header can
+     truncate/split the response forwarded to the client.
+     Credits: Dimas Fariski Setyawan Putra (nyxsorcerer)
+
+  *) SECURITY: CVE-2023-25690: HTTP request splitting with
+     mod_rewrite and mod_proxy (cve.mitre.org)
+     Some mod_proxy configurations on Apache HTTP Server versions
+     2.4.0 through 2.4.55 allow a HTTP Request Smuggling attack.
+     Configurations are affected when mod_proxy is enabled along with
+     some form of RewriteRule or ProxyPassMatch in which a non-specific
+     pattern matches some portion of the user-supplied request-target (URL)
+     data and is then re-inserted into the proxied request-target
+     using variable substitution. For example, something like:
+        RewriteEngine on
+        RewriteRule "^/here/(.*)" "http://example.com:8080/elsewhere?$1";; [P]
+        ProxyPassReverse /here/  http://example.com:8080/
+     Request splitting/smuggling could result in bypass of access
+     controls in the proxy server, proxying unintended URLs to
+     existing origin servers, and cache poisoning.
+     Credits: Lars Krapf of Adobe
+
   *) rotatelogs: Add -T flag to allow subsequent rotated logfiles to be
      truncated without the initial logfile being truncated.  [Eric Covener]
 
@@ -112,6 +164,7 @@ Changes with Apache 2.4.55
        The checks for this in nghttp2 v1.50.0+ are disabled.
      - Extensive testing in production done by Alessandro Bianchi (@alexskynet)
        on the v2.0.x versions for stability. Many thanks!
+
   *) mod_proxy_http2: fixed #235 by no longer forwarding 'Host:' header when
      request ':authority' is known. Improved test case that did not catch that
      the previous 'fix' was incorrect.
@@ -319,6 +372,9 @@ Changes with Apache 2.4.54
      domain names in the *.ts.net space.
      [Stefan Eissing]
 
+  *) core: Change default value of LimitRequestBody from 0 (unlimited)
+     to 1GB. [Eric Covener]
+
 Changes with Apache 2.4.53
 
   *) SECURITY: CVE-2022-23943: mod_sed: Read/write beyond bounds
diff --git a/debian/NEWS b/debian/NEWS
new file mode 100644
index 00000000..a55a9d70
--- /dev/null
+++ b/debian/NEWS
@@ -0,0 +1,9 @@
+apache2 (2.4.54-3) unstable; urgency=medium
+
+  This version does not automatically enable the apache2 config snippet for
+  /manual anymore. If you want to have it enabled you will need to do this
+  yourself, e.g. with
+
+    /usr/sbin/a2enconf apache2-doc
+
+ -- Yadd <yadd@debian.org>  Sat, 01 Apr 2023 08:17:08 +0400
diff --git a/debian/changelog b/debian/changelog
index 4ae13cf0..a6602864 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,24 @@
+apache2 (2.4.57-2) unstable; urgency=medium
+
+  * Revert debian/* changes (Bookworm freeze)
+
+ -- Yadd <yadd@debian.org>  Thu, 13 Apr 2023 07:26:51 +0400
+
+apache2 (2.4.57-1) unstable; urgency=medium
+
+  * New upstream version 2.4.57
+  * Drop 2.4.56-regression patches
+
+ -- Yadd <yadd@debian.org>  Sat, 08 Apr 2023 06:57:16 +0400
+
+apache2 (2.4.56-2) unstable; urgency=medium
+
+  * Fix regression in mod_rewrite introduced in version 2.4.56
+    (Closes: #1033284)
+  * Fix regression in http2 introduced by 2.4.56 (Closes: #1033408)
+
+ -- Yadd <yadd@debian.org>  Sun, 02 Apr 2023 06:54:25 +0400
+
 apache2 (2.4.56-1) unstable; urgency=medium
 
   * New upstream version (Closes: #1032476, CVE-2023-27522, CVE-2023-25690)
diff --git a/debian/config-dir/sites-available/default-ssl.conf b/debian/config-dir/sites-available/default-ssl.conf
index 9de96fa2..330280de 100644
--- a/debian/config-dir/sites-available/default-ssl.conf
+++ b/debian/config-dir/sites-available/default-ssl.conf
@@ -45,8 +45,8 @@
 	#   certificates for client authentication or alternatively one
 	#   huge file containing all of them (file must be PEM encoded)
 	#   Note: Inside SSLCACertificatePath you need hash symlinks
-	#         to point to the certificate files. Use the provided
-	#         Makefile to update the hash symlinks after changes.
+	#	  to point to the certificate files. Use the provided
+	#	  Makefile to update the hash symlinks after changes.
 	#SSLCACertificatePath /etc/ssl/certs/
 	#SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt
 
@@ -55,8 +55,8 @@
 	#   authentication or alternatively one huge file containing all
 	#   of them (file must be PEM encoded)
 	#   Note: Inside SSLCARevocationPath you need hash symlinks
-	#         to point to the certificate files. Use the provided
-	#         Makefile to update the hash symlinks after changes.
+	#	  to point to the certificate files. Use the provided
+	#	  Makefile to update the hash symlinks after changes.
 	#SSLCARevocationPath /etc/apache2/ssl.crl/
 	#SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl
 
diff --git a/docs/manual/mod/core.html.tr.utf8 b/docs/manual/mod/core.html.tr.utf8
index ed1dba5c..5d87a514 100644
--- a/docs/manual/mod/core.html.tr.utf8
+++ b/docs/manual/mod/core.html.tr.utf8
@@ -33,7 +33,6 @@
 <a href="../ja/mod/core.html" hreflang="ja" rel="alternate" title="Japanese">&nbsp;ja&nbsp;</a> |
 <a href="../tr/mod/core.html" title="Türkçe">&nbsp;tr&nbsp;</a></p>
 </div>
-<div class="outofdate">Bu çeviri güncel olmayabilir. Son değişiklikler için İngilizce sürüm geçerlidir.</div>
 <table class="module"><tr><th><a href="module-dict.html#Description">Açıklama:</a></th><td>Apache HTTP Sunucusunda daima mevcut olan çekirdek
  özellikler</td></tr>
 <tr><th><a href="module-dict.html#Status">Durum:</a></th><td>Çekirdek</td></tr></table>
@@ -1359,6 +1358,11 @@ DocumentRoot "/var/www/${servername}/htdocs"</pre>
 &lt;/IfDefine&gt;</pre>
 
 
+    <div class="warning"><h3>Ek Bilgi</h3>
+      <p>Bu yönerge, çalışma zamanında değil, yapılandırma işlemi sırasında
+      değerlendirilir. Sonuç olarak, bu yönerge bir <code class="directive"><a href="#if">&lt;If&gt;</a></code> bölümü içine alınarak koşullu olarak
+      değerlendirilemez.</p>
+    </div>
 
 </div>
 <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
@@ -1696,7 +1700,7 @@ ErrorLogFormat "[%{uc}t] [%-m:%-l] [R:%L] [C:%{C}L] %7F: %E: %M"
 ErrorLogFormat request "[%{uc}t] [R:%L] Request %k on C:%{c}L pid:%P tid:%T"
 ErrorLogFormat request "[%{uc}t] [R:%L] UA:'%+{User-Agent}i'"
 ErrorLogFormat request "[%{uc}t] [R:%L] Referer:'%+{Referer}i'"
-ErrorLogFormat connection "[%{uc}t] [C:%{c}L] local\ %a remote\ %A"</pre>
+ErrorLogFormat connection "[%{uc}t] [C:%{c}L] remote\ %a local\ %A"</pre>
 
 
 
@@ -2252,6 +2256,13 @@ takdirde uygulanacak yönergeleri barındırır.</td></tr>
     yönerge için kullanılabilir olmayacaktır.
     </div>
 
+    <div class="warning"><code class="directive">Define</code>,
+    <code class="directive">Include</code> ve <code class="directive">Error</code> gibi
+    yapılandırma ayrıştırılırken etkili olan yönergeler, bir <code class="directive">&lt;If&gt;</code> yapılandırma bölümü içine alınarak koşullu
+    hale getirilemez. Bu bölümler, çalışma anında nasıl değerlendirildiklerine
+    bakılmaksızın, her zaman yapılandırmanın bir parçasıdır.
+    </div>
+
 
 <h3>Ayrıca bakınız:</h3>
 <ul>
diff --git a/docs/manual/mod/mod_md.html.fr.utf8 b/docs/manual/mod/mod_md.html.fr.utf8
index 737cfbe7..22a15ac2 100644
--- a/docs/manual/mod/mod_md.html.fr.utf8
+++ b/docs/manual/mod/mod_md.html.fr.utf8
@@ -29,8 +29,6 @@
 <p><span>Langues Disponibles: </span><a href="../en/mod/mod_md.html" hreflang="en" rel="alternate" title="English">&nbsp;en&nbsp;</a> |
 <a href="../fr/mod/mod_md.html" title="Français">&nbsp;fr&nbsp;</a></p>
 </div>
-<div class="outofdate">Cette traduction peut être périmée. Vérifiez la version
-            anglaise pour les changements récents.</div>
 <table class="module"><tr><th><a href="module-dict.html#Description">Description:</a></th><td>Gestion des domaines au sein des serveurs virtuels et obtention
     de certificats via le protocole ACME
     </td></tr>
@@ -736,6 +734,12 @@
 		vérification valide pour les certificats génériques. Si vous
 		avez besoin d'un tel certificat, vous devez alors définir cette
 		directive.
+            </p><p>
+	        Il est maintenant possible d'utiliser cette directive dans une
+		section <code class="directive"><a href="#mdomain">MDomain</a></code> pour
+		spécifier une commande spécifique au domaine considéré. Cela
+		permet de configurer un script spécifique au fournisseur de DNS
+		concerné.
             </p><p>
                 Reportez vous à la section sur les certificats génériques pour
 		plus de détails.
diff --git a/docs/manual/mod/mod_rewrite.html.en b/docs/manual/mod/mod_rewrite.html.en
index 1631fe0c..30d74341 100644
--- a/docs/manual/mod/mod_rewrite.html.en
+++ b/docs/manual/mod/mod_rewrite.html.en
@@ -1307,6 +1307,16 @@ cannot use <code>$N</code> in the substitution string!
         <td>Escape non-alphanumeric characters in backreferences <em>before</em>
         applying the transformation. <em><a href="../rewrite/flags.html#flag_b">details ...</a></em></td>
     </tr>
+<tr class="odd">
+        <td>BCTLS</td>
+        <td>Like [B], but only escape control characters and spaces.
+        <em><a href="../rewrite/flags.html#flag_bctls">details ...</a></em></td>
+    </tr>
+<tr>
+        <td>BNE</td>
+        <td>Characters of [B] or [BCTLS] which should <strong>not</strong> be escaped.
+        <em><a href="../rewrite/flags.html#flag_bne">details ...</a></em></td>
+     </tr>
 <tr class="odd">
         <td>backrefnoplus|BNP</td>
         <td>If backreferences are being escaped, spaces should be escaped to
diff --git a/docs/manual/mod/mod_rewrite.html.fr.utf8 b/docs/manual/mod/mod_rewrite.html.fr.utf8
index fcb07527..2f2625a9 100644
--- a/docs/manual/mod/mod_rewrite.html.fr.utf8
+++ b/docs/manual/mod/mod_rewrite.html.fr.utf8
@@ -1415,6 +1415,17 @@ substitution !
 	dans les références arrières <em>avant</em>
 	d'appliquer la transformation. <em><a href="../rewrite/flags.html#flag_b">détails ...</a></em></td>
     </tr>
+<tr class="odd">
+        <td>BCTLS</td>
+        <td>Identique à [B], mais n'échappe que les espaces et les caractères de
+	contrôle. <em><a href="../rewrite/flags.html#flag_bctls">détails ...</a></em></td>
+    </tr>
+<tr>
+        <td>BNE</td>
+	<td>Les caractères de [B] ou [BCTLS] qui <strong>ne doivent pas</strong>
+	être échappés.  <em><a href="../rewrite/flags.html#flag_bne">détails
+	...</a></em></td>
+    </tr>
 <tr class="odd">
         <td>backrefnoplus|BNP</td>
         <td>Avec ce drapeau, si les références arrières sont échappées,
diff --git a/docs/manual/programs/rotatelogs.html.fr.utf8 b/docs/manual/programs/rotatelogs.html.fr.utf8
index c5f8ee1d..fc71646f 100644
--- a/docs/manual/programs/rotatelogs.html.fr.utf8
+++ b/docs/manual/programs/rotatelogs.html.fr.utf8
@@ -30,8 +30,6 @@
 <a href="../ko/programs/rotatelogs.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a> |
 <a href="../tr/programs/rotatelogs.html" hreflang="tr" rel="alternate" title="Türkçe">&nbsp;tr&nbsp;</a></p>
 </div>
-<div class="outofdate">Cette traduction peut être périmée. Vérifiez la version
-            anglaise pour les changements récents.</div>
 
      <p><code>rotatelogs</code> est un programme simple à utiliser en
      conjonction avec la fonctionnalité d'Apache de redirection dans un
@@ -120,6 +118,15 @@ chaînes de format contenant des caractères '%' sont cependant
 respectées.
 </dd>
 
+<dt><code>-T</code></dt>
+<dd>Provoque la troncature de tous les fichiers journaux lors de leur ouverture,
+à l'exception du fichier journal initial. Cela s'avère utile lorsque la chaîne
+de formatage contient quelque chose qui va se répéter de manière cyclique, comme
+le jour du mois par exemple. Disponible à partir de la version 2.4.56 du serveur
+HTTP Apache.
+</dd>
+
+
 <dt><code>-v</code></dt>
 <dd>Affiche une sortie verbeuse sur STDERR. La sortie contient le
 résultat de l'interprétation de la configuration, ainsi que toutes les
@@ -252,6 +259,15 @@ spécifier un décalage.</dd>
      tronquant au démarrage, puis une fois par jour. Ce scénario implique qu'un
      processus séparé (tel que tail) traite le fichier en temps réel.</p>
 
+<div class="example"><pre class="prettyprint lang-config">CustomLog "|bin/rotatelogs -T /var/log/logfile.%d 86400" common</pre>
+</div>
+
+<p>Si le serveur est démarré ou redémarré le premier du mois, cela s'ajoute à la
+fin de <code>/var/log/logfile.01</code>. Lorsqu'une entrée de journal est écrite
+le deux du mois, <code>/var/log/logfile.02</code> est tronqué et les nouvelles
+entrées seront ajoutées à partir du début du fichier. Cet exemple conserve
+environ 1 mois de journaux sans nécessiter de maintenance externe.</p>
+
 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
 <div class="section">
 <h2><a name="portability" id="portability">Portabilité</a></h2>
diff --git a/docs/manual/programs/rotatelogs.html.tr.utf8 b/docs/manual/programs/rotatelogs.html.tr.utf8
index dd0156c3..22d438b6 100644
--- a/docs/manual/programs/rotatelogs.html.tr.utf8
+++ b/docs/manual/programs/rotatelogs.html.tr.utf8
@@ -30,7 +30,6 @@
 <a href="../ko/programs/rotatelogs.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a> |
 <a href="../tr/programs/rotatelogs.html" title="Türkçe">&nbsp;tr&nbsp;</a></p>
 </div>
-<div class="outofdate">Bu çeviri güncel olmayabilir. Son değişiklikler için İngilizce sürüm geçerlidir.</div>
 
      <p><code><strong>rotatelogs</strong></code>, Apache'nin borulu günlük
      dosyaları özelliği ile birlikte kullanmak için tasarlanmış basit bir
@@ -109,6 +108,13 @@
     Dosya ismine bir sonek eklenmez, ancak biçem dizgesi '%' karakteri
     içeriyorsa buna uyulur.</dd>
 
+    <dt><code>-T</code></dt>
+    <dd>Açıldığında ilk günlük dosyası dışındaki tüm dosyaların kırpılmasına
+    neden olur. Bu, biçem dizgesi ayın günü gibi döngüsel bir şey içerdiğinde
+    kullanışlıdır. 2.4.56 ve sonrasında mevcuttur.
+    </dd>
+
+
     <dt><code><strong>-v</strong></code></dt>
     <dd>Standart hataya verilen çıktı daha ayrıntılı olur. Çıktı,
     yapılandırma çözümlemesinin sonuçlarını ve tüm dosya açma/kapama
@@ -191,9 +197,8 @@
 <div class="section">
 <h2><a name="examples" id="examples">Örnekler</a></h2>
 
-<div class="example"><p><code>
-     CustomLog "|bin/rotatelogs /var/log/logfile 86400" common
-</code></p></div>
+<div class="example"><pre class="prettyprint lang-config">CustomLog "|bin/rotatelogs /var/log/logfile 86400" common</pre>
+</div>
 
      <p>nnnn, günlük kaydının başladığı sistem zamanı olmak üzere
      /var/log/logfile.nnnn dosyası oluşturulur. Bu zaman, daima döngü
@@ -201,36 +206,41 @@
      kullanabilirsiniz. Her döngü süresinin sonunda (burada 24 saat sonra)
      yeni bir günlük dosyası açılır.</p>
 
-<div class="example"><p><code>
-     CustomLog "|bin/rotatelogs -l /var/log/logfile.%Y.%m.%d 86400" common
-</code></p></div>
+<div class="example"><pre class="prettyprint lang-config">CustomLog "|bin/rotatelogs -l /var/log/logfile.%Y.%m.%d 86400" common</pre>
+</div>
 
      <p>yyyy, yıl; mm, ay; dd, ayın gününü belirtmek üzere
      /var/log/logfile.yyyy.mm.dd dosyası oluşturulur. Her gün yerel zamanla
      geceyarısı yeni bir günlük dosyasına geçilecektir.</p>
 
-<div class="example"><p><code>
-     CustomLog "|bin/rotatelogs /var/log/logfile 5M" common
-</code></p></div>
+<div class="example"><pre class="prettyprint lang-config">CustomLog "|bin/rotatelogs /var/log/logfile 5M" common</pre>
+</div>
 
      <p>Günlük dosyası 5 megabaytlık olunca yenisinin oluşturulmasını sağlar.
      </p>
 
-<div class="example"><p><code>
-     ErrorLog "|bin/rotatelogs /var/log/errorlog.%Y-%m-%d-%H_%M_%S 5M"
-</code></p></div>
+<div class="example"><pre class="prettyprint lang-config">ErrorLog "|bin/rotatelogs /var/log/errorlog.%Y-%m-%d-%H_%M_%S 5M"</pre>
+</div>
      <p>Hata günlüğünün 5 megabaytta bir
      <code>errorlog.YYYY-mm-dd-HH_MM_SS</code> biçemli bir isimle
      oluşturulmasını sağlar.</p>
 
-<div class="example"><p><code>
-     CustomLog "|bin/rotatelogs -t /var/log/logfile 86400" common
-</code></p></div>
+<div class="example"><pre class="prettyprint lang-config">CustomLog "|bin/rotatelogs -t /var/log/logfile 86400" common</pre>
+</div>
 
-     <p>/var/log/logfile dosyasını oluşturur, sunucu başlatılırken ve günde
+     <p><code>/var/log/logfile</code> dosyasını oluşturur, sunucu başlatılırken ve günde
        bir kere dosyanın tepesi kırpılır. Bu senaryoda ayrı bir sürecin (tail
        gibi) dosyayı gerçek zamanlı işleyeceği umulur.</p>
 
+<div class="example"><pre class="prettyprint lang-config">CustomLog "|bin/rotatelogs -T /var/log/logfile.%d 86400" common</pre>
+</div>
+
+     <p>Sunucu ayın birinde başlatılırsa (veya yeniden başlatılırsa), bu,
+     <code>/var/log/logfile.01</code> dosyasının sonuna eklenir. Ayın ikinci
+     günü bir günlük girişi yazıldığında, <code>/var/log/logfile.02</code>
+     kırpılır ve en üste yeni girdiler eklenir. Bu örnek, özel bir bakım
+     gerektirmeden yaklaşık 1 aylık günlük tutar.</p>
+
 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
 <div class="section">
 <h2><a name="portability" id="portability">Taşınabilirlik</a></h2>
diff --git a/docs/manual/rewrite/flags.html.en b/docs/manual/rewrite/flags.html.en
index 5ffd1b2e..5e175f17 100644
--- a/docs/manual/rewrite/flags.html.en
+++ b/docs/manual/rewrite/flags.html.en
@@ -34,6 +34,8 @@ providing detailed explanations and examples.</p>
 <div id="quickview"><a href="https://www.apache.org/foundation/contributing.html"; class="badge"><img src="https://www.apache.org/images/SupportApache-small.png"; alt="Support Apache!" /></a><ul id="toc"><li><img alt="" src="../images/down.gif" /> <a href="#introduction">Introduction</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#flag_b">B (escape backreferences)</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#flag_bnp">BNP|backrefnoplus (don't escape space to +)</a></li>
+<li><img alt="" src="../images/down.gif" /> <a href="#flag_bctls">BCTLS</a></li>
+<li><img alt="" src="../images/down.gif" /> <a href="#flag_bne">BNE</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#flag_c">C|chain</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#flag_co">CO|cookie</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#flag_dpi">DPI|discardpath</a></li>
@@ -85,10 +87,6 @@ of how you might use them.</p>
 <h2><a name="flag_b" id="flag_b">B (escape backreferences)</a></h2>
 <p>The [B] flag instructs <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> to escape non-alphanumeric
 characters before applying the transformation.</p>
-<p>In 2.4.26 and later, you can limit the escaping to specific characters
-in backreferences by listing them: <code>[B=#?;]</code>. Note: The space
-character can be used in the list of characters to escape, but it cannot be
-the last character in the list.</p>
 
 <p><code>mod_rewrite</code> has to unescape URLs before mapping them,
 so backreferences are unescaped at the time they are applied.
@@ -120,6 +118,20 @@ when the backend may break if presented with an unescaped URL.</p>
 
 <p>An alternative to this flag is using a <code class="directive"><a href="../mod/mod_rewrite.html#rewritecond">RewriteCond</a></code> to capture against %{THE_REQUEST} which will capture
 strings in the encoded form.</p>
+
+<p>In 2.4.26 and later, you can limit the escaping to specific characters
+in backreferences by listing them: <code>[B=#?;]</code>. Note: The space
+character can be used in the list of characters to escape, but you must quote
+the entire third argument of <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code>
+and the space must not be the last character in the list.</p>
+
+<pre class="prettyprint lang-config"># Escape spaces and question marks.  The quotes around the final argument 
+# are required when a space is included.
+RewriteRule "^search/(.*)$" "/search.php?term=$1" "[B= ?]"</pre>
+
+
+<p>To limit the characters escaped this way, see <a href="flag_bne">flag_bne</a>
+and <a href="flag_bctls">flag_bctls</a></p>
 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
 <div class="section">
 <h2><a name="flag_bnp" id="flag_bnp">BNP|backrefnoplus (don't escape space to +)</a></h2>
@@ -127,8 +139,40 @@ strings in the encoded form.</p>
 in a backreference to %20 rather than '+'. Useful when the backreference
 will be used in the path component rather than the query string.</p>
 
+<pre class="prettyprint lang-config"># Escape spaces to %20 in the path instead of + as used in form submission via
+# the query string
+RewriteRule "^search/(.*)$" "/search.php/$1" "[B,BNP]"</pre>
+
+
+
 <p>This flag is available in version 2.4.26 and later.</p>
+</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
+<div class="section">
+<h2><a name="flag_bctls" id="flag_bctls">BCTLS</a></h2>
+<p>The [BCTLS] flag is similar to the [B] flag, but only escapes
+control characters and the space character. This is the same set of
+characters rejected when they are copied into the query string unencoded.
+</p>
+
+<pre class="prettyprint lang-config"># Escape control characters and spaces
+RewriteRule "^search/(.*)$" "/search.php/$1" "[BCTLS]"</pre>
+
+
+<p>This flag is available in version 2.4.57 and later.</p>
+
+</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
+<div class="section">
+<h2><a name="flag_bne" id="flag_bne">BNE</a></h2>
+<p>The list of characters in [BNE=...] are treated as exclusions to the
+characters of the [B] or [BCTLS] flags. The listed characters will not be
+escaped.
+</p>
+
+<pre class="prettyprint lang-config"># Escape the default characters, but leave /
+RewriteRule "^search/(.*)$" "/search.php?term=$1" "[B,BNE=/]"</pre>
+
 
+<p>This flag is available in version 2.4.57 and later.</p>
 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
 <div class="section">
 <h2><a name="flag_c" id="flag_c">C|chain</a></h2>
@@ -210,7 +254,7 @@ attribute is set to the specified value.  Typical values are <code>None</code>,
 <p>Consider this example:</p>
 
 <pre class="prettyprint lang-config">RewriteEngine On
-RewriteRule "^/index\.html" "-" [CO=frontdoor:yes:.example.com:1440:/]</pre>
+RewriteRule   "^/index\.html"   "-" [CO=frontdoor:yes:.example.com:1440:/]</pre>
 
 
 <p>In the example give, the rule doesn't rewrite the request.
@@ -295,8 +339,8 @@ value of '1' if the requested URI is an image file. Then, that
 environment variable is used to exclude those requests from the access
 log.</p>
 
-<pre class="prettyprint lang-config">RewriteRule "\.(png|gif|jpg)$" "-" [E=image:1]
-CustomLog "logs/access_log" combined env=!image</pre>
+<pre class="prettyprint lang-config">RewriteRule "\.(png|gif|jpg)$"   "-" [E=image:1]
+CustomLog   "logs/access_log"    combined env=!image</pre>
 
 
 <p>Note that this same effect can be obtained using <code class="directive"><a href="../mod/mod_setenvif.html#setenvif">SetEnvIf</a></code>. This technique is offered as
@@ -321,7 +365,7 @@ allows more flexibility in assigning a Forbidden status.</p>
 <p>The following rule will forbid <code>.exe</code> files from being
 downloaded from your server.</p>
 
-<pre class="prettyprint lang-config">RewriteRule "\.exe" "-" [F]</pre>
+<pre class="prettyprint lang-config">RewriteRule "\.exe"   "-" [F]</pre>
 
 
 <p>This example uses the "-" syntax for the rewrite target, which means
@@ -341,7 +385,7 @@ longer available.</p>
 <p>As with the [F] flag, you will typically use the "-" syntax for the
 rewrite target when using the [G] flag:</p>
 
-<pre class="prettyprint lang-config">RewriteRule "oldproduct" "-" [G,NC]</pre>
+<pre class="prettyprint lang-config">RewriteRule "oldproduct"   "-" [G,NC]</pre>
 
 
 <p>When using [G], an [L] is implied - that is, the response is returned
@@ -354,7 +398,7 @@ immediately, and no further rules are evaluated.</p>
 handler. For example, one might use this to force all files without a
 file extension to be parsed by the php handler:</p>
 
-<pre class="prettyprint lang-config">RewriteRule "!\." "-" [H=application/x-httpd-php]</pre>
+<pre class="prettyprint lang-config">RewriteRule "!\."  "-" [H=application/x-httpd-php]</pre>
 
 
 <p>
@@ -416,8 +460,8 @@ argument to <code>index.php</code>, however, the <code class="directive"><a href
 is already for <code>index.php</code>, the <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> will be skipped.</p>
 
 <pre class="prettyprint lang-config">RewriteBase "/"
-RewriteCond "%{REQUEST_URI}" "!=/index.php"
-RewriteRule "^(.*)" "/index.php?req=$1" [L,PT]</pre>
+RewriteCond "%{REQUEST_URI}" !=/index.php
+RewriteRule "^(.*)"          "/index.php?req=$1" [L,PT]</pre>
 
 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
 <div class="section">
@@ -440,11 +484,11 @@ pattern still matches (i.e., while the URI still contains an
 <code>A</code>), perform this substitution (i.e., replace the
 <code>A</code> with a <code>B</code>).</p>
 
-<p>In 2.4.8 and later, this module returns an error after 32,000 iterations to
+<p>In 2.4.8 and later, this module returns an error after 10,000 iterations to
 protect against unintended looping.  An alternative maximum number of
 iterations can be specified by adding to the N flag.  </p>
 <pre class="prettyprint lang-config"># Be willing to replace 1 character in each pass of the loop
-RewriteRule "(.+)[&gt;&lt;;]$" "$1" [N=64000]
+RewriteRule "(.+)[&gt;&lt;;]$" "$1" [N=32000]
 # ... or, give up if after 10 loops
 RewriteRule "(.+)[&gt;&lt;;]$" "$1" [N=10]</pre>
 
@@ -688,19 +732,21 @@ URI in request' warnings.
 <p>The [S] flag is used to skip rules that you don't want to run. The
 syntax of the skip flag is [S=<em>N</em>], where <em>N</em> signifies
 the number of rules to skip (provided the <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">
-RewriteRule</a></code> matches). This can be thought of as a <code>goto</code>
-statement in your rewrite ruleset. In the following example, we only want
-to run the <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> if the
-requested URI doesn't correspond with an actual file.</p>
+RewriteRule</a></code> and any preceding <code class="directive"><a href="../mod/mod_rewrite.html#rewritecond">
+RewriteCond</a></code> directives match). This can be thought of as a
+<code>goto</code> statement in your rewrite ruleset. In the following
+example, we only want to run the <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">
+RewriteRule</a></code> if the requested URI doesn't correspond with an
+actual file.</p>
 
 <pre class="prettyprint lang-config"># Is the request for a non-existent file?
-RewriteCond "%{REQUEST_FILENAME}" "!-f"
-RewriteCond "%{REQUEST_FILENAME}" "!-d"
+RewriteCond "%{REQUEST_FILENAME}" !-f
+RewriteCond "%{REQUEST_FILENAME}" !-d
 # If so, skip these two RewriteRules
-RewriteRule ".?" "-" [S=2]
+RewriteRule ".?"                  "-" [S=2]
 
-RewriteRule "(.*\.gif)" "images.php?$1"
-RewriteRule "(.*\.html)" "docs.php?$1"</pre>
+RewriteRule "(.*\.gif)"           "images.php?$1"
+RewriteRule "(.*\.html)"          "docs.php?$1"</pre>
 
 
 <p>This technique is useful because a <code class="directive"><a href="../mod/mod_rewrite.html#rewritecond">RewriteCond</a></code> only applies to the
@@ -712,18 +758,18 @@ use this to make pseudo if-then-else constructs: The last rule of
 the then-clause becomes <code>skip=N</code>, where N is the
 number of rules in the else-clause:</p>
 <pre class="prettyprint lang-config"># Does the file exist?
-RewriteCond "%{REQUEST_FILENAME}" "!-f"
-RewriteCond "%{REQUEST_FILENAME}" "!-d"
+RewriteCond "%{REQUEST_FILENAME}" !-f
+RewriteCond "%{REQUEST_FILENAME}" !-d
 # Create an if-then-else construct by skipping 3 lines if we meant to go to the "else" stanza.
-RewriteRule ".?" "-" [S=3]
+RewriteRule ".?"                  "-" [S=3]
 
 # IF the file exists, then:
-    RewriteRule "(.*\.gif)" "images.php?$1"
+    RewriteRule "(.*\.gif)"  "images.php?$1"
     RewriteRule "(.*\.html)" "docs.php?$1"
     # Skip past the "else" stanza.
-    RewriteRule ".?" "-" [S=1]
+    RewriteRule ".?"         "-" [S=1]
 # ELSE...
-    RewriteRule "(.*)" "404.php?file=$1"
+    RewriteRule "(.*)"       "404.php?file=$1"
 # END</pre>
 
 
@@ -740,7 +786,7 @@ sent. This has the same effect as the <code class="directive"><a href="../mod/mo
 source code as plain text, if requested in a particular way:</p>
 
 <pre class="prettyprint lang-config"># Serve .pl files as plain text
-RewriteRule "\.pl$" "-" [T=text/plain]</pre>
+RewriteRule "\.pl$"  "-" [T=text/plain]</pre>
 
 
 <p>Or, perhaps, if you have a camera that produces jpeg images without
@@ -748,7 +794,7 @@ file extensions, you could force those images to be served with the
 correct MIME type by virtue of their file names:</p>
 
 <pre class="prettyprint lang-config"># Files with 'IMG' in the name are jpg images.
-RewriteRule "IMG" "-" [T=image/jpg]</pre>
+RewriteRule "IMG"  "-" [T=image/jpg]</pre>
 
 
 <p>Please note that this is a trivial example, and could be better done
diff --git a/docs/manual/rewrite/flags.html.fr.utf8 b/docs/manual/rewrite/flags.html.fr.utf8
index 75d9aa84..4c3e4864 100644
--- a/docs/manual/rewrite/flags.html.fr.utf8
+++ b/docs/manual/rewrite/flags.html.fr.utf8
@@ -88,13 +88,7 @@ d'utilisation.</p>
 <div class="section">
 <h2><a name="flag_b" id="flag_b">B (échappement dans les références arrières)</a></h2>
 <p>Avec le drapeau [B], la directive <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> échappe les caractères
-non-alphanumériques avant d'appliquer la transformation. A partir
-de la version 2.4.26, vous pouvez limiter l'échappement dans les
-références arrières à une liste de caractères que vous pouvez spécifiez comme
-dans cet exemple : <code>[B=#?;]</code>. Notez que l'espace peut faire
-partie de la liste des caractères à échapper, mais qu'il ne doit pas
-être le dernier caractère de cette liste.
-</p>
+non-alphanumériques avant d'appliquer la transformation.</p>
 
 <p><code>mod_rewrite</code> doit supprimer les séquences d'échappement
 des URLs avant leur
@@ -138,6 +132,22 @@ si on présente à ce dernier une URL non échappée.</p>
 %{THE_REQUEST}, les chaînes capturées se présentant
 alors sous la forme codée.</p>
 
+<p>A partir
+de la version 2.4.26, vous pouvez limiter l'échappement dans les
+références arrières à une liste de caractères que vous pouvez spécifiez comme
+dans cet exemple : <code>[B=#?;]</code>. Notez que l'espace peut faire
+partie de la liste des caractères à échapper, mais que vous devez mettre entre
+guillemets le troisième argument de la directive <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> et que l'espace ne doit pas
+être le dernier caractère de cette liste.
+</p>
+
+<pre class="prettyprint lang-config"># Échappement des espaces et des points d'interrogation. Les guillemets autour
+# du dernier argument sont obligatoires lorsque l'espace est inclus.
+RewriteRule "^search/(.*)$" "/search.php?term=$1" "[B= ?]"</pre>
+
+
+<p>Pour définir la liste des caractères à échapper de cette manière, voir <a href="flag_bne">flag_bne</a> et <a href="flag_bctls">flag_bctls</a></p>
+
 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
 <div class="section">
 <h2><a name="flag_bnp" id="flag_bnp">BNP|backrefnoplus (ne pas échapper
@@ -147,9 +157,43 @@ espace en %20 au lieu de '+' dans les références arrières. Ceci s'avère
 utile lorsque la référence arrière est utilisée dans la partie chemin,
 et non dans les paramètres de la requête.</p>
 
+<pre class="prettyprint lang-config"># Échappe le caractère espace en %20 dans le chemin au lieu de + comme dans la
+# soumission de formulaire à l'aide de la chaîne de paramètres
+RewriteRule "^search/(.*)$" "/search.php/$1" "[B,BNP]"</pre>
+
+
 <p>Ce drapeau est disponible à partir de la version 2.4.26 du serveur HTTP
 Apache.</p>
 
+<h3><a name="flag_bctls" id="flag_bctls">BCTLS</a></h3>
+<p>Le drapeau [BCTLS] est similaire à [B], à la différence que seuls les espaces
+et les caractères de contrôle sont échappés. Il s'agit du même jeu de caractères
+rejetés lorsqu'ils sont copiés dans la chaîne de paramètres non codée.
+</p>
+
+<pre class="prettyprint lang-config"># Échappe les espaces et les caractères de contrôle
+RewriteRule "^search/(.*)$" "/search.php/$1" "[BCTLS]"</pre>
+
+
+<p>Ce drapeau est disponible à partir de la version 2.4.57 du serveur HTTP
+Apache.</p>
+
+
+
+<h3><a name="flag_bne" id="flag_bne">BNE</a></h3>
+<p>Les caractères listés dans [BNE=...] sont exclus des listes de caractères
+correspondant aux drapeaux [B] ou [BCTLS]. Ils ne seront donc pas échappés.
+</p>
+
+<pre class="prettyprint lang-config"># Échappe les caractères par défaut, sauf /
+RewriteRule "^search/(.*)$" "/search.php?term=$1" "[B,BNE=/]"</pre>
+
+ 
+<p>Ce drapeau est disponible à partir de la version 2.4.57 du serveur HTTP
+Apache.</p>
+
+
+
 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
 <div class="section">
 <h2><a name="flag_c" id="flag_c">C|chain</a></h2>
@@ -234,7 +278,7 @@ partir de la version 2.4.47 du serveur HTTP Apache.</dd>
 <p>Voici un exemple :</p>
 
 <pre class="prettyprint lang-config">RewriteEngine On
-RewriteRule "^/index\.html" "-" [CO=frontdoor:yes:.example.org:1440:/]</pre>
+RewriteRule   "^/index\.html"   "-" [CO=frontdoor:yes:.example.com:1440:/]</pre>
 
 
 <p>Dans l'exemple ci-dessus, la règle ne réécrit
@@ -321,10 +365,9 @@ avec une valeur de '1' si l'URI de la requête correspond à un fichier
 image. Cette variable d'environnement est ensuite utilisée pour exclure
 une telle requête du journal des accès.</p>
 
-<div class="example"><p><code>
-RewriteRule "\.(png|gif|jpg)" "-" [E=image:1]<br />
-CustomLog "logs/access_log" combined env=!image
-</code></p></div>
+<pre class="prettyprint lang-config">RewriteRule "\.(png|gif|jpg)$"   "-" [E=image:1]
+CustomLog   "logs/access_log"    combined env=!image</pre>
+
 
 <p>Notez que le même effet peut être obtenu à l'aide de la directive
 <code class="directive"><a href="../mod/mod_setenvif.html#setenvif">SetEnvIf</a></code>. Cette technique
@@ -351,7 +394,7 @@ Forbidden.</p>
 <p>La règle suivante va interdire la téléchargement de fichiers
 <code>.exe</code> depuis votre serveur.</p>
 
-<pre class="prettyprint lang-config">RewriteRule "\.exe" "-" [F]</pre>
+<pre class="prettyprint lang-config">RewriteRule "\.exe"   "-" [F]</pre>
 
 
 <p>Cet exemple utilise la syntaxe "-" pour la cible de réécriture, ce
@@ -372,7 +415,7 @@ disponible auparavant ne l'est plus actuellement.</p>
 <p>Comme dans le cas du drapeau [F], on utilise en général la syntaxe
 "-" pour la cible de réécriture lorsqu'on utilise le drapeau [G] :</p>
 
-<pre class="prettyprint lang-config">RewriteRule "oldproduct" "-" [G,NC]</pre>
+<pre class="prettyprint lang-config">RewriteRule "oldproduct"   "-" [G,NC]</pre>
 
 
 <p>Lorsqu'on utilise [G], [L] est implicite - c'est à dire que la
@@ -386,7 +429,7 @@ spécifié. Par exemple, on peut utiliser ce drapeau pour forcer
 l'interprétation de tous les fichiers sans extension par le gestionnaire
 php :</p>
 
-<pre class="prettyprint lang-config">RewriteRule "!\." "-" [H=application/x-httpd-php]</pre>
+<pre class="prettyprint lang-config">RewriteRule "!\."  "-" [H=application/x-httpd-php]</pre>
 
 
 <p>
@@ -455,8 +498,8 @@ directive <code class="directive"><a href="../mod/mod_rewrite.html#rewritecond">
 la requête concerne déjà <code>index.php</code>, la directive <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> sera sautée.</p>
 
 <pre class="prettyprint lang-config">RewriteBase "/"
-RewriteCond "%{REQUEST_URI}" "!=/index.php"
-RewriteRule "^(.*)" "/index.php?req=$1" [L,PT]</pre>
+RewriteCond "%{REQUEST_URI}" !=/index.php
+RewriteRule "^(.*)"          "/index.php?req=$1" [L,PT]</pre>
 
 </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
 <div class="section">
@@ -484,10 +527,10 @@ effectuer la substitution (c'est à dire, remplacer le <code>A</code> par
 un <code>B</code>).</p>
 
 <p>A partir de la version 2.4.8, ce module renvoie une erreur après
-32000 itérations afin d'éviter les boucles infinies. Ce nombre maximum
+10000 itérations afin d'éviter les boucles infinies. Ce nombre maximum
 d'itération peut être modifié via le drapeau N.</p>
 <pre class="prettyprint lang-config"># On veut remplacer 1 caractère à chaque itération de la boucle
-RewriteRule "(.+)[&gt;&lt;;]$" "$1" [N=64000]
+RewriteRule "(.+)[&gt;&lt;;]$" "$1" [N=32000]
 # ... ou s'arrêter après 10 itérations
 RewriteRule "(.+)[&gt;&lt;;]$" "$1" [N=10]</pre>
 
@@ -745,19 +788,21 @@ avertissements 'Invalid URI in request'.
 <p>Le drapeau [S] sert à sauter des règles que vous ne voulez pas voir
 exécuter. La syntaxe du drapeau [S] est [S=<em>N</em>], où
 <em>N</em> correspond au nombre de règles à sauter (sous
-réserve que la règle <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> corresponde).
+réserve que la règle <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> corresponde et qu'au moins
+une condition <code class="directive"><a href="../mod/mod_rewrite.html#rewritecond">RewriteCond</a></code>
+préalable soit vérifiée). 
 Ceci peut s'interpréter comme une instruction
 <code>goto</code>  dans votre jeu de règles de réécriture. Dans
 l'exemple suivant, nous ne voulons exécuter la règle <code class="directive"><a href="../mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> que si l'URI demandé ne
 correspond pas à un fichier existant.</p>
 <pre class="prettyprint lang-config"># La requête concerne-t-elle un fichier qui n'existe pas ?
-RewriteCond "%{REQUEST_FILENAME}" "!-f"
-RewriteCond "%{REQUEST_FILENAME}" "!-d"
+RewriteCond "%{REQUEST_FILENAME}" !-f
+RewriteCond "%{REQUEST_FILENAME}" !-d
 # Si c'est la cas, on saute les deux règles de réécriture suivantes
-RewriteRule ".?" "-" [S=2]
+RewriteRule ".?"                  "-" [S=2]
 
-RewriteRule "(.*\.gif)" "images.php?$1"
-RewriteRule "(.*\.html)" "docs.php?$1"</pre>
+RewriteRule "(.*\.gif)"           "images.php?$1"
+RewriteRule "(.*\.html)"          "docs.php?$1"</pre>
 
 
 
@@ -772,18 +817,19 @@ d'élaborer des pseudo-constructions if-then-else : la dernière règle du
 bloc then contiendra <code>skip=N</code>, où N est le nombre de règles
 contenues dans le bloc else :</p>
 <pre class="prettyprint lang-config"># Est-ce que le fichier existe ?
-RewriteCond "%{REQUEST_FILENAME}" "!-f"
-RewriteCond "%{REQUEST_FILENAME}" "!-d"
-# Create an if-then-else construct by skipping 3 lines if we meant to go to the "else" stanza.
-RewriteRule ".?" "-" [S=3]
+RewriteCond "%{REQUEST_FILENAME}" !-f
+RewriteCond "%{REQUEST_FILENAME}" !-d
+# Créer une structure conditionnelle if-then-else en sautant 3 lignes si nous
+# avions l'intention d'aller au bloc "else".
+RewriteRule ".?"                  "-" [S=3]
 
 # Si le fichier existe, alors :
-RewriteRule "(.*\.gif)" "images.php?$1"
+    RewriteRule "(.*\.gif)"  "images.php?$1"
     RewriteRule "(.*\.html)" "docs.php?$1"
-    # Skip past the "else" stanza.
-    RewriteRule ".?" "-" [S=1]
+    # Passer le bloc "else".
+    RewriteRule ".?"         "-" [S=1]
 # ELSE...
-RewriteRule "(.*)" "404.php?file=$1
+    RewriteRule "(.*)"       "404.php?file=$1"
 # END</pre>
 
 
@@ -801,7 +847,7 @@ du code source Perl en tant que plein texte, s'il est requis d'une
 certaine manière :</p>
 
 <pre class="prettyprint lang-config"># Sert les fichier .pl en tant que plein texte
-RewriteRule "\.pl$" "-" [T=text/plain]</pre>
+RewriteRule "\.pl$"  "-" [T=text/plain]</pre>
 
 
 <p>Ou encore, si vous possédez une caméra qui produit des fichiers
@@ -809,7 +855,7 @@ images jpeg sans extension, vous pouvez forcer le renvoi de ces images
 avec le type MIME correct en se basant sur le nom du fichier :</p>
 
 <pre class="prettyprint lang-config"># Les fichiers dont le nom contient 'IMG' sont des images jpg.
-RewriteRule "IMG" "-" [T=image/jpg]</pre>
+RewriteRule "IMG"  "-" [T=image/jpg]</pre>
 
 
 <p>Notez cependant qu'il s'agit d'un exemple trivial, et que le problème
diff --git a/docs/manual/sections.html.tr.utf8 b/docs/manual/sections.html.tr.utf8
index be6ff8a7..b3a7cbf9 100644
--- a/docs/manual/sections.html.tr.utf8
+++ b/docs/manual/sections.html.tr.utf8
@@ -29,7 +29,6 @@
 <a href="./ko/sections.html" hreflang="ko" rel="alternate" title="Korean">&nbsp;ko&nbsp;</a> |
 <a href="./tr/sections.html" title="Türkçe">&nbsp;tr&nbsp;</a></p>
 </div>
-<div class="outofdate">Bu çeviri güncel olmayabilir. Son değişiklikler için İngilizce sürüm geçerlidir.</div>
 
     <p><a href="configuring.html">Yapılandırma dosyaları</a>ndaki
        yönergeler sunucunun tamamına uygulanacağı gibi sadece belli dizinler,
@@ -349,9 +348,9 @@ ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofail
     <p>Bazı bölüm türleri başka bölüm türlerinin içinde olabilir. Bir yandan,
       <code class="directive"><a href="./mod/core.html#files">&lt;Files&gt;</a></code> bölümü
       <code class="directive"><a href="./mod/core.html#directory">&lt;Directory&gt;</a></code> bölümünün
-      içinde bulunabilirken diğer yandan bir <code class="directive"><a href="./mod/core.html#if">&lt;If&gt;</a></code> bölümü <code class="directive"><a href="./mod/core.html#directory">&lt;Directory&gt;</a></code>, <code class="directive"><a href="./mod/core.html#location">&lt;Location&gt;</a></code> ve <code class="directive"><a href="./mod/core.html#files">&lt;Files&gt;</a></code> bölümlerinde bulunabilir fakat 
-      başka bir <code class="directive"><a href="./mod/core.html#if">&lt;If&gt;</a></code> bölümünün 
-      içinde bulunamaz. Bu bölümlerin düzenli ifadeli türevleri de benzer tarzda 
+      içinde bulunabilirken diğer yandan bir <code class="directive"><a href="./mod/core.html#if">&lt;If&gt;</a></code> bölümü <code class="directive"><a href="./mod/core.html#directory">&lt;Directory&gt;</a></code>, <code class="directive"><a href="./mod/core.html#location">&lt;Location&gt;</a></code> ve <code class="directive"><a href="./mod/core.html#files">&lt;Files&gt;</a></code> bölümlerinde bulunabilir fakat
+      başka bir <code class="directive"><a href="./mod/core.html#if">&lt;If&gt;</a></code> bölümünün
+      içinde bulunamaz. Bu bölümlerin düzenli ifadeli türevleri de benzer tarzda
       davranır.</p>
 
     <p>İç içe bölümler, aynı türdeki iç içe olmayan bölümlerin sonrasına
@@ -440,7 +439,9 @@ ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofail
       ve <code class="directive"><a href="./mod/core.html#locationmatch">&lt;LocationMatch&gt;</a></code>
       aynı anda işleme sokulur.</li>
 
-      <li><code class="directive"><a href="./mod/core.html#if">&lt;If&gt;</a></code>
+      <li><code class="directive"><a href="./mod/core.html#if">&lt;If&gt;</a></code> bölümleri,
+      önceki bağlamlardan herhangi birinin içine alınmış olsalar bile.
+
       </li>
     </ol>
 
@@ -448,31 +449,41 @@ ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofail
     <ul>
         <li><code class="directive"><a href="./mod/core.html#directory">&lt;Directory&gt;</a></code>
         bölümündekiler hariç, her grup, yapılandırma dosyasında bulundukları
-        sıraya göre işleme sokulurlar. Örneğin, 4. grupta <em>/foo/bar</em> için yapılan 
-        bir istek <code>&lt;Location "/foo/bar"&gt;</code> ve <code>&lt;Location 
-        "/foo"&gt;</code> bölümleriyle de eşleşir ve bunlar yapılandırma 
+        sıraya göre işleme sokulurlar. Örneğin, 4. grupta <em>/foo/bar</em> için yapılan
+        bir istek <code>&lt;Location "/foo/bar"&gt;</code> ve <code>&lt;Location
+        "/foo"&gt;</code> bölümleriyle de eşleşir ve bunlar yapılandırma
         dosyalarında bulundukları sıraya göre değerlendirilir.</li>
-      
-        <li>Yukarıda 1. grup olan <code class="directive"><a href="./mod/core.html#directory">&lt;Directory&gt;</a></code> bölümü en kısa dizin elemanından en uzun 
-        dizin elemanına doğru işleme sokulur. Yani, örneğin, <code>&lt;Directory 
-        "/var/web/dir"&gt;</code> bölümü <code>&lt;Directory    
+
+        <li>Yukarıda 1. grup olan <code class="directive"><a href="./mod/core.html#directory">&lt;Directory&gt;</a></code> bölümü en kısa dizin elemanından en uzun
+        dizin elemanına doğru işleme sokulur. Yani, örneğin, <code>&lt;Directory
+        "/var/web/dir"&gt;</code> bölümü <code>&lt;Directory
         "/var/web/dir/subdir"&gt;</code> bölümünden önce işleme sokulacaktır.</li>
-    
-        <li>Eğer aynı dizin için birden fazla <code class="directive"><a href="./mod/core.html#directory">&lt;Directory&gt;</a></code> bölümü varsa bunlar yapılandırma 
+
+        <li>Eğer aynı dizin için birden fazla <code class="directive"><a href="./mod/core.html#directory">&lt;Directory&gt;</a></code> bölümü varsa bunlar yapılandırma
         dosyasında bulundukları sıraya göre işleme sokulurlar.</li>
-      
-        <li><code class="directive"><a href="./mod/core.html#include">Include</a></code> yönergeleri ile 
-        yapılandırmaya dahil edilen dosyaların içerikleri <code class="directive"><a href="./mod/core.html#include">Include</a></code> yönergesinin bulunduğu yere konulduktan 
+
+        <li><code class="directive"><a href="./mod/core.html#include">Include</a></code> yönergeleri ile
+        yapılandırmaya dahil edilen dosyaların içerikleri <code class="directive"><a href="./mod/core.html#include">Include</a></code> yönergesinin bulunduğu yere konulduktan
         sonra işleme sokulurlar.</li>
 
        <li><code class="directive"><a href="./mod/core.html#virtualhost">&lt;VirtualHost&gt;</a></code>
        bölümlerinin içindeki bölümler, sanal konak tanımı dışındaki
-       karşılıklarından <em>sonra</em> uygulanırlar. Bu yöntemle ana sunucu 
+       karşılıklarından <em>sonra</em> uygulanırlar. Bu yöntemle ana sunucu
        yapılandırmasındaki tanımlar geçersiz kılınabilir</li>
 
        <li>İstek <code class="module"><a href="./mod/mod_proxy.html">mod_proxy</a></code> tarafından sunulduğu takdirde,
        <code class="directive"><a href="./mod/mod_proxy.html#proxy">&lt;Proxy&gt;</a></code> taşıyıcısı
        işlem sırasında <code class="directive"><a href="./mod/core.html#directory">&lt;Directory&gt;</a></code> taşıyıcısının yerini alır.</li>
+
+       <li>katıştırma düzeni üzerindeki etkisi nedeniyle, ilgili yapılandırma
+       yönergelerini <code class="directive"><a href="./mod/core.html#if">&lt;If&gt;</a></code>'in
+       içinde ve dışında karıştırırken dikkatli olunmalıdır.  Doğrudan
+       <code class="directive"><a href="./mod/core.html#else">&lt;Else&gt;</a></code> kullanımının
+       yardımı olabilir.</li>
+
+       <li><code>.htaccess</code> içinde <code class="directive"><a href="./mod/core.html#if">&lt;If&gt;</a></code> kullanıldığında, üst dizindeki sarmalanmış
+       yönergeler, alt dizinde sarmalanmamış yönergelerden <em>sonra</em>
+       birleştirilir.</li>
     </ul>
 
     <div class="note"><h3>Bazı Teknik Bilgiler</h3>
@@ -484,35 +495,35 @@ ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofail
       tamamen elden çıkarılır.
     </div>
 
-  <h3><a name="relationship-module-configuration" id="relationship-module-configuration">Modüllerle 
+  <h3><a name="relationship-module-configuration" id="relationship-module-configuration">Modüllerle
     yapılandırma bölümleri arasındaki ilişki</a></h3>
-  
-    <p>Yapılandırma bölümlerini okurken örneğin <code class="module"><a href="./mod/mod_rewrite.html">mod_rewrite</a></code>  
-      gibi belli modüllerin yönergelerinin bu bölümlere nasıl katılacağı ve  
-      ne zaman nasıl işleneceği gibi sorular sıkça aklımızdan geçer. Bunun 
-      belli bir yanıtı yoktur ve biraz temel bilgi gerektirir. Her httpd 
-      modülü yapılandırmasını kendi yönetir ve httpd.conf içindeki 
-      yönergelerinin her biri belli bir bağlamdaki bir yapılandırmayı 
+
+    <p>Yapılandırma bölümlerini okurken örneğin <code class="module"><a href="./mod/mod_rewrite.html">mod_rewrite</a></code>
+      gibi belli modüllerin yönergelerinin bu bölümlere nasıl katılacağı ve
+      ne zaman nasıl işleneceği gibi sorular sıkça aklımızdan geçer. Bunun
+      belli bir yanıtı yoktur ve biraz temel bilgi gerektirir. Her httpd
+      modülü yapılandırmasını kendi yönetir ve httpd.conf içindeki
+      yönergelerinin her biri belli bir bağlamdaki bir yapılandırmayı
       belirtir. httpd bir komutu okunduğu sırada çalıştırmaz.</p>
-    
-    <p>Çalışma anında, httpd çekirdeği geçerli isteğe hangilerinin 
-      uygulanacağını belirlemek için yukarıda açıklanan sırada tanımlı 
-      yapılandırma bölümlerini tekrar tekrar okur. Eşleşen ilk bölümün bu 
-      istek için geçerli yapılandırmayı içerdiği varsayılır. Eğer alt 
-      bölümlerden biri de eşleşmişse bu bölümlerde yönergeleri bulunan her 
-      modüle yapılandırmasını iki bölüm arasında katıştırma şansı verilir. 
-      Sonuç üçüncü bir yapılandırma olup işlem bütün yapılandırma bölümleri 
+
+    <p>Çalışma anında, httpd çekirdeği geçerli isteğe hangilerinin
+      uygulanacağını belirlemek için yukarıda açıklanan sırada tanımlı
+      yapılandırma bölümlerini tekrar tekrar okur. Eşleşen ilk bölümün bu
+      istek için geçerli yapılandırmayı içerdiği varsayılır. Eğer alt
+      bölümlerden biri de eşleşmişse bu bölümlerde yönergeleri bulunan her
+      modüle yapılandırmasını iki bölüm arasında katıştırma şansı verilir.
+      Sonuç üçüncü bir yapılandırma olup işlem bütün yapılandırma bölümleri
       değerlendirilene kadar sürer.</p>
-    
-    <p>Yukarıdaki adımların ardından HTTP isteğiyle ilgili "asıl" işlem 
-      başlar: her modül ondan istenen görevleri gerçekleştirme şansına sahip 
-      olur. Nasıl davranacaklarını belirlemek için kendilerinin katıştırılmış 
+
+    <p>Yukarıdaki adımların ardından HTTP isteğiyle ilgili "asıl" işlem
+      başlar: her modül ondan istenen görevleri gerçekleştirme şansına sahip
+      olur. Nasıl davranacaklarını belirlemek için kendilerinin katıştırılmış
       son yapılandırmalarını http çekirdeğinden alabilirler.</p>
-    
-    <p>Sürecin tamamı bir örnekle görselleştirilebilir. Aşağıdaki örnekte 
-      belli bir HTTP başlığını ayarlamak için <code class="module"><a href="./mod/mod_headers.html">mod_headers</a></code> 
-      modülünün <code class="directive"><a href="./mod/mod_headers.html#header">Header</a></code> yönergesi 
-      kullanılmıştır. <code>/example/index.html</code> isteği için httpd 
+
+    <p>Sürecin tamamı bir örnekle görselleştirilebilir. Aşağıdaki örnekte
+      belli bir HTTP başlığını ayarlamak için <code class="module"><a href="./mod/mod_headers.html">mod_headers</a></code>
+      modülünün <code class="directive"><a href="./mod/mod_headers.html#header">Header</a></code> yönergesi
+      kullanılmıştır. <code>/example/index.html</code> isteği için httpd
       <code>CustomHeaderName</code> başlığına hangi değeri atayacaktır?
     </p>
     <pre class="prettyprint lang-config">&lt;Directory "/"&gt;
@@ -525,37 +536,37 @@ ProxyPass "/" "balancer://mycluster/" stickysession=JSESSIONID|jsessionid nofail
 &lt;Directory "/example"&gt;
     Header set CustomHeaderName iki
 &lt;/Directory&gt;</pre>
-    
+
     <ul>
-        <li><code class="directive">Directory</code> "/" eşleşir ve ilk yapılandırma 
-          olarak <code>CustomHeaderName</code> başlığı <code>bir</code> 
+        <li><code class="directive">Directory</code> "/" eşleşir ve ilk yapılandırma
+          olarak <code>CustomHeaderName</code> başlığı <code>bir</code>
           değeriyle oluşturulur.</li>
-        
-        <li><code class="directive">Directory</code> "/example" eşleşir ve 
-          <code class="module"><a href="./mod/mod_headers.html">mod_headers</a></code> modülünün koduna göre bir katıştırma 
-          durumundan yeni değer eskiyi geçersiz kılacağından yeni bir 
-          yapılandırma ile <code>CustomHeaderName</code> başlığının değeri 
+
+        <li><code class="directive">Directory</code> "/example" eşleşir ve
+          <code class="module"><a href="./mod/mod_headers.html">mod_headers</a></code> modülünün koduna göre bir katıştırma
+          durumundan yeni değer eskiyi geçersiz kılacağından yeni bir
+          yapılandırma ile <code>CustomHeaderName</code> başlığının değeri
           <code>iki</code> yapılır.</li>
-        
-        <li><code class="directive">FilesMatch</code> ".*" eşleşir ve başka bir 
-          katıştırma fırsatı doğar: <code>CustomHeaderName</code> başlığının 
+
+        <li><code class="directive">FilesMatch</code> ".*" eşleşir ve başka bir
+          katıştırma fırsatı doğar: <code>CustomHeaderName</code> başlığının
           değeri <code>yedi</code> yapılır.</li>
-        
-        <li>Neticede HHP isteğinin sonraki adımlarında 
-          <code class="module"><a href="./mod/mod_headers.html">mod_headers</a></code> çağrılıp <code>yedi</code> değeri 
-          atanmış <code>CustomHeaderName</code> başlığını işleme sokması 
-          istenecektir. <code class="module"><a href="./mod/mod_headers.html">mod_headers</a></code> normalde işini yapmak 
-          için bu yapılandırmayı kullanacaktır. Fakat bundan, bir yönergenin  
-          gerekli olmaması veya kullanımdan kaldırılması ve benzeri nedenlerle 
-          yapılandırmada iptal edilmesi gibi daha karmaşık bir eylemi bir 
+
+        <li>Neticede HHP isteğinin sonraki adımlarında
+          <code class="module"><a href="./mod/mod_headers.html">mod_headers</a></code> çağrılıp <code>yedi</code> değeri
+          atanmış <code>CustomHeaderName</code> başlığını işleme sokması
+          istenecektir. <code class="module"><a href="./mod/mod_headers.html">mod_headers</a></code> normalde işini yapmak
+          için bu yapılandırmayı kullanacaktır. Fakat bundan, bir yönergenin
+          gerekli olmaması veya kullanımdan kaldırılması ve benzeri nedenlerle
+          yapılandırmada iptal edilmesi gibi daha karmaşık bir eylemi bir
           modülün gerçekleştiremeyeceği anlamı çıkarılmamalıdır.</li>
     </ul>
 
-    <p><code class="directive">Directory</code> ile aynı katıştırma sırasından dolayı 
-      bu durum .htaccess için de geçerlidir. Burada anlaşılması gereken husus, 
-      <code class="directive">Directory</code> ve <code class="directive">FilesMatch</code> 
-      gibi yapılandırma bölümlerinin <code class="directive"><a href="./mod/mod_headers.html#header">Header</a></code> veya <code class="directive"><a href="./mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> gibi modüle özgü 
-      yönergelerle karşılaştırılmamasıdır, çünkü bunlar farklı seviyelerde 
+    <p><code class="directive">Directory</code> ile aynı katıştırma sırasından dolayı
+      bu durum .htaccess için de geçerlidir. Burada anlaşılması gereken husus,
+      <code class="directive">Directory</code> ve <code class="directive">FilesMatch</code>
+      gibi yapılandırma bölümlerinin <code class="directive"><a href="./mod/mod_headers.html#header">Header</a></code> veya <code class="directive"><a href="./mod/mod_rewrite.html#rewriterule">RewriteRule</a></code> gibi modüle özgü
+      yönergelerle karşılaştırılmamasıdır, çünkü bunlar farklı seviyelerde
       işlem görür.
     </p>
   
diff --git a/docs/manual/style/version.ent b/docs/manual/style/version.ent
index 29e0dfc7..30ec0ddd 100644
--- a/docs/manual/style/version.ent
+++ b/docs/manual/style/version.ent
@@ -19,6 +19,6 @@
 
 <!ENTITY httpd.major "2">
 <!ENTITY httpd.minor "4">
-<!ENTITY httpd.patch "56">
+<!ENTITY httpd.patch "57">
 
 <!ENTITY httpd.docs "2.4">
diff --git a/httpd.spec b/httpd.spec
index c0c788eb..c253895e 100644
--- a/httpd.spec
+++ b/httpd.spec
@@ -4,7 +4,7 @@
 
 Summary: Apache HTTP Server
 Name: httpd
-Version: 2.4.56
+Version: 2.4.57
 Release: 1
 URL: http://httpd.apache.org/
 Vendor: Apache Software Foundation
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
index 402c23a3..ace7c43e 100644
--- a/include/ap_mmn.h
+++ b/include/ap_mmn.h
@@ -594,7 +594,7 @@
  * 20120211.124 (2.4.51-dev) Add name_ex to struct proxy_worker_shared
  * 20120211.125 (2.4.55-dev) Export mod_http2.h as public header
  * 20120211.126 (2.4.55-dev) Add additional hcmethod_t enums and PROXY_WORKER_IS_ERROR
- *
+ * 20120211.127 (2.4.56-dev) Add ap_proxy_canonenc_ex
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -602,7 +602,7 @@
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20120211
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 126                 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 127                 /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
diff --git a/include/ap_release.h b/include/ap_release.h
index c858aaea..a5f511ae 100644
--- a/include/ap_release.h
+++ b/include/ap_release.h
@@ -43,7 +43,7 @@
 
 #define AP_SERVER_MAJORVERSION_NUMBER 2
 #define AP_SERVER_MINORVERSION_NUMBER 4
-#define AP_SERVER_PATCHLEVEL_NUMBER   56
+#define AP_SERVER_PATCHLEVEL_NUMBER   57
 #define AP_SERVER_DEVBUILD_BOOLEAN    0
 
 /* Synchronize the above with docs/manual/style/version.ent */
diff --git a/modules/http/mod_mime.c b/modules/http/mod_mime.c
index 03d1c411..700f824f 100644
--- a/modules/http/mod_mime.c
+++ b/modules/http/mod_mime.c
@@ -755,7 +755,7 @@ static int find_ct(request_rec *r)
     mime_dir_config *conf;
     apr_array_header_t *exception_list;
     char *ext;
-    const char *fn, *fntmp, *type, *charset = NULL, *resource_name;
+    const char *fn, *fntmp, *type, *charset = NULL, *resource_name, *qm;
     int found_metadata = 0;
 
     if (r->finfo.filetype == APR_DIR) {
@@ -775,6 +775,19 @@ static int find_ct(request_rec *r)
     if (conf->use_path_info & 1) {
         resource_name = apr_pstrcat(r->pool, r->filename, r->path_info, NULL);
     }
+    /*
+     * In the reverse proxy case r->filename might contain a query string if
+     * the nocanon option was used with ProxyPass.
+     * If this is the case cut off the query string as the last parameter in
+     * this query string might end up on an extension we take care about, but
+     * we only want to match against path components not against query
+     * parameters.
+     */
+    else if ((r->proxyreq == PROXYREQ_REVERSE)
+             && (apr_table_get(r->notes, "proxy-nocanon"))
+             && ((qm = ap_strchr_c(r->filename, '?')) != NULL)) {
+        resource_name = apr_pstrmemdup(r->pool, r->filename, qm - r->filename);
+    }
     else {
         resource_name = r->filename;
     }
diff --git a/modules/http2/h2_request.c b/modules/http2/h2_request.c
index bddbad51..20e94cd8 100644
--- a/modules/http2/h2_request.c
+++ b/modules/http2/h2_request.c
@@ -279,7 +279,7 @@ static request_rec *my_ap_create_request(conn_rec *c)
 apr_bucket *h2_request_create_bucket(const h2_request *req, request_rec *r)
 {
     conn_rec *c = r->connection;
-    apr_table_t *headers = apr_table_copy(r->pool, req->headers);
+    apr_table_t *headers = apr_table_clone(r->pool, req->headers);
     const char *uri = req->path;
 
     AP_DEBUG_ASSERT(req->authority);
@@ -303,7 +303,7 @@ static void assign_headers(request_rec *r, const h2_request *req,
 {
     const char *cl;
 
-    r->headers_in = apr_table_copy(r->pool, req->headers);
+    r->headers_in = apr_table_clone(r->pool, req->headers);
     if (req->authority) {
         /* for internal handling, we have to simulate that :authority
          * came in as Host:, RFC 9113 ch. says that mismatches between
diff --git a/modules/http2/mod_proxy_http2.c b/modules/http2/mod_proxy_http2.c
index aa299b93..5abccab0 100644
--- a/modules/http2/mod_proxy_http2.c
+++ b/modules/http2/mod_proxy_http2.c
@@ -154,29 +154,41 @@ static int proxy_http2_canon(request_rec *r, char *url)
         if (apr_table_get(r->notes, "proxy-nocanon")) {
             path = url;   /* this is the raw path */
         }
-        else {
-            path = ap_proxy_canonenc(r->pool, url, (int)strlen(url),
-                                     enc_path, 0, r->proxyreq);
+        else if (apr_table_get(r->notes, "proxy-noencode")) {
+            path = url;   /* this is the encoded path already */
             search = r->args;
-            if (search && *(ap_scan_vchar_obstext(search))) {
-                /*
-                 * We have a raw control character or a ' ' in r->args.
-                 * Correct encoding was missed.
-                 */
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
-                              "To be forwarded query string contains control "
-                              "characters or spaces");
-                return HTTP_FORBIDDEN;
+        }
+        else {
+            core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+            int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+            path = ap_proxy_canonenc_ex(r->pool, url, (int)strlen(url),
+                                        enc_path, flags, r->proxyreq);
+            if (!path) {
+                return HTTP_BAD_REQUEST;
             }
+            search = r->args;
         }
         break;
     case PROXYREQ_PROXY:
         path = url;
         break;
     }
-
-    if (path == NULL) {
-        return HTTP_BAD_REQUEST;
+    /*
+     * If we have a raw control character or a ' ' in nocanon path or
+     * r->args, correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10420)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
+    if (search && *ap_scan_vchar_obstext(search)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10412)
+                      "To be forwarded query string contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
     }
 
     if (port != def_port) {
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
index 5195ceee..f93f23f0 100644
--- a/modules/mappers/mod_rewrite.c
+++ b/modules/mappers/mod_rewrite.c
@@ -106,6 +106,8 @@
 #include "mod_rewrite.h"
 #include "ap_expr.h"
 
+#include "test_char.h"
+
 static ap_dbd_t *(*dbd_acquire)(request_rec*) = NULL;
 static void (*dbd_prepare)(server_rec*, const char*, const char*) = NULL;
 static const char* really_last_key = "rewrite_really_last";
@@ -174,6 +176,7 @@ static const char* really_last_key = "rewrite_really_last";
 #define RULEFLAG_ESCAPENOPLUS       (1<<18)
 #define RULEFLAG_QSLAST             (1<<19)
 #define RULEFLAG_QSNONE             (1<<20) /* programattic only */
+#define RULEFLAG_ESCAPECTLS         (1<<21)
 
 /* return code of the rewrite rule
  * the result may be escaped - or not
@@ -327,7 +330,8 @@ typedef struct {
     data_item *cookie;               /* added cookies                         */
     int        skip;                 /* number of next rules to skip          */
     int        maxrounds;            /* limit on number of loops with N flag  */
-    char       *escapes;             /* specific backref escapes              */
+    const char *escapes;             /* specific backref escapes              */
+    const char *noescapes;           /* specific backref chars not to escape  */
 } rewriterule_entry;
 
 typedef struct {
@@ -427,7 +431,9 @@ static apr_global_mutex_t *rewrite_mapr_lock_acquire = NULL;
 static const char *rewritemap_mutex_type = "rewrite-map";
 
 /* Optional functions imported from mod_ssl when loaded: */
-static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int noplus);
+static char *escape_backref(apr_pool_t *p, const char *path,
+                            const char *escapeme, const char *noescapeme,
+                            int flags);
 
 /*
  * +-------------------------------------------------------+
@@ -654,14 +660,21 @@ static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix,
  * Escapes a backreference in a similar way as php's urlencode does.
  * Based on ap_os_escape_path in server/util.c
  */
-static char *escape_backref(apr_pool_t *p, const char *path, const char *escapeme, int noplus) {
-    char *copy = apr_palloc(p, 3 * strlen(path) + 3);
+static char *escape_backref(apr_pool_t *p, const char *path,
+                            const char *escapeme, const char *noescapeme,
+                            int flags)
+{
+    char *copy = apr_palloc(p, 3 * strlen(path) + 1);
     const unsigned char *s = (const unsigned char *)path;
     unsigned char *d = (unsigned char *)copy;
-    unsigned c;
+    int noplus = (flags & RULEFLAG_ESCAPENOPLUS) != 0;
+    int ctls = (flags & RULEFLAG_ESCAPECTLS) != 0;
+    unsigned char c;
 
     while ((c = *s)) {
-        if (!escapeme) { 
+        if (((ctls ? !TEST_CHAR(c, T_VCHAR_OBSTEXT) : !escapeme)
+             || (escapeme && ap_strchr_c(escapeme, c)))
+            && (!noescapeme || !ap_strchr_c(noescapeme, c))) {
             if (apr_isalnum(c) || c == '_') {
                 *d++ = c;
             }
@@ -672,23 +685,8 @@ static char *escape_backref(apr_pool_t *p, const char *path, const char *escapem
                 d = c2x(c, '%', d);
             }
         }
-        else { 
-            const char *esc = escapeme;
-            while (*esc) { 
-                if (c == *esc) { 
-                    if (c == ' ' && !noplus) { 
-                        *d++ = '+';
-                    }
-                    else { 
-                        d = c2x(c, '%', d);
-                    }
-                    break;
-                }
-                ++esc;
-            }
-            if (!*esc) { 
-                *d++ = c;
-            }
+        else {
+            *d++ = c;
         }
         ++s;
     }
@@ -2469,7 +2467,8 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry)
                     /* escape the backreference */
                     char *tmp2, *tmp;
                     tmp = apr_pstrmemdup(pool, bri->source + bri->regmatch[n].rm_so, span);
-                    tmp2 = escape_backref(pool, tmp, entry->escapes, entry->flags & RULEFLAG_ESCAPENOPLUS);
+                    tmp2 = escape_backref(pool, tmp, entry->escapes, entry->noescapes,
+                                          entry->flags);
                     rewritelog((ctx->r, 5, ctx->perdir, "escaping backreference '%s' to '%s'",
                             tmp, tmp2));
 
@@ -3541,13 +3540,24 @@ static const char *cmd_rewriterule_setflag(apr_pool_t *p, void *_cfg,
     case 'B':
         if (!*key || !strcasecmp(key, "ackrefescaping")) {
             cfg->flags |= RULEFLAG_ESCAPEBACKREF;
-            if (val && *val) { 
+            if (val && *val) {
                 cfg->escapes = val;
             }
         }
+        else if (!strcasecmp(key, "NE")) {
+            if (val && *val) {
+                cfg->noescapes = val;
+            }
+            else {
+                return "flag 'BNE' wants a list of characters (i.e. [BNE=...])";
+            }
+        }
         else if (!strcasecmp(key, "NP") || !strcasecmp(key, "ackrefernoplus")) { 
             cfg->flags |= RULEFLAG_ESCAPENOPLUS;
         }
+        else if (!strcasecmp(key, "CTLS")) {
+            cfg->flags |= RULEFLAG_ESCAPECTLS|RULEFLAG_ESCAPEBACKREF;
+        }
         else {
             ++error;
         }
@@ -3809,7 +3819,6 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
                            "'", NULL);
     }
 
-    /* arg3: optional flags field */
     newrule->forced_mimetype     = NULL;
     newrule->forced_handler      = NULL;
     newrule->forced_responsecode = HTTP_MOVED_TEMPORARILY;
@@ -3818,6 +3827,9 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
     newrule->cookie = NULL;
     newrule->skip   = 0;
     newrule->maxrounds = REWRITE_MAX_ROUNDS;
+    newrule->escapes = newrule->noescapes = NULL;
+
+    /* arg3: optional flags field */
     if (a3 != NULL) {
         if ((err = cmd_parseflagfield(cmd->pool, newrule, a3,
                                       cmd_rewriterule_setflag)) != NULL) {
@@ -3854,6 +3866,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
     if (*(a2_end-1) == '?') {
         /* a literal ? at the end of the unsubstituted rewrite rule */
         newrule->flags |= RULEFLAG_QSNONE;
+        *(a2_end-1) = '\0'; /* trailing ? has done its job */
     }
     else if (newrule->flags & RULEFLAG_QSDISCARD) {
         if (NULL == ap_strchr(newrule->output, '?')) {
@@ -4745,13 +4758,19 @@ static int hook_uri2file(request_rec *r)
     }
 
     if (rulestatus) {
-        unsigned skip;
-        apr_size_t flen;
-
-        if (r->args && *(ap_scan_vchar_obstext(r->args))) {
+        unsigned skip_absolute = is_absolute_uri(r->filename, NULL);
+        apr_size_t flen =  r->filename ? strlen(r->filename) : 0;
+        int to_proxyreq = (flen > 6 && strncmp(r->filename, "proxy:", 6) == 0);
+        int will_escape = skip_absolute && (rulestatus != ACTION_NOESCAPE);
+
+        if (r->args
+                && !will_escape
+                && *(ap_scan_vchar_obstext(r->args))) {
             /*
              * We have a raw control character or a ' ' in r->args.
              * Correct encoding was missed.
+             * Correct encoding was missed and we're not going to escape
+             * it before returning.
              */
             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10410)
                           "Rewritten query string contains control "
@@ -4766,8 +4785,7 @@ static int hook_uri2file(request_rec *r)
             return n;
         }
 
-        flen = r->filename ? strlen(r->filename) : 0;
-        if (flen > 6 && strncmp(r->filename, "proxy:", 6) == 0) {
+        if (to_proxyreq) {
             /* it should be go on as an internal proxy request */
 
             /* check if the proxy module is enabled, so
@@ -4809,7 +4827,7 @@ static int hook_uri2file(request_rec *r)
                         r->filename));
             return OK;
         }
-        else if ((skip = is_absolute_uri(r->filename, NULL)) > 0) {
+        else if (skip_absolute > 0) {
             int n;
 
             /* it was finally rewritten to a remote URL */
@@ -4817,7 +4835,7 @@ static int hook_uri2file(request_rec *r)
             if (rulestatus != ACTION_NOESCAPE) {
                 rewritelog((r, 1, NULL, "escaping %s for redirect",
                             r->filename));
-                r->filename = escape_absolute_uri(r->pool, r->filename, skip);
+                r->filename = escape_absolute_uri(r->pool, r->filename, skip_absolute);
             }
 
             /* append the QUERY_STRING part */
@@ -5041,9 +5059,17 @@ static int hook_fixup(request_rec *r)
      */
     rulestatus = apply_rewrite_list(r, dconf->rewriterules, dconf->directory);
     if (rulestatus) {
-        unsigned skip;
+        unsigned skip_absolute = is_absolute_uri(r->filename, NULL);
+        int to_proxyreq = 0;
+        int will_escape = 0;
 
-        if (r->args && *(ap_scan_vchar_obstext(r->args))) {
+        l = strlen(r->filename);
+        to_proxyreq = l > 6 && strncmp(r->filename, "proxy:", 6) == 0;
+        will_escape = skip_absolute && (rulestatus != ACTION_NOESCAPE);
+
+        if (r->args
+               && !will_escape
+               &&  *(ap_scan_vchar_obstext(r->args))) {
             /*
              * We have a raw control character or a ' ' in r->args.
              * Correct encoding was missed.
@@ -5061,8 +5087,7 @@ static int hook_fixup(request_rec *r)
             return n;
         }
 
-        l = strlen(r->filename);
-        if (l > 6 && strncmp(r->filename, "proxy:", 6) == 0) {
+        if (to_proxyreq) {
             /* it should go on as an internal proxy request */
 
             /* make sure the QUERY_STRING and
@@ -5086,7 +5111,7 @@ static int hook_fixup(request_rec *r)
                         "%s [OK]", r->filename));
             return OK;
         }
-        else if ((skip = is_absolute_uri(r->filename, NULL)) > 0) {
+        else if (skip_absolute > 0) {
             /* it was finally rewritten to a remote URL */
 
             /* because we are in a per-dir context
@@ -5095,7 +5120,7 @@ static int hook_fixup(request_rec *r)
              */
             if (dconf->baseurl != NULL) {
                 /* skip 'scheme://' */
-                cp = r->filename + skip;
+                cp = r->filename + skip_absolute;
 
                 if ((cp = ap_strchr(cp, '/')) != NULL && *(++cp)) {
                     rewritelog((r, 2, dconf->directory,
@@ -5140,7 +5165,7 @@ static int hook_fixup(request_rec *r)
             if (rulestatus != ACTION_NOESCAPE) {
                 rewritelog((r, 1, dconf->directory, "escaping %s for redirect",
                             r->filename));
-                r->filename = escape_absolute_uri(r->pool, r->filename, skip);
+                r->filename = escape_absolute_uri(r->pool, r->filename, skip_absolute);
             }
 
             /* append the QUERY_STRING part */
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index 9225bc9b..537c3c25 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -963,6 +963,8 @@ PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent,
     }
 
     if (found) {
+        unsigned int encoded = ent->flags & PROXYPASS_MAP_ENCODED;
+
         /* A proxy module is assigned this URL, check whether it's interested
          * in the request itself (e.g. proxy_wstunnel cares about Upgrade
          * requests only, and could hand over to proxy_http otherwise).
@@ -982,6 +984,9 @@ PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent,
         if (ent->flags & PROXYPASS_NOQUERY) {
             apr_table_setn(r->notes, "proxy-noquery", "1");
         }
+        if (encoded) {
+            apr_table_setn(r->notes, "proxy-noencode", "1");
+        }
 
         if (servlet_uri) {
             ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(10248)
@@ -995,13 +1000,13 @@ PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent,
              */
             AP_DEBUG_ASSERT(strlen(r->uri) >= strlen(servlet_uri));
             strcpy(r->uri, servlet_uri);
-            return DONE;
         }
-
-        ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(03464)
-                      "URI path '%s' matches proxy handler '%s'", r->uri,
-                      found);
-        return OK;
+        else {
+            ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(03464)
+                          "URI path '%s' matches proxy handler '%s'", r->uri,
+                          found);
+        }
+        return (encoded) ? DONE : OK;
     }
 
     return HTTP_CONTINUE;
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index 5c08e99c..c51145e0 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -76,6 +76,10 @@ enum enctype {
     enc_path, enc_search, enc_user, enc_fpath, enc_parm
 };
 
+/* Flags for ap_proxy_canonenc_ex */
+#define PROXY_CANONENC_FORCEDEC 0x01
+#define PROXY_CANONENC_NOENCODEDSLASHENCODING 0x02
+
 typedef enum {
     NONE, TCP, OPTIONS, HEAD, GET, CPING, PROVIDER, OPTIONS11, HEAD11, GET11, EOT
 } hcmethod_t;
@@ -676,6 +680,8 @@ PROXY_DECLARE(apr_status_t) ap_proxy_strncpy(char *dst, const char *src,
                                              apr_size_t dlen);
 PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
 PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
+PROXY_DECLARE(char *)ap_proxy_canonenc_ex(apr_pool_t *p, const char *x, int len, enum enctype t,
+                                          int flags, int proxyreq);
 PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
                                        int forcedec, int proxyreq);
 PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
index e46bd903..65773ce7 100644
--- a/modules/proxy/mod_proxy_ajp.c
+++ b/modules/proxy/mod_proxy_ajp.c
@@ -65,23 +65,37 @@ static int proxy_ajp_canon(request_rec *r, char *url)
     if (apr_table_get(r->notes, "proxy-nocanon")) {
         path = url;   /* this is the raw path */
     }
-    else {
-        path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                                 r->proxyreq);
+    else if (apr_table_get(r->notes, "proxy-noencode")) {
+        path = url;   /* this is the encoded path already */
         search = r->args;
-        if (search && *(ap_scan_vchar_obstext(search))) {
-            /*
-             * We have a raw control character or a ' ' in r->args.
-             * Correct encoding was missed.
-             */
-             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10406)
-                           "To be forwarded query string contains control "
-                           "characters or spaces");
-             return HTTP_FORBIDDEN;
+    }
+    else {
+        core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+        int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+        path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                    r->proxyreq);
+        if (!path) {
+            return HTTP_BAD_REQUEST;
         }
+        search = r->args;
+    }
+    /*
+     * If we have a raw control character or a ' ' in nocanon path or
+     * r->args, correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10418)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
+    if (search && *ap_scan_vchar_obstext(search)) {
+         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10406)
+                       "To be forwarded query string contains control "
+                       "characters or spaces");
+         return HTTP_FORBIDDEN;
     }
-    if (path == NULL)
-        return HTTP_BAD_REQUEST;
 
     if (port != def_port)
          apr_snprintf(sport, sizeof(sport), ":%d", port);
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index 7f990084..b8b452d0 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -102,23 +102,37 @@ static int proxy_balancer_canon(request_rec *r, char *url)
     if (apr_table_get(r->notes, "proxy-nocanon")) {
         path = url;   /* this is the raw path */
     }
-    else {
-        path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                                 r->proxyreq);
+    else if (apr_table_get(r->notes, "proxy-noencode")) {
+        path = url;   /* this is the encoded path already */
         search = r->args;
-        if (search && *(ap_scan_vchar_obstext(search))) {
-            /*
-             * We have a raw control character or a ' ' in r->args.
-             * Correct encoding was missed.
-             */
-             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10407)
-                           "To be forwarded query string contains control "
-                           "characters or spaces");
-             return HTTP_FORBIDDEN;
+    }
+    else {
+        core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+        int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+        path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                    r->proxyreq);
+        if (!path) {
+            return HTTP_BAD_REQUEST;
         }
+        search = r->args;
+    }
+    /*
+     * If we have a raw control character or a ' ' in nocanon path or
+     * r->args, correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10416)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
+    if (search && *ap_scan_vchar_obstext(search)) {
+         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10407)
+                       "To be forwarded query string contains control "
+                       "characters or spaces");
+         return HTTP_FORBIDDEN;
     }
-    if (path == NULL)
-        return HTTP_BAD_REQUEST;
 
     r->filename = apr_pstrcat(r->pool, "proxy:" BALANCER_PREFIX, host,
             "/", path, (search) ? "?" : "", (search) ? search : "", NULL);
diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c
index 3382b9bf..831bd15a 100644
--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -92,15 +92,30 @@ static int proxy_fcgi_canon(request_rec *r, char *url)
         host = apr_pstrcat(r->pool, "[", host, "]", NULL);
     }
 
-    if (apr_table_get(r->notes, "proxy-nocanon")) {
-        path = url;   /* this is the raw path */
+    if (apr_table_get(r->notes, "proxy-nocanon")
+        || apr_table_get(r->notes, "proxy-noencode")) {
+        path = url;   /* this is the raw/encoded path */
     }
     else {
-        path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                             r->proxyreq);
+        core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+        int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+        path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                    r->proxyreq);
+        if (!path) {
+            return HTTP_BAD_REQUEST;
+        }
+    }
+    /*
+     * If we have a raw control character or a ' ' in nocanon path,
+     * correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10414)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
     }
-    if (path == NULL)
-        return HTTP_BAD_REQUEST;
 
     r->filename = apr_pstrcat(r->pool, "proxy:fcgi://", host, sport, "/",
                               path, NULL);
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
index 3237a2ba..a3fb10a9 100644
--- a/modules/proxy/mod_proxy_ftp.c
+++ b/modules/proxy/mod_proxy_ftp.c
@@ -289,6 +289,8 @@ static int proxy_ftp_canon(request_rec *r, char *url)
     apr_pool_t *p = r->pool;
     const char *err;
     apr_port_t port, def_port;
+    core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+    int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
 
     /* */
     if (ap_cstr_casecmpn(url, "ftp:", 4) == 0) {
@@ -327,7 +329,8 @@ static int proxy_ftp_canon(request_rec *r, char *url)
     else
         parms = "";
 
-    path = ap_proxy_canonenc(p, url, strlen(url), enc_path, 0, r->proxyreq);
+    path = ap_proxy_canonenc_ex(p, url, strlen(url), enc_path, flags,
+                                r->proxyreq);
     if (path == NULL)
         return HTTP_BAD_REQUEST;
     if (!ftp_check_string(path))
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index 51d19a0a..1842c49e 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -121,29 +121,42 @@ static int proxy_http_canon(request_rec *r, char *url)
         if (apr_table_get(r->notes, "proxy-nocanon")) {
             path = url;   /* this is the raw path */
         }
-        else {
-            path = ap_proxy_canonenc(r->pool, url, strlen(url),
-                                     enc_path, 0, r->proxyreq);
+        else if (apr_table_get(r->notes, "proxy-noencode")) {
+            path = url;   /* this is the encoded path already */
             search = r->args;
-            if (search && *(ap_scan_vchar_obstext(search))) {
-                /*
-                 * We have a raw control character or a ' ' in r->args.
-                 * Correct encoding was missed.
-                 */
-                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10408)
-                              "To be forwarded query string contains control "
-                              "characters or spaces");
-                return HTTP_FORBIDDEN;
+        }
+        else {
+            core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+            int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+            path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path,
+                                        flags, r->proxyreq);
+            if (!path) {
+                return HTTP_BAD_REQUEST;
             }
+            search = r->args;
         }
         break;
     case PROXYREQ_PROXY:
         path = url;
         break;
     }
-
-    if (path == NULL)
-        return HTTP_BAD_REQUEST;
+    /*
+     * If we have a raw control character or a ' ' in nocanon path or
+     * r->args, correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10415)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
+    if (search && *ap_scan_vchar_obstext(search)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10408)
+                      "To be forwarded query string contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
 
     if (port != def_port)
         apr_snprintf(sport, sizeof(sport), ":%d", port);
diff --git a/modules/proxy/mod_proxy_scgi.c b/modules/proxy/mod_proxy_scgi.c
index 493757d3..5444a5c4 100644
--- a/modules/proxy/mod_proxy_scgi.c
+++ b/modules/proxy/mod_proxy_scgi.c
@@ -179,6 +179,8 @@ static int scgi_canon(request_rec *r, char *url)
     char *host, sport[sizeof(":65535")];
     const char *err, *path;
     apr_port_t port, def_port;
+    core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+    int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
 
     if (ap_cstr_casecmpn(url, SCHEME "://", sizeof(SCHEME) + 2)) {
         return DECLINED;
@@ -205,8 +207,8 @@ static int scgi_canon(request_rec *r, char *url)
         host = apr_pstrcat(r->pool, "[", host, "]", NULL);
     }
 
-    path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                             r->proxyreq);
+    path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                r->proxyreq);
     if (!path) {
         return HTTP_BAD_REQUEST;
     }
diff --git a/modules/proxy/mod_proxy_uwsgi.c b/modules/proxy/mod_proxy_uwsgi.c
index 92e153cc..fd76c955 100644
--- a/modules/proxy/mod_proxy_uwsgi.c
+++ b/modules/proxy/mod_proxy_uwsgi.c
@@ -84,10 +84,29 @@ static int uwsgi_canon(request_rec *r, char *url)
         host = apr_pstrcat(r->pool, "[", host, "]", NULL);
     }
 
-    path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                             r->proxyreq);
-    if (!path) {
-        return HTTP_BAD_REQUEST;
+    if (apr_table_get(r->notes, "proxy-nocanon")
+        || apr_table_get(r->notes, "proxy-noencode")) {
+        path = url;   /* this is the raw/encoded path */
+    }
+    else {
+        core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+        int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+        path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                    r->proxyreq);
+        if (!path) {
+            return HTTP_BAD_REQUEST;
+        }
+    }
+    /*
+     * If we have a raw control character or a ' ' in nocanon path,
+     * correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10417)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
     }
 
     r->filename =
diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
index 88f86a49..30ba1b49 100644
--- a/modules/proxy/mod_proxy_wstunnel.c
+++ b/modules/proxy/mod_proxy_wstunnel.c
@@ -110,23 +110,37 @@ static int proxy_wstunnel_canon(request_rec *r, char *url)
     if (apr_table_get(r->notes, "proxy-nocanon")) {
         path = url;   /* this is the raw path */
     }
-    else {
-        path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                                 r->proxyreq);
+    else if (apr_table_get(r->notes, "proxy-noencode")) {
+        path = url;   /* this is the encoded path already */
         search = r->args;
-        if (search && *(ap_scan_vchar_obstext(search))) {
-            /*
-             * We have a raw control character or a ' ' in r->args.
-             * Correct encoding was missed.
-             */
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10409)
-                          "To be forwarded query string contains control "
-                          "characters or spaces");
-            return HTTP_FORBIDDEN;
+    }
+    else {
+        core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+        int flags = d->allow_encoded_slashes && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+        path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                    r->proxyreq);
+        if (!path) {
+            return HTTP_BAD_REQUEST;
         }
+        search = r->args;
+    }
+    /*
+     * If we have a raw control character or a ' ' in nocanon path or
+     * r->args, correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10419)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
+    if (search && *ap_scan_vchar_obstext(search)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10409)
+                      "To be forwarded query string contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
     }
-    if (path == NULL)
-        return HTTP_BAD_REQUEST;
 
     if (port != def_port)
         apr_snprintf(sport, sizeof(sport), ":%d", port);
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 8267f1b9..caafde0b 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -200,14 +200,16 @@ PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x)
  * and encodes those which must be encoded, and does not touch
  * those which must not be touched.
  */
-PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len,
-                                       enum enctype t, int forcedec,
-                                       int proxyreq)
+PROXY_DECLARE(char *)ap_proxy_canonenc_ex(apr_pool_t *p, const char *x, int len,
+                                          enum enctype t, int flags,
+                                          int proxyreq)
 {
     int i, j, ch;
     char *y;
     char *allowed;  /* characters which should not be encoded */
     char *reserved; /* characters which much not be en/de-coded */
+    int forcedec = flags & PROXY_CANONENC_FORCEDEC;
+    int noencslashesenc = flags & PROXY_CANONENC_NOENCODEDSLASHENCODING;
 
 /*
  * N.B. in addition to :@&=, this allows ';' in an http path
@@ -256,17 +258,29 @@ PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len,
  * decode it if not already done. do not decode reverse proxied URLs
  * unless specifically forced
  */
-        if ((forcedec || (proxyreq && proxyreq != PROXYREQ_REVERSE)) && ch == '%') {
+        if ((forcedec || noencslashesenc
+            || (proxyreq && proxyreq != PROXYREQ_REVERSE)) && ch == '%') {
             if (!apr_isxdigit(x[i + 1]) || !apr_isxdigit(x[i + 2])) {
                 return NULL;
             }
             ch = ap_proxy_hex2c(&x[i + 1]);
-            i += 2;
             if (ch != 0 && strchr(reserved, ch)) {  /* keep it encoded */
-                ap_proxy_c2hex(ch, &y[j]);
-                j += 2;
+                y[j++] = x[i++];
+                y[j++] = x[i++];
+                y[j] = x[i];
                 continue;
             }
+            if (noencslashesenc && !forcedec && (proxyreq == PROXYREQ_REVERSE)) {
+                /*
+                 * In the reverse proxy case when we only want to keep encoded
+                 * slashes untouched revert back to '%' which will cause
+                 * '%' to be encoded in the following.
+                 */
+                ch = '%';
+            }
+            else {
+                i += 2;
+            }
         }
 /* recode it, if necessary */
         if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
@@ -281,6 +295,22 @@ PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len,
     return y;
 }
 
+/*
+ * Convert a URL-encoded string to canonical form.
+ * It decodes characters which need not be encoded,
+ * and encodes those which must be encoded, and does not touch
+ * those which must not be touched.
+ */
+PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len,
+                                       enum enctype t, int forcedec,
+                                       int proxyreq)
+{
+    int flags;
+
+    flags = forcedec ? PROXY_CANONENC_FORCEDEC : 0;
+    return ap_proxy_canonenc_ex(p, x, len, t, flags, proxyreq);
+}
+
 /*
  * Parses network-location.
  *    urlp           on input the URL; on output the path, after the leading /
diff --git a/test/README.pytest b/test/README.pytest
index 5949e12b..474030bd 100644
--- a/test/README.pytest
+++ b/test/README.pytest
@@ -72,7 +72,7 @@ Development
 -----------
 
 Adding a test in an existing file is done by adding a method. Its name
-must start with 'test_' and the common practise is to have the name
+must start with 'test_' and the common practice is to have the name
 of the test suite there as well. All http2 tests start with 'test_h2_'.
 
 Following this can be any characters. If you make test cases of a
diff --git a/test/modules/http2/test_004_post.py b/test/modules/http2/test_004_post.py
index 97f05e25..44f31d2c 100644
--- a/test/modules/http2/test_004_post.py
+++ b/test/modules/http2/test_004_post.py
@@ -5,6 +5,7 @@ import json
 import os
 import re
 import sys
+import time
 
 import pytest
 
@@ -173,6 +174,8 @@ CustomLog logs/test_004_30 issue_203
         r = env.curl_get(url, 5, options=["--http2", "-H", "Range: bytes=0-{0}".format(chunk-1)])
         assert 206 == r.response["status"]
         assert chunk == len(r.response["body"].decode('utf-8'))
+        # Wait for log completeness
+        time.sleep(1)
         # now check what response lengths have actually been reported
         lines = open(logfile).readlines()
         log_h2_full = json.loads(lines[-3])
diff --git a/test/modules/http2/test_600_h2proxy.py b/test/modules/http2/test_600_h2proxy.py
index 9591ce57..e93ba1ae 100644
--- a/test/modules/http2/test_600_h2proxy.py
+++ b/test/modules/http2/test_600_h2proxy.py
@@ -78,24 +78,30 @@ class TestH2Proxy:
         conf.install()
         assert env.apache_restart() == 0
         url = env.mkurl("https", "cgi", f"/h2proxy/{env.http_port}/hello.py")
-        r = env.curl_get(url, 5)
-        assert r.response["status"] == 200
-        assert r.json["h2_stream_id"] == "1"
         if enable_reuse == "on":
-            # reuse is not guarantueed for each request, but we expect some
+            # reuse is not guaranteed for each request, but we expect some
             # to do it and run on a h2 stream id > 1
             reused = False
-            for _ in range(10):
-                r = env.curl_get(url, 5)
-                assert r.response["status"] == 200
-                if int(r.json["h2_stream_id"]) > 1:
+            count = 10
+            r = env.curl_raw([url] * count, 5)
+            response = r.response
+            for n in range(count):
+                assert response["status"] == 200
+                if n == (count - 1):
+                    break
+                response = response["previous"]
+            assert r.json[0]["h2_stream_id"] == "1"
+            for n in range(1, count):
+                if int(r.json[n]["h2_stream_id"]) > 1:
                     reused = True
                     break
             assert reused
         else:
-            r = env.curl_get(url, 5)
+            r = env.curl_raw([url, url], 5)
+            assert r.response["previous"]["status"] == 200
             assert r.response["status"] == 200
-            assert r.json["h2_stream_id"] == "1"
+            assert r.json[0]["h2_stream_id"] == "1"
+            assert r.json[1]["h2_stream_id"] == "1"
 
     # do some flexible setup from #235 to proper connection selection
     @pytest.mark.parametrize("enable_reuse", [ "on", "off" ])
@@ -119,16 +125,13 @@ class TestH2Proxy:
         conf.install()
         assert env.apache_restart() == 0
         url = env.mkurl("https", "cgi", f"/h2proxy/{env.http_port}/hello.py")
-        r = env.curl_get(url, 5)
-        assert r.response["status"] == 200
-        assert int(r.json["port"]) == env.http_port
-        # going to another backend port must create a new connection and
-        # we should see stream id one again
-        url = env.mkurl("https", "cgi", f"/h2proxy/{env.http_port2}/hello.py")
-        r = env.curl_get(url, 5)
+        url2 = env.mkurl("https", "cgi", f"/h2proxy/{env.http_port2}/hello.py")
+        r = env.curl_raw([url, url2], 5)
+        assert r.response["previous"]["status"] == 200
+        assert int(r.json[0]["port"]) == env.http_port
         assert r.response["status"] == 200
         exp_port = env.http_port if enable_reuse == "on" else env.http_port2
-        assert int(r.json["port"]) == exp_port
+        assert int(r.json[1]["port"]) == exp_port
 
     # lets do some error tests
     def test_h2_600_30(self, env):
diff --git a/test/pyhttpd/curl.py b/test/pyhttpd/curl.py
index 338e82ce..2b6840b1 100644
--- a/test/pyhttpd/curl.py
+++ b/test/pyhttpd/curl.py
@@ -32,7 +32,7 @@ class CurlPiper:
         return self._r.response if self._r else None
 
     def start(self):
-        self.args, self.headerfile = self.env.curl_complete_args(self.url, timeout=5, options=[
+        self.args, self.headerfile = self.env.curl_complete_args([self.url], timeout=5, options=[
             "-T", "-", "-X", "POST", "--trace-ascii", "%", "--trace-time"])
         sys.stderr.write("starting: {0}\n".format(self.args))
         self.proc = subprocess.Popen(self.args, stdin=subprocess.PIPE,
diff --git a/test/pyhttpd/env.py b/test/pyhttpd/env.py
index af856eff..2c918593 100644
--- a/test/pyhttpd/env.py
+++ b/test/pyhttpd/env.py
@@ -65,6 +65,8 @@ class HttpdTestSetup:
         "proxy_http",
     ]
 
+    CURL_STDOUT_SEPARATOR = "===CURL_STDOUT_SEPARATOR==="
+
     def __init__(self, env: 'HttpdTestEnv'):
         self.env = env
         self._source_dirs = [os.path.dirname(inspect.getfile(HttpdTestSetup))]
@@ -497,14 +499,26 @@ class HttpdTestEnv:
         if not os.path.exists(path):
             return os.makedirs(path)
 
-    def run(self, args, intext=None, debug_log=True):
+    def run(self, args, stdout_list=False, intext=None, debug_log=True):
         if debug_log:
             log.debug(f"run: {args}")
         start = datetime.now()
         p = subprocess.run(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE,
                            input=intext.encode() if intext else None)
+        stdout_as_list = None
+        if stdout_list:
+            try:
+                out = p.stdout.decode()
+                if HttpdTestSetup.CURL_STDOUT_SEPARATOR in out:
+                    stdout_as_list = out.split(HttpdTestSetup.CURL_STDOUT_SEPARATOR)
+                    if not stdout_as_list[len(stdout_as_list) - 1]:
+                        stdout_as_list.pop()
+                p.stdout.replace(HttpdTestSetup.CURL_STDOUT_SEPARATOR.encode(), b'')
+            except:
+                pass
         return ExecResult(args=args, exit_code=p.returncode,
                           stdout=p.stdout, stderr=p.stderr,
+                          stdout_as_list=stdout_as_list,
                           duration=datetime.now() - start)
 
     def mkurl(self, scheme, hostname, path='/'):
@@ -637,10 +651,9 @@ class HttpdTestEnv:
                 os.remove(os.path.join(self.gen_dir, fname))
         self._curl_headerfiles_n = 0
 
-    def curl_complete_args(self, urls, timeout=None, options=None,
+    def curl_complete_args(self, urls, stdout_list=False,
+                           timeout=None, options=None,
                            insecure=False, force_resolve=True):
-        if not isinstance(urls, list):
-            urls = [urls]
         u = urlparse(urls[0])
         #assert u.hostname, f"hostname not in url: {urls[0]}"
         headerfile = f"{self.gen_dir}/curl.headers.{self._curl_headerfiles_n}"
@@ -649,6 +662,8 @@ class HttpdTestEnv:
         args = [
             self._curl, "-s", "--path-as-is", "-D", headerfile,
         ]
+        if stdout_list:
+            args.extend(['-w', '%{stdout}' + HttpdTestSetup.CURL_STDOUT_SEPARATOR])
         if u.scheme == 'http':
             pass
         elif insecure:
@@ -731,10 +746,16 @@ class HttpdTestEnv:
 
     def curl_raw(self, urls, timeout=10, options=None, insecure=False,
                  force_resolve=True):
+        if not isinstance(urls, list):
+            urls = [urls]
+        stdout_list = False
+        if len(urls) > 1:
+            stdout_list = True
         args, headerfile = self.curl_complete_args(
-            urls=urls, timeout=timeout, options=options, insecure=insecure,
+            urls=urls, stdout_list=stdout_list,
+            timeout=timeout, options=options, insecure=insecure,
             force_resolve=force_resolve)
-        r = self.run(args)
+        r = self.run(args, stdout_list=stdout_list)
         if r.exit_code == 0:
             self.curl_parse_headerfile(headerfile, r=r)
             if r.json:
diff --git a/test/pyhttpd/nghttp.py b/test/pyhttpd/nghttp.py
index fe4a1aed..f27e40d3 100644
--- a/test/pyhttpd/nghttp.py
+++ b/test/pyhttpd/nghttp.py
@@ -251,7 +251,9 @@ class Nghttp:
             f.write("--DSAJKcd9876\n")
         if not options:
             options = []
-        options.extend(["--data=%s" % reqbody])
+        options.extend([ 
+            "--data=%s" % reqbody, 
+            "-HContent-Type: multipart/form-data; boundary=DSAJKcd9876"])
         return self._raw(url, timeout, options)
 
     def upload(self, url, fpath, timeout=5, options=None):
diff --git a/test/pyhttpd/result.py b/test/pyhttpd/result.py
index 04ea825a..3789461b 100644
--- a/test/pyhttpd/result.py
+++ b/test/pyhttpd/result.py
@@ -6,7 +6,9 @@ from typing import Optional, Dict, List
 class ExecResult:
 
     def __init__(self, args: List[str], exit_code: int,
-                 stdout: bytes, stderr: bytes = None, duration: timedelta = None):
+                 stdout: bytes, stderr: bytes = None,
+                 stdout_as_list: List[bytes] = None,
+                 duration: timedelta = None):
         self._args = args
         self._exit_code = exit_code
         self._stdout = stdout if stdout is not None else b''
@@ -17,7 +19,10 @@ class ExecResult:
         self._assets = []
         # noinspection PyBroadException
         try:
-            out = self._stdout.decode()
+            if stdout_as_list is None:
+                out = self._stdout.decode()
+            else:
+                out = "[" + ','.join(stdout_as_list) + "]"
             self._json_out = json.loads(out)
         except:
             self._json_out = None
diff --git a/test/travis_run_linux.sh b/test/travis_run_linux.sh
index 58370700..f7a72d29 100755
--- a/test/travis_run_linux.sh
+++ b/test/travis_run_linux.sh
@@ -122,8 +122,23 @@ if ! test -v SKIP_TESTING; then
         test -v TEST_INSTALL || make install
         pushd test/perl-framework
             perl Makefile.PL -apxs $PREFIX/bin/apxs
-            make test APACHE_TEST_EXTRA_ARGS="${TEST_ARGS} ${TESTS}"
-            RV=$?
+            make test APACHE_TEST_EXTRA_ARGS="${TEST_ARGS} ${TESTS}" | tee test.log
+            RV=${PIPESTATUS[0]}
+            # re-run failing tests with -v, avoiding set -e
+            if [ $RV -ne 0 ]; then
+                #mv t/logs/error_log t/logs/error_log_save
+                FAILERS=""
+                while read FAILER; do
+                    FAILERS="$FAILERS $FAILER"
+                done < <(awk '/Failed:/{print $1}' test.log)
+                if [ -n "$FAILERS" ]; then
+                    t/TEST -v $FAILERS || true
+                fi
+                # set -e would have killed us after the original t/TEST
+                rm -f test.log
+                #mv t/logs/error_log_save t/logs/error_log
+                false
+            fi
         popd
     fi
 

Reply to: