/[echolot]/trunk/Echolot/Storage/File.pm
ViewVC logotype

Contents of /trunk/Echolot/Storage/File.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 55 - (show annotations) (download)
Sat Jun 22 23:35:55 2002 UTC (10 years, 11 months ago) by weasel
File size: 21965 byte(s)
fixed some spelling typo
1 package Echolot::Storage::File;
2
3 # (c) 2002 Peter Palfrader <peter@palfrader.org>
4 # $Id: File.pm,v 1.11 2002/06/22 23:35:55 weasel Exp $
5 #
6
7 =pod
8
9 =head1 Name
10
11 Echolot::Storage::File - Storage backend for echolot
12
13 =head1 DESCRIPTION
14
15 This package provides several functions for data storage for echolot.
16
17 =over
18
19 =cut
20
21 use strict;
22 use warnings;
23 use XML::Parser;
24 use XML::Dumper;
25 use IO::Handle;
26 use English;
27 use Carp qw{cluck confess};
28 use Fcntl ':flock'; # import LOCK_* constants
29 use Fcntl ':seek'; # import LOCK_* constants
30 use Echolot::Tools;
31
32 =item B<new> (I<%args>)
33
34 Creates a new storage backend object.
35 args keys:
36
37 =over
38
39 =item I<datadir>
40
41 The basedir where this module may store it's configuration and pinging
42 data.
43
44 =back
45
46 =cut
47
48 my $CONSTANTS = {
49 'metadatafile' => 'metadata'
50 };
51
52 $ENV{'PATH'} = '/bin:/usr/bin';
53 delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
54
55 my $METADATA_VERSION = 1;
56
57 sub new {
58 my ($class, %params) = @_;
59 my $self = {};
60 bless $self, $class;
61
62 defined($params{'datadir'}) or
63 confess ('No datadir option passed to new');
64 $self->{'datadir'} = $params{'datadir'};
65 $self->{'DELAY_COMMIT'} = 0;
66
67 $self->delay_commit();
68 $self->metadata_open() or
69 cluck ('Opening Metadata failed. Exiting'),
70 exit 1;
71 $self->metadata_read() or
72 cluck ('Reading Metadata from Storage failed. Exiting'),
73 exit 1;
74 $self->pingdata_open() or
75 cluck ('Opening Ping files failed. Exiting'),
76 exit 1;
77 $self->enable_commit();
78
79 return $self;
80 };
81
82 sub commit($) {
83 my ($self) = @_;
84
85 if ($self->{'DELAY_COMMIT'}) {
86 $self->{'COMMIT_PENDING'} = 1;
87 return;
88 };
89 $self->metadata_write();
90 $self->{'COMMIT_PENDING'} = 0;
91 };
92
93 sub delay_commit($) {
94 my ($self) = @_;
95
96 $self->{'DELAY_COMMIT'}++;
97 };
98 sub enable_commit($) {
99 my ($self) = @_;
100
101 $self->{'DELAY_COMMIT'}--;
102 $self->commit() if ($self->{'COMMIT_PENDING'} && ! $self->{'DELAY_COMMIT'});
103 };
104
105 sub finish($) {
106 my ($self) = @_;
107
108 $self->pingdata_close();
109 $self->metadata_write();
110 $self->metadata_close();
111 };
112
113
114
115
116 sub metadata_open($) {
117 my ($self) = @_;
118
119 $self->{'METADATA_FH'} = new IO::Handle;
120 my $filename = $self->{'datadir'} .'/'. $CONSTANTS->{'metadatafile'};
121
122 if ( -e $filename ) {
123 open($self->{'METADATA_FH'}, '+<' . $filename) or
124 cluck("Cannot open $filename for reading: $!"),
125 return 0;
126 } else {
127 open($self->{'METADATA_FH'}, '+>' . $filename) or
128 cluck("Cannot open $filename for reading: $!"),
129 return 0;
130 };
131 flock($self->{'METADATA_FH'}, LOCK_EX) or
132 cluck("Cannot get exclusive lock on $filename: $!"),
133 return 0;
134 };
135
136 sub metadata_close($) {
137 my ($self) = @_;
138
139 flock($self->{'METADATA_FH'}, LOCK_UN) or
140 cluck("Error when releasing lock on metadata file: $!"),
141 return -1;
142 close($self->{'METADATA_FH'}) or
143 cluck("Error when closing metadata file: $!"),
144 return 0;
145 };
146
147
148 sub metadata_read($) {
149 my ($self) = @_;
150
151 $self->{'METADATA'} = ();
152 seek($self->{'METADATA_FH'}, 0, SEEK_SET) or
153 cluck("Cannot seek to start of metadata file: $!"),
154 return 0;
155 eval {
156 my $parser = new XML::Parser(Style => 'Tree');
157 my $tree = $parser->parse( $self->{'METADATA_FH'} );
158 my $dump = new XML::Dumper;
159 $self->{'METADATA'} = $dump->xml2pl($tree);
160 };
161 $EVAL_ERROR and
162 cluck("Error when reading from metadata file: $EVAL_ERROR"),
163 return 0;
164
165 defined($self->{'METADATA'}->{'version'}) or
166 cluck("Stored data lacks version header"),
167 return 0;
168 ($self->{'METADATA'}->{'version'} == ($METADATA_VERSION)) or
169 cluck("Metadata version mismatch ($self->{'METADATA'}->{'version'} vs. $METADATA_VERSION)"),
170 return 0;
171
172
173 defined($self->{'METADATA'}->{'secret'}) or
174 $self->{'METADATA'}->{'secret'} = Echolot::Tools::make_random ( 16, armor => 1 ),
175 $self->commit();
176
177 return 1;
178 };
179
180 sub metadata_write($) {
181 my ($self) = @_;
182
183 # FIXME XML::Dumper bug workaround
184 # There is a bug in pl2xml that changes data passed (cf. Debian Bug #148969 and #148970
185 # at http://bugs.debian.org/148969 and http://bugs.debian.org/148970
186 require Data::Dumper;
187 my $storedata;
188 eval ( Data::Dumper->Dump( [ $self->{'METADATA'} ], [ 'storedata' ] ));
189
190 my $dump = new XML::Dumper;
191 my $data = $dump->pl2xml($storedata);
192 my $fh = $self->{'METADATA_FH'};
193
194 seek($fh, 0, SEEK_SET) or
195 cluck("Cannot seek to start of metadata file: $!"),
196 return 0;
197 truncate($fh, 0) or
198 cluck("Cannot truncate metadata file to zero length: $!"),
199 return 0;
200 print($fh "<!-- vim:set syntax=xml: -->\n") or
201 cluck("Error when writing to metadata file: $!"),
202 return 0;
203 print($fh $data) or
204 cluck("Error when writing to metadata file: $!"),
205 return 0;
206 $fh->flush();
207
208 return 1;
209 };
210
211
212
213
214
215 sub pingdata_open_one($$$$) {
216 my ($self, $remailer_addr, $type, $key) = @_;
217
218 defined ($self->{'METADATA'}->{'remailers'}->{$remailer_addr}) or
219 cluck ("$remailer_addr does not exist in Metadata"),
220 return 0;
221 defined ($self->{'METADATA'}->{'remailers'}->{$remailer_addr}->{'keys'}) or
222 cluck ("$remailer_addr has no keys in Metadata"),
223 return 0;
224 defined ($self->{'METADATA'}->{'remailers'}->{$remailer_addr}->{'keys'}->{$type}) or
225 cluck ("$remailer_addr type $type does not exist in Metadata"),
226 return 0;
227 defined ($self->{'METADATA'}->{'remailers'}->{$remailer_addr}->{'keys'}->{$type}->{$key}) or
228 cluck ("$remailer_addr type $type key $key does not exist in Metadata"),
229 return 0;
230
231
232 my $basename = $self->{'METADATA'}->{'remailers'}->{$remailer_addr}->{'stats'}->{$type}->{$key};
233 defined($basename) or
234 $basename = $self->{'METADATA'}->{'remailers'}->{$remailer_addr}->{'stats'}->{$type}->{$key} = $remailer_addr.'.'.$type.'.'.$key.'.'.time.'.'.$PROCESS_ID.'_'.Echolot::Globals::get()->{'internalcounter'}++,
235 $self->commit();
236
237 my $filename = $self->{'datadir'} .'/'. $basename;
238
239 for my $direction ('out', 'done') {
240 my $fh = new IO::Handle;
241 if ( -e $filename.'.'.$direction ) {
242 open($fh, '+<' . $filename.'.'.$direction) or
243 cluck("Cannot open $filename.$direction for reading: $!"),
244 return 0;
245 $self->{'PING_FHS'}->{$remailer_addr}->{$type}->{$key}->{$direction} = $fh;
246 } else {
247 open($fh, '+>' . $filename.'.'.$direction) or
248 cluck("Cannot open $filename.$direction for reading: $!"),
249 return 0;
250 $self->{'PING_FHS'}->{$remailer_addr}->{$type}->{$key}->{$direction} = $fh;
251 };
252 flock($fh, LOCK_EX) or
253 cluck("Cannot get exclusive lock on $remailer_addr $type $key $direction pings: $!"),
254 return 0;
255 };
256
257 return 1;
258 };
259
260 sub pingdata_open($) {
261 my ($self) = @_;
262
263 for my $remailer_addr ( keys %{$self->{'METADATA'}->{'remailers'}} ) {
264 for my $type ( keys %{$self->{'METADATA'}->{'remailers'}->{$remailer_addr}->{'keys'}} ) {
265 for my $key ( keys %{$self->{'METADATA'}->{'remailers'}->{$remailer_addr}->{'keys'}->{$type}} ) {
266 $self->pingdata_open_one($remailer_addr, $type, $key);
267 };
268 };
269 };
270 return 1;
271 };
272
273 sub get_ping_fh($$$$$) {
274 my ($self, $remailer_addr, $type, $key, $direction) = @_;
275
276 defined ($self->{'METADATA'}->{'remailers'}->{$remailer_addr}) or
277 cluck ("$remailer_addr does not exist in Metadata"),
278 return 0;
279
280 my @pings;
281 my $fh = $self->{'PING_FHS'}->{$remailer_addr}->{$type}->{$key}->{$direction};
282
283 defined ($fh) or
284 $self->pingdata_open_one($remailer_addr, $type, $key),
285 $fh = $self->{'PING_FHS'}->{$remailer_addr}->{$type}->{$key}->{$direction};
286 defined ($fh) or
287 cluck ("$remailer_addr; type=$type; key=$key has no assigned filehandle for $direction pings"),
288 return 0;
289
290 return $fh;
291 };
292
293 sub pingdata_close() {
294 my ($self) = @_;
295
296 for my $remailer_addr ( keys %{$self->{'PING_FHS'}} ) {
297 for my $type ( keys %{$self->{'PING_FHS'}->{$remailer_addr}} ) {
298 for my $key ( keys %{$self->{'PING_FHS'}->{$remailer_addr}->{$type}} ) {
299 for my $direction ( keys %{$self->{'PING_FHS'}->{$remailer_addr}->{$type}->{$key}} ) {
300
301 my $fh = $self->{'PING_FHS'}->{$remailer_addr}->{$type}->{$key}->{$direction};
302 flock($fh, LOCK_UN) or
303 cluck("Error when releasing lock on $remailer_addr type $type key $key direction $direction pings: $!"),
304 return 0;
305 close ($fh) or
306 cluck("Error when closing $remailer_addr type $type key $key direction $direction pings: $!"),
307 return 0;
308 };
309 };
310 };
311 };
312 return 1;
313 };
314
315 sub get_pings($$$$$) {
316 my ($self, $remailer_addr, $type, $key, $direction) = @_;
317
318 my @pings;
319
320 my $fh = $self->get_ping_fh($remailer_addr, $type, $key, $direction) or
321 cluck ("$remailer_addr; type=$type; key=$key has no assigned filehandle for $direction pings"),
322 return 0;
323
324 seek($fh, 0, SEEK_SET) or
325 cluck("Cannot seek to start of $remailer_addr type $type key $key direction $direction pings: $!"),
326 return 0;
327
328 if ($direction eq 'out') {
329 @pings = map {chomp; $_; } <$fh>;
330 } elsif ($direction eq 'done') {
331 @pings = map {chomp; my @arr = split (/\s+/, $_, 2); \@arr; } <$fh>;
332 } else {
333 confess("What the hell am I doing here? $remailer_addr; $type; $key; $direction"),
334 return 0;
335 };
336 return @pings;
337 };
338
339
340
341
342
343
344 sub register_pingout($$$$) {
345 my ($self, $remailer_addr, $type, $key, $sent_time) = @_;
346
347 #require Data::Dumper;
348 #print Data::Dumper->Dump( [ $self->{'PING_FHS'} ] );
349
350 my $fh = $self->get_ping_fh($remailer_addr, $type, $key, 'out') or
351 cluck ("$remailer_addr; type=$type; key=$key has no assigned filehandle for out pings"),
352 return 0;
353
354 seek($fh, 0, SEEK_END) or
355 cluck("Cannot seek to end of $remailer_addr; type=$type; key=$key; out pings: $!"),
356 return 0;
357 print($fh $sent_time."\n") or
358 cluck("Error when writing to $remailer_addr; type=$type; key=$key; out pings: $!"),
359 return 0;
360 $fh->flush();
361 print "registering pingout at $sent_time for $remailer_addr ($type; $key)\n";
362
363 return 1;
364 };
365
366 sub register_pingdone($$$$$) {
367 my ($self, $remailer_addr, $type, $key, $sent_time, $latency) = @_;
368
369 defined ($self->{'METADATA'}->{'remailers'}->{$remailer_addr}) or
370 cluck ("$remailer_addr does not exist in Metadata"),
371 return 0;
372
373 my @outpings = $self->get_pings($remailer_addr, $type, $key, 'out');
374 my $origlen = scalar (@outpings);
375 @outpings = grep { $_ != $sent_time } @outpings;
376 ($origlen == scalar (@outpings)) and
377 warn("No ping outstanding for $remailer_addr, $key, $sent_time\n"),
378 return 1;
379
380 # write ping to done
381 my $fh = $self->get_ping_fh($remailer_addr, $type, $key, 'done') or
382 cluck ("$remailer_addr; type=$type; key=$key has no assigned filehandle for done pings"),
383 return 0;
384 seek($fh, 0, SEEK_END) or
385 cluck("Cannot seek to end of $remailer_addr out pings: $!"),
386 return 0;
387 print($fh $sent_time." ".$latency."\n") or
388 cluck("Error when writing to $remailer_addr out pings: $!"),
389 return 0;
390 $fh->flush();
391
392 # rewrite outstanding pings
393 $fh = $self->get_ping_fh($remailer_addr, $type, $key, 'out') or
394 cluck ("$remailer_addr; type=$type; key=$key has no assigned filehandle for out pings"),
395 return 0;
396 seek($fh, 0, SEEK_SET) or
397 cluck("Cannot seek to start of outgoing pings file for remailer $remailer_addr; key=$key: $!"),
398 return 0;
399 truncate($fh, 0) or
400 cluck("Cannot truncate outgoing pings file for remailer $remailer_addr; key=$key file to zero length: $!"),
401 return 0;
402 print($fh (join "\n", @outpings), (scalar @outpings ? "\n" : '') ) or
403 cluck("Error when writing to outgoing pings file for remailer $remailer_addr; key=$key file: $!"),
404 return 0;
405 $fh->flush();
406 print "registering pingdone from $sent_time with latency $latency for $remailer_addr ($type; $key)\n";
407
408 return 1;
409 };
410
411
412
413
414
415 sub add_prospective_address($$$$) {
416 my ($self, $addr, $reason, $additional) = @_;
417
418 return 1 if defined $self->{'METADATA'}->{'addresses'}->{$addr};
419 push @{ $self->{'METADATA'}->{'prospective_addresses'}{$addr} }, time().'; '. $reason. '; '. $additional;
420 $self->commit();
421 };
422
423 sub commit_prospective_address($) {
424 my ($self) = @_;
425
426 for my $addr (keys %{$self->{'METADATA'}->{'prospective_addresses'}}) {
427 if (defined $self->{'METADATA'}->{'addresses'}->{$addr}) {
428 delete $self->{'METADATA'}->{'prospective_addresses'}->{$addr};
429 next;
430 };
431
432 # expire old prospective addresses
433 while (@{ $self->{'METADATA'}->{'prospective_addresses'}->{$addr} }) {
434 my ($time, $reason, $additional) = split(/;\s*/, $self->{'METADATA'}->{'prospective_addresses'}->{$addr}->[0] );
435 if ($time < time() - Echolot::Config::get()->{'prospective_addresses_ttl'} ) {
436 shift @{ $self->{'METADATA'}->{'prospective_addresses'}->{$addr} };
437 } else {
438 last;
439 };
440 };
441
442 unless (scalar @{ $self->{'METADATA'}->{'prospective_addresses'}->{$addr} }) {
443 delete $self->{'METADATA'}->{'prospective_addresses'}->{$addr};
444 next;
445 };
446
447 my %reasons;
448 for my $line ( @{ $self->{'METADATA'}->{'prospective_addresses'}->{$addr} } ) {
449 my ($time, $reason, $additional) = split(/;\s*/, $line);
450 push @{ $reasons{$reason} }, $additional;
451 };
452
453 # got prospective by reply to own remailer-conf or remailer-key request
454 if ( defined $reasons{'self-capsstring-conf'} || defined $reasons{'self-capsstring-key'} ) {
455 $self->add_address($addr);
456 delete $self->{'METADATA'}->{'prospective_addresses'}->{$addr};
457 next;
458 }
459
460 # was listed in reliable's remailer-conf reply; @adds holds suggestors
461 my @adds;
462 push @adds, @{ $reasons{'reliable-caps-reply-type1'} } if defined $reasons{'reliable-caps-reply-type1'};
463 push @adds, @{ $reasons{'reliable-caps-reply-type2'} } if defined $reasons{'reliable-caps-reply-type2'};
464 if (scalar @adds) {
465 my %unique;
466 @adds = grep { ! $unique{$_}++; } @adds;
467 if (scalar @adds >= Echolot::Config::get()->{'reliable_auto_add_min'} ) {
468 $self->add_address($addr);
469 delete $self->{'METADATA'}->{'prospective_addresses'}->{$addr};
470 next;
471 };
472 };
473 };
474
475 $self->commit();
476 };
477
478 sub get_addresses($) {
479 my ($self) = @_;
480
481 my @addresses = keys %{$self->{'METADATA'}->{'addresses'}};
482 my @return_data = map {
483 my %tmp;
484 $tmp{'status'} = $self->{'METADATA'}->{'addresses'}->{$_}->{'status'};
485 $tmp{'id'} = $self->{'METADATA'}->{'addresses'}->{$_}->{'id'};
486 $tmp{'address'} = $_;
487 \%tmp;
488 } @addresses;
489 return @return_data;
490 };
491
492 sub add_address($$) {
493 my ($self, $addr) = @_;
494
495 my @all_addresses = $self->get_addresses();
496 my $maxid = 0;
497 for my $addr (@all_addresses) {
498 if ($addr->{'id'} > $maxid) {
499 $maxid = $addr->{'id'};
500 };
501 };
502
503 my $remailer = {
504 id => $maxid + 1,
505 status => 'active',
506 ttl => Echolot::Config::get()->{'addresses_default_ttl'}
507 };
508
509 # FIXME logging and such
510 print "Adding address $addr\n";
511
512 $self->{'METADATA'}->{'addresses'}->{$addr} = $remailer;
513 };
514
515
516 sub get_address_by_id($$) {
517 my ($self, $id) = @_;
518
519 my @addresses = grep {$self->{'METADATA'}->{'addresses'}->{$_}->{'id'} == $id}
520 keys %{$self->{'METADATA'}->{'addresses'}};
521 return undef unless (scalar @addresses);
522 if (scalar @addresses >= 2) {
523 cluck("Searching for address by id '$id' gives more than one result");
524 };
525 my %return_data = %{$self->{'METADATA'}->{'addresses'}->{$addresses[0]}};
526 $return_data{'address'} = $addresses[0];
527 return \%return_data;
528 };
529
530 sub decrease_ttl($$) {
531 my ($self, $address) = @_;
532
533 defined ($self->{'METADATA'}->{'addresses'}->{$address}) or
534 cluck ("$address does not exist in Metadata address list"),
535 return 0;
536 $self->{'METADATA'}->{'addresses'}->{$address}->{'ttl'} --;
537 $self->{'METADATA'}->{'addresses'}->{$address}->{'status'} = 'ttl timeout',
538 warn("Remailer $address disabled: ttl expired\n")
539 if ($self->{'METADATA'}->{'addresses'}->{$address}->{'ttl'} <= 0);
540 # FIXME have proper logging
541 $self->commit();
542 return 1;
543 };
544
545 sub restore_ttl($$) {
546 my ($self, $address) = @_;
547
548 defined ($self->{'METADATA'}->{'addresses'}->{$address}) or
549 cluck ("$address does not exist in Metadata address list"),
550 return 0;
551 $self->{'METADATA'}->{'addresses'}->{$address}->{'ttl'} = Echolot::Config::get()->{'addresses_default_ttl'};
552 $self->{'METADATA'}->{'addresses'}->{$address}->{'status'} = 'active' if
553 ($self->{'METADATA'}->{'addresses'}->{$address}->{'status'} eq 'ttl timeout');
554 $self->commit();
555 return 1;
556 };
557
558 sub set_caps($$$$$$) {
559 my ($self, $type, $caps, $nick, $address, $timestamp) = @_;
560 if (! defined $self->{'METADATA'}->{'remailers'}->{$address}) {
561 $self->{'METADATA'}->{'remailers'}->{$address} =
562 {
563 status => 'active',
564 pingit => Echolot::Config::get()->{'ping_new'},
565 showit => Echolot::Config::get()->{'show_new'},
566 };
567 };
568
569 if (! defined $self->{'METADATA'}->{'remailers'}->{$address}->{'conf'}) {
570 $self->{'METADATA'}->{'remailers'}->{$address}->{'conf'} =
571 {
572 nick => $nick,
573 type => $type,
574 capabilities => $caps,
575 last_update => $timestamp
576 };
577 } else {
578 my $conf = $self->{'METADATA'}->{'remailers'}->{$address}->{'conf'};
579 if ($conf->{'last_update'} >= $timestamp) {
580 warn ("Stored data is already newer for remailer $nick\n");
581 return 1;
582 };
583 $conf->{'last_update'} = $timestamp;
584 if ($conf->{'nick'} ne $nick) {
585 warn ($conf->{'nick'}." was renamed to $nick\n");
586 $conf->{'nick'} = $nick;
587 };
588 if ($conf->{'capabilities'} ne $caps) {
589 warn ("$nick has a new caps string '$caps' old: '".$conf->{'capabilities'}."'\n");
590 $conf->{'capabilities'} = $caps;
591 };
592 if ($conf->{'type'} ne $type) {
593 warn ("$nick has a new type string '$type'\n");
594 $conf->{'type'} = $type;
595 };
596 };
597 $self->commit();
598
599 return 1;
600 };
601
602 sub set_key($$$$$$$$$) {
603 my ($self, $type, $nick, $address, $key, $keyid, $version, $caps, $summary, $timestamp) = @_;
604
605 if (! defined $self->{'METADATA'}->{'remailers'}->{$address}) {
606 $self->{'METADATA'}->{'remailers'}->{$address} =
607 {
608 status => 'active',
609 pingit => Echolot::Config::get()->{'ping_new'},
610 showit => Echolot::Config::get()->{'show_new'},
611 };
612 };
613
614 if (! defined $self->{'METADATA'}->{'remailers'}->{$address}->{'keys'}) {
615 $self->{'METADATA'}->{'remailers'}->{$address}->{'keys'} = {};
616 };
617 if (! defined $self->{'METADATA'}->{'remailers'}->{$address}->{'keys'}->{$type}) {
618 $self->{'METADATA'}->{'remailers'}->{$address}->{'keys'}->{$type} = {};
619 };
620
621 if (! defined $self->{'METADATA'}->{'remailers'}->{$address}->{'keys'}->{$type}->{$keyid}) {
622 $self->{'METADATA'}->{'remailers'}->{$address}->{'keys'}->{$type}->{$keyid} =
623 {
624 key => $key,
625 summary => $summary,
626 nick => $nick,
627 last_update => $timestamp
628 };
629 } else {
630 my $keyref = $self->{'METADATA'}->{'remailers'}->{$address}->{'keys'}->{$type}->{$keyid};
631 if ($keyref->{'last_update'} >= $timestamp) {
632 warn ("Stored data is already newer for remailer $nick\n");
633 return 1;
634 };
635 $keyref->{'last_update'} = $timestamp;
636 if ($keyref->{'nick'} ne $nick) {
637 warn ("$nick has a new key nick string '$nick' old: '".$keyref->{'nick'}."'\n");
638 $keyref->{'nick'} = $nick;
639 };
640 if ($keyref->{'summary'} ne $summary) {
641 warn ("$nick has a new key summary string '$summary' old: '".$keyref->{'summary'}."'\n");
642 $keyref->{'summary'} = $summary;
643 };
644 if ($keyref->{'key'} ne $key) {
645 #warn ("$nick has a new key string '$key' old: '".$keyref->{'key'}."' - This probably should not happen\n");
646 warn ("$nick has a new key string for same keyid $keyid\n");
647 $keyref->{'key'} = $key;
648 };
649 };
650 $self->commit();
651
652 return 1;
653 };
654
655 sub get_secret($) {
656 my ($self) = @_;
657
658 return $self->{'METADATA'}->{'secret'};
659 };
660
661 sub get_remailers($) {
662 my ($self) = @_;
663
664 my @remailers = keys %{$self->{'METADATA'}->{'remailers'}};
665 return @remailers;
666 };
667
668 sub get_types($$) {
669 my ($self, $remailer) = @_;
670
671 defined ($self->{'METADATA'}->{'remailers'}->{$remailer}) or
672 cluck ("$remailer does not exist in Metadata remailer list"),
673 return 0;
674
675 return () unless defined $self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'};
676 my @types = keys %{$self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}};
677 return @types;
678 };
679
680 sub has_type($$$) {
681 my ($self, $remailer, $type) = @_;
682
683 defined ($self->{'METADATA'}->{'remailers'}->{$remailer}) or
684 cluck ("$remailer does not exist in Metadata remailer list"),
685 return 0;
686
687 return 0 unless defined $self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'};
688 return 0 unless defined $self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}->{$type};
689 return 0 unless scalar keys %{$self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}->{$type}};
690 return 1;
691 };
692
693 sub get_keys($$) {
694 my ($self, $remailer, $type) = @_;
695
696 defined ($self->{'METADATA'}->{'remailers'}->{$remailer}) or
697 cluck ("$remailer does not exist in Metadata remailer list"),
698 return 0;
699
700 defined ($self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}->{$type}) or
701 cluck ("$remailer does not have type '$type' in Metadata remailer list"),
702 return 0;
703
704 my @keys = keys %{$self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}->{$type}};
705 return @keys;
706 };
707
708 sub get_key($$$$) {
709 my ($self, $remailer, $type, $key) = @_;
710
711 defined ($self->{'METADATA'}->{'remailers'}->{$remailer}) or
712 cluck ("$remailer does not exist in Metadata remailer list"),
713 return 0;
714
715 defined ($self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}->{$type}) or
716 cluck ("$remailer does not have type '$type' in Metadata remailer list"),
717 return 0;
718
719 defined ($self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}->{$type}->{$key}) or
720 cluck ("$remailer does not have key '$key' in type '$type' in Metadata remailer list"),
721 return 0;
722
723 my %result = (
724 summary => $self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}->{$type}->{$key}->{'summary'},
725 key => $self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}->{$type}->{$key}->{'key'},
726 nick => $self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}->{$type}->{$key}->{'nick'},
727 last_update => $self->{'METADATA'}->{'remailers'}->{$remailer}->{'keys'}->{$type}->{$key}->{'last_update'}
728 );
729
730 return %result;
731 };
732
733 sub get_capabilities($$) {
734 my ($self, $remailer) = @_;
735
736 return undef unless defined $self->{'METADATA'}->{'remailers'}->{$remailer}->{'conf'};
737 return $self->{'METADATA'}->{'remailers'}->{$remailer}->{'conf'}->{'capabilities'};
738 };
739
740 sub get_nick($$) {
741 my ($self, $remailer) = @_;
742
743 return undef unless defined $self->{'METADATA'}->{'remailers'}->{$remailer}->{'conf'};
744 return $self->{'METADATA'}->{'remailers'}->{$remailer}->{'conf'}->{'nick'};
745 };
746
747 =back
748
749 =cut
750
751 # vim: set ts=4 shiftwidth=4:

  ViewVC Help
Powered by ViewVC 1.1.5