+=head2 getparsedaddrs
+
+ my $address = getparsedaddrs($address);
+ my @address = getparsedaddrs($address);
+
+Returns the output from Mail::Address->parse, or the cached output if
+this address has been parsed before. In SCALAR context returns the
+first address parsed.
+
+=cut
+
+
+our %_parsedaddrs;
+sub getparsedaddrs {
+ my $addr = shift;
+ return () unless defined $addr;
+ return wantarray?@{$_parsedaddrs{$addr}}:$_parsedaddrs{$addr}[0]
+ if exists $_parsedaddrs{$addr};
+ {
+ # don't display the warnings from Mail::Address->parse
+ local $SIG{__WARN__} = sub { };
+ @{$_parsedaddrs{$addr}} = Mail::Address->parse($addr);
+ }
+ return wantarray?@{$_parsedaddrs{$addr}}:$_parsedaddrs{$addr}[0];
+}
+
+our $_maintainer;
+our $_maintainer_rev;
+sub getmaintainers {
+ return $_maintainer if $_maintainer;
+ my %maintainer;
+ my %maintainer_rev;
+ for my $file (@config{qw(maintainer_file maintainer_file_override pseduo_maint_file)}) {
+ next unless defined $file;
+ my $maintfile = new IO::File $file,'r' or
+ &quitcgi("Unable to open $file: $!");
+ while(<$maintfile>) {
+ next unless m/^(\S+)\s+(\S.*\S)\s*$/;
+ ($a,$b)=($1,$2);
+ $a =~ y/A-Z/a-z/;
+ $maintainer{$a}= $b;
+ for my $maint (map {lc($_->address)} getparsedaddrs($b)) {
+ push @{$maintainer_rev{$maint}},$a;
+ }
+ }
+ close($maintfile);
+ }
+ $_maintainer = \%maintainer;
+ $_maintainer_rev = \%maintainer_rev;
+ return $_maintainer;
+}
+sub getmaintainers_reverse{
+ return $_maintainer_rev if $_maintainer_rev;
+ getmaintainers();
+ return $_maintainer_rev;
+}
+
+=head2 getpseudodesc
+
+ my $pseudopkgdesc = getpseudodesc(...);
+
+Returns the entry for a pseudo package from the
+$config{pseudo_desc_file}. In cases where pseudo_desc_file is not
+defined, returns an empty arrayref.
+
+This function can be used to see if a particular package is a
+pseudopackage or not.
+
+=cut
+
+our $_pseudodesc;
+sub getpseudodesc {
+ return $_pseudodesc if $_pseudodesc;
+ my %pseudodesc;
+
+ if (not defined $config{pseudo_desc_file}) {
+ $_pseudodesc = {};
+ return $_pseudodesc;
+ }
+ my $pseudo = IO::File->new($config{pseudo_desc_file},'r')
+ or die "Unable to open $config{pseudo_desc_file}: $!";
+ while(<$pseudo>) {
+ next unless m/^(\S+)\s+(\S.*\S)\s*$/;
+ $pseudodesc{lc $1} = $2;
+ }
+ close($pseudo);
+ $_pseudodesc = \%pseudodesc;
+ return $_pseudodesc;
+}
+
+
+=head1 DATE
+
+ my $english = secs_to_english($seconds);
+ my ($days,$english) = secs_to_english($seconds);
+
+XXX This should probably be changed to use Date::Calc
+
+=cut
+
+sub secs_to_english{
+ my ($seconds) = @_;
+
+ my $days = int($seconds / 86400);
+ my $years = int($days / 365);
+ $days %= 365;
+ my $result;
+ my @age;
+ push @age, "1 year" if ($years == 1);
+ push @age, "$years years" if ($years > 1);
+ push @age, "1 day" if ($days == 1);
+ push @age, "$days days" if ($days > 1);
+ $result .= join(" and ", @age);
+
+ return wantarray?(int($seconds/86400),$result):$result;
+}
+
+