| 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/&/&/g;
|
| 286 |
|
|
$output =~ s/"/"/g;
|
| 287 |
|
|
$output =~ s/</</g;
|
| 288 |
|
|
$output =~ s/>/>/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:
|