/[echolot]/trunk/Echolot/Stats.pm
ViewVC logotype

Contents of /trunk/Echolot/Stats.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 217 - (hide annotations) (download)
Mon Jul 29 13:35:47 2002 UTC (10 years, 10 months ago) by weasel
File size: 26535 byte(s)
Build keyrings in results.private too
1 weasel 22 package Echolot::Stats;
2    
3     # (c) 2002 Peter Palfrader <peter@palfrader.org>
4 weasel 217 # $Id: Stats.pm,v 1.25 2002/07/29 13:35:47 weasel Exp $
5 weasel 22 #
6    
7     =pod
8    
9     =head1 Name
10    
11     Echolot::Stats - produce Stats, keyrings et al
12    
13     =head1 DESCRIPTION
14    
15     This package provides functions for generating remailer stats,
16     and keyrings.
17    
18     =cut
19    
20     use strict;
21     use Carp qw{cluck};
22    
23 weasel 29 use constant DAYS => 12;
24 weasel 56 use constant SECS_PER_DAY => 24 * 60 * 60;
25 weasel 107 use English;
26 weasel 112 use HTML::Template;
27 weasel 29
28     use Statistics::Distrib::Normal qw{};
29    
30 weasel 22 my @WDAY = qw{Sun Mon Tue Wed Thu Fri Sat};
31     my @MON = qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec};
32    
33 weasel 29 my $NORMAL = new Statistics::Distrib::Normal;
34     $NORMAL->mu(0);
35     $NORMAL->sigma(1);
36 weasel 22
37     sub makeDate() {
38     my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime();
39     sprintf("%s %02d %s %4d %02d:%02d:%02d GMT",
40     $WDAY[$wday],
41     $mday,
42     $MON[$mon],
43     $year + 1900,
44     $hour,
45     $min,
46     $sec);
47     };
48    
49     sub makeMinHr($$) {
50     my ($sec, $includesec) = @_;
51     my ($s, $m, $h);
52    
53     if (defined $sec) {
54     $s = $sec % 60;
55     $m = $sec / 60 % 60;
56     $h = int ($sec / 60 / 60);
57     };
58 weasel 42 if ((! defined $sec) || ($sec < 0) || ($h > 99)) {
59 weasel 22 $h = 99;
60     $m = 59;
61     $s = 59;
62     };
63    
64     if ($includesec) {
65     if ($h) { return sprintf ("%2d:%02d:%02d", $h, $m, $s); }
66     elsif ($m) { return sprintf ( " %2d:%02d", $m, $s); }
67     else { return sprintf ( " %2d", $s); };
68     } else {
69     if ($h) { return sprintf ("%2d:%02d", $h, $m); }
70     else { return sprintf ( " :%02d", $m); };
71     };
72     };
73    
74 weasel 42 sub build_list1_latencystr($) {
75 weasel 22 my ($lat) = @_;
76    
77 weasel 29 my $str = '?' x DAYS;
78     for my $day (0 .. DAYS - 1) {
79     substr($str, DAYS - 1 - $day, 1) =
80 weasel 22 (defined $lat->[$day]) ?
81     ($lat->[$day] < 300 ? '#' :
82     ($lat->[$day] < 3600 ? '*' :
83     ($lat->[$day] < 14400 ? '+' :
84     ($lat->[$day] < 86400 ? '-' :
85     ($lat->[$day] < 172800 ? '.' :
86     '_'
87     )))))
88     : ' ';
89     };
90     return $str;
91     }
92    
93 weasel 42 sub build_list2_latencystr($) {
94 weasel 22 my ($lat) = @_;
95    
96 weasel 29 my $str = '?' x DAYS;
97     for my $day (0 .. DAYS - 1) {
98     substr($str, DAYS - 1 - $day, 1) =
99 weasel 22 (defined $lat->[$day]) ?
100     ($lat->[$day] < 20*60 ? '0' :
101     ($lat->[$day] < 1*3600 ? '1' :
102     ($lat->[$day] < 2*3600 ? '2' :
103     ($lat->[$day] < 3*3600 ? '3' :
104     ($lat->[$day] < 4*3600 ? '4' :
105     ($lat->[$day] < 5*3600 ? '5' :
106     ($lat->[$day] < 6*3600 ? '6' :
107     ($lat->[$day] < 7*3600 ? '7' :
108     ($lat->[$day] < 8*3600 ? '8' :
109     ($lat->[$day] < 9*3600 ? '9' :
110     ($lat->[$day] < 12*3600 ? 'A' :
111     ($lat->[$day] < 18*3600 ? 'B' :
112     ($lat->[$day] < 24*3600 ? 'C' :
113     ($lat->[$day] < 30*3600 ? 'D' :
114     ($lat->[$day] < 36*3600 ? 'E' :
115     ($lat->[$day] < 42*3600 ? 'F' :
116     ($lat->[$day] < 48*3600 ? 'G' :
117     'H'
118     )))))))))))))))))
119     : '?';
120     };
121     return $str;
122     }
123    
124 weasel 42 sub build_list2_reliabilitystr($) {
125 weasel 22 my ($rel) = @_;
126    
127 weasel 29 my $str = '?' x DAYS;
128     for my $day (0 .. DAYS - 1) {
129     substr($str, DAYS - 1 - $day, 1) =
130 weasel 22 (defined $rel->[$day]) ?
131 weasel 52 (($rel->[$day] >= 0.9999) ?
132     #(($rel->[$day] == 1) ?
133 weasel 22 '+' :
134     (int ($rel->[$day]*10)))
135     : '?';
136     };
137     return $str;
138     }
139    
140 weasel 42 sub build_list2_capsstr($) {
141 weasel 22 my ($caps) = @_;
142    
143     my %caps;
144     $caps{'middle'} = ($caps =~ m/\bmiddle\b/i);
145     $caps{'post'} = ($caps =~ m/\bpost\b/i) || ($caps =~ m/\banon-post-to\b/i);
146     $caps{'mix'} = ($caps =~ m/\bmix\b/i);
147     $caps{'remix'} = ($caps =~ m/\bremix\b/i);
148     $caps{'remix2'} = ($caps =~ m/\bremix2\b/i);
149     $caps{'hybrid'} = ($caps =~ m/\bhybrid\b/i);
150     $caps{'repgp2'} = ($caps =~ m/\brepgp2\b/i);
151     $caps{'repgp'} = ($caps =~ m/\brepgp\b/i);
152     $caps{'pgponly'} = ($caps =~ m/\bpgponly\b/i);
153     $caps{'ext'} = ($caps =~ m/\bext\b/i);
154     $caps{'max'} = ($caps =~ m/\bmax\b/i);
155     $caps{'test'} = ($caps =~ m/\btest\b/i);
156     $caps{'latent'} = ($caps =~ m/\blatent\b/i);
157     $caps{'ek'} = ($caps =~ m/\bek\b/i);
158     $caps{'ekx'} = ($caps =~ m/\bekx\b/i);
159     $caps{'esub'} = ($caps =~ m/\besub\b/i);
160     $caps{'inflt'} = ($caps =~ m/\binflt\d+\b/i);
161     $caps{'rhop'} = ($caps =~ m/\brhop\d+\b/i);
162     ($caps{'klen'}) = ($caps =~ m/\bklen(\d+)\b/i);
163    
164     my $str =
165     ($caps{'middle'} ? 'D' : ' ') .
166     ($caps{'post'} ? 'P' : ' ') .
167     ($caps{'remix2'} ? '2' : ($caps{'remix'} ? 'R' : ($caps{'mix'} ? 'M' : ' ' ))) .
168     ($caps{'hybrid'} ? 'H' : ' ') .
169     ($caps{'repgp2'} ? '2' : ($caps{'repgp'} ? 'G' : ' ' )) .
170     ($caps{'pgponly'} ? 'O' : ' ') .
171     ($caps{'ext'} ? 'X' : ' ') .
172     ($caps{'max'} ? 'A' : ' ') .
173     ($caps{'test'} ? 'T' : ' ') .
174     ($caps{'latent'} ? 'L' : ' ') .
175     ($caps{'ekx'} ? 'E' : ($caps{'ek'} ? 'e' : ' ' )) .
176     ($caps{'esub'} ? 'U' : ' ') .
177     ($caps{'inflt'} ? 'I' : ' ') .
178     ($caps{'rhop'} ? 'N' : ' ') .
179     (defined $caps{'klen'} ?
180     ($caps{'klen'} >= 900 ? '9' : (
181     $caps{'klen'} >= 800 ? '8' : (
182     $caps{'klen'} >= 700 ? '7' : (
183     $caps{'klen'} >= 600 ? '6' : (
184     $caps{'klen'} >= 500 ? '5' : (
185     $caps{'klen'} >= 400 ? '4' : (
186     $caps{'klen'} >= 300 ? '3' : (
187     $caps{'klen'} >= 200 ? '2' : (
188     $caps{'klen'} >= 100 ? '1' : '0'
189     )))))))))
190     : ' ');
191     return $str;
192     }
193    
194    
195     sub calculate($$) {
196 weasel 42 my ($addr, $types) = @_;
197 weasel 22 my $now = time();
198    
199     my @out;
200     my @done;
201    
202 weasel 42 for my $type (@$types) {
203     next unless Echolot::Globals::get()->{'storage'}->has_type($addr, $type);
204     my @keys = Echolot::Globals::get()->{'storage'}->get_keys($addr, $type);
205     for my $key (@keys) {
206     push @out, grep {$_ > $now - DAYS * SECS_PER_DAY} Echolot::Globals::get()->{'storage'}->get_pings($addr, $type, $key, 'out');
207     push @done, grep {$_->[0] > $now - DAYS * SECS_PER_DAY} Echolot::Globals::get()->{'storage'}->get_pings($addr, $type, $key, 'done');
208     };
209 weasel 22 };
210    
211     my $latency = 0;
212     my $received = 0;
213     my $sent = 0;
214     my @latency;
215     my @received;
216     my @sent;
217     for my $done (@done) {
218 weasel 29 $latency += $done->[1]; $latency [int(($now - $done->[0]) / SECS_PER_DAY)] += $done->[1];
219     $sent ++; $sent [int(($now - $done->[0]) / SECS_PER_DAY)] ++;
220     $received ++; $received[int(($now - $done->[0]) / SECS_PER_DAY)] ++;
221 weasel 22 };
222     $latency /= (scalar @done) if (scalar @done);
223 weasel 42 $latency = undef unless (scalar @done);
224 weasel 29 for ( 0 .. DAYS - 1 ) {
225 weasel 22 $latency[$_] /= $received[$_] if ($received[$_]);
226     };
227    
228 weasel 29 my $variance = 0;
229     $variance += ($latency - $_->[1]) ** 2 for (@done);
230     $variance /= (scalar @done) if (scalar @done);
231    
232     my $deviation = sqrt($variance);
233    
234     if (scalar @out) {
235 weasel 42 my @p =
236     ($deviation != 0) ?
237     $NORMAL->utp( map { ($now - $_ - $latency) / $deviation } @out ) :
238     map { 0 } @out;
239 weasel 29 for (my $i=0; $i < scalar @out; $i++) {
240     $sent ++; $sent [int(($now - $out[$i]) / SECS_PER_DAY)] ++;
241     $received += $p[$i]; $received[int(($now - $out[$i]) / SECS_PER_DAY)] += $p[$i];
242     };
243 weasel 22 };
244     $received /= $sent if ($sent);
245 weasel 29 for ( 0 .. DAYS - 1 ) {
246 weasel 22 $received[$_] /= $sent[$_] if ($sent[$_]);
247     };
248    
249    
250    
251     return {
252     avr_latency => $latency,
253     avr_reliability => $received,
254     latency_day => \@latency,
255     reliability_day => \@received
256     };
257     };
258    
259 weasel 215 sub read_file($;$) {
260     my ($name, $fail_ok) = @_;
261    
262     unless (open (F, $name)) {
263     cluck("Could not open '$name': $!") unless ($fail_ok);
264     return undef;
265     };
266     local $/ = undef;
267     my $result = <F>;
268     close (F);
269    
270     return $result;
271     };
272    
273 weasel 112 sub write_file($$;$) {
274     my ($filebasename, $html_template, $output) = @_;
275 weasel 22
276 weasel 112 my $filename = $filebasename.'.txt';
277     open(F, '>'.$filename) or
278     cluck("Cannot open $filename: $!\n"),
279     return 0;
280     print F $output;
281     close (F);
282 weasel 22
283 weasel 112 return 1 unless defined $html_template;
284    
285 weasel 165 $output =~ s/&/&amp;/g;
286     $output =~ s/"/&quot;/g;
287     $output =~ s/</&lt;/g;
288     $output =~ s/>/&gt;/g;
289 weasel 112 my $template = HTML::Template->new(
290     filename => $html_template,
291 weasel 139 strict => 0,
292 weasel 112 global_vars => 1 );
293     $template->param ( list => $output );
294     $template->param ( CURRENT_TIMESTAMP => scalar gmtime() );
295     $template->param ( SITE_NAME => Echolot::Config::get()->{'sitename'} );
296 weasel 138 $template->param ( seperate_rlist => Echolot::Config::get()->{'seperate_rlists'} );
297 weasel 139 $template->param ( combined_list => Echolot::Config::get()->{'combined_list'} );
298 weasel 187 $template->param ( version => Echolot::Globals::get()->{'version'} );
299 weasel 22
300 weasel 112 $filename = $filebasename.'.html';
301 weasel 22 open(F, '>'.$filename) or
302     cluck("Cannot open $filename: $!\n"),
303     return 0;
304 weasel 112 print F $template->output();
305     close (F);
306 weasel 22
307 weasel 112 return 1;
308     };
309    
310 weasel 215 sub build_mlist1($$$$$;$) {
311     my ($rems, $broken1, $broken2, $sameop, $filebasename, $html_template) = @_;
312 weasel 112
313     my $output = '';
314 weasel 215 $output .= sprintf "\nGroups of remailers sharing a machine or operator:\n$sameop\n" if (defined $sameop);
315     $output .= sprintf "\nBroken type-I remailer chains:\n$broken1\n" if (defined $broken1);
316     $output .= sprintf "\nBroken type-II remailer chains:\n$broken2\n" if (defined $broken2);
317    
318 weasel 112 $output .= sprintf "Last update: %s\n", makeDate();
319     $output .= sprintf "mixmaster history latency uptime\n";
320     $output .= sprintf "--------------------------------------------\n";
321    
322 weasel 22 for my $remailer (@$rems) {
323 weasel 112 $output .= sprintf "%-14s %-12s %8s %6.2f%%\n",
324 weasel 160 substr($remailer->{'nick'},0,14),
325 weasel 42 build_list1_latencystr($remailer->{'stats'}->{'latency_day'}),
326 weasel 22 makeMinHr($remailer->{'stats'}->{'avr_latency'}, 1),
327     $remailer->{'stats'}->{'avr_reliability'} * 100;
328     };
329 weasel 112
330     write_file($filebasename, $html_template, $output) or
331     cluck("writefile failed"),
332     return 0;
333     return 1;
334 weasel 22 };
335    
336 weasel 215 sub build_rlist1($$$$$;$) {
337     my ($rems, $broken1, $broken2, $sameop, $filebasename, $html_template) = @_;
338 weasel 22
339 weasel 112 my $output = '';
340 weasel 42 for my $remailer (sort {$a->{'caps'} cmp $b->{'caps'}} @$rems) {
341 weasel 112 $output .= $remailer->{'caps'}."\n"
342 weasel 42 }
343    
344 weasel 215 $output .= sprintf "\nGroups of remailers sharing a machine or operator:\n$sameop\n" if (defined $sameop);
345     $output .= sprintf "\nBroken type-I remailer chains:\n$broken1\n" if (defined $broken1);
346     $output .= sprintf "\nBroken type-II remailer chains:\n$broken2\n" if (defined $broken2);
347 weasel 42
348 weasel 138 $output .= sprintf "\n";
349 weasel 112 $output .= sprintf "Last update: %s\n", makeDate();
350     $output .= sprintf "remailer email address history latency uptime\n";
351     $output .= sprintf "-----------------------------------------------------------------------\n";
352 weasel 42
353     for my $remailer (@$rems) {
354 weasel 160 $output .= sprintf "%-8s %-32s %-12s %8s %6.2f%%\n",
355     substr($remailer->{'nick'},0,8),
356     substr($remailer->{'address'},0,32),
357 weasel 42 build_list1_latencystr($remailer->{'stats'}->{'latency_day'}),
358     makeMinHr($remailer->{'stats'}->{'avr_latency'}, 1),
359     $remailer->{'stats'}->{'avr_reliability'} * 100;
360     };
361    
362 weasel 112
363     write_file($filebasename, $html_template, $output) or
364     cluck("writefile failed"),
365     return 0;
366     return 1;
367 weasel 42 };
368    
369    
370 weasel 215 sub build_list2($$$$$;$) {
371     my ($rems, $broken1, $broken2, $sameop, $filebasename, $html_template) = @_;
372 weasel 42
373 weasel 112 my $output = '';
374 weasel 22
375 weasel 112 $output .= sprintf "Stats-Version: 2.0\n";
376     $output .= sprintf "Generated: %s\n", makeDate();
377     $output .= sprintf "Mixmaster Latent-Hist Latent Uptime-Hist Uptime Options\n";
378     $output .= sprintf "------------------------------------------------------------------------\n";
379    
380 weasel 22 for my $remailer (@$rems) {
381 weasel 112 $output .= sprintf "%-12s %-12s %6s %-12s %5.1f%% %s\n",
382 weasel 160 substr($remailer->{'nick'},0,12),
383 weasel 42 build_list2_latencystr($remailer->{'stats'}->{'latency_day'}),
384 weasel 22 makeMinHr($remailer->{'stats'}->{'avr_latency'}, 0),
385 weasel 42 build_list2_reliabilitystr($remailer->{'stats'}->{'reliability_day'}),
386 weasel 22 $remailer->{'stats'}->{'avr_reliability'} * 100,
387 weasel 42 build_list2_capsstr($remailer->{'caps'});
388 weasel 22 };
389 weasel 29
390 weasel 215 $output .= sprintf "\nGroups of remailers sharing a machine or operator:\n$sameop\n" if (defined $sameop);
391     $output .= sprintf "\nBroken type-I remailer chains:\n$broken1\n" if (defined $broken1);
392     $output .= sprintf "\nBroken type-II remailer chains:\n$broken2\n" if (defined $broken2);
393 weasel 42
394 weasel 112 $output .= sprintf "\n\n\nRemailer-Capabilities:\n\n";
395 weasel 29 for my $remailer (sort {$a->{'caps'} cmp $b->{'caps'}} @$rems) {
396 weasel 112 $output .= $remailer->{'caps'}."\n" if defined $remailer->{'caps'};
397 weasel 29 }
398    
399 weasel 112 write_file($filebasename, $html_template, $output) or
400     cluck("writefile failed"),
401     return 0;
402     return 1;
403 weasel 22 };
404    
405 weasel 215 sub build_clist($$$$$;$) {
406     my ($remhash, $broken1, $broken2, $sameop, $filebasename, $html_template) = @_;
407 weasel 22
408 weasel 139 my $output = '';
409    
410     $output .= sprintf "Stats-Version: 2.0.1\n";
411     $output .= sprintf "Generated: %s\n", makeDate();
412     $output .= sprintf "Mixmaster Latent-Hist Latent Uptime-Hist Uptime Options Type\n";
413     $output .= sprintf "------------------------------------------------------------------------------------\n";
414    
415     my $all;
416     for my $type (keys %$remhash) {
417     for my $remailer (@{$remhash->{$type}}) {
418     $all->{ $remailer->{'nick'} }->{$type} = $remailer
419     };
420     };
421    
422     for my $nick (sort {$a cmp $b} keys %$all) {
423     for my $type (sort {$a cmp $b} keys %{$all->{$nick}}) {
424     $output .= sprintf "%-12s %-12s %6s %-12s %5.1f%% %s %s\n",
425     $nick,
426     build_list2_latencystr($all->{$nick}->{$type}->{'stats'}->{'latency_day'}),
427     makeMinHr($all->{$nick}->{$type}->{'stats'}->{'avr_latency'}, 0),
428     build_list2_reliabilitystr($all->{$nick}->{$type}->{'stats'}->{'reliability_day'}),
429     $all->{$nick}->{$type}->{'stats'}->{'avr_reliability'} * 100,
430     build_list2_capsstr($all->{$nick}->{$type}->{'caps'}),
431     $type;
432     };
433     };
434    
435 weasel 215 $output .= sprintf "\nGroups of remailers sharing a machine or operator:\n$sameop\n" if (defined $sameop);
436     $output .= sprintf "\nBroken type-I remailer chains:\n$broken1\n" if (defined $broken1);
437     $output .= sprintf "\nBroken type-II remailer chains:\n$broken2\n" if (defined $broken2);
438 weasel 139
439     $output .= sprintf "\n\n\nRemailer-Capabilities:\n\n";
440     for my $nick (sort {$a cmp $b} keys %$all) {
441     for my $type (keys %{$all->{$nick}}) {
442     $output .= $all->{$nick}->{$type}->{'caps'}."\n", last if defined $all->{$nick}->{$type}->{'caps'};
443     };
444     }
445    
446     write_file($filebasename, $html_template, $output) or
447     cluck("writefile failed"),
448     return 0;
449     return 1;
450     };
451    
452    
453 weasel 42 sub build_rems($) {
454     my ($types) = @_;
455    
456 weasel 22 my %rems;
457 weasel 79 for my $remailer (Echolot::Globals::get()->{'storage'}->get_remailers()) {
458     my $addr = $remailer->{'address'};
459 weasel 42 my $has_type = 0;
460     for my $type (@$types) {
461     $has_type = 1, last if (Echolot::Globals::get()->{'storage'}->has_type($addr, $type));
462     };
463     next unless $has_type;
464 weasel 22
465 weasel 29 my $rem = {
466 weasel 42 'stats' => calculate($addr,$types),
467     'nick' => Echolot::Globals::get()->{'storage'}->get_nick($addr),
468     'caps' => Echolot::Globals::get()->{'storage'}->get_capabilities($addr),
469 weasel 79 'address' => $addr,
470     'showit' => $remailer->{'showit'}
471 weasel 22 };
472 weasel 207 $rem->{'latency'} = $rem->{'stats'}->{'avr_latency'}; # for sorting purposes only
473     $rem->{'latency'} = 9999 unless defined $rem->{'latency'};
474 weasel 29
475 weasel 42 $rems{$addr} = $rem if (defined $rem->{'stats'} && defined $rem->{'nick'} && defined $rem->{'address'} && defined $rem->{'caps'} );
476 weasel 22 };
477    
478 weasel 207 my $sort_by_latency = Echolot::Config::get()->{'stats_sort_by_latency'};
479 weasel 42 my @rems =
480 weasel 22 sort {
481 weasel 56 - ($a->{'stats'}->{'avr_reliability'} <=> $b->{'stats'}->{'avr_reliability'}) ||
482 weasel 207 (($a->{'latency'} <=> $b->{'latency'}) * $sort_by_latency) ||
483 weasel 56 ($a->{'nick'} cmp $b->{'nick'})
484 weasel 42 } map { $rems{$_} } keys %rems;
485    
486     return \@rems;
487     };
488 weasel 22
489 weasel 42 sub build_lists() {
490    
491 weasel 139 my $clist;
492     my $pubclist;
493     my $rems;
494     my $pubrems;
495 weasel 215
496     my $broken1 = read_file( Echolot::Config::get()->{'broken1'}, 1);
497     my $broken2 = read_file( Echolot::Config::get()->{'broken2'}, 1);
498     my $sameop = read_file( Echolot::Config::get()->{'sameop'}, 1);
499    
500 weasel 139 $rems = build_rems(['mix']);
501     @$pubrems = grep { $_->{'showit'} } @$rems;
502 weasel 215 build_mlist1( $rems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'mlist');
503     build_list2( $rems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'mlist2');
504     build_mlist1( $pubrems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'mlist', Echolot::Config::get()->{'templates'}->{'mlist'});
505     build_list2( $pubrems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'mlist2', Echolot::Config::get()->{'templates'}->{'mlist2'});
506 weasel 139 if (Echolot::Config::get()->{'combined_list'}) {
507     $clist->{'mix'} = $rems;
508 weasel 148 $pubclist->{'mix'} = $pubrems; $pubrems = undef;
509 weasel 139 };
510 weasel 42
511 weasel 85 $rems = build_rems(['cpunk-rsa', 'cpunk-dsa', 'cpunk-clear']);
512 weasel 139 @$pubrems = grep { $_->{'showit'} } @$rems;
513 weasel 215 build_rlist1( $rems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'rlist');
514     build_list2( $rems,$broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'rlist2');
515     build_rlist1( $pubrems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'rlist', Echolot::Config::get()->{'templates'}->{'rlist'});
516     build_list2( $pubrems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'rlist2', Echolot::Config::get()->{'templates'}->{'rlist2'});
517 weasel 139 if (Echolot::Config::get()->{'combined_list'} && ! Echolot::Config::get()->{'seperate_rlists'}) {
518     $clist->{'cpunk'} = $rems;
519 weasel 148 $pubclist->{'cpunk'} = $pubrems; $pubrems = undef;
520 weasel 139 };
521 weasel 138
522     if (Echolot::Config::get()->{'seperate_rlists'}) {
523     $rems = build_rems(['cpunk-rsa']);
524 weasel 139 @$pubrems = grep { $_->{'showit'} } @$rems;
525 weasel 215 build_rlist1( $rems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'rlist-rsa', Echolot::Config::get()->{'templates'}->{'rlist-rsa'});
526     build_list2( $rems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'rlist2-rsa', Echolot::Config::get()->{'templates'}->{'rlist2-rsa'});
527     build_rlist1( $pubrems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'rlist-rsa', Echolot::Config::get()->{'templates'}->{'rlist-rsa'});
528     build_list2( $pubrems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'rlist2-rsa', Echolot::Config::get()->{'templates'}->{'rlist2-rsa'});
529 weasel 139 if (Echolot::Config::get()->{'combined_list'}) {
530     $clist->{'cpunk-rsa'} = $rems;
531 weasel 148 $pubclist->{'cpunk-rsa'} = $pubrems; $pubrems = undef;
532 weasel 139 };
533 weasel 138
534     $rems = build_rems(['cpunk-dsa']);
535 weasel 139 @$pubrems = grep { $_->{'showit'} } @$rems;
536 weasel 215 build_rlist1( $rems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'rlist-dsa', Echolot::Config::get()->{'templates'}->{'rlist-dsa'});
537     build_list2( $rems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'rlist2-dsa', Echolot::Config::get()->{'templates'}->{'rlist2-dsa'});
538     build_rlist1( $pubrems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'rlist-dsa', Echolot::Config::get()->{'templates'}->{'rlist-dsa'});
539     build_list2( $pubrems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'rlist2-dsa', Echolot::Config::get()->{'templates'}->{'rlist2-dsa'});
540 weasel 139 if (Echolot::Config::get()->{'combined_list'}) {
541     $clist->{'cpunk-dsa'} = $rems;
542 weasel 148 $pubclist->{'cpunk-dsa'} = $pubrems; $pubrems = undef;
543 weasel 139 };
544 weasel 138
545     $rems = build_rems(['cpunk-clear']);
546 weasel 139 @$pubrems = grep { $_->{'showit'} } @$rems;
547 weasel 215 build_rlist1( $rems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'rlist-clear', Echolot::Config::get()->{'templates'}->{'rlist-clear'});
548     build_list2( $rems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'rlist2-clear', Echolot::Config::get()->{'templates'}->{'rlist2-clear'});
549     build_rlist1( $pubrems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'rlist-clear', Echolot::Config::get()->{'templates'}->{'rlist-clear'});
550     build_list2( $pubrems, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'rlist2-clear', Echolot::Config::get()->{'templates'}->{'rlist2-clear'});
551 weasel 139 if (Echolot::Config::get()->{'combined_list'}) {
552     $clist->{'cpunk-clear'} = $rems;
553 weasel 148 $pubclist->{'cpunk-clear'} = $pubrems; $pubrems = undef;
554 weasel 139 };
555     };
556     if (Echolot::Config::get()->{'combined_list'}) {
557 weasel 215 build_clist( $clist, $broken1, $broken2, $sameop, Echolot::Config::get()->{'private_resultdir'}.'/'.'clist', Echolot::Config::get()->{'templates'}->{'clist'});
558     build_clist( $pubclist, $broken1, $broken2, $sameop, Echolot::Config::get()->{'resultdir'}.'/'.'clist', Echolot::Config::get()->{'templates'}->{'clist'});
559 weasel 139 };
560 weasel 22 };
561    
562 weasel 25
563     sub build_mixring() {
564     my $filename = Echolot::Config::get()->{'resultdir'}.'/pubring.mix';
565     open(F, '>'.$filename) or
566     cluck("Cannot open $filename: $!\n"),
567     return 0;
568     $filename = Echolot::Config::get()->{'resultdir'}.'/type2.list';
569     open(T2L, '>'.$filename) or
570     cluck("Cannot open $filename: $!\n"),
571     return 0;
572 weasel 217 $filename = Echolot::Config::get()->{'private_resultdir'}.'/pubring.mix';
573     open(F_PRIV, '>'.$filename) or
574     cluck("Cannot open $filename: $!\n"),
575     return 0;
576     $filename = Echolot::Config::get()->{'private_resultdir'}.'/type2.list';
577     open(T2L_PRIV, '>'.$filename) or
578     cluck("Cannot open $filename: $!\n"),
579     return 0;
580 weasel 25
581 weasel 160 my $data;
582 weasel 79 for my $remailer (Echolot::Globals::get()->{'storage'}->get_remailers()) {
583     my $addr = $remailer->{'address'};
584 weasel 25 next unless Echolot::Globals::get()->{'storage'}->has_type($addr, 'mix');
585    
586     my %key;
587     for my $keyid (Echolot::Globals::get()->{'storage'}->get_keys($addr, 'mix')) {
588     my %new_key = Echolot::Globals::get()->{'storage'}->get_key($addr, 'mix', $keyid);
589    
590     if (!defined $key{'last_update'} || $key{'last_update'} < $new_key{'last_update'} ) {
591     %key = %new_key;
592     };
593     };
594    
595 weasel 217 $key{'showit'} = $remailer->{'showit'};
596 weasel 29 if ( defined Echolot::Globals::get()->{'storage'}->get_nick($addr) ) {
597 weasel 160 $data->{$key{'summary'}} = \%key;
598 weasel 217 $data->{$key{'summary'}} = \%key;
599 weasel 29 };
600 weasel 25 };
601    
602 weasel 160 for my $indx (sort {$a cmp $b} keys %$data) {
603     my $key = $data->{$indx};
604 weasel 217 if ($key->{'showit'}) {
605     print F $key->{'summary'}."x\n\n";
606     print F $key->{'key'},"\n\n";
607     print T2L $key->{'summary'},"\n";
608     };
609     print F_PRIV $key->{'summary'}."x\n\n";
610     print F_PRIV $key->{'key'},"\n\n";
611     print T2L_PRIV $key->{'summary'},"\n";
612 weasel 160 };
613    
614 weasel 25 close(F);
615     close(T2L);
616 weasel 217 close(F_PRIV);
617     close(T2L_PRIV);
618 weasel 25 };
619    
620 weasel 107
621    
622 weasel 167 sub build_pgpring_type($$$$) {
623     my ($type, $GnuPG, $keyring, $keyids) = @_;
624 weasel 107
625     for my $remailer (Echolot::Globals::get()->{'storage'}->get_remailers()) {
626     my $addr = $remailer->{'address'};
627     next unless Echolot::Globals::get()->{'storage'}->has_type($addr, $type);
628    
629     my %key;
630 weasel 167 my $final_keyid;
631 weasel 107 for my $keyid (Echolot::Globals::get()->{'storage'}->get_keys($addr, $type)) {
632     my %new_key = Echolot::Globals::get()->{'storage'}->get_key($addr, $type, $keyid);
633    
634     if (!defined $key{'last_update'} || $key{'last_update'} < $new_key{'last_update'} ) {
635     %key = %new_key;
636 weasel 167 $final_keyid = $keyid;
637 weasel 107 };
638     };
639    
640     # only if we have a conf
641     if ( defined Echolot::Globals::get()->{'storage'}->get_nick($addr) ) {
642     my ( $stdin_fh, $stdout_fh, $stderr_fh, $status_fh )
643     = ( IO::Handle->new(),
644     IO::Handle->new(),
645     IO::Handle->new(),
646     IO::Handle->new(),
647     );
648     my $handles = GnuPG::Handles->new (
649     stdin => $stdin_fh,
650     stdout => $stdout_fh,
651     stderr => $stderr_fh,
652     status => $status_fh
653     );
654     my $pid = $GnuPG->wrap_call(
655     commands => [ '--import' ],
656     command_args => [qw{--no-options --no-default-keyring --fast-list-mode --keyring}, $keyring, '--', '-' ],
657     handles => $handles );
658     print $stdin_fh $key{'key'};
659     close($stdin_fh);
660    
661     my $stdout = join '', <$stdout_fh>; close($stdout_fh);
662     my $stderr = join '', <$stderr_fh>; close($stderr_fh);
663     my $status = join '', <$status_fh>; close($status_fh);
664    
665     waitpid $pid, 0;
666    
667     ($stdout eq '') or
668     cluck("GnuPG returned something in stdout '$stdout' while adding key for '$addr': So what?\n");
669     unless ($status =~ /^^\[GNUPG:\] IMPORTED /m) {
670     if ($status =~ /^^\[GNUPG:\] IMPORT_RES /m) {
671     cluck("GnuPG status '$status' indicates more than one key for '$addr' imporeted. Ignoring.\n");
672     } else {
673     cluck("GnuPG status '$status' didn't indicate key for '$addr' was imporeted correctly. Ignoring.\n");
674     };
675     };
676 weasel 217 $keyids->{$final_keyid} = $remailer->{'showit'};
677 weasel 107 };
678     };
679    
680     return 1;
681     };
682    
683 weasel 167 sub build_pgpring_export($$$$) {
684     my ($GnuPG, $keyring, $file, $keyids) = @_;
685 weasel 107
686     my ( $stdin_fh, $stdout_fh, $stderr_fh, $status_fh )
687     = ( IO::Handle->new(),
688     IO::Handle->new(),
689     IO::Handle->new(),
690     IO::Handle->new(),
691     );
692     my $handles = GnuPG::Handles->new (
693     stdin => $stdin_fh,
694     stdout => $stdout_fh,
695     stderr => $stderr_fh,
696     status => $status_fh
697     );
698     my $pid = $GnuPG->wrap_call(
699     commands => [ '--export' ],
700 weasel 167 command_args => [qw{--no-options --no-default-keyring --keyring}, $keyring, @$keyids ],
701 weasel 107 handles => $handles );
702     close($stdin_fh);
703    
704     my $stdout = join '', <$stdout_fh>; close($stdout_fh);
705     my $stderr = join '', <$stderr_fh>; close($stderr_fh);
706     my $status = join '', <$status_fh>; close($status_fh);
707    
708     waitpid $pid, 0;
709    
710     open (F, ">$file") or
711     cluck ("Cannot open '$file': $!"),
712     return 0;
713     print F $stdout;
714     close F;
715     return 1;
716     };
717    
718     sub build_pgpring() {
719     my $GnuPG = new GnuPG::Interface;
720 weasel 212 $GnuPG->call( Echolot::Config::get()->{'gnupg'} ) if (Echolot::Config::get()->{'gnupg'});
721 weasel 107 $GnuPG->options->hash_init(
722     armor => 1,
723     homedir => Echolot::Config::get()->{'gnupghome'} );
724     $GnuPG->options->meta_interactive( 0 );
725    
726     my $keyring = Echolot::Config::get()->{'tmpdir'}.'/'.
727     Echolot::Globals::get()->{'hostname'}.".".time.'.'.$PROCESS_ID.'_'.Echolot::Globals::get()->{'internalcounter'}++.'.keyring';
728    
729    
730 weasel 217 my $keyids = {};
731 weasel 167 build_pgpring_type('cpunk-rsa', $GnuPG, $keyring, $keyids) or
732 weasel 107 cluck("build_pgpring_type failed"),
733     return undef;
734    
735 weasel 217 build_pgpring_export($GnuPG, $keyring, Echolot::Config::get()->{'resultdir'}.'/pgp-rsa.asc', [ grep {$keyids->{$_}} keys %$keyids ]) or
736 weasel 107 cluck("build_pgpring_export failed"),
737     return undef;
738    
739 weasel 217 build_pgpring_export($GnuPG, $keyring, Echolot::Config::get()->{'private_resultdir'}.'/pgp-rsa.asc', [ keys %$keyids ]) or
740     cluck("build_pgpring_export failed"),
741     return undef;
742    
743 weasel 167 build_pgpring_type('cpunk-dsa', $GnuPG, $keyring, $keyids) or
744 weasel 107 cluck("build_pgpring_type failed"),
745     return undef;
746    
747 weasel 217 build_pgpring_export($GnuPG, $keyring, Echolot::Config::get()->{'resultdir'}.'/pgp-all.asc', [ grep {$keyids->{$_}} keys %$keyids ]) or
748 weasel 107 cluck("build_pgpring_export failed"),
749     return undef;
750    
751 weasel 217 build_pgpring_export($GnuPG, $keyring, Echolot::Config::get()->{'private_resultdir'}.'/pgp-all.asc', [ keys %$keyids ]) or
752     cluck("build_pgpring_export failed"),
753     return undef;
754    
755 weasel 107
756     unlink ($keyring) or
757     cluck("Cannot unlink tmp keyring '$keyring'"),
758     return undef;
759     unlink ($keyring.'~'); # gnupg does those evil backups
760     };
761    
762     sub build_stats() {
763 weasel 42 build_lists();
764 weasel 107 };
765     sub build_keys() {
766 weasel 25 build_mixring();
767 weasel 107 build_pgpring();
768 weasel 22 };
769    
770     1;
771     # vim: set ts=4 shiftwidth=4:

  ViewVC Help
Powered by ViewVC 1.1.5