Fabian Keil, lead developer
David Schmidt
- Hal Burgiss
Lee Rian
Roland Rosenfeld
Ian Silvester
Johny Agotnes
Rodrigo Barbosa
Moritz Barsnick
+ Hal Burgiss
Ian Cummings
Brian Dessent
Jon Foster
DEFINE_CGI_PARAM_NO_RADIO("crunch-server-header", ACTION_CRUNCH_SERVER_HEADER, ACTION_STRING_SERVER_HEADER, "X-Whatever:")
DEFINE_ACTION_STRING ("deanimate-gifs", ACTION_DEANIMATE, ACTION_STRING_DEANIMATE)
DEFINE_CGI_PARAM_RADIO ("deanimate-gifs", ACTION_DEANIMATE, ACTION_STRING_DEANIMATE, "first", 0)
+DEFINE_ACTION_STRING ("delay-response", ACTION_DELAY_RESPONSE, ACTION_STRING_DELAY_RESPONSE)
+DEFINE_CGI_PARAM_NO_RADIO("delay-response", ACTION_DELAY_RESPONSE, ACTION_STRING_DELAY_RESPONSE, "100")
DEFINE_CGI_PARAM_RADIO ("deanimate-gifs", ACTION_DEANIMATE, ACTION_STRING_DEANIMATE, "last", 1)
DEFINE_ACTION_BOOL ("downgrade-http-version", ACTION_DOWNGRADE)
#ifdef FEATURE_EXTERNAL_FILTERS
memchr \
memmove \
memset \
+ nanosleep \
poll \
putenv \
random \
</variablelist>
</sect3>
+
+<!-- ~~~~~ New section ~~~~~ -->
+<sect3 renderas="sect4" id="delay-response">
+<title>delay-response</title>
+
+<variablelist>
+ <varlistentry>
+ <term>Typical use:</term>
+ <listitem>
+ <para>Delay responses to the client to reduce the load</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Effect:</term>
+ <listitem>
+ <para>
+ Delays responses to the client by sending the response in ca. 10 byte chunks.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Type:</term>
+ <!-- boolean, parameterized, Multi-value -->
+ <listitem>
+ <para>Parameterized.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Parameter:</term>
+ <listitem>
+ <para>
+ <quote>Number of milliseconds</quote>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Notes:</term>
+ <listitem>
+ <para>
+ Sometimes when JavaScript code is used to fetch advertisements
+ it doesn't respect Privoxy's blocks and retries to fetch the
+ same resource again causing unnecessary load on the client.
+ </para>
+ <para>
+ This action delays responses to the client and can be combined
+ with <literal><link linkend="block">blocks</link></literal>
+ to slow down the JavaScript code, thus reducing
+ the load on the client.
+ </para>
+ <para>
+ When used without <literal><link linkend="block">blocks</link></literal>
+ the action can also be used to simulate a slow internet connection.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Example usage:</term>
+ <listitem>
+ <screen>+delay-response{100}</screen>
+ </listitem>
+ </varlistentry>
+</variablelist>
+</sect3>
+
+
<!-- ~~~~~ New section ~~~~~ -->
<sect3 renderas="sect4" id="downgrade-http-version">
<title>downgrade-http-version</title>
<sect1 renderas="sect2" id="download" label=""><title>Download</title>
<para>
You can <ulink url="/sf-download-mirror/">download Privoxy here</ulink>,
- from <ulink url="http://www.silvester.org.uk/privoxy/">this mirror</ulink>,
+ from <ulink url="https://www.silvester.org.uk/privoxy/">this mirror</ulink>,
or from <ulink url="https://sourceforge.net/projects/ijbswa/files/">SourceForge</ulink>.
</para>
<para>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "PROGRAMLISTING"> $ utils/changelog2doc.pl /tmp/change.log >| doc/source/changelog.sgml</pre>
+ <pre class="PROGRAMLISTING">
+ $ utils/changelog2doc.pl /tmp/change.log >| doc/source/changelog.sgml</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="100%">
<tr>
<td>
- <pre class=
- "PROGRAMLISTING"> cvs -z3 -d:pserver:anonymous@ijbswa.cvs.sourceforge.net:/cvsroot/ijbswa co os2setup</pre>
+ <pre class="PROGRAMLISTING">
+ cvs -z3 -d:pserver:anonymous@ijbswa.cvs.sourceforge.net:/cvsroot/ijbswa co os2setup</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="100%">
<tr>
<td>
- <pre class=
- "PROGRAMLISTING"> cvs -z3 -d:pserver:anonymous@ijbswa.cvs.sourceforge.net:/cvsroot/ijbswa co OSXPackageBuilder</pre>
+ <pre class="PROGRAMLISTING">
+ cvs -z3 -d:pserver:anonymous@ijbswa.cvs.sourceforge.net:/cvsroot/ijbswa co OSXPackageBuilder</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="100%">
<tr>
<td>
- <pre class=
- "PROGRAMLISTING"> cvs -z3 -d:pserver:anonymous@ijbswa.cvs.sourceforge.net:/cvsroot/ijbswa co osxsetup</pre>
+ <pre class="PROGRAMLISTING">
+ cvs -z3 -d:pserver:anonymous@ijbswa.cvs.sourceforge.net:/cvsroot/ijbswa co osxsetup</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="100%">
<tr>
<td>
- <pre class=
- "PROGRAMLISTING"> cvs -z3 -d:pserver:anonymous@ijbswa.cvs.sourceforge.net:/cvsroot/ijbswa co macsetup</pre>
+ <pre class="PROGRAMLISTING">
+ cvs -z3 -d:pserver:anonymous@ijbswa.cvs.sourceforge.net:/cvsroot/ijbswa co macsetup</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="100%">
<tr>
<td>
- <pre class=
- "SCREEN"> { -crunch-incoming-cookies -crunch-outgoing-cookies -session-cookies-only -filter{content-cookies} }
+ <pre class="SCREEN">
+ { -crunch-incoming-cookies -crunch-outgoing-cookies -session-cookies-only -filter{content-cookies} }
.example.com</pre>
</td>
</tr>
</div>
<div class="SECT1">
<h1 class="SECT1"><a name="COPYRIGHT" id="COPYRIGHT">7. Privoxy Copyright, License and History</a></h1>
- <p>Copyright © 2001-2017 by Privoxy Developers <code class="EMAIL"><<a href=
+ <p>Copyright © 2001-2018 by Privoxy Developers <code class="EMAIL"><<a href=
"mailto:privoxy-devel@lists.privoxy.org">privoxy-devel@lists.privoxy.org</a>></code></p>
<p>Some source code is based on code Copyright © 1997 by Anonymous Coders and Junkbusters, Inc. and licensed
under the <i class="CITETITLE">GNU General Public License</i>.</p>
Helping hands and donations are welcome:
- ââ\82¬Â¢ https://www.privoxy.org/faq/general.html#PARTICIPATE
+ • https://www.privoxy.org/faq/general.html#PARTICIPATE
- ââ\82¬Â¢ https://www.privoxy.org/faq/general.html#DONATE
+ • https://www.privoxy.org/faq/general.html#DONATE
</pre>
<head>
<title>Privoxy sponsors</title>
<link rel="STYLESHEET" type="text/css" href="../p_doc.css">
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="description" content="List of sponsors of the Privoxy project.">
</head>
<body class="ARTICLE" bgcolor="#EEEEEE" text="#000000" link="#0000FF" vlink="#840084" alink="#0000FF">
<html>
<head>
<meta name="generator" content="HTML Tidy for Linux/x86 (vers 7 December 2008), see www.w3.org">
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Privoxy - Team Photos</title>
<link rel="stylesheet" type="text/css" href="../p_doc.css">
<style type="text/css">
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="DOWNGRADE-HTTP-VERSION" id="DOWNGRADE-HTTP-VERSION">8.5.13.
+ <h4 class="SECT3"><a name="DELAY-RESPONSE" id="DELAY-RESPONSE">8.5.13. delay-response</a></h4>
+ <div class="VARIABLELIST">
+ <dl>
+ <dt>Typical use:</dt>
+ <dd>
+ <p>Delay responses to the client to reduce the load</p>
+ </dd>
+ <dt>Effect:</dt>
+ <dd>
+ <p>Delays responses to the client by sending the response in ca. 10 byte chunks.</p>
+ </dd>
+ <dt>Type:</dt>
+ <dd>
+ <p>Parameterized.</p>
+ </dd>
+ <dt>Parameter:</dt>
+ <dd>
+ <p><span class="QUOTE">"Number of milliseconds"</span></p>
+ </dd>
+ <dt>Notes:</dt>
+ <dd>
+ <p>Sometimes when JavaScript code is used to fetch advertisements it doesn't respect Privoxy's blocks and
+ retries to fetch the same resource again causing unnecessary load on the client.</p>
+ <p>This action delays responses to the client and can be combined with <tt class="LITERAL"><a href=
+ "actions-file.html#BLOCK">blocks</a></tt> to slow down the JavaScript code, thus reducing the load on the
+ client.</p>
+ <p>When used without <tt class="LITERAL"><a href="actions-file.html#BLOCK">blocks</a></tt> the action can
+ also be used to simulate a slow internet connection.</p>
+ </dd>
+ <dt>Example usage:</dt>
+ <dd>
+ <table border="0" bgcolor="#E0E0E0" width="90%">
+ <tr>
+ <td>
+ <pre class="SCREEN">+delay-response{100}</pre>
+ </td>
+ </tr>
+ </table>
+ </dd>
+ </dl>
+ </div>
+ </div>
+ <div class="SECT3">
+ <h4 class="SECT3"><a name="DOWNGRADE-HTTP-VERSION" id="DOWNGRADE-HTTP-VERSION">8.5.14.
downgrade-http-version</a></h4>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="EXTERNAL-FILTER" id="EXTERNAL-FILTER">8.5.14. external-filter</a></h4>
+ <h4 class="SECT3"><a name="EXTERNAL-FILTER" id="EXTERNAL-FILTER">8.5.15. external-filter</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="FAST-REDIRECTS" id="FAST-REDIRECTS">8.5.15. fast-redirects</a></h4>
+ <h4 class="SECT3"><a name="FAST-REDIRECTS" id="FAST-REDIRECTS">8.5.16. fast-redirects</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="FILTER" id="FILTER">8.5.16. filter</a></h4>
+ <h4 class="SECT3"><a name="FILTER" id="FILTER">8.5.17. filter</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{js-annoyances} # Get rid of particularly annoying JavaScript abuse.</pre>
+ <pre class="SCREEN">
+ +filter{js-annoyances} # Get rid of particularly annoying JavaScript abuse.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{js-events} # Kill JavaScript event bindings and timers (Radically destructive! Only for extra nasty sites).</pre>
+ <pre class="SCREEN">
+ +filter{js-events} # Kill JavaScript event bindings and timers (Radically destructive! Only for extra nasty sites).</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{html-annoyances} # Get rid of particularly annoying HTML abuse.</pre>
+ <pre class="SCREEN">
+ +filter{html-annoyances} # Get rid of particularly annoying HTML abuse.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{content-cookies} # Kill cookies that come in the HTML or JS content.</pre>
+ <pre class="SCREEN">
+ +filter{content-cookies} # Kill cookies that come in the HTML or JS content.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{refresh-tags} # Kill automatic refresh tags if refresh time is larger than 9 seconds.</pre>
+ <pre class="SCREEN">
+ +filter{refresh-tags} # Kill automatic refresh tags if refresh time is larger than 9 seconds.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{img-reorder} # Reorder attributes in <img> tags to make the banners-by-* filters more effective.</pre>
+ <pre class="SCREEN">
+ +filter{img-reorder} # Reorder attributes in <img> tags to make the banners-by-* filters more effective.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{banners-by-link} # Kill banners by their links to known clicktrackers.</pre>
+ <pre class="SCREEN">
+ +filter{banners-by-link} # Kill banners by their links to known clicktrackers.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{webbugs} # Squish WebBugs (1x1 invisible GIFs used for user tracking).</pre>
+ <pre class="SCREEN">
+ +filter{webbugs} # Squish WebBugs (1x1 invisible GIFs used for user tracking).</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{tiny-textforms} # Extend those tiny textareas up to 40x80 and kill the hard wrap.</pre>
+ <pre class="SCREEN">
+ +filter{tiny-textforms} # Extend those tiny textareas up to 40x80 and kill the hard wrap.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{jumping-windows} # Prevent windows from resizing and moving themselves.</pre>
+ <pre class="SCREEN">
+ +filter{jumping-windows} # Prevent windows from resizing and moving themselves.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{frameset-borders} # Give frames a border and make them resizable.</pre>
+ <pre class="SCREEN">
+ +filter{frameset-borders} # Give frames a border and make them resizable.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{iframes} # Removes all detected iframes. Should only be enabled for individual sites.</pre>
+ <pre class="SCREEN">
+ +filter{iframes} # Removes all detected iframes. Should only be enabled for individual sites.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{demoronizer} # Fix MS's non-standard use of standard charsets.</pre>
+ <pre class="SCREEN">
+ +filter{demoronizer} # Fix MS's non-standard use of standard charsets.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{fun} # Text replacements for subversive browsing fun!</pre>
+ <pre class="SCREEN">
+ +filter{fun} # Text replacements for subversive browsing fun!</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{crude-parental} # Crude parental filtering. Note that this filter doesn't work reliably.</pre>
+ <pre class="SCREEN">
+ +filter{crude-parental} # Crude parental filtering. Note that this filter doesn't work reliably.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{ie-exploits} # Disable some known Internet Explorer bug exploits.</pre>
+ <pre class="SCREEN">
+ +filter{ie-exploits} # Disable some known Internet Explorer bug exploits.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{site-specifics} # Cure for site-specific problems. Don't apply generally!</pre>
+ <pre class="SCREEN">
+ +filter{site-specifics} # Cure for site-specific problems. Don't apply generally!</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{no-ping} # Removes non-standard ping attributes in <a> and <area> tags.</pre>
+ <pre class="SCREEN">
+ +filter{no-ping} # Removes non-standard ping attributes in <a> and <area> tags.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{google} # CSS-based block for Google text ads. Also removes a width limitation and the toolbar advertisement.</pre>
+ <pre class="SCREEN">
+ +filter{google} # CSS-based block for Google text ads. Also removes a width limitation and the toolbar advertisement.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{yahoo} # CSS-based block for Yahoo text ads. Also removes a width limitation.</pre>
+ <pre class="SCREEN">
+ +filter{yahoo} # CSS-based block for Yahoo text ads. Also removes a width limitation.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{msn} # CSS-based block for MSN text ads. Also removes tracking URLs and a width limitation.</pre>
+ <pre class="SCREEN">
+ +filter{msn} # CSS-based block for MSN text ads. Also removes tracking URLs and a width limitation.</pre>
</td>
</tr>
</table>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN">+filter{blogspot} # Cleans up some Blogspot blogs. Read the fine print before using this.</pre>
+ <pre class="SCREEN">
+ +filter{blogspot} # Cleans up some Blogspot blogs. Read the fine print before using this.</pre>
</td>
</tr>
</table>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="FORCE-TEXT-MODE" id="FORCE-TEXT-MODE">8.5.17. force-text-mode</a></h4>
+ <h4 class="SECT3"><a name="FORCE-TEXT-MODE" id="FORCE-TEXT-MODE">8.5.18. force-text-mode</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="FORWARD-OVERRIDE" id="FORWARD-OVERRIDE">8.5.18. forward-override</a></h4>
+ <h4 class="SECT3"><a name="FORWARD-OVERRIDE" id="FORWARD-OVERRIDE">8.5.19. forward-override</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="HANDLE-AS-EMPTY-DOCUMENT" id="HANDLE-AS-EMPTY-DOCUMENT">8.5.19.
+ <h4 class="SECT3"><a name="HANDLE-AS-EMPTY-DOCUMENT" id="HANDLE-AS-EMPTY-DOCUMENT">8.5.20.
handle-as-empty-document</a></h4>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="HANDLE-AS-IMAGE" id="HANDLE-AS-IMAGE">8.5.20. handle-as-image</a></h4>
+ <h4 class="SECT3"><a name="HANDLE-AS-IMAGE" id="HANDLE-AS-IMAGE">8.5.21. handle-as-image</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="HIDE-ACCEPT-LANGUAGE" id="HIDE-ACCEPT-LANGUAGE">8.5.21.
+ <h4 class="SECT3"><a name="HIDE-ACCEPT-LANGUAGE" id="HIDE-ACCEPT-LANGUAGE">8.5.22.
hide-accept-language</a></h4>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="HIDE-CONTENT-DISPOSITION" id="HIDE-CONTENT-DISPOSITION">8.5.22.
+ <h4 class="SECT3"><a name="HIDE-CONTENT-DISPOSITION" id="HIDE-CONTENT-DISPOSITION">8.5.23.
hide-content-disposition</a></h4>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="HIDE-IF-MODIFIED-SINCE" id="HIDE-IF-MODIFIED-SINCE">8.5.23.
+ <h4 class="SECT3"><a name="HIDE-IF-MODIFIED-SINCE" id="HIDE-IF-MODIFIED-SINCE">8.5.24.
hide-if-modified-since</a></h4>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="HIDE-FROM-HEADER" id="HIDE-FROM-HEADER">8.5.24. hide-from-header</a></h4>
+ <h4 class="SECT3"><a name="HIDE-FROM-HEADER" id="HIDE-FROM-HEADER">8.5.25. hide-from-header</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="HIDE-REFERRER" id="HIDE-REFERRER">8.5.25. hide-referrer</a></h4><a name=
+ <h4 class="SECT3"><a name="HIDE-REFERRER" id="HIDE-REFERRER">8.5.26. hide-referrer</a></h4><a name=
"HIDE-REFERER" id="HIDE-REFERER"></a>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="HIDE-USER-AGENT" id="HIDE-USER-AGENT">8.5.26. hide-user-agent</a></h4>
+ <h4 class="SECT3"><a name="HIDE-USER-AGENT" id="HIDE-USER-AGENT">8.5.27. hide-user-agent</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="LIMIT-CONNECT" id="LIMIT-CONNECT">8.5.27. limit-connect</a></h4>
+ <h4 class="SECT3"><a name="LIMIT-CONNECT" id="LIMIT-CONNECT">8.5.28. limit-connect</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="LIMIT-COOKIE-LIFETIME" id="LIMIT-COOKIE-LIFETIME">8.5.28.
+ <h4 class="SECT3"><a name="LIMIT-COOKIE-LIFETIME" id="LIMIT-COOKIE-LIFETIME">8.5.29.
limit-cookie-lifetime</a></h4>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="PREVENT-COMPRESSION" id="PREVENT-COMPRESSION">8.5.29. prevent-compression</a></h4>
+ <h4 class="SECT3"><a name="PREVENT-COMPRESSION" id="PREVENT-COMPRESSION">8.5.30. prevent-compression</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="OVERWRITE-LAST-MODIFIED" id="OVERWRITE-LAST-MODIFIED">8.5.30.
+ <h4 class="SECT3"><a name="OVERWRITE-LAST-MODIFIED" id="OVERWRITE-LAST-MODIFIED">8.5.31.
overwrite-last-modified</a></h4>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="REDIRECT" id="REDIRECT">8.5.31. redirect</a></h4>
+ <h4 class="SECT3"><a name="REDIRECT" id="REDIRECT">8.5.32. redirect</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="SERVER-HEADER-FILTER" id="SERVER-HEADER-FILTER">8.5.32.
+ <h4 class="SECT3"><a name="SERVER-HEADER-FILTER" id="SERVER-HEADER-FILTER">8.5.33.
server-header-filter</a></h4>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="SERVER-HEADER-TAGGER" id="SERVER-HEADER-TAGGER">8.5.33.
+ <h4 class="SECT3"><a name="SERVER-HEADER-TAGGER" id="SERVER-HEADER-TAGGER">8.5.34.
server-header-tagger</a></h4>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="SESSION-COOKIES-ONLY" id="SESSION-COOKIES-ONLY">8.5.34.
+ <h4 class="SECT3"><a name="SESSION-COOKIES-ONLY" id="SESSION-COOKIES-ONLY">8.5.35.
session-cookies-only</a></h4>
<div class="VARIABLELIST">
<dl>
</div>
</div>
<div class="SECT3">
- <h4 class="SECT3"><a name="SET-IMAGE-BLOCKER" id="SET-IMAGE-BLOCKER">8.5.35. set-image-blocker</a></h4>
+ <h4 class="SECT3"><a name="SET-IMAGE-BLOCKER" id="SET-IMAGE-BLOCKER">8.5.36. set-image-blocker</a></h4>
<div class="VARIABLELIST">
<dl>
<dt>Typical use:</dt>
</div>
</div>
<div class="SECT3">
- <h3 class="SECT3"><a name="SUMMARY" id="SUMMARY">8.5.36. Summary</a></h3>
+ <h3 class="SECT3"><a name="SUMMARY" id="SUMMARY">8.5.37. Summary</a></h3>
<p>Note that many of these actions have the potential to cause a page to misbehave, possibly even not to
display at all. There are many ways a site designer may choose to design his site, and what HTTP header
content, and other criteria, he may depend on. There is no way to have hard and fast rules for all sites. See
these. If not, you will get a friendly error message. Internet access is not necessary either.</p>
<ul>
<li>
- <p>Privoxy main page:</p><a name="AEN5956" id="AEN5956"></a>
+ <p>Privoxy main page:</p><a name="AEN5990" id="AEN5990"></a>
<blockquote class="BLOCKQUOTE">
<p><a href="http://config.privoxy.org/" target="_top">http://config.privoxy.org/</a></p>
</blockquote>
</li>
<li>
<p>Show information about the current configuration, including viewing and editing of actions
- files:</p><a name="AEN5964" id="AEN5964"></a>
+ files:</p><a name="AEN5998" id="AEN5998"></a>
<blockquote class="BLOCKQUOTE">
<p><a href="http://config.privoxy.org/show-status" target=
"_top">http://config.privoxy.org/show-status</a></p>
</blockquote>
</li>
<li>
- <p>Show the source code version numbers:</p><a name="AEN5969" id="AEN5969"></a>
+ <p>Show the source code version numbers:</p><a name="AEN6003" id="AEN6003"></a>
<blockquote class="BLOCKQUOTE">
<p><a href="http://config.privoxy.org/show-version" target=
"_top">http://config.privoxy.org/show-version</a></p>
</blockquote>
</li>
<li>
- <p>Show the browser's request headers:</p><a name="AEN5974" id="AEN5974"></a>
+ <p>Show the browser's request headers:</p><a name="AEN6008" id="AEN6008"></a>
<blockquote class="BLOCKQUOTE">
<p><a href="http://config.privoxy.org/show-request" target=
"_top">http://config.privoxy.org/show-request</a></p>
</blockquote>
</li>
<li>
- <p>Show which actions apply to a URL and why:</p><a name="AEN5979" id="AEN5979"></a>
+ <p>Show which actions apply to a URL and why:</p><a name="AEN6013" id="AEN6013"></a>
<blockquote class="BLOCKQUOTE">
<p><a href="http://config.privoxy.org/show-url-info" target=
"_top">http://config.privoxy.org/show-url-info</a></p>
<li>
<p>Toggle Privoxy on or off. This feature can be turned off/on in the main <tt class="FILENAME">config</tt>
file. When toggled <span class="QUOTE">"off"</span>, <span class="QUOTE">"Privoxy"</span> continues to run,
- but only as a pass-through proxy, with no actions taking place:</p><a name="AEN5987" id="AEN5987"></a>
+ but only as a pass-through proxy, with no actions taking place:</p><a name="AEN6021" id="AEN6021"></a>
<blockquote class="BLOCKQUOTE">
<p><a href="http://config.privoxy.org/toggle" target="_top">http://config.privoxy.org/toggle</a></p>
</blockquote>
- <p>Short cuts. Turn off, then on:</p><a name="AEN5991" id="AEN5991"></a>
+ <p>Short cuts. Turn off, then on:</p><a name="AEN6025" id="AEN6025"></a>
<blockquote class="BLOCKQUOTE">
<p><a href="http://config.privoxy.org/toggle?set=disable" target=
"_top">http://config.privoxy.org/toggle?set=disable</a></p>
- </blockquote><a name="AEN5994" id="AEN5994"></a>
+ </blockquote><a name="AEN6028" id="AEN6028"></a>
<blockquote class="BLOCKQUOTE">
<p><a href="http://config.privoxy.org/toggle?set=enable" target=
"_top">http://config.privoxy.org/toggle?set=enable</a></p>
<table border="0" bgcolor="#E0E0E0" width="90%">
<tr>
<td>
- <pre class=
- "SCREEN"> forward-socks4a / socks-gw.example.com:1080 www-cache.isp.example.net:8080
+ <pre class="SCREEN">
+ forward-socks4a / socks-gw.example.com:1080 www-cache.isp.example.net:8080
forward .example.com .</pre>
</td>
</tr>
</div>
<div class="SECT1">
<h1 class="SECT1"><a name="COPYRIGHT" id="COPYRIGHT">12. Privoxy Copyright, License and History</a></h1>
- <p>Copyright © 2001-2017 by Privoxy Developers <code class="EMAIL"><<a href=
+ <p>Copyright © 2001-2018 by Privoxy Developers <code class="EMAIL"><<a href=
"mailto:privoxy-devel@lists.privoxy.org">privoxy-devel@lists.privoxy.org</a>></code></p>
<p>Some source code is based on code Copyright © 1997 by Anonymous Coders and Junkbusters, Inc. and licensed
under the <i class="CITETITLE">GNU General Public License</i>.</p>
<p>Current Privoxy Team:</p>
<p class="LITERALLAYOUT"> Fabian Keil, lead developer<br>
David Schmidt<br>
- Hal Burgiss<br>
Lee Rian<br>
Roland Rosenfeld<br>
Ian Silvester</p>
<p class="LITERALLAYOUT"> Johny Agotnes<br>
Rodrigo Barbosa<br>
Moritz Barsnick<br>
+ Hal Burgiss<br>
Ian Cummings<br>
Brian Dessent<br>
Jon Foster<br>
<dt>8.5.10. <a href="actions-file.html#CRUNCH-SERVER-HEADER">crunch-server-header</a></dt>
<dt>8.5.11. <a href="actions-file.html#CRUNCH-OUTGOING-COOKIES">crunch-outgoing-cookies</a></dt>
<dt>8.5.12. <a href="actions-file.html#DEANIMATE-GIFS">deanimate-gifs</a></dt>
- <dt>8.5.13. <a href="actions-file.html#DOWNGRADE-HTTP-VERSION">downgrade-http-version</a></dt>
- <dt>8.5.14. <a href="actions-file.html#EXTERNAL-FILTER">external-filter</a></dt>
- <dt>8.5.15. <a href="actions-file.html#FAST-REDIRECTS">fast-redirects</a></dt>
- <dt>8.5.16. <a href="actions-file.html#FILTER">filter</a></dt>
- <dt>8.5.17. <a href="actions-file.html#FORCE-TEXT-MODE">force-text-mode</a></dt>
- <dt>8.5.18. <a href="actions-file.html#FORWARD-OVERRIDE">forward-override</a></dt>
- <dt>8.5.19. <a href="actions-file.html#HANDLE-AS-EMPTY-DOCUMENT">handle-as-empty-document</a></dt>
- <dt>8.5.20. <a href="actions-file.html#HANDLE-AS-IMAGE">handle-as-image</a></dt>
- <dt>8.5.21. <a href="actions-file.html#HIDE-ACCEPT-LANGUAGE">hide-accept-language</a></dt>
- <dt>8.5.22. <a href="actions-file.html#HIDE-CONTENT-DISPOSITION">hide-content-disposition</a></dt>
- <dt>8.5.23. <a href="actions-file.html#HIDE-IF-MODIFIED-SINCE">hide-if-modified-since</a></dt>
- <dt>8.5.24. <a href="actions-file.html#HIDE-FROM-HEADER">hide-from-header</a></dt>
- <dt>8.5.25. <a href="actions-file.html#HIDE-REFERRER">hide-referrer</a></dt>
- <dt>8.5.26. <a href="actions-file.html#HIDE-USER-AGENT">hide-user-agent</a></dt>
- <dt>8.5.27. <a href="actions-file.html#LIMIT-CONNECT">limit-connect</a></dt>
- <dt>8.5.28. <a href="actions-file.html#LIMIT-COOKIE-LIFETIME">limit-cookie-lifetime</a></dt>
- <dt>8.5.29. <a href="actions-file.html#PREVENT-COMPRESSION">prevent-compression</a></dt>
- <dt>8.5.30. <a href="actions-file.html#OVERWRITE-LAST-MODIFIED">overwrite-last-modified</a></dt>
- <dt>8.5.31. <a href="actions-file.html#REDIRECT">redirect</a></dt>
- <dt>8.5.32. <a href="actions-file.html#SERVER-HEADER-FILTER">server-header-filter</a></dt>
- <dt>8.5.33. <a href="actions-file.html#SERVER-HEADER-TAGGER">server-header-tagger</a></dt>
- <dt>8.5.34. <a href="actions-file.html#SESSION-COOKIES-ONLY">session-cookies-only</a></dt>
- <dt>8.5.35. <a href="actions-file.html#SET-IMAGE-BLOCKER">set-image-blocker</a></dt>
- <dt>8.5.36. <a href="actions-file.html#SUMMARY">Summary</a></dt>
+ <dt>8.5.13. <a href="actions-file.html#DELAY-RESPONSE">delay-response</a></dt>
+ <dt>8.5.14. <a href="actions-file.html#DOWNGRADE-HTTP-VERSION">downgrade-http-version</a></dt>
+ <dt>8.5.15. <a href="actions-file.html#EXTERNAL-FILTER">external-filter</a></dt>
+ <dt>8.5.16. <a href="actions-file.html#FAST-REDIRECTS">fast-redirects</a></dt>
+ <dt>8.5.17. <a href="actions-file.html#FILTER">filter</a></dt>
+ <dt>8.5.18. <a href="actions-file.html#FORCE-TEXT-MODE">force-text-mode</a></dt>
+ <dt>8.5.19. <a href="actions-file.html#FORWARD-OVERRIDE">forward-override</a></dt>
+ <dt>8.5.20. <a href="actions-file.html#HANDLE-AS-EMPTY-DOCUMENT">handle-as-empty-document</a></dt>
+ <dt>8.5.21. <a href="actions-file.html#HANDLE-AS-IMAGE">handle-as-image</a></dt>
+ <dt>8.5.22. <a href="actions-file.html#HIDE-ACCEPT-LANGUAGE">hide-accept-language</a></dt>
+ <dt>8.5.23. <a href="actions-file.html#HIDE-CONTENT-DISPOSITION">hide-content-disposition</a></dt>
+ <dt>8.5.24. <a href="actions-file.html#HIDE-IF-MODIFIED-SINCE">hide-if-modified-since</a></dt>
+ <dt>8.5.25. <a href="actions-file.html#HIDE-FROM-HEADER">hide-from-header</a></dt>
+ <dt>8.5.26. <a href="actions-file.html#HIDE-REFERRER">hide-referrer</a></dt>
+ <dt>8.5.27. <a href="actions-file.html#HIDE-USER-AGENT">hide-user-agent</a></dt>
+ <dt>8.5.28. <a href="actions-file.html#LIMIT-CONNECT">limit-connect</a></dt>
+ <dt>8.5.29. <a href="actions-file.html#LIMIT-COOKIE-LIFETIME">limit-cookie-lifetime</a></dt>
+ <dt>8.5.30. <a href="actions-file.html#PREVENT-COMPRESSION">prevent-compression</a></dt>
+ <dt>8.5.31. <a href="actions-file.html#OVERWRITE-LAST-MODIFIED">overwrite-last-modified</a></dt>
+ <dt>8.5.32. <a href="actions-file.html#REDIRECT">redirect</a></dt>
+ <dt>8.5.33. <a href="actions-file.html#SERVER-HEADER-FILTER">server-header-filter</a></dt>
+ <dt>8.5.34. <a href="actions-file.html#SERVER-HEADER-TAGGER">server-header-tagger</a></dt>
+ <dt>8.5.35. <a href="actions-file.html#SESSION-COOKIES-ONLY">session-cookies-only</a></dt>
+ <dt>8.5.36. <a href="actions-file.html#SET-IMAGE-BLOCKER">set-image-blocker</a></dt>
+ <dt>8.5.37. <a href="actions-file.html#SUMMARY">Summary</a></dt>
</dl>
</dd>
<dt>8.6. <a href="actions-file.html#ALIASES">Aliases</a></dt>
}
+/*********************************************************************
+ *
+ * Function : write_socket_delayed
+ *
+ * Description : Write the contents of buf (for n bytes) to
+ * socket fd, optionally delaying the operation.
+ *
+ * Parameters :
+ * 1 : fd = File descriptor (aka. handle) of socket to write to.
+ * 2 : buf = Pointer to data to be written.
+ * 3 : len = Length of data to be written to the socket "fd".
+ * 4 : delay = Delay in milliseconds.
+ *
+ * Returns : 0 on success (entire buffer sent).
+ * nonzero on error.
+ *
+ *********************************************************************/
+int write_socket_delayed(jb_socket fd, const char *buf, size_t len, unsigned int delay)
+{
+ size_t i = 0;
+
+ if (delay == 0)
+ {
+ return write_socket(fd, buf, len);
+ }
+
+ while (i < len)
+ {
+ size_t write_length;
+ enum {MAX_WRITE_LENGTH = 10};
+
+ if ((i + MAX_WRITE_LENGTH) > len)
+ {
+ write_length = len - i;
+ }
+ else
+ {
+ write_length = MAX_WRITE_LENGTH;
+ }
+
+ privoxy_millisleep(delay);
+
+ if (write_socket(fd, buf + i, write_length) != 0)
+ {
+ return 1;
+ }
+ i += write_length;
+ }
+
+ return 0;
+
+}
+
+
/*********************************************************************
*
* Function : read_socket
extern jb_socket connect_to(const char *host, int portnum, struct client_state *csp);
extern int write_socket(jb_socket fd, const char *buf, size_t n);
+extern int write_socket_delayed(jb_socket fd, const char *buf, size_t len, unsigned int delay);
extern int read_socket(jb_socket fd, char *buf, int n);
extern int data_is_available(jb_socket fd, int seconds_to_wait);
extern void close_socket(jb_socket fd);
* Purpose : Main file. Contains main() method, main loop, and
* the main connection-handling function.
*
- * Copyright : Written by and Copyright (C) 2001-2017 the
+ * Copyright : Written by and Copyright (C) 2001-2018 the
* Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
#endif
+/*********************************************************************
+ *
+ * Function : get_write_delay
+ *
+ * Description : Parse the delay-response parameter.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : Number of milliseconds to delay writes.
+ *
+ *********************************************************************/
+static unsigned int get_write_delay(const struct client_state *csp)
+{
+ unsigned int delay;
+ char *endptr;
+ char *newval;
+
+ if ((csp->action->flags & ACTION_DELAY_RESPONSE) == 0)
+ {
+ return 0;
+ }
+ newval = csp->action->string[ACTION_STRING_DELAY_RESPONSE];
+
+ delay = (unsigned)strtol(newval, &endptr, 0);
+ if (*endptr != '\0')
+ {
+ log_error(LOG_LEVEL_FATAL,
+ "Invalid delay-response{} parameter: '%s'", newval);
+ }
+
+ return delay;
+
+}
+
+
/*********************************************************************
*
* Function : client_protocol_is_unsupported
log_error(LOG_LEVEL_CLF,
"%s - - [%T] \"%s\" 400 0", csp->ip_addr_str, req);
freez(req);
- write_socket(csp->cfd, response, strlen(response));
+ write_socket_delayed(csp->cfd, response, strlen(response),
+ get_write_delay(csp));
return TRUE;
}
csp->ip_addr_str);
log_error(LOG_LEVEL_CLF,
"%s - - [%T] \"%s\" 417 0", csp->ip_addr_str, csp->http->cmd);
- write_socket(csp->cfd, UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE,
- strlen(UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE));
+ write_socket_delayed(csp->cfd,
+ UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE,
+ strlen(UNSUPPORTED_CLIENT_EXPECTATION_ERROR_RESPONSE),
+ get_write_delay(csp));
return TRUE;
}
log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
csp->ip_addr_str, csp->http->cmd);
- write_socket(csp->cfd, CHEADER, strlen(CHEADER));
+ write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER),
+ get_write_delay(csp));
destroy_list(headers);
return JB_ERR_PARSE;
csp->ip_addr_str, csp->http->cmd, req);
freez(req);
- write_socket(csp->cfd, MISSING_DESTINATION_RESPONSE, strlen(MISSING_DESTINATION_RESPONSE));
+ write_socket_delayed(csp->cfd, MISSING_DESTINATION_RESPONSE,
+ strlen(MISSING_DESTINATION_RESPONSE), get_write_delay(csp));
destroy_list(headers);
return JB_ERR_PARSE;
csp->ip_addr_str, http->ocmd, status_code, rsp->content_length);
/* Write the answer to the client */
- if (write_socket(csp->cfd, rsp->head, rsp->head_length)
- || write_socket(csp->cfd, rsp->body, rsp->content_length))
+ if (write_socket_delayed(csp->cfd, rsp->head, rsp->head_length, get_write_delay(csp))
+ || write_socket_delayed(csp->cfd, rsp->body, rsp->content_length, get_write_delay(csp)))
{
/* There is nothing we can do about it. */
- log_error(LOG_LEVEL_ERROR,
- "Couldn't deliver the error message through client socket %d: %E",
- csp->cfd);
+ log_error(LOG_LEVEL_CONNECT,
+ "Couldn't deliver the error message for %s through client socket %d: %E",
+ http->url, csp->cfd);
}
/* Clean up and return */
log_error(LOG_LEVEL_CONNECT,
"No request line on socket %d received in time. Timeout: %d.",
csp->cfd, csp->config->socket_timeout);
- write_socket(csp->cfd, CLIENT_CONNECTION_TIMEOUT_RESPONSE,
- strlen(CLIENT_CONNECTION_TIMEOUT_RESPONSE));
+ write_socket_delayed(csp->cfd, CLIENT_CONNECTION_TIMEOUT_RESPONSE,
+ strlen(CLIENT_CONNECTION_TIMEOUT_RESPONSE),
+ get_write_delay(csp));
}
else
{
}
if (status != CHUNK_STATUS_BODY_COMPLETE)
{
- write_socket(csp->cfd, CLIENT_BODY_PARSE_ERROR_RESPONSE,
- strlen(CLIENT_BODY_PARSE_ERROR_RESPONSE));
+ write_socket_delayed(csp->cfd, CLIENT_BODY_PARSE_ERROR_RESPONSE,
+ strlen(CLIENT_BODY_PARSE_ERROR_RESPONSE), get_write_delay(csp));
log_error(LOG_LEVEL_CLF,
"%s - - [%T] \"Failed reading chunked client body\" 400 0", csp->ip_addr_str);
return JB_ERR_PARSE;
freez(req);
if (JB_ERR_OK != err)
{
- write_socket(csp->cfd, CHEADER, strlen(CHEADER));
+ write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER),
+ get_write_delay(csp));
/* XXX: Use correct size */
log_error(LOG_LEVEL_CLF, "%s - - [%T] \"Invalid request\" 400 0", csp->ip_addr_str);
log_error(LOG_LEVEL_ERROR,
csp->ip_addr_str);
log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 400 0",
csp->ip_addr_str, csp->http->cmd);
- write_socket(csp->cfd, CHEADER, strlen(CHEADER));
+ write_socket_delayed(csp->cfd, CHEADER, strlen(CHEADER), get_write_delay(csp));
return JB_ERR_PARSE;
}
csp->flags |= CSP_FLAG_CLIENT_HEADER_PARSING_DONE;
/*
* A header filter broke the request line - bail out.
*/
- write_socket(csp->cfd, MESSED_UP_REQUEST_RESPONSE, strlen(MESSED_UP_REQUEST_RESPONSE));
+ write_socket_delayed(csp->cfd, MESSED_UP_REQUEST_RESPONSE,
+ strlen(MESSED_UP_REQUEST_RESPONSE), get_write_delay(csp));
/* XXX: Use correct size */
log_error(LOG_LEVEL_CLF,
"%s - - [%T] \"Invalid request generated\" 500 0", csp->ip_addr_str);
csp->http->hostport);
}
else if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
- && (flush_socket(csp->server_connection.sfd, csp->client_iob) < 0))
+ && (flush_iob(csp->server_connection.sfd, csp->client_iob, 0) < 0))
{
write_failure = 1;
log_error(LOG_LEVEL_CONNECT, "Failed sending request body to: %s: %E",
struct http_request *http;
long len = 0; /* for buffer sizes (and negative error codes) */
int buffer_and_filter_content = 0;
+ unsigned int write_delay;
/* Skeleton for HTTP response, if we should intercept the request */
struct http_response *rsp;
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
watch_client_socket = 0 == (csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING);
#endif
+ write_delay = get_write_delay(csp);
for (;;)
{
log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header");
}
- if (write_socket(csp->cfd, hdr, strlen(hdr))
- || write_socket(csp->cfd,
- ((p != NULL) ? p : csp->iob->cur), (size_t)csp->content_length))
+ if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay)
+ || write_socket_delayed(csp->cfd,
+ ((p != NULL) ? p : csp->iob->cur),
+ (size_t)csp->content_length, write_delay))
{
log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E");
freez(hdr);
}
hdrlen = strlen(hdr);
- if (write_socket(csp->cfd, hdr, hdrlen)
- || ((flushed = flush_socket(csp->cfd, csp->iob)) < 0)
- || (write_socket(csp->cfd, csp->receive_buffer, (size_t)len)))
+ if (write_socket_delayed(csp->cfd, hdr, hdrlen, write_delay)
+ || ((flushed = flush_iob(csp->cfd, csp->iob, write_delay) < 0)
+ || (write_socket_delayed(csp->cfd, csp->receive_buffer,
+ (size_t)len, write_delay))))
{
log_error(LOG_LEVEL_CONNECT,
"Flush header and buffers to client failed: %E");
}
else
{
- if (write_socket(csp->cfd, csp->receive_buffer, (size_t)len))
+ if (write_socket_delayed(csp->cfd, csp->receive_buffer,
+ (size_t)len, write_delay))
{
log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
mark_server_socket_tainted(csp);
"Applying the MS IIS5 hack didn't help.");
log_error(LOG_LEVEL_CLF,
"%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
- write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
- strlen(INVALID_SERVER_HEADERS_RESPONSE));
+ write_socket_delayed(csp->cfd,
+ INVALID_SERVER_HEADERS_RESPONSE,
+ strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
mark_server_socket_tainted(csp);
return;
}
csp->headers->first->str);
log_error(LOG_LEVEL_CLF,
"%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
- write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
- strlen(INVALID_SERVER_HEADERS_RESPONSE));
+ write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
+ strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
free_http_request(http);
mark_server_socket_tainted(csp);
return;
{
log_error(LOG_LEVEL_CLF,
"%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
- write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
- strlen(INVALID_SERVER_HEADERS_RESPONSE));
+ write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
+ strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
free_http_request(http);
mark_server_socket_tainted(csp);
return;
* may be in the buffer)
*/
- if (write_socket(csp->cfd, hdr, strlen(hdr))
- || ((len = flush_socket(csp->cfd, csp->iob)) < 0))
+ if (write_socket_delayed(csp->cfd, hdr, strlen(hdr), write_delay)
+ || ((len = flush_iob(csp->cfd, csp->iob, write_delay)) < 0))
{
log_error(LOG_LEVEL_CONNECT, "write header to client failed: %E");
"Applying the MS IIS5 hack didn't help.");
log_error(LOG_LEVEL_CLF,
"%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
- write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
- strlen(INVALID_SERVER_HEADERS_RESPONSE));
+ write_socket_delayed(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
+ strlen(INVALID_SERVER_HEADERS_RESPONSE), write_delay);
mark_server_socket_tainted(csp);
return;
}
* message to the client, flush the rest, and get out of the way.
*/
list_remove_all(csp->headers);
- if (write_socket(csp->cfd, CSUCCEED, strlen(CSUCCEED)))
+ if (write_socket_delayed(csp->cfd, CSUCCEED,
+ strlen(CSUCCEED), get_write_delay(csp)))
{
return;
}
log_error(LOG_LEVEL_CONNECT,
"Rejecting connection from %s. Maximum number of connections reached.",
csp->ip_addr_str);
- write_socket(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
- strlen(TOO_MANY_CONNECTIONS_RESPONSE));
+ write_socket_delayed(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
+ strlen(TOO_MANY_CONNECTIONS_RESPONSE), get_write_delay(csp));
close_socket(csp->cfd);
freez(csp->ip_addr_str);
freez(csp->listen_addr_str);
log_error(LOG_LEVEL_ERROR,
"Unable to take any additional connections: %E. Active threads: %d",
active_threads);
- write_socket(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
- strlen(TOO_MANY_CONNECTIONS_RESPONSE));
+ write_socket_delayed(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
+ strlen(TOO_MANY_CONNECTIONS_RESPONSE), get_write_delay(csp));
close_socket(csp->cfd);
csp->flags &= ~CSP_FLAG_ACTIVE;
}
* to deserve their own file but don't really fit in
* any other file.
*
- * Copyright : Written by and Copyright (C) 2001-2016 the
+ * Copyright : Written by and Copyright (C) 2001-2018 the
* Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
#endif /* ndef HAVE_STRLCAT */
+/*********************************************************************
+ *
+ * Function : privoxy_millisleep
+ *
+ * Description : Sleep a number of milliseconds
+ *
+ * Parameters :
+ * 1 : delay: Number of milliseconds to sleep
+ *
+ * Returns : -1 on error, 0 otherwise
+ *
+ *********************************************************************/
+int privoxy_millisleep(unsigned milliseconds)
+{
+#ifdef HAVE_NANOSLEEP
+ struct timespec rqtp = {0};
+ struct timespec rmtp = {0};
+
+ rqtp.tv_sec = milliseconds / 1000;
+ rqtp.tv_nsec = (milliseconds % 1000) * 1000 * 1000;
+
+ return nanosleep(&rqtp, &rmtp);
+#elif defined (_WIN32)
+ Sleep(milliseconds);
+
+ return 0;
+#elif defined(__OS2__)
+ DosSleep(milliseconds * 10);
+
+ return 0;
+#else
+#warning Missing privoxy_milisleep() implementation. delay-response{} will not work.
+
+ return -1;
+#endif /* def HAVE_NANOSLEEP */
+
+}
+
+
#if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
/*********************************************************************
*
#define strlcat privoxy_strlcat
#endif /* ndef HAVE_STRLCAT */
+extern int privoxy_millisleep(unsigned milliseconds);
+
#if defined(__cplusplus)
}
#endif
/*********************************************************************
*
- * Function : flush_socket
+ * Function : flush_iob
*
* Description : Write any pending "buffered" content.
*
* Parameters :
* 1 : fd = file descriptor of the socket to read
* 2 : iob = The I/O buffer to flush, usually csp->iob.
+ * 3 : delay = Number of milliseconds to delay the writes
*
* Returns : On success, the number of bytes written are returned (zero
* indicates nothing was written). On error, -1 is returned,
* file, the results are not portable.
*
*********************************************************************/
-long flush_socket(jb_socket fd, struct iob *iob)
+long flush_iob(jb_socket fd, struct iob *iob, unsigned int delay)
{
long len = iob->eod - iob->cur;
return(0);
}
- if (write_socket(fd, iob->cur, (size_t)len))
+ if (write_socket_delayed(fd, iob->cur, (size_t)len, delay))
{
return(-1);
}
#define FILTER_CLIENT_HEADERS 0
#define FILTER_SERVER_HEADERS 1
-extern long flush_socket(jb_socket fd, struct iob *iob);
+extern long flush_iob(jb_socket fd, struct iob *iob, unsigned int delay);
extern jb_err add_to_iob(struct iob *iob, const size_t buffer_limit, char *src, long n);
extern void clear_iob(struct iob *iob);
extern jb_err decompress_iob(struct client_state *csp);
#define ACTION_HIDE_ACCEPT_LANGUAGE 0x04000000UL
/** Action bitmap: Limit the cookie lifetime */
#define ACTION_LIMIT_COOKIE_LIFETIME 0x08000000UL
+/** Action bitmap: Delay writes */
+#define ACTION_DELAY_RESPONSE 0x10000000UL
/** Action string index: How to deanimate GIFs */
#define ACTION_STRING_CHANGE_X_FORWARDED_FOR 17
/** Action string index: how many minutes cookies should be valid. */
#define ACTION_STRING_LIMIT_COOKIE_LIFETIME 18
+/** Action string index: how many milliseconds writes should be delayed. */
+#define ACTION_STRING_DELAY_RESPONSE 19
/** Number of string actions. */
-#define ACTION_STRING_COUNT 19
+#define ACTION_STRING_COUNT 20
/* To make the ugly hack in sed easier to understand */
id="deanimate_last" @deanimate-gifs-param-last@><label
for="deanimate_last">last frame</label></td>
</tr>
+ <tr class="bg1" align="left" valign="top">
+ <td class="en1" align="center" valign="middle"><input type="radio"
+ name="delay_response" value="Y" @delay-response-y@
+ ></td>
+ <td class="dis1" align="center" valign="middle"><input type="radio"
+ name="delay_response" value="N" @delay-response-n@
+ ></td>
+ <td class="noc1" align="center" valign="middle"><input type="radio"
+ name="delay_response" value="X" @delay-response-x@
+ ></td>
+ <td class="action"><a href="@user-manual@@actions-help-prefix@DELAY-RESPONSE">delay-response</a></td>
+ <td>Send the response in ca. 10 byte chunks and delay each chunk.</td>
+ </tr>
+ <tr class="bg1" align="left" valign="top" id="delay-response_opts">
+ <td class="en1"> </td>
+ <td class="dis1"> </td>
+ <td class="noc1"> </td>
+ <td> </td>
+ <td>Number of milliseconds to delay chunks:<br>
+ <input type="text" name="delay_response_mode" size="40" value="@delay-response-param@">
+ </td>
+ </tr>
<tr class="bg1" align="left" valign="top">
<td class="en1" align="center" valign="middle"><input type="radio"
name="downgrade_http_version" value="Y" @downgrade-http-version-y@></td>