- Check header names for valid characters before
[privoxy.git] / tools / privoxy-log-parser.pl
index aa70abb..d666b75 100755 (executable)
@@ -8,7 +8,7 @@
 #
 # http://www.fabiankeil.de/sourcecode/privoxy-log-parser/
 #
-# $Id: privoxy-log-parser.pl,v 1.119 2008/11/03 16:30:50 fk Exp $
+# $Id: privoxy-log-parser.pl,v 1.134 2009/01/10 16:31:22 fk Exp $
 #
 # TODO:
 #       - LOG_LEVEL_CGI, LOG_LEVEL_ERROR, LOG_LEVEL_WRITE content highlighting
@@ -106,6 +106,7 @@ sub prepare_our_stuff () {
         CGI             => 'light_green',
         Redirect        => 'cyan',
         Error           => 'light_red',
+        Crunch          => 'cyan',
         'Fatal error'   => 'light_red',
         'Gif-Deanimate' => 'blue',
         Force           => 'red',
@@ -265,7 +266,6 @@ sub paint_it ($) {
     return $colour_code;
 }
 
-
 sub get_semantic_html_markup ($) {
 ###############################################################
 # Takes a string and returns a span element
@@ -438,7 +438,6 @@ sub print_outro () {
     }
 }
 
-
 sub get_line_end () {
 
     my $line_end = "\n";
@@ -467,7 +466,6 @@ sub get_colour_html_markup ($) {
     return $code;
 }
 
-
 sub default_colours () {
     # XXX: Properly
     our $bg_code;
@@ -752,7 +750,6 @@ sub highlight_matched_pattern ($$$) {
     return $result;
 }
 
-
 sub highlight_matched_path ($$) {
 
     my $result = shift; # XXX: Stupid name;
@@ -765,7 +762,6 @@ sub highlight_matched_path ($$) {
     return $result;
 }
 
-
 sub highlight_url ($) {
 
     my $url = shift;
@@ -803,7 +799,7 @@ sub handle_loglevel_header ($) {
     # scan: Accept: image/png,image/*;q=0.8,*/*;q=0.5
     if ($c =~ m/^scan: ((?>[^:]+)):/) {
         my $header = $1;
-        if (!defined($header_colours{$header})) {
+        if (!defined($header_colours{$header}) and $header =~ /^[\d\w-]*$/) {
             debug_message "Registering previously unknown header $1" if DEBUG_HEADER_REGISTERING;
 
             if (REGISTER_HEADERS_WITH_THE_SAME_COLOUR) {
@@ -914,6 +910,8 @@ sub handle_loglevel_header ($) {
           or $c =~ m/^Reducing white space in /
           or $c =~ m/^Ignoring single quote in /
           or $c =~ m/^Converting tab to space in /
+          or $c =~ m/A HTTP\/1\.1 response without/
+          or $c =~ m/Disabled filter mode on behalf of the client/
             )
     {
         # XXX: Some of these may need highlighting
@@ -950,6 +948,8 @@ sub handle_loglevel_header ($) {
         # Ignoring single quote in 'X-LWS-Test: "This  is  quoted" this is not "this  is  " but "  this again   is  not'
         # Converting tab to space in 'X-LWS-Test:   "This  is  quoted" this   is  not "this  is  "  but  "\
         #  this again   is  not'
+        # A HTTP/1.1 response without Connection header implies keep-alive.
+        # Disabled filter mode on behalf of the client.
 
     } elsif ($c =~ m/^scanning headers for:/) {
 
@@ -1181,7 +1181,6 @@ sub handle_loglevel_re_filter ($) {
     return $content;
 }
 
-
 sub handle_loglevel_redirect ($) {
 
     my $c = shift;
@@ -1290,7 +1289,6 @@ sub handle_loglevel_gif_deanimate ($) {
     return $content;
 }
 
-
 sub handle_loglevel_request ($) {
 
     my $content = shift;
@@ -1330,6 +1328,32 @@ sub handle_loglevel_request ($) {
     return $content;
 }
 
+sub handle_loglevel_crunch ($) {
+
+    my $content = shift;
+    our %h;
+    our %reason_colours;
+
+    # Blocked: ads.example.org/
+
+    # Highlight crunch reason
+    foreach my $reason (keys %reason_colours) {
+        $content =~ s@($reason)@$reason_colours{$reason}$1$h{'Standard'}@g;
+    }
+    # Highlight request URL
+    $content = highlight_matched_pattern($content, 'request_', '(?<= )[^ \[]*$');
+
+    if ($content =~ m/\[too long, truncated\]$/) {
+
+        # Blocked: config.privoxy.org/edit-actions-submit?f=3&v=1176116716&s=7&Submit=Submit\
+        #  [...]&filter... [too long, truncated]
+        $content = highlight_matched_pattern($content, 'request_', '^.*(?=\.\.\. \[too long, truncated\]$)');
+
+    }
+
+    return $content;
+}
+
 sub handle_loglevel_connect ($) {
 
     my $c = shift;
@@ -1337,14 +1361,14 @@ sub handle_loglevel_connect ($) {
     our %req;
     our %h;
 
-    if ($c =~ m/via [^\s]+ to: [^\s]+/) {
+    if ($c =~ m/^via [^\s]+ to: [^\s]+/) {
 
         # Connect: via 10.0.0.1:8123 to: www.example.org.noconnect
 
         $c = highlight_matched_host($c, '(?<=via )[^\s]+');
         $c = highlight_matched_host($c, '(?<=to: )[^\s]+');
 
-    } elsif ($c =~ m/connect to: .* failed: .*/) {
+    } elsif ($c =~ m/^connect to: .* failed: .*/) {
 
         # connect to: www.example.org.noconnect failed: Operation not permitted
 
@@ -1352,14 +1376,14 @@ sub handle_loglevel_connect ($) {
 
         $c =~ s@(?<=failed: )(.*)@$h{'error'}$1$h{'Standard'}@;
 
-    } elsif ($c =~ m/to ([^\s]*) successful$/) {
+    } elsif ($c =~ m/^to ([^\s]*) successful$/) {
 
         # Connect: to www.nzherald.co.nz successful
 
         return '' if SUPPRESS_SUCCESSFUL_CONNECTIONS;
         $c = highlight_matched_host($c, '(?<=to )[^\s]+');
 
-    } elsif ($c =~ m/to ([^\s]*)$/) {
+    } elsif ($c =~ m/^to ([^\s]*)$/) {
 
         # Connect: to lists.sourceforge.net:443
 
@@ -1419,7 +1443,13 @@ sub handle_loglevel_connect ($) {
     
         $c =~ s@(?<=socks5_connect: )(.*)@$h{'error'}$1$h{'Standard'}@;
 
-    } elsif ($c =~ m/^Found reusable socket/) {
+    } elsif ($c =~ m/^Created new connection to/) {
+
+        # Created new connection to www.privoxy.org:80 on socket 11.
+        $c = highlight_matched_host($c, '(?<=connection to )[^\s]+');
+        $c =~ s@(?<=on socket )(\d+)@$h{'Number'}$1$h{'Standard'}@;
+
+    } elsif ($c =~ m/^^Found reusable socket/) {
 
         # Found reusable socket 9 for www.privoxy.org:80 in slot 0.
         $c =~ s@(?<=Found reusable socket )(\d+)@$h{'Number'}$1$h{'Standard'}@;
@@ -1448,17 +1478,22 @@ sub handle_loglevel_connect ($) {
 
     } elsif ($c =~ m/^Socket/) {
 
-        # Socket 18 for www.privoxy.org:80 in slot 0 is no longer usable. Closing.
         # Socket 16 already forgotten or never remembered.
         $c =~ s@(?<=Socket )(\d+)@$h{'Number'}$1$h{'Standard'}@;
-        $c = highlight_matched_host($c, '(?<=for )[^\s]+');
-        $c =~ s@(?<=in slot )(\d+)@$h{'Number'}$1$h{'Standard'}@;
 
     } elsif ($c =~ m/^The connection to/) {
 
-        # The connection to www.privoxy.org:80 in slot 0 timed out. Closing.
+        # The connection to www.privoxy.org:80 in slot 6 timed out. Closing socket 19. Timeout is: 61.
+        # The connection to 10.0.0.1:80 in slot 0 is no longer usable. Closing socket 4.
         $c = highlight_matched_host($c, '(?<=connection to )[^\s]+');
         $c =~ s@(?<=in slot )(\d+)@$h{'Number'}$1$h{'Standard'}@;
+        $c =~ s@(?<=Closing socket )(\d+)@$h{'Number'}$1$h{'Standard'}@;
+        $c =~ s@(?<=Timeout is: )(\d+)@$h{'Number'}$1$h{'Standard'}@;
+
+    } elsif ($c =~ m/^Waiting for/) {
+
+        # Waiting for 1 connections to timeout.
+        $c =~ s@(?<=^Waiting for )(\d+)@$h{'Number'}$1$h{'Standard'}@;
 
     } elsif ($c =~ m/^Initialized/) {
 
@@ -1473,11 +1508,33 @@ sub handle_loglevel_connect ($) {
         $c =~ s@(?<=Actual content length: )(\d+)@$h{'Number'}$1$h{'Standard'}@;
         $c =~ s@(?<=received: )(\d+)@$h{'Number'}$1$h{'Standard'}@;
 
-    } elsif ($c =~ m/^Looks like we reached/ or
-             $c =~ m/^Unsetting keep-alive flag/) {
+    } elsif ($c =~ m/^Continuing buffering headers/) {
+
+        # Continuing buffering headers. byte_count: 19. header_offset: 517. len: 536.
+        $c =~ s@(?<=byte_count: )(\d+)@$h{'Number'}$1$h{'Standard'}@;
+        $c =~ s@(?<=header_offset: )(\d+)@$h{'Number'}$1$h{'Standard'}@;
+        $c =~ s@(?<=len: )(\d+)@$h{'Number'}$1$h{'Standard'}@;
+
+    } elsif ($c =~ m/^Received \d+ bytes while/) {
+
+        # Received 206 bytes while expecting 12103.
+        $c =~ s@(?<=Received )(\d+)@$h{'Number'}$1$h{'Standard'}@;
+        $c =~ s@(?<=expecting )(\d+)@$h{'Number'}$1$h{'Standard'}@;
+
+    } elsif ($c =~ m/^Connection from/) {
+
+        # Connection from 81.163.28.218 dropped due to ACL
+        $c =~ s@(?<=^Connection from )((?:\d+\.?){4})@$h{'Number'}$1$h{'Standard'}@;
+
+    } elsif ($c =~ m/^Looks like we rea/ or
+             $c =~ m/^Unsetting keep-alive flag/ or
+             $c =~ m/^No connections to wait/) {
 
         # Looks like we reached the end of the last chunk. We better stop reading.
+        # Looks like we read the end of the last chunk together with the server \
+        #  headers. We better stop reading.
         # Unsetting keep-alive flag.
+        # No connections to wait for left.
 
     } else {
 
@@ -1737,6 +1794,7 @@ sub parse_loop () {
         'Connect'       => \&handle_loglevel_connect,
         'Redirect'      => \&handle_loglevel_redirect,
         'Request'       => \&handle_loglevel_request,
+        'Crunch'        => \&handle_loglevel_crunch,
         'Gif-Deanimate' => \&handle_loglevel_gif_deanimate,
         'Info'          => \&handle_loglevel_info,
         'CGI'           => \&handle_loglevel_cgi,
@@ -1750,7 +1808,7 @@ sub parse_loop () {
  
         $output = '';
 
-        if (m/^(\w{3} \d{2}) (\d\d:\d\d:\d\d)\.?(\d+)? (?:Privoxy\(([^\)]*)\)) ([\w -]*): (.*)$/) {
+        if (m/^(\w{3} \d{2}) (\d\d:\d\d:\d\d)\.?(\d+)? (?:Privoxy\()?([^\)\s]*)[\)]? ([\w -]*): (.*)$/) {
             # XXX: Put in req hash?
             $day = $1;
             $time_stamp = $2;