Merge branch 'master' of ssh://git.privoxy.org:23/git/privoxy
authorLee <ler762@users.sourceforge.net>
Mon, 15 Jun 2020 02:07:34 +0000 (22:07 -0400)
committerLee <ler762@users.sourceforge.net>
Mon, 15 Jun 2020 02:07:34 +0000 (22:07 -0400)
18 files changed:
GNUmakefile.in
cgi.c
default.action.master
doc/source/faq.sgml
doc/webserver/faq/configuration.html
doc/webserver/faq/copyright.html
doc/webserver/faq/general.html
doc/webserver/faq/index.html
doc/webserver/faq/misc.html
errlog.c
jcc.c
miscutil.c
miscutil.h
parsers.c
regression-tests.action
ssl.c
tools/privoxy-log-parser.pl
tools/privoxy-regression-test.pl

index f5ca9da..92ef0a1 100644 (file)
@@ -736,6 +736,7 @@ ssplit.@OBJEXT@:    ssplit.c    ssplit.h    config.h miscutil.h
 urlmatch.@OBJEXT@:  urlmatch.c  urlmatch.h  config.h $(PROJECT_H_DEPS) errlog.h miscutil.h ssplit.h
 client-tags.@OBJEXT@: client-tags.c client-tags.h config.h $(PROJECT_H_DEPS) errlog.h miscutil.h ssplit.h
 fuzz.@OBJEXT@: fuzz.c config.h $(PROJECT_H_DEPS) errlog.h miscutil.h ssplit.h
+ssl.@OBJEXT@: ssl.c ssl.h config.h $(PROJECT_H_DEPS) encode.h errlog.h jcc.h miscutil.h
 
 # GNU regex
 gnu_regex.@OBJEXT@: gnu_regex.c gnu_regex.h config.h
diff --git a/cgi.c b/cgi.c
index 580e2bf..15ef256 100644 (file)
--- a/cgi.c
+++ b/cgi.c
@@ -1515,13 +1515,15 @@ static void get_locale_time(char *buf, size_t buffer_size)
 #elif defined(MUTEX_LOCKS_AVAILABLE)
    privoxy_mutex_lock(&localtime_mutex);
    timeptr = localtime(&current_time);
-   privoxy_mutex_unlock(&localtime_mutex);
 #else
    timeptr = localtime(&current_time);
 #endif
 
    strftime(buf, buffer_size, "%a %b %d %X %Z %Y", timeptr);
 
+#if !defined(HAVE_LOCALTIME_R) && defined(MUTEX_LOCKS_AVAILABLE)
+   privoxy_mutex_unlock(&localtime_mutex);
+#endif
 }
 
 
index 64396a4..99eb553 100644 (file)
@@ -961,6 +961,9 @@ stats./.*\.gif\?
 go.idmnet.bbelements.com/please/showit/
 # Blocked URL = http://gm-link.com/tm_image.asp?c=12345&x=0&u=email@address.tld&orc.gif
 gm-link.com/
+# Blocked URL = https://collector.githubapp.com/github/page_view?dimensions[page]=https%3A%2F%2Fgithub.com%2Fopenbsd%2Fsrc%2Fblob%2F5ecdd0566b441ae0b99e73f410875e05dc0fa5b7%2Flib%2Flibc%2Finclude%2Fthread_private.h&dimensions[title]=src%2Fthread_private.h%20at%205ecdd0566b441ae0b99e73f410875e05dc0fa5b7%20%C2%B7%20openbsd%2Fsrc%20%C2%B7%20GitHub&dimensions[referrer]=https%3A%2F%2Fgithub.com%2Fopenbsd%2Fsrc%2Fsearch%3Fq%3D_MUTEX_LOCK%26unscoped_q%3D_MUTEX_LOCK&dimensions[user_agent]=Mozilla%2F5.0%20(X11%3B%20ElectroBSD%20amd64%3B%20rv%3A68.0)%20Gecko%2F20100101%20Firefox%2F68.0&dimensions[screen_resolution]=1366x768&dimensions[pixel_ratio]=1&dimensions[browser_resolution]=1362x636&dimensions[tz_seconds]=7200&dimensions[timestamp]=1591515169218&dimensions[referrer]=&dimensions[request_id]=22CA%3AE6F6%3A271ED2A%3A3839C5D%3A5EDB8295&dimensions[visitor_id]=5184934927058829974&dimensions[region_edge]=ams&dimensions[region_render]=ams&dimensions[user_id]=929183&dimensions[user_login]=openbsd&dimensions[repository_id]=66966208&dimensions[repository_nwo]=openbsd%2Fsrc&dimensions[repository_public]=true&dimensions[repository_is_fork]=false&dimensions[repository_network_root_id]=66966208&dimensions[repository_network_root_nwo]=openbsd%2Fsrc&dimensions[repository_explore_github_marketplace_ci_cta_shown]=false&&measures[performance_timing]=1-172-172-13996-12735-12426-12394-3858-172-172-172--13996-0---172-3853-3412-0--&&&dimensions[cid]=268614077.1591515169
+collector.githubapp.com/
+
 
 #############################################################################
 # Site-specific block patterns;
@@ -2161,6 +2164,8 @@ disqus.com/
 oss-fuzz.com/
 # URL = https://sourcepoint.vice.com/mms/choice_select?choice_id=523912&requestUUID=a98ca09e-5c1f-4aa4-b28e-ab5b26150859-1591162630861&href=https%3A%2F%2Fwww.vice.com%2Fen_us%2Farticle%2F7kpb9a%2Fhow-to-protest-racist-violence-instead-of-posting-blackout-tuesday-square
 sourcepoint.vice.com/
