First try to design a new interface for persistent data.
[onis.git] / onis
1 #!/usr/bin/perl
2 ##########################################################################
3 #    onis 0.7.2                                               2005-01-21 #
4 #---=============--------------------------------------------------------#
5 # Language: Perl                                                         #
6 # Purpose:  Generating statistics                                        #
7 # Input:    IRC-Logfiles                                                 #
8 # Output:   One HTML file                                                #
9 # Version:  0.7.2 (unstable)                                             #
10 # License:  GPL                                                          #
11 # Homepage: http://verplant.org/onis/                                    #
12 # Authors:  Florian octo Forster <octo@verplant.org>                     #
13 #           Contributions are listed in THANKS                           #
14 ##########################################################################
15
16 BEGIN
17 {
18         if ($0 =~ m#^(.*)[/\\]#) { chdir ($1); }
19
20         unshift (@INC, 'lib');
21
22         # 0x0010   Language (make not-translated lines red/yellow)
23         # 0x0020   Parser (dropped lines)
24         # 0x0040   Parser (time information)
25         # 0x0100   Data::Core (host unsharp)
26         # 0x0200   Data::Persistent
27         # 0x0400   Data::Core (dump incoming data to stderr)
28         # 0x0800   Data::Core (initializing)
29         # 0x1000   Onis::Users
30         $::DEBUG = 0x0000;
31 }
32
33 use strict;
34 use warnings;
35
36 use Onis::Config qw/get_config parse_argv read_config/;
37 use File::Basename qw/dirname/;
38 use Fcntl qw/:flock/;
39
40 use vars qw/$VERSION/;
41
42 $VERSION = '0.7.2';
43
44 our $FILEINFO;
45 our $PURGE_LOGS = 0;
46
47 print STDERR $/, __FILE__, ': $Id: onis,v 1.18 2005/01/21 18:59:59 octo Exp $' if ($::DEBUG);
48
49 parse_argv (@ARGV);
50 read_config (get_config ('config') ? get_config ('config') : 'config');
51 read_config (scalar get_config ('theme')) if (get_config ('theme'));
52
53 my $output = get_config ('output');
54 if (!$output)
55 {
56         $output = "reports/onis.html";
57 }
58
59 foreach ('Core', get_config ('plugin'))
60 {
61         my $module = ucfirst (lc ($_));
62         require "Onis/Plugins/$module.pm";
63 }
64
65 if (!get_config ('input'))
66 {
67         print STDERR <<EOF;
68
69 Usage: $0 [options] <logfile> [logfile logfile ..]
70
71 Options:
72         --config                Specify alternate config file
73         --output <file>         Defines the file to write the HTML to.
74         --overwrite <bool>      Overwrites files without prompting.
75         --channel <channel>     Defines the channel's name.
76         --logtype <type>        Defines the logfile's type.
77                                 See 'config' for a complete list.
78         --user <name>           Define's the generator's name.
79
80 For a full list of all options please read the ``config'' file.
81 EOF
82         exit (1);
83 }
84
85 if (-e $output)
86 {
87         my $overwrite = 0;
88         if (get_config ('overwrite'))
89         {
90                 my $tmp = lc (get_config ('overwrite'));
91                 if ($tmp eq 'true' or $tmp eq 'yes' or $tmp eq 'on')
92                 {
93                         $overwrite = 1;
94                 }
95         }
96         
97         if (!$overwrite)
98         {
99                 print STDERR <<MESSAGE;
100
101 WARNING: The output file ``$output'' already exists
102
103   You can set the ``overwrite'' option in the config
104   file to disable this dialog.
105
106 MESSAGE
107                 print STDERR 'Are you sure you want to overwrite it? [Y|n] ';
108                 my $answer = <STDIN>;
109                 exit (1) if ($answer =~ m/n/i);
110         }
111 }
112
113 my $logtype = 'Eggdrop';
114 if (get_config ('logtype'))
115 {
116         $logtype = ucfirst (lc (get_config ('logtype')));
117 }
118
119 require "Onis/Parser/$logtype.pm";
120 require Onis::Parser::Persistent;
121 require Onis::Data::Persistent;
122 import Onis::Parser qw/parse last_date/;
123 import Onis::Parser::Persistent qw#newfile#;
124 import Onis::Data::Persistent qw#init#;
125
126 $FILEINFO = init ('$FILEINFO', 'hash');
127
128 if (get_config ('purge_logs'))
129 {
130         my $temp = lc (get_config ('purge_logs'));
131         if (($temp eq 'truncate') or ($temp eq 'shorten'))
132         {
133                 $PURGE_LOGS = 1;
134         }
135         elsif (($temp eq 'delete') or ($temp eq 'remove')
136                         or ($temp eq 'del'))
137         {
138                 $PURGE_LOGS = 2;
139         }
140 }
141
142 for (get_config ('input'))
143 {
144         my $file = $_;
145         my $logfile;
146         my $status = 4;
147         my $position = 0;
148         my $mtime;
149         my $size;
150         my $inode;
151
152         ($inode, $size, $mtime) = (stat ($file))[1,7,9];
153
154         print STDERR $/, $/, __FILE__, " --- New File ``$file'' ---" if ($::DEBUG & 0x200);
155         
156         if (!defined ($mtime))
157         {
158                 print STDERR $/, __FILE__, ": Unable to stat file ``$file''";
159                 next;
160         }
161         else
162         {
163                 print STDERR $/, __FILE__, ": ``$file'': " if ($::DEBUG & 0x200);
164                 if (defined ($FILEINFO->{$inode}{'mtime'}))
165                 {
166                         if ($FILEINFO->{$inode}{'mtime'} == $mtime)
167                         {
168                                 print STDERR "File did not change. Skipping." if ($::DEBUG & 0x200);
169                                 next;
170                         }
171                         elsif ($FILEINFO->{$inode}{'mtime'} < $mtime)
172                         {
173                                 print STDERR "File changed. Reading it again." if ($::DEBUG & 0x200);
174                         }
175                         else
176                         {
177                                 print STDERR "File ``$file'' is older than expected. There might be a problem!";
178                         }
179                 }
180                 else
181                 {
182                         print STDERR "File appears to be new. Reading it." if ($::DEBUG & 0x200);
183                 }
184                 $FILEINFO->{$inode}{'mtime'} = $mtime;
185         }
186         
187         # truncate
188         if ($PURGE_LOGS == 1)
189         {
190                 unless (open ($logfile, '+< ' . $file))
191                 {
192                         print STDERR $/, __FILE__, ": Unable to open file ``$file'': $!";
193                         next;
194                 }
195         }
196         else
197         {
198                 unless (open ($logfile, '< ' . $file))
199                 {
200                         print STDERR $/, __FILE__, ": Unable to open file ``$file'': $!";
201                         next;
202                 }
203         }
204         
205         if ($PURGE_LOGS)
206         {
207                 unless (flock ($logfile, LOCK_EX))
208                 {
209                         print STDERR $/, __FILE__, ": Unable to get an exclusive lock for file ``$file'': $!";
210                         close ($logfile);
211                         next;
212                 }
213         }
214         else
215         {
216                 unless (flock ($logfile, LOCK_SH))
217                 {
218                         print STDERR $/, __FILE__, ": Unable to get a shared lock for file ``$file'': $!";
219                         close ($logfile);
220                         next;
221                 }
222         }
223         
224         newfile ($FILEINFO->{$inode});
225         while (<$logfile>)
226         {
227                 s/\n|\r//g;
228                 $status = parse ($_);
229
230                 # 0 == rewind file
231                 # 1 == line parsed
232                 # 2 == unable to parse
233                 # 3 == line old
234                 # 4 == don't have date
235
236                 if ($status == 0)
237                 {
238                         print STDERR $/, __FILE__, ": Rewinding file ``$file''" if ($::DEBUG & 0x200);
239                         seek ($logfile, 0, 0);
240                         $position = 0;
241                 }
242                 elsif (($status == 1) or ($status == 2)
243                                 or ($status == 3))
244                 {
245                         $position = tell ($logfile);
246                 }
247                 elsif ($status == 4)
248                 {
249                         # void
250                 }
251                 else
252                 {
253                         print STDERR $/, __FILE__, ": Parser returned unknown status code: ``$status''";
254                 }
255         }
256
257         if ($PURGE_LOGS and (($status == 1)
258                                 or ($status == 2)
259                                 or ($status == 3)))
260         {
261                 if (($PURGE_LOGS > 1)
262                         #and (($position + 1) >= $size)
263                         )
264                 {
265                         # delete file
266                         print STDERR $/, __FILE__, ": Deleting empty file ``$file''" if ($::DEBUG & 0x200);
267                         close ($logfile);
268
269                         if (-w $file)
270                         {
271                                 unless (unlink ($file))
272                                 {
273                                         print STDERR $/, __FILE__, ": Unable to delete empty file ``$file'': $!";
274                                 }
275                                 delete ($FILEINFO->{$inode});
276                         }
277                         else
278                         {
279                                 print STDERR $/, __FILE__, ": Won't delete ``$file''. Set it to writeable first!";
280                         }
281                 }
282                 else
283                 {
284                         seek ($logfile, 0, 0);
285                         if (truncate ($logfile, 0))
286                         {
287                                 print $logfile &last_date ();
288                                 print STDERR $/, __FILE__, ": Truncated ``$file''" if ($::DEBUG & 0x200);
289                         }
290                         else
291                         {
292                                 print STDERR $/, __FILE__, ": Couldn't truncate file ``$file'': $!";
293                         }
294                         
295                         close ($logfile);
296                 }
297         }
298         else
299         {       
300                 close ($logfile);
301         }
302 }
303
304 require Onis::Data::Core;
305 require Onis::Html;
306 import Onis::Data::Core qw#print_output#;
307 import Onis::Html qw#open_file close_file#;
308
309 if (open_file ($output))
310 {
311         print_output ();
312         close_file ();
313 }
314 else
315 {
316         # Fail and make noise! ;)
317         print STDERR <<MESSAGE;
318
319 ERROR: Unable to open output file
320
321 The output file ``$output'' could not be opened. Please make sure to set
322 the permissions right and try again.
323
324 MESSAGE
325         exit (1);
326 }
327
328 exit (0);
329
330 END
331 {
332         print $/ if ($::DEBUG);
333 }