// Rewrite Apache logs that have incorrect dates
1
2
3
4
5
6
7
8
9
10 use strict;
11 use warnings;
12
13
14 our ($VERSION) = '$Revision$' =~ m{ \$Revision: \s+ (\S+) }xms;
15
16
17 use HTTP::Date;
18
19 my @DAYS = qw(Sun Mon Tue Wed Thu Fri Sat);
20 my @MONTHS = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
21
22 my $wrong_datetime = shift @ARGV;
23 my $right_datetime = shift @ARGV;
24
25 my ($timezone) = $right_datetime =~ m/ ([+-]\d\d\d\d)\z/xms;
26
27 my $seconds_diff = str2time($right_datetime) - str2time($wrong_datetime);
28
29 foreach my $file (@ARGV) {
30 print "Rewriting $file\n";
31 open my $IN, '<', $file
32 or die "Can't open $file: $!\n";
33 open my $OUT, '>', "$file.rewritten"
34 or die "Can't write to $file.rewritten: $!\n";
35 while (<$IN>) {
36 if (m{
37 \A
38 (.+\s+)
39 \[
40 (
41 \d\d/\w\w\w/\d\d\d\d
42 :\d\d:\d\d:\d\d
43 \s
44 [\+\-]\d\d\d\d
45 )
46 \]
47 (\s+.+)
48 \z
49 }xms) {
50 print {$OUT}
51 $1, q{[},
52 rewrite_access_datetime($2, $seconds_diff, $timezone),
53 q{]}, $3;
54 }
55 elsif (m{
56 \A
57 \[
58 (
59 \w\w\w \s \w\w\w \s \d\d \s
60 \d\d:\d\d:\d\d \s
61 \d\d\d\d
62 )
63 \]
64 (\s+.+)
65 \z
66 }xms) {
67 print {$OUT}
68 q{[},
69 rewrite_error_datetime($1, $seconds_diff),
70 q{]}, $2;
71 }
72 else {
73 print {$OUT} $_;
74 }
75 }
76 }
77
78 sub rewrite_access_datetime {
79 my ($datetime, $seconds_diff, $timezone) = @_;
80
81 my ($sign, $hours, $minutes) = $timezone =~ m/\A([+-])(\d\d)(\d\d)\z/xms;
82 my $seconds_offset = ($hours * 60 + $minutes) * 60;
83
84 $datetime = str2time($datetime) + $seconds_diff;
85 if ($sign eq q{+}) {
86 $datetime = $datetime + $seconds_offset;
87 }
88 elsif ($sign eq q{-}) {
89 $datetime = $datetime - $seconds_offset;
90 }
91
92 my ($sec, $min, $hour, $mday, $mon, $year) = gmtime $datetime;
93 return sprintf '%02d/%s/%04d:%02d:%02d:%02d %s',
94 $mday, $MONTHS[$mon], $year + 1900, $hour, $min, $sec, $timezone;
95 }
96
97 sub rewrite_error_datetime {
98 my ($datetime, $seconds_diff) = @_;
99
100 $datetime = str2time($datetime) + $seconds_diff;
101
102 my ($sec, $min, $hour, $mday, $mon, $year, $wday) = gmtime $datetime;
103 return sprintf '%s %s %02d %02d:%02d:%02d %04d',
104 $DAYS[$wday], $MONTHS[$mon], $mday, $hour, $min, $sec, $year + 1900;
105 }