+# URL = https://collector.githubapp.com/github/page_view?dimensions[page]=https%3A%2F%2Fgithub.com%2Fopenbsd%2Fsrc%2Fblob%2F5ecdd0566b441ae0b99e73f410875e05dc0fa5b7%2Flib%2Flibc%2Finclude%2Fthread_private.h&dimensions[title]=src%2Fthread_private.h%20at%205ecdd0566b441ae0b99e73f410875e05dc0fa5b7%20%C2%B7%20openbsd%2Fsrc%20%C2%B7%20GitHub&dimensions[referrer]=https%3A%2F%2Fgithub.com%2Fopenbsd%2Fsrc%2Fsearch%3Fq%3D_MUTEX_LOCK%26unscoped_q%3D_MUTEX_LOCK&dimensions[user_agent]=Mozilla%2F5.0%20(X11%3B%20ElectroBSD%20amd64%3B%20rv%3A68.0)%20Gecko%2F20100101%20Firefox%2F68.0&dimensions[screen_resolution]=1366x768&dimensions[pixel_ratio]=1&dimensions[browser_resolution]=1362x636&dimensions[tz_seconds]=7200&dimensions[timestamp]=1591515169218&dimensions[referrer]=&dimensions[request_id]=22CA%3AE6F6%3A271ED2A%3A3839C5D%3A5EDB8295&dimensions[visitor_id]=5184934927058829974&dimensions[region_edge]=ams&dimensions[region_render]=ams&dimensions[user_id]=929183&dimensions[user_login]=openbsd&dimensions[repository_id]=66966208&dimensions[repository_nwo]=openbsd%2Fsrc&dimensions[repository_public]=true&dimensions[repository_is_fork]=false&dimensions[repository_network_root_id]=66966208&dimensions[repository_network_root_nwo]=openbsd%2Fsrc&dimensions[repository_explore_github_marketplace_ci_cta_shown]=false&&measures[performance_timing]=1-172-172-13996-12735-12426-12394-3858-172-172-172--13996-0---172-3853-3412-0--&&&dimensions[cid]=268614077.1591515169
+collector.githubapp.com/
 
 {+redirect{s@.*url=@http://@} -block}
 # Sticky Actions = +redirect -block
index 9de4fde..14a4d6e 100644 (file)
@@ -25,7 +25,7 @@
 
  Purpose     :  FAQ
 
- Copyright (C) 2001-2018 Privoxy Developers https://www.privoxy.org/
+ Copyright (C) 2001-2020 Privoxy Developers https://www.privoxy.org/
  See LICENSE.
 
  Based partially on the Internet Junkbuster FAQ originally written by and
@@ -69,7 +69,7 @@
  <subscript>
 <!-- Completely the wrong markup, but very little is allowed  -->
 <!-- in this part of an article. FIXME -->
- <link linkend="copyright">Copyright</link> &my-copy; 2001-2018 by
+ <link linkend="copyright">Copyright</link> &my-copy; 2001-2020 by
  <ulink url="https://www.privoxy.org/">Privoxy Developers</ulink>
  </subscript>
 </pubdate>
@@ -115,10 +115,6 @@ Hal.
  <ulink url="https://www.privoxy.org/">Privoxy</ulink>.
  It is not a substitute for the
  <ulink url="../user-manual/index.html"><citetitle>Privoxy User Manual</citetitle></ulink>.
-<!--
- This works, at least in some situations:
- Test: <ulink url="privoxy-user-manual.pdf"><citetitle>User Manual</citetitle></ulink>.
--->
  </para>
 
 <!-- Include privoxy.sgml boilerplate: -->
@@ -551,7 +547,7 @@ warranty? Registration?</title>
 </para>
 <variablelist>
  <varlistentry>
-  <term>Gold (10000 EUR/year)</term>
+  <term>Gold (12000 USD/year)</term>
   <listitem>
    <para>
     Logo shown at the bottom of the
@@ -562,7 +558,7 @@ warranty? Registration?</title>
   </listitem>
  </varlistentry>
  <varlistentry>
-  <term>Silver (1000 EUR/year)</term>
+  <term>Silver (1200 USD/year)</term>
   <listitem>
    <para>
     Logo shown randomly at the bottom of the
@@ -573,7 +569,7 @@ warranty? Registration?</title>
   </listitem>
  </varlistentry>
  <varlistentry>
-  <term>Bronze (500 EUR/year)</term>
+  <term>Bronze (600 USD/year)</term>
   <listitem>
    <para>
     Logo and link on the <ulink url="https://www.privoxy.org/sponsors/">sponsor page</ulink>.
@@ -1341,7 +1337,8 @@ and thus avoid individual browser configuration?</title>
  amount of guesswork. It is not realistic to catch all of these short of
  disabling Javascript, which would break many sites. And lastly, if the
  cookies are embedded in a HTTPS/SSL secure session via Javascript, they are beyond
- <application>Privoxy's</application> reach.
+ <application>Privoxy's</application> reach unless you enable
+ <ulink url="../user-manual/actions-file.html#HTTPS-INSPECTION">https-inspection</ulink>.
 </para>
 <para>
  All in all, &my-app; can help manage cookies in general, can help minimize
@@ -1996,9 +1993,17 @@ ads used to be. Why?</title>
 <sect2 renderas="sect3" id="ssl">
 <title>How can Privoxy filter Secure (HTTPS) URLs?</title>
 <para>
- Since secure HTTP connections are encrypted SSL sessions between your browser
- and the secure site, and are meant to be reliably <emphasis>secure</emphasis>,
- there is little that <application>Privoxy</application> can do but hand the raw
+ If you enable
+ <ulink url="../user-manual/actions-file.html#HTTPS-INSPECTION">https-inspection</ulink>
+ <application>Privoxy</application> will impersonate the destination
+ server and can thus filter encrypted requests and responses as well.
+</para>
+<para>
+ Without
+ <ulink url="../user-manual/actions-file.html#HTTPS-INSPECTION">https-inspection</ulink>
+ secure HTTP connections are encrypted SSL sessions between your
+ browser and the secure site, and there is little
+ that <application>Privoxy</application> can do but hand the raw
  gibberish data though from one end to the other unprocessed.
 </para>
 <para>
@@ -2034,8 +2039,9 @@ ads used to be. Why?</title>
   for HTTPS.
 </para>
 <para>
-  Adding HTTP/2 support is on the TODO list but currently
-  nobody is known to work on it.
+  Adding HTTP/2 support is on the
+  <ulink url="https://www.privoxy.org/gitweb/?p=privoxy.git;a=blob_plain;f=TODO;hb=HEAD">TODO</ulink>
+  list but currently nobody is known to work on it.
 </para>
 </sect2>
 
index 76ce468..9c30195 100644 (file)
       trickier because the syntax can vary widely, and thus requires a certain amount of guesswork. It is not realistic
       to catch all of these short of disabling Javascript, which would break many sites. And lastly, if the cookies are
       embedded in a HTTPS/SSL secure session via Javascript, they are beyond <span class="APPLICATION">Privoxy's</span>
-      reach.</p>
+      reach unless you enable <a href="../user-manual/actions-file.html#HTTPS-INSPECTION" target=
+      "_top">https-inspection</a>.</p>
       <p>All in all, <span class="APPLICATION">Privoxy</span> can help manage cookies in general, can help minimize the
       loss of privacy posed by cookies, but can't realistically stop all cookies.</p>
     </div>
index 1a0a7d6..262accb 100644 (file)
@@ -33,7 +33,7 @@
     "APPLICATION">Junkbuster</span> (tm) FAQ, and modified as appropriate for <span class=
     "APPLICATION">Privoxy</span>.</p>
     <div class="SECT2">
-      <h2 class="SECT2"><a name="AEN1499" id="AEN1499">7.1. License</a></h2>
+      <h2 class="SECT2"><a name="AEN1504" id="AEN1504">7.1. License</a></h2>
       <p><span class="APPLICATION">Privoxy</span> is free software; you can redistribute it and/or modify it under the
       terms of the <i class="CITETITLE">GNU General Public License</i>, version 2, as published by the Free Software
       Foundation.</p>
@@ -43,7 +43,7 @@
       "CITETITLE">license</i></a> for details.</p>
     </div>
     <div class="SECT2">
-      <h2 class="SECT2"><a name="AEN1508" id="AEN1508">7.2. History</a></h2>
+      <h2 class="SECT2"><a name="AEN1513" id="AEN1513">7.2. History</a></h2>
       <p>A long time ago, there was the <span class="APPLICATION">Internet Junkbuster</span>, by Anonymous Coders and
       Junkbusters Corporation. This saved many users a lot of pain in the early days of web advertising and user
       tracking.</p>
index 5659c95..93ce92f 100644 (file)
       <p>We are currently offering the following sponsor levels as an experiment:</p>
       <div class="VARIABLELIST">
         <dl>
-          <dt>Gold (10000 EUR/year)</dt>
+          <dt>Gold (12000 USD/year)</dt>
           <dd>
             <p>Logo shown at the bottom of the <a href="https://www.privoxy.org/" target="_top">Privoxy homepage</a>.
             Logo, link and self description on the <a href="https://www.privoxy.org/sponsors/" target="_top">sponsor
             page</a>.</p>
           </dd>
-          <dt>Silver (1000 EUR/year)</dt>
+          <dt>Silver (1200 USD/year)</dt>
           <dd>
             <p>Logo shown randomly at the bottom of the <a href="https://www.privoxy.org/" target="_top">Privoxy
             homepage</a>. Logo, link and self description on the <a href="https://www.privoxy.org/sponsors/" target=
             "_top">sponsor page</a>.</p>
           </dd>
-          <dt>Bronze (500 EUR/year)</dt>
+          <dt>Bronze (600 USD/year)</dt>
           <dd>
             <p>Logo and link on the <a href="https://www.privoxy.org/sponsors/" target="_top">sponsor page</a>.</p>
           </dd>
index 07a7967..878eb93 100644 (file)
@@ -12,7 +12,7 @@
   <div class="ARTICLE">
     <div class="TITLEPAGE">
       <h1 class="TITLE"><a name="AEN2" id="AEN2">Privoxy Frequently Asked Questions</a></h1>
-      <p class="PUBDATE"><sub><a href="copyright.html">Copyright</a> &copy; 2001-2018 by <a href=
+      <p class="PUBDATE"><sub><a href="copyright.html">Copyright</a> &copy; 2001-2020 by <a href=
       "https://www.privoxy.org/" target="_top">Privoxy Developers</a></sub><br></p>
       <div>
         <div class="ABSTRACT">
         <dt>7. <a href="copyright.html">Privoxy Copyright, License and History</a></dt>
         <dd>
           <dl>
-            <dt>7.1. <a href="copyright.html#AEN1499">License</a></dt>
-            <dt>7.2. <a href="copyright.html#AEN1508">History</a></dt>
+            <dt>7.1. <a href="copyright.html#AEN1504">License</a></dt>
+            <dt>7.2. <a href="copyright.html#AEN1513">History</a></dt>
           </dl>
         </dd>
       </dl>
index b57d029..12a4549 100644 (file)
     </div>
     <div class="SECT2">
       <h3 class="SECT2"><a name="SSL" id="SSL">4.15. How can Privoxy filter Secure (HTTPS) URLs?</a></h3>
-      <p>Since secure HTTP connections are encrypted SSL sessions between your browser and the secure site, and are
-      meant to be reliably <span class="emphasis"><i class="EMPHASIS">secure</i></span>, there is little that
+      <p>If you enable <a href="../user-manual/actions-file.html#HTTPS-INSPECTION" target="_top">https-inspection</a>
+      <span class="APPLICATION">Privoxy</span> will impersonate the destination server and can thus filter encrypted
+      requests and responses as well.</p>
+      <p>Without <a href="../user-manual/actions-file.html#HTTPS-INSPECTION" target="_top">https-inspection</a> secure
+      HTTP connections are encrypted SSL sessions between your browser and the secure site, and there is little that
       <span class="APPLICATION">Privoxy</span> can do but hand the raw gibberish data though from one end to the other
       unprocessed.</p>
       <p>The only exception to this is blocking by host patterns, as the client needs to tell <span class=
       <h3 class="SECT2"><a name="HTTP2" id="HTTP2">4.16. Does Privoxy support HTTP/2?</a></h3>
       <p>Privoxy currently doesn't parse HTTP/2 but applications can tunnel HTTP/2 through Privoxy if Privoxy is
       configured to allow CONNECT requests (default) which are also used for HTTPS.</p>
-      <p>Adding HTTP/2 support is on the TODO list but currently nobody is known to work on it.</p>
+      <p>Adding HTTP/2 support is on the <a href=
+      "https://www.privoxy.org/gitweb/?p=privoxy.git;a=blob_plain;f=TODO;hb=HEAD" target="_top">TODO</a> list but
+      currently nobody is known to work on it.</p>
     </div>
     <div class="SECT2">
       <h3 class="SECT2"><a name="SECURE" id="SECURE">4.17. Privoxy runs as a <span class="QUOTE">"server"</span>. How
index 05a2c82..7cc4e20 100644 (file)
--- a/errlog.c
+++ b/errlog.c
@@ -533,21 +533,12 @@ static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size)
    int tz_length = 0;
 
    time (&now);
-#ifdef HAVE_GMTIME_R
-   gmt = *gmtime_r(&now, &gmt);
-#elif defined(MUTEX_LOCKS_AVAILABLE)
-   privoxy_mutex_lock(&gmtime_mutex);
-   gmt = *gmtime(&now);
-   privoxy_mutex_unlock(&gmtime_mutex);
-#else
-   gmt = *gmtime(&now);
-#endif
+   gmt = *privoxy_gmtime_r(&now, &gmt);
 #ifdef HAVE_LOCALTIME_R
    tm_now = localtime_r(&now, &dummy);
 #elif defined(MUTEX_LOCKS_AVAILABLE)
    privoxy_mutex_lock(&localtime_mutex);
    tm_now = localtime(&now);
-   privoxy_mutex_unlock(&localtime_mutex);
 #else
    tm_now = localtime(&now);
 #endif
@@ -556,6 +547,9 @@ static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size)
    mins = hrs * 60 + tm_now->tm_min - gmt.tm_min;
 
    length = strftime(buffer, buffer_size, "%d/%b/%Y:%H:%M:%S ", tm_now);
+#if !defined(HAVE_LOCALTIME_R) && defined(MUTEX_LOCKS_AVAILABLE)
+   privoxy_mutex_unlock(&localtime_mutex);
+#endif
 
    if (length > (size_t)0)
    {
diff --git a/jcc.c b/jcc.c
index 0654f80..6d91bd0 100644 (file)
--- a/jcc.c
+++ b/jcc.c
@@ -3553,17 +3553,6 @@ static void chat(struct client_state *csp)
    {
       return;
    }
-#ifdef FEATURE_HTTPS_INSPECTION
-   /*
-    * Log the request unless we're https inspecting
-    * in which case we don't have the path yet and
-    * will log the request later.
-    */
-   if (!client_use_ssl(csp))
-#endif
-   {
-      log_error(LOG_LEVEL_REQUEST, "%s%s", http->hostport, http->path);
-   }
 
    /* decide how to route the HTTP request */
    fwd = forward_url(csp, http);
@@ -3648,6 +3637,18 @@ static void chat(struct client_state *csp)
    }
 #endif
 
+#ifdef FEATURE_HTTPS_INSPECTION
+   /*
+    * Log the request unless we're https inspecting
+    * in which case we don't have the path yet and
+    * will log the request later.
+    */
+   if (!client_use_ssl(csp))
+#endif
+   {
+      log_error(LOG_LEVEL_REQUEST, "%s%s", http->hostport, http->path);
+   }
+
    if (http->ssl && connect_port_is_forbidden(csp))
    {
       const char *acceptable_connect_ports =
@@ -4240,7 +4241,7 @@ static void serve(struct client_state *csp)
          {
             log_error(LOG_LEVEL_CONNECT,
                "Closing server socket %d connected to %s. "
-               "Keep-alive %u. Tainted: %u. Socket alive %u. Timeout: %u.",
+               "Keep-alive: %u. Tainted: %u. Socket alive: %u. Timeout: %u.",
                csp->server_connection.sfd, csp->server_connection.host,
                0 != (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE),
                0 != (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED),
index 9af7bed..488a774 100644 (file)
@@ -7,7 +7,7 @@
  *                to deserve their own file but don't really fit in
  *                any other file.
  *
- * Copyright   :  Written by and Copyright (C) 2001-2018 the
+ * Copyright   :  Written by and Copyright (C) 2001-2020 the
  *                Privoxy team. https://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
@@ -61,6 +61,7 @@
 
 #include "project.h"
 #include "miscutil.h"
+#include "jcc.h"
 #include "errlog.h"
 
 /*********************************************************************
@@ -218,18 +219,18 @@ void *malloc_or_die(size_t buffer_size)
  *                Exits if the file can't be opened
  *
  * Parameters  :
- *          1  :  pidfile = Path of the pidfile that gets created.
+ *          1  :  pid_file = Path of the pid file that gets created.
  *
  * Returns     :  N/A
  *
  *********************************************************************/
-void write_pid_file(const char *pidfile)
+void write_pid_file(const char *pid_file)
 {
    FILE   *fp;
 
-   if ((fp = fopen(pidfile, "w")) == NULL)
+   if ((fp = fopen(pid_file, "w")) == NULL)
    {
-      log_error(LOG_LEVEL_FATAL, "can't open pidfile '%s': %E", pidfile);
+      log_error(LOG_LEVEL_FATAL, "can't open pid file '%s': %E", pid_file);
    }
    else
    {
@@ -854,6 +855,53 @@ int privoxy_millisleep(unsigned milliseconds)
 }
 
 
+/*********************************************************************
+ *
+ * Function    :  privoxy_gmtime_r
+ *
+ * Description :  Behave like gmtime_r() and convert a
+ *                time_t to a struct tm.
+ *
+ * Parameters  :
+ *          1  :  time_spec: The time to convert
+ *          2  :  result: The struct tm to use as storage
+ *
+ * Returns     :  Pointer to the result or NULL on error.
+ *
+ *********************************************************************/
+struct tm *privoxy_gmtime_r(const time_t *time_spec, struct tm *result)
+{
+   struct tm *timeptr;
+
+#ifdef HAVE_GMTIME_R
+   timeptr = gmtime_r(time_spec, result);
+#elif defined(MUTEX_LOCKS_AVAILABLE)
+   privoxy_mutex_lock(&gmtime_mutex);
+   timeptr = gmtime(time_spec);
+#else
+#warning Using unlocked gmtime()
+   timeptr = gmtime(time_spec);
+#endif
+
+   if (timeptr == NULL)
+   {
+#if !defined(HAVE_GMTIME_R) && defined(MUTEX_LOCKS_AVAILABLE)
+      privoxy_mutex_unlock(&gmtime_mutex);
+#endif
+      return NULL;
+   }
+
+#if !defined(HAVE_GMTIME_R)
+   *result = *timeptr;
+   timeptr = result;
+#ifdef MUTEX_LOCKS_AVAILABLE
+   privoxy_mutex_unlock(&gmtime_mutex);
+#endif
+#endif
+
+   return timeptr;
+}
+
 #if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
 /*********************************************************************
  *
index 4add05d..4f81299 100644 (file)
@@ -50,7 +50,7 @@ extern char *strdup_or_die(const char *str);
 extern void *malloc_or_die(size_t buffer_size);
 
 #if defined(unix)
-extern void write_pid_file(const char *pidfile);
+extern void write_pid_file(const char *pid_file);
 #endif /* unix */
 
 extern unsigned int hash_string(const char* s);
@@ -92,6 +92,7 @@ size_t privoxy_strlcat(char *destination, const char *source, size_t size);
 #endif /* ndef HAVE_STRLCAT */
 
 extern int privoxy_millisleep(unsigned milliseconds);
+extern struct tm *privoxy_gmtime_r(const time_t *time_spec, struct tm *result);
 
 #if defined(__cplusplus)
 }
index 37a647c..15abc40 100644 (file)
--- a/parsers.c
+++ b/parsers.c
@@ -2748,9 +2748,8 @@ static jb_err server_last_modified(struct client_state *csp, char **header)
          time_t now;
          struct tm *timeptr = NULL;
          long int rtime;
-#ifdef HAVE_GMTIME_R
          struct tm gmt;
-#endif
+
          now = time(NULL);
          rtime = (long int)difftime(now, last_modified);
          if (rtime)
@@ -2769,15 +2768,7 @@ static jb_err server_last_modified(struct client_state *csp, char **header)
                rtime *= -1;
             }
             last_modified += rtime;
-#ifdef HAVE_GMTIME_R
-            timeptr = gmtime_r(&last_modified, &gmt);
-#elif defined(MUTEX_LOCKS_AVAILABLE)
-            privoxy_mutex_lock(&gmtime_mutex);
-            timeptr = gmtime(&last_modified);
-            privoxy_mutex_unlock(&gmtime_mutex);
-#else
-            timeptr = gmtime(&last_modified);
-#endif
+            timeptr = privoxy_gmtime_r(&last_modified, &gmt);
             if ((NULL == timeptr) || !strftime(newheader,
                   sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr))
             {
@@ -2787,7 +2778,6 @@ static jb_err server_last_modified(struct client_state *csp, char **header)
                freez(*header);
                return JB_ERR_OK;
             }
-
             freez(*header);
             *header = strdup("Last-Modified: ");
             string_append(header, newheader);
@@ -3413,9 +3403,7 @@ static jb_err client_host(struct client_state *csp, char **header)
 static jb_err client_if_modified_since(struct client_state *csp, char **header)
 {
    char newheader[50];
-#ifdef HAVE_GMTIME_R
    struct tm gmt;
-#endif
    struct tm *timeptr = NULL;
    time_t tm = 0;
    const char *newval;
@@ -3473,15 +3461,7 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header)
                   *header);
             }
             tm += rtime * (negative_range ? -1 : 1);
-#ifdef HAVE_GMTIME_R
-            timeptr = gmtime_r(&tm, &gmt);
-#elif defined(MUTEX_LOCKS_AVAILABLE)
-            privoxy_mutex_lock(&gmtime_mutex);
-            timeptr = gmtime(&tm);
-            privoxy_mutex_unlock(&gmtime_mutex);
-#else
-            timeptr = gmtime(&tm);
-#endif
+            timeptr = privoxy_gmtime_r(&tm, &gmt);
             if ((NULL == timeptr) || !strftime(newheader,
                   sizeof(newheader), "%a, %d %b %Y %H:%M:%S GMT", timeptr))
             {
@@ -3491,7 +3471,6 @@ static jb_err client_if_modified_since(struct client_state *csp, char **header)
                freez(*header);
                return JB_ERR_OK;
             }
-
             freez(*header);
             *header = strdup("If-Modified-Since: ");
             string_append(header, newheader);
@@ -4032,18 +4011,9 @@ static void add_cookie_expiry_date(char **cookie, time_t lifetime)
    char tmp[50];
    struct tm *timeptr = NULL;
    time_t expiry_date = time(NULL) + lifetime;
-#ifdef HAVE_GMTIME_R
    struct tm gmt;
 
-   timeptr = gmtime_r(&expiry_date, &gmt);
-#elif defined(MUTEX_LOCKS_AVAILABLE)
-   privoxy_mutex_lock(&gmtime_mutex);
-   timeptr = gmtime(&expiry_date);
-   privoxy_mutex_unlock(&gmtime_mutex);
-#else
-   timeptr = gmtime(&expiry_date);
-#endif
-
+   timeptr = privoxy_gmtime_r(&expiry_date, &gmt);
    if (NULL == timeptr)
    {
       log_error(LOG_LEVEL_FATAL,
@@ -4386,9 +4356,10 @@ static jb_err parse_header_time(const char *header_time, time_t *result)
          {
             char recreated_date[100];
             struct tm *tm;
+            struct tm storage;
             time_t result2;
 
-            tm = gmtime(result);
+            tm = privoxy_gmtime_r(result, &storage);
             if (!strftime(recreated_date, sizeof(recreated_date),
                time_formats[i], tm))
             {
index a1bc8e3..9393a0f 100644 (file)
@@ -210,6 +210,28 @@ TAG:^add-header\{X-Custom-Header: yes, please\}$
 # Expect Header = Referer: http://config.privoxy.org/foo/baaz.html
 TAG:^client-header-filter\{hide-tor-exit-notation\}$
 
+#######################################################
+# Test client-header-filter{no-brotli-accepted}.
+#######################################################
+
+{+client-header-filter{no-brotli-accepted}}
+# Set Header    = Accept-Encoding: gzip, deflate, br
+# Expect Header = Accept-Encoding: gzip, deflate
+#
+# Set Header    = Accept-Encoding: gzip, br, deflate
+# Expect Header = Accept-Encoding: gzip, deflate
+#
+# Set Header    = Accept-Encoding: br, gzip, deflate
+# Expect Header = Accept-Encoding: gzip, deflate
+#
+# Set Header    = Accept-Encoding: br
+# Expect Header = Accept-Encoding:
+#
+# Set Header    = Accept-Encoding: gzip, deflate
+# Expect Header = NO CHANGE
+#
+TAG:^client-header-filter\{no-brotli-accepted\}$
+
 #######################################################
 # Test crunch-client-header{}.
 #######################################################
diff --git a/ssl.c b/ssl.c
index 852a9ce..313174f 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -1337,17 +1337,16 @@ static int generate_certificate_valid_date(time_t time_spec, char *buffer,
                                            size_t buffer_size)
 {
    struct tm valid_date;
+   struct tm *timeptr;
    size_t ret;
 
-#ifndef HAVE_GMTIME_R
-#error HTTP inspection currently requires gmtime_r() which seems to be missing
-#endif
-   if (NULL == gmtime_r(&time_spec, &valid_date))
+   timeptr = privoxy_gmtime_r(&time_spec, &valid_date);
+   if (NULL == timeptr)
    {
       return 1;
    }
 
-   ret = strftime(buffer, buffer_size, "%Y%m%d%H%M%S", &valid_date);
+   ret = strftime(buffer, buffer_size, "%Y%m%d%H%M%S", timeptr);
    if (ret != 14)
    {
       return 1;
index dc8eea1..0963993 100755 (executable)
@@ -1061,7 +1061,7 @@ sub handle_loglevel_re_filter($) {
                 return '';
         }
 
-        $c =~ s@(?<=\(size )(\d+)\)(?= with)@$h{'Number'}$1$h{'Standard'}@;
+        $c =~ s@(?<=\(size )(\d+)@$h{'Number'}$1$h{'Standard'}@;
         $c =~ s@(?<=\(new size )(\d+)@$h{'Number'}$1$h{'Standard'}@;
         $c =~ s@(?<=produced )(\d+)(?= hits)@$h{'Number'}$1$h{'Standard'}@;
 
@@ -1759,6 +1759,11 @@ sub handle_loglevel_connect($) {
         # Forwarded the last 1954 bytes
         $c =~ s@(?<=the last )(\d+)@$h{'Number'}$1$h{'Standard'}@;
 
+    } elsif ($c =~ m/^Waiting for the next client connection. Currently active threads:/) {
+
+        # Waiting for the next client connection. Currently active threads: 30
+        $c =~ s@(?<=threads: )(\d+)@$h{'Number'}$1$h{'Standard'}@;
+
     } elsif ($c =~ m/^Looks like we / or
              $c =~ m/^Unsetting keep-alive flag/ or
              $c =~ m/^No connections to wait/ or
@@ -2012,14 +2017,19 @@ sub gather_loglevel_clf_stats($) {
     our %cli_options;
 
     # +0200] "GET https://www.youtube.com/watch?v=JmcA9LIIXWw HTTP/1.1" 200 68004
-    $content =~ m/^[+-]\d{4}\] "(\w+) (.+) (HTTP\/\d\.\d)" (\d+) (\d+)/;
+    # +0200] "VERSION-CONTROL http://p.p/ HTTP/1.1" 200 2787
+    $content =~ m/^[+-]\d{4}\] "([^ ]+) (.+) (HTTP\/\d\.\d)" (\d+) (\d+)/;
     $method       = $1;
     $resource     = $2;
     $http_version = $3;
     $status_code  = $4;
     $size         = $5;
 
+    $stats{requests_clf}++;
+
     unless (defined $method) {
+        # +0200] "Invalid request" 400 0
+        return if ($content =~ m/^[+-]\d{4}\] "Invalid request"/);
         print("Failed to parse: $content\n");
         return;
     }
@@ -2030,12 +2040,11 @@ sub gather_loglevel_clf_stats($) {
     $stats{'http-version'}{$http_version}++;
 
     if ($cli_options{'host-statistics-threshold'} != 0) {
-        $resource =~ m@(?:http[s]://)([^/]+)/?@;
+        $resource =~ m@(?:https?://)?([^/]+)/?@;
         $stats{'hosts'}{$1}++;
     }
     $stats{'content-size-total'} += $size;
     $stats{'status-code'}{$status_code}++;
-    $stats{requests_clf}++;
 }
 
 sub gather_loglevel_request_stats($$) {
index f93ffb5..c00ea3c 100755 (executable)
@@ -17,7 +17,7 @@
 # - Document magic Expect Header values
 # - Internal fuzz support?
 #
-# Copyright (c) 2007-2016 Fabian Keil <fk@fabiankeil.de>
+# Copyright (c) 2007-2020 Fabian Keil <fk@fabiankeil.de>
 #
 # Permission to use, copy, modify, and distribute this software for any
 # purpose with or without fee is hereby granted, provided that the above
@@ -38,7 +38,7 @@ use strict;
 use Getopt::Long;
 
 use constant {
-    PRT_VERSION => 'Privoxy-Regression-Test 0.7',
+    PRT_VERSION => 'Privoxy-Regression-Test 0.7.1',
  
     CURL => 'curl',
 
@@ -83,7 +83,7 @@ use constant {
     REDIRECT_TEST       =>108,
 };
 
-sub init_our_variables () {
+sub init_our_variables() {
 
     our $leading_log_time = LEADING_LOG_TIME;
     our $leading_log_date = LEADING_LOG_DATE;
@@ -91,7 +91,7 @@ sub init_our_variables () {
     our $log_level = get_default_log_level();
 }
 
-sub get_default_log_level () {
+sub get_default_log_level() {
     
     my $log_level = 0;
 
@@ -113,7 +113,7 @@ sub get_default_log_level () {
 #
 ############################################################################
 
-sub parse_tag ($) {
+sub parse_tag($) {
 
     my $tag = shift;
 
@@ -129,10 +129,10 @@ sub parse_tag ($) {
     return $tag;
 }
 
-sub check_for_forbidden_characters ($) {
+sub check_for_forbidden_characters($) {
 
     my $string = shift;
-    my $allowed = '[-=\dA-Za-z~{}:./();\t ,+@"_%?&*^]';
+    my $allowed = '[-=\dA-Za-z~{}\[\]:./();\t ,+@"_%?&*^]';
 
     unless ($string =~ m/^$allowed*$/o) {
         my $forbidden = $string;
@@ -152,7 +152,7 @@ sub load_regression_tests() {
 
 # XXX: Contains a lot of code duplicated from load_action_files()
 #      that should be factored out.
-sub load_regression_tests_from_file ($) {
+sub load_regression_tests_from_file($) {
     my $action_file = shift;
 
     # initialized here
@@ -274,7 +274,7 @@ sub load_regression_tests_from_file ($) {
                 l(LL_FILE_LOADING, "Sticky actions: " . $sticky_actions);
                 $regression_tests[$si][$ri]{'sticky-actions'} = $sticky_actions;
             } else {
-                log_and_die("Sticky URL without Sticky Actions: $value");
+                log_and_die("Sticky URL without Sticky Actions in $action_file: $value");
             }
 
         } else {
@@ -297,7 +297,7 @@ sub load_regression_tests_from_file ($) {
 }
 
 
-sub load_regression_tests_through_privoxy () {
+sub load_regression_tests_through_privoxy() {
 
     our $privoxy_cgi_url;
     our @privoxy_config;
@@ -350,7 +350,7 @@ sub load_regression_tests_through_privoxy () {
     load_action_files(\@actionfiles);
 }
 
-sub token_starts_new_test ($) {
+sub token_starts_new_test($) {
 
     my $token = shift;
     my @new_test_directives = ('set header', 'fetch test',
@@ -364,7 +364,7 @@ sub token_starts_new_test ($) {
     return 0;
 }
 
-sub tokenize ($) {
+sub tokenize($) {
 
     my ($token, $value) = (undef, undef);
 
@@ -396,7 +396,7 @@ sub tokenize ($) {
     return ($token, $value);
 }
 
-sub enlist_new_test ($$$$$$) {
+sub enlist_new_test($$$$$$) {
 
     my ($regression_tests, $token, $value, $si, $ri, $number) = @_;
     my $type;
@@ -504,7 +504,7 @@ sub mark_matching_tests_for_skipping($) {
 
 # XXX: Shares a lot of code with load_regression_tests_from_file()
 #      that should be factored out.
-sub load_action_files ($) {
+sub load_action_files($) {
 
     # initialized here
     our %actions;
@@ -654,7 +654,7 @@ sub load_action_files ($) {
                     l(LL_FILE_LOADING, "Sticky actions: " . $sticky_actions);
                     $regression_tests[$si][$ri]{'sticky-actions'} = $sticky_actions;
                 } else {
-                    log_and_die("Sticky URL without Sticky Actions: $value");
+                    log_and_die("Sticky URL without Sticky Actions in $actionfile: $value");
                 }
 
             } else {
@@ -683,7 +683,7 @@ sub load_action_files ($) {
 ############################################################################
 
 # Fisher Yates shuffle from Perl's "How do I shuffle an array randomly?" FAQ
-sub fisher_yates_shuffle ($) {
+sub fisher_yates_shuffle($) {
     my $deck = shift;
     my $i = @$deck;
     while ($i--) {
@@ -692,7 +692,7 @@ sub fisher_yates_shuffle ($) {
     }
 }
 
-sub execute_regression_tests () {
+sub execute_regression_tests() {
 
     our @regression_tests;
     my $loops = get_cli_option('loops');
@@ -781,7 +781,7 @@ sub execute_regression_tests () {
     }
 }
 
-sub get_skip_reason ($) {
+sub get_skip_reason($) {
     my $test = shift;
     my $skip_reason = undef;
 
@@ -802,7 +802,7 @@ sub get_skip_reason ($) {
     return $skip_reason;
 }
 
-sub level_is_unacceptable ($) {
+sub level_is_unacceptable($) {
     my $level = shift;
     my $min_level = get_cli_option('min-level');
     my $max_level = get_cli_option('max-level');
@@ -831,7 +831,7 @@ sub level_is_unacceptable ($) {
     return $reason;
 }
 
-sub dependency_unsatisfied ($) {
+sub dependency_unsatisfied($) {
 
     my $level = shift;
     our %dependencies;
@@ -872,7 +872,7 @@ sub dependency_unsatisfied ($) {
     return $dependency_problem;
 }
 
-sub register_dependency ($$) {
+sub register_dependency($$) {
 
     my $level = shift;
     my $dependency = shift;
@@ -892,7 +892,7 @@ sub register_dependency ($$) {
     }
 }
 
-sub execute_method_test ($) {
+sub execute_method_test($) {
 
     my $test = shift;
     my $buffer_ref;
@@ -914,7 +914,7 @@ sub execute_method_test ($) {
     return check_status_code_result($status_code, $expected_status_code);
 }
 
-sub execute_redirect_test ($) {
+sub execute_redirect_test($) {
 
     my $test = shift;
     my $buffer_ref;
@@ -959,7 +959,7 @@ sub execute_redirect_test ($) {
     return $success;
 }
 
-sub execute_dumb_fetch_test ($) {
+sub execute_dumb_fetch_test($) {
 
     my $test = shift;
     my $buffer_ref;
@@ -983,7 +983,7 @@ sub execute_dumb_fetch_test ($) {
     return check_status_code_result($status_code, $expected_status_code);
 }
 
-sub execute_block_test ($) {
+sub execute_block_test($) {
 
     my $test = shift;
     my $url = $test->{'data'};
@@ -992,7 +992,7 @@ sub execute_block_test ($) {
     return defined $final_results->{'+block'};
 }
 
-sub execute_sticky_actions_test ($) {
+sub execute_sticky_actions_test($) {
 
     my $test = shift;
     my $url = $test->{'data'};
@@ -1023,7 +1023,7 @@ sub execute_sticky_actions_test ($) {
     return $verified_actions == @sticky_actions;
 }
 
-sub get_final_results ($) {
+sub get_final_results($) {
 
     my $url = shift;
     my $curl_parameters = '';
@@ -1068,7 +1068,7 @@ sub get_final_results ($) {
     return \%final_results;
 }
 
-sub check_status_code_result ($$) {
+sub check_status_code_result($$) {
 
     my $status_code = shift;
     my $expected_status_code = shift;
@@ -1100,7 +1100,7 @@ sub check_status_code_result ($$) {
     return $result;
 }
 
-sub execute_client_header_regression_test ($) {
+sub execute_client_header_regression_test($) {
 
     my $test = shift;
     my $buffer_ref;
@@ -1113,7 +1113,7 @@ sub execute_client_header_regression_test ($) {
     return check_header_result($test, $header);
 }
 
-sub execute_server_header_regression_test ($) {
+sub execute_server_header_regression_test($) {
 
     my $test = shift;
     my $buffer_ref;
@@ -1126,12 +1126,12 @@ sub execute_server_header_regression_test ($) {
     return check_header_result($test, $header);
 }
 
-sub interpret_result ($) {
+sub interpret_result($) {
     my $success = shift;
     return $success ? "Success" : "Failure";
 }
 
-sub check_header_result ($$) {
+sub check_header_result($$) {
 
     my $test = shift;
     my $header = shift;
@@ -1183,7 +1183,7 @@ sub check_header_result ($$) {
     return $success;
 }
 
-sub get_header_name ($) {
+sub get_header_name($) {
 
     my $header = shift;
 
@@ -1192,7 +1192,7 @@ sub get_header_name ($) {
     return $header;
 }
 
-sub get_header ($$) {
+sub get_header($$) {
 
     our $filtered_request = '';
 
@@ -1252,7 +1252,7 @@ sub get_header ($$) {
     return $header;
 }
 
-sub get_server_header ($$) {
+sub get_server_header($$) {
 
     my $buffer_ref = shift;
     my $test = shift;
@@ -1290,7 +1290,7 @@ sub get_server_header ($$) {
     return $header;
 }
 
-sub get_status_code ($) {
+sub get_status_code($) {
 
     my $buffer_ref = shift;
     my @buffer = @{$buffer_ref}; 
@@ -1310,12 +1310,12 @@ sub get_status_code ($) {
     }
 }
 
-sub get_test_keys () {
+sub get_test_keys() {
     return ('tag', 'data', 'expect-header', 'ignore');
 }
 
 # XXX: incomplete
-sub test_content_as_string ($) {
+sub test_content_as_string($) {
 
     my $test = shift;
 
@@ -1356,7 +1356,7 @@ sub fuzz_header($) {
 #
 ############################################################################
 
-sub get_cgi_page_or_else ($) {
+sub get_cgi_page_or_else($) {
 
     my $cgi_url = shift;
     my $content_ref = get_page_with_curl($cgi_url);
@@ -1383,7 +1383,7 @@ sub get_cgi_page_or_else ($) {
 }
 
 # XXX: misleading name
-sub get_show_request_with_curl ($) {
+sub get_show_request_with_curl($) {
 
     our $privoxy_cgi_url;
     my $test = shift;
@@ -1407,7 +1407,7 @@ sub get_show_request_with_curl ($) {
     return get_cgi_page_or_else($curl_parameters);
 }
 
-sub get_head_with_curl ($) {
+sub get_head_with_curl($) {
 
     our $fellatio_url = FELLATIO_URL;
     my $test = shift;
@@ -1426,7 +1426,7 @@ sub get_head_with_curl ($) {
     return get_page_with_curl($curl_parameters);
 }
 
-sub get_page_with_curl ($) {
+sub get_page_with_curl($) {
 
     our $proxy;
 
@@ -1452,6 +1452,8 @@ sub get_page_with_curl ($) {
     $curl_line .= " --user-agent '" . PRT_VERSION . "' ";
     # We aren't too patient
     $curl_line .= " --max-time '" . get_cli_option('max-time') . "' ";
+    # We don't want curl to treat "[]", "{}" etc. special
+    $curl_line .= " --globoff ";
 
     $curl_line .= $parameters;
     # XXX: still necessary?
@@ -1485,7 +1487,7 @@ sub get_page_with_curl ($) {
 #
 ############################################################################
 
-sub array_as_string ($) {
+sub array_as_string($) {
     my $array_ref = shift;
     my $string = '';
 
@@ -1496,13 +1498,13 @@ sub array_as_string ($) {
     return $string;
 }
 
-sub show_test ($) {
+sub show_test($) {
     my $test = shift;
     log_message('Test is:' . test_content_as_string($test));
 }
 
 # Conditional log
-sub l ($$) {
+sub l($$) {
     our $log_level;
     my $this_level = shift;
     my $message = shift;
@@ -1510,14 +1512,14 @@ sub l ($$) {
     log_message($message) if ($log_level & $this_level);
 }
 
-sub log_and_die ($) {
+sub log_and_die($) {
     my $message = shift;
 
     log_message('Oh noes. ' . $message . ' Fatal error. Exiting.');
     exit;
 }
 
-sub log_message ($) {
+sub log_message($) {
 
     my $message = shift;
 
@@ -1548,7 +1550,7 @@ sub log_message ($) {
     printf("%s\n", $message);
 }
 
-sub log_result ($$) {
+sub log_result($$) {
 
     our $filtered_request;
 
@@ -1630,16 +1632,16 @@ sub log_result ($$) {
     log_message($message) if (!$result or cli_option_is_set('verbose'));
 }
 
-sub quote ($) {
+sub quote($) {
     my $s = shift;
     return '\'' . $s . '\'';
 }
 
-sub print_version () {
+sub print_version() {
     printf PRT_VERSION . "\n";
 }
 
-sub list_test_types () {
+sub list_test_types() {
     my %test_types = (
         'Client header test'  => CLIENT_HEADER_TEST,
         'Server header test'  =>  2,
@@ -1657,7 +1659,7 @@ sub list_test_types () {
     }
 }
 
-sub help () {
+sub help() {
 
     our %cli_options;
 
@@ -1700,7 +1702,7 @@ Try "perldoc $0" for more information
     exit(0);
 }
 
-sub init_cli_options () {
+sub init_cli_options() {
 
     our %cli_options;
     our $log_level;
@@ -1715,7 +1717,7 @@ sub init_cli_options () {
     $cli_options{'retries'}   = CLI_RETRIES;
 }
 
-sub parse_cli_options () {
+sub parse_cli_options() {
 
     our %cli_options;
     our $log_level;
@@ -1747,7 +1749,7 @@ sub parse_cli_options () {
     $log_level |= $cli_options{'debug'};
 }
 
-sub cli_option_is_set ($) {
+sub cli_option_is_set($) {
 
     our %cli_options;
     my $cli_option = shift;
@@ -1755,7 +1757,7 @@ sub cli_option_is_set ($) {
     return defined $cli_options{$cli_option};
 }
 
-sub get_cli_option ($) {
+sub get_cli_option($) {
 
     our %cli_options;
     my $cli_option = shift;
@@ -1796,7 +1798,7 @@ sub start_forks($) {
     }
 }
 
-sub main () {
+sub main() {
 
     init_our_variables();
     parse_cli_options();