aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Youri/Check/Output
diff options
context:
space:
mode:
authorNicolas Vigier <boklm@mageia.org>2011-01-06 01:07:55 +0000
committerNicolas Vigier <boklm@mageia.org>2011-01-06 01:07:55 +0000
commita4f149873af1e9cff9ab0829adfcd3eca1a3780d (patch)
treec1345b951f4c67e3e9c5bf57f984c3e9f901f17f /lib/Youri/Check/Output
downloadmga-youri-core-a4f149873af1e9cff9ab0829adfcd3eca1a3780d.tar
mga-youri-core-a4f149873af1e9cff9ab0829adfcd3eca1a3780d.tar.gz
mga-youri-core-a4f149873af1e9cff9ab0829adfcd3eca1a3780d.tar.bz2
mga-youri-core-a4f149873af1e9cff9ab0829adfcd3eca1a3780d.tar.xz
mga-youri-core-a4f149873af1e9cff9ab0829adfcd3eca1a3780d.zip
search in core, nonfree, tainted instead of main, contrib
Diffstat (limited to 'lib/Youri/Check/Output')
-rw-r--r--lib/Youri/Check/Output/File.pm203
-rw-r--r--lib/Youri/Check/Output/File/Format.pm66
-rw-r--r--lib/Youri/Check/Output/File/Format/HTML.pm222
-rw-r--r--lib/Youri/Check/Output/File/Format/RSS.pm68
-rw-r--r--lib/Youri/Check/Output/File/Format/Text.pm88
-rw-r--r--lib/Youri/Check/Output/Mail.pm156
-rw-r--r--lib/Youri/Check/Output/Mail/Format.pm66
-rw-r--r--lib/Youri/Check/Output/Mail/Format/HTML.pm158
-rw-r--r--lib/Youri/Check/Output/Mail/Format/Text.pm83
9 files changed, 1110 insertions, 0 deletions
diff --git a/lib/Youri/Check/Output/File.pm b/lib/Youri/Check/Output/File.pm
new file mode 100644
index 0000000..5363e8e
--- /dev/null
+++ b/lib/Youri/Check/Output/File.pm
@@ -0,0 +1,203 @@
+# $Id: Text.pm 523 2005-10-11 08:36:49Z misc $
+package Youri::Check::Output::File;
+
+=head1 NAME
+
+Youri::Check::Output::File - Report results in files
+
+=head1 DESCRIPTION
+
+This plugin reports results in files. Additional subplugins handle specific
+formats.
+
+=cut
+
+use warnings;
+use strict;
+use Carp;
+use File::Basename;
+use File::Path;
+use DateTime;
+use Youri::Utils;
+use base 'Youri::Check::Output';
+
+sub _init {
+ my $self = shift;
+ my %options = (
+ to => '', # target directory
+ noclean => 0, # don't clean up target directory
+ noempty => 0, # don't generate empty reports
+ formats => undef,
+ @_
+ );
+
+ croak "no format defined" unless $options{formats};
+ croak "formats should be an hashref" unless ref $options{formats} eq 'HASH';
+
+ my $now = DateTime->now(time_zone => 'local');
+ my $time = "the " . $now->ymd() . " at " . $now->hms();
+
+ $self->{_to} = $options{to};
+ $self->{_noclean} = $options{noclean};
+ $self->{_noempty} = $options{noempty};
+ $self->{_time} = $time;
+
+ foreach my $id (keys %{$options{formats}}) {
+ print "Creating format $id\n" if $options{verbose};
+ eval {
+ push(
+ @{$self->{_formats}},
+ create_instance(
+ 'Youri::Check::Output::File::Format',
+ id => $id,
+ test => $options{test},
+ verbose => $options{verbose},
+ %{$options{formats}->{$id}}
+ )
+ );
+ };
+ print STDERR "Failed to create format $id: $@\n" if $@;
+ }
+
+ croak "no formats created" unless @{$self->{_formats}};
+}
+
+sub _init_report {
+ my ($self) = @_;
+
+ # clean up output directory
+ unless ($self->{_test} || $self->{_noclean} || !$self->{_to}) {
+ my @files = glob($self->{_to} . '/*');
+ rmtree(\@files) if @files;
+ }
+}
+
+sub _global_report {
+ my ($self, $resultset, $type, $columns, $links) = @_;
+
+ foreach my $format (@{$self->{_formats}}) {
+ my $iterator = $resultset->get_iterator(
+ $type,
+ [ 'package' ]
+ );
+
+ return if $self->{_noempty} && ! $iterator->has_results();
+
+ my $content = $format->get_report(
+ $self->{_time},
+ "$type global report",
+ $iterator,
+ $type,
+ $columns,
+ $links,
+ undef
+ );
+
+ # create and register file
+ my $extension = $format->extension();
+ $self->_write_file(
+ "$self->{_to}/$type.$extension",
+ $content
+ );
+ push(
+ @{$self->{_files}->{global}->{$type}},
+ $extension
+ );
+ }
+}
+
+sub _individual_report {
+ my ($self, $resultset, $type, $columns, $links, $maintainer) = @_;
+
+ foreach my $format (@{$self->{_formats}}) {
+ my $iterator = $resultset->get_iterator(
+ $type,
+ [ 'package' ],
+ { maintainer => [ $maintainer ] }
+ );
+
+ return if $self->{_noempty} && ! $iterator->has_results();
+
+ my $content = $format->get_report(
+ $self->{_time},
+ "$type individual report for $maintainer",
+ $iterator,
+ $type,
+ $columns,
+ $links,
+ $maintainer
+ );
+
+ # create and register file
+ my $extension = $format->extension();
+ $self->_write_file(
+ "$self->{_to}/$maintainer/$type.$extension",
+ $content
+ );
+ push(
+ @{$self->{_files}->{maintainers}->{$maintainer}->{$type}},
+ $extension
+ );
+ }
+}
+
+sub _finish_report {
+ my ($self, $types, $maintainers) = @_;
+
+ foreach my $format (@{$self->{_formats}}) {
+ next unless $format->can('get_index');
+ my $extension = $format->extension();
+ print STDERR "writing global index page\n" if $self->{_verbose};
+ $self->_write_file(
+ "$self->{_to}/index.$extension",
+ $format->get_index(
+ $self->{_time},
+ "QA global report",
+ $self->{_files}->{global},
+ [ keys %{$self->{_files}->{maintainers}} ],
+ )
+ );
+ foreach my $maintainer (@$maintainers) {
+ print STDERR "writing index page for $maintainer\n" if $self->{_verbose};
+
+ $self->_write_file(
+ "$self->{_to}/$maintainer/index.$extension",
+ $format->get_index(
+ $self->{_time},
+ "QA report for $maintainer",
+ $self->{_files}->{maintainers}->{$maintainer},
+ undef,
+ )
+ );
+ }
+ }
+}
+
+sub _write_file {
+ my ($self, $file, $content) = @_;
+
+ return unless $content;
+
+ my $dirname = dirname($file);
+ mkpath($dirname) unless -d $dirname;
+
+ if ($self->{_test}) {
+ *OUT = *STDOUT;
+ } else {
+ open(OUT, ">$file") or die "Can't open file $file: $!";
+ }
+
+ print OUT $$content;
+
+ close(OUT) unless $self->{_test};
+}
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2002-2006, YOURI project
+
+This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/lib/Youri/Check/Output/File/Format.pm b/lib/Youri/Check/Output/File/Format.pm
new file mode 100644
index 0000000..c91a28b
--- /dev/null
+++ b/lib/Youri/Check/Output/File/Format.pm
@@ -0,0 +1,66 @@
+# $Id: Base.pm 579 2006-01-09 21:17:54Z guillomovitch $
+package Youri::Check::Output::File::Format;
+
+=head1 NAME
+
+Youri::Check::Output::File::Format - Abstract file format support
+
+=head1 DESCRIPTION
+
+This abstract class defines the format support interface for
+L<Youri::Check::Output::File>.
+
+=cut
+
+use warnings;
+use strict;
+use Carp;
+
+sub new {
+ my $class = shift;
+ croak "Abstract class" if $class eq __PACKAGE__;
+
+ my %options = (
+ id => '',
+ test => 0,
+ verbose => 0,
+ @_
+ );
+
+ my $self = bless {
+ _id => $options{id},
+ _test => $options{test},
+ _verbose => $options{verbose},
+ }, $class;
+
+ $self->_init(%options);
+
+ return $self;
+}
+
+sub _init {
+ # do nothing
+}
+
+=head2 get_id()
+
+Returns format handler identity.
+
+=cut
+
+sub get_id {
+ my ($self) = @_;
+ croak "Not a class method" unless ref $self;
+
+ return $self->{_id};
+}
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2002-2006, YOURI project
+
+This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/lib/Youri/Check/Output/File/Format/HTML.pm b/lib/Youri/Check/Output/File/Format/HTML.pm
new file mode 100644
index 0000000..c498bbd
--- /dev/null
+++ b/lib/Youri/Check/Output/File/Format/HTML.pm
@@ -0,0 +1,222 @@
+# $Id: HTML.pm 1179 2006-08-05 08:30:57Z warly $
+package Youri::Check::Output::File::Format::HTML;
+
+=head1 NAME
+
+Youri::Check::Output::File::Format::HTML - File HTML format support
+
+=head1 DESCRIPTION
+
+This format plugin for L<Youri::Check::Output::File> provides HTML format
+support.
+
+=cut
+
+use warnings;
+use strict;
+use Carp;
+use CGI;
+use base 'Youri::Check::Output::File::Format';
+
+sub extension {
+ return 'html';
+}
+
+sub _init {
+ my $self = shift;
+ my %options = (
+ style => <<EOF, # css style
+h1 {
+ text-align:center;
+}
+table {
+ border-style:solid;
+ border-width:1px;
+ border-color:black;
+ width:100%;
+}
+tr.odd {
+ background-color:white;
+}
+tr.even {
+ background-color:silver;
+}
+p.footer {
+ font-size:smaller;
+ text-align:center;
+}
+EOF
+ @_
+ );
+
+ $self->{_style} = $options{style};
+ $self->{_cgi} = CGI->new();
+}
+
+sub get_report {
+ my ($self, $time, $title, $iterator, $type, $columns, $links, $maintainer) = @_;
+
+ my $content;
+ my $lead_columns = [
+ $maintainer ?
+ qw/package media/ :
+ qw/package media maintainer/
+ ];
+ my $line;
+ my @results;
+ $content .= $self->{_cgi}->start_table();
+ $content .= $self->{_cgi}->Tr([
+ $self->{_cgi}->th([
+ @$lead_columns,
+ @$columns
+ ])
+ ]);
+ while (my $result = $iterator->get_result()) {
+ if (@results && $result->{package} ne $results[0]->{package}) {
+ $content .= $self->_get_formated_results(
+ $lead_columns,
+ $columns,
+ $links,
+ $line++ % 2 ? 'odd' : 'even',
+ \@results
+ );
+ @results = ();
+ }
+ push(@results, $result);
+ }
+ $content .= $self->_get_formated_results(
+ $lead_columns,
+ $columns,
+ $links,
+ $line++ % 2 ? 'odd' : 'even',
+ \@results
+ );
+ $content .= $self->{_cgi}->end_table();
+
+ return $self->_get_html_page($time, $title, \$content);
+}
+
+sub get_index {
+ my ($self, $time, $title, $reports, $maintainers) = @_;
+
+ my $content;
+
+ if ($reports) {
+ $content .= $self->{_cgi}->h2("Reports");
+ my @types = keys %{$reports};
+
+ $content .= $self->{_cgi}->start_ul();
+ foreach my $type (sort @types) {
+ my $item;
+ $item = $self->{_cgi}->a(
+ { href => "$type.html" },
+ $type
+ );
+ foreach my $extension (@{$reports->{$type}}) {
+ next if ($extension eq extension());
+ $item .= " ".$self->{_cgi}->a(
+ { href => "$type.$extension" },
+ "[$extension]"
+ );
+ }
+ $content .= $self->{_cgi}->li($item);
+ }
+ $content .= $self->{_cgi}->end_ul();
+ }
+
+ if ($maintainers) {
+ $content .= $self->{_cgi}->h2("Individual reports");
+
+ $content .= $self->{_cgi}->start_ul();
+ foreach my $maintainer (sort @{$maintainers}) {
+ $content .= $self->{_cgi}->li(
+ $self->{_cgi}->a(
+ { href => "$maintainer/index.html" },
+ _obfuscate($maintainer)
+ )
+ );
+ }
+ $content .= $self->{_cgi}->end_ul();
+ }
+
+ return $self->_get_html_page($time, $title, \$content);
+}
+
+sub _get_formated_results {
+ my ($self, $lead_columns, $columns, $links, $class, $results) = @_;
+
+ my $content;
+ $content .= $self->{_cgi}->end_Tr();
+ for my $i (0 .. $#$results) {
+ $content .= $self->{_cgi}->start_Tr(
+ { class => $class }
+ );
+ if ($i == 0) {
+ # first line contains spanned cells
+ $content .= $self->{_cgi}->td(
+ { rowspan => scalar @$results },
+ [
+ map { $results->[$i]->{$_} }
+ @$lead_columns
+ ]
+ );
+ }
+ $content .= $self->{_cgi}->td(
+ [
+ map {
+ $links->{$_} && $results->[$i]->{$links->{$_}} ?
+ $self->{_cgi}->a(
+ { href => $results->[$i]->{$links->{$_}} },
+ $self->{_cgi}->escapeHTML($results->[$i]->{$_})
+ ) :
+ $self->{_cgi}->escapeHTML($results->[$i]->{$_})
+ } @$columns
+ ]
+ );
+ $content .= $self->{_cgi}->end_Tr();
+ }
+
+ return $content;
+}
+
+
+sub _get_html_page {
+ my ($self, $time, $title, $body) = @_;
+
+ my $content;
+ $content .= $self->{_cgi}->start_html(
+ -title => $title,
+ -style => { code => $self->{_style} }
+ );
+ $content .= $self->{_cgi}->h1($title);
+ $content .= $$body;
+ $content .= $self->{_cgi}->hr();
+ $content .= $self->{_cgi}->p(
+ { class => 'footer' },
+ "Page generated $time"
+ );
+ $content .= $self->{_cgi}->end_html();
+
+ return \$content;
+}
+
+sub _obfuscate {
+ my ($email) = @_;
+
+ return unless $email;
+
+ $email =~ s/\@/ at /;
+ $email =~ s/\./ dot /;
+
+ return $email;
+}
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2002-2006, YOURI project
+
+This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/lib/Youri/Check/Output/File/Format/RSS.pm b/lib/Youri/Check/Output/File/Format/RSS.pm
new file mode 100644
index 0000000..66ffc61
--- /dev/null
+++ b/lib/Youri/Check/Output/File/Format/RSS.pm
@@ -0,0 +1,68 @@
+# $Id$
+package Youri::Check::Output::File::Format::RSS;
+
+=head1 NAME
+
+Youri::Check::Output::File::Format::RSS - File RSS format support
+
+=head1 DESCRIPTION
+
+This format plugin for L<Youri::Check::Output::File> provides RSS format
+support.
+
+=cut
+
+use warnings;
+use strict;
+use Carp;
+use XML::RSS;
+use base 'Youri::Check::Output::File::Format';
+
+sub extension {
+ return 'rss';
+}
+
+sub get_report {
+ my ($self, $time, $title, $iterator, $type, $columns, $links, $maintainer) = @_;
+
+ return unless $maintainer;
+
+ my $rss = new XML::RSS (version => '2.0');
+ $rss->channel(
+ title => $title,
+ description => $title,
+ language => 'en',
+ ttl => 1440
+ );
+
+ while (my $result = $iterator->get_result()) {
+ if ($type eq 'updates') {
+ $rss->add_item(
+ title => "$result->{package} $result->{available} is available",
+ description => "Current version is $result->{current}",
+ link => $result->{url} ?
+ $result->{url} : $result->{source},
+ guid => "$result->{package}-$result->{available}"
+ );
+ } else {
+ $rss->add_item(
+ title => "[$type] $result->{package}",
+ description => join("\n", (map { $result->{$_} || '' } @$columns)),
+ link => $result->{url},
+ guid => "$type-$result->{package}"
+ );
+ }
+ }
+
+ return \$rss->as_string();
+}
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2002-2006, YOURI project
+
+This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/lib/Youri/Check/Output/File/Format/Text.pm b/lib/Youri/Check/Output/File/Format/Text.pm
new file mode 100644
index 0000000..d9f774d
--- /dev/null
+++ b/lib/Youri/Check/Output/File/Format/Text.pm
@@ -0,0 +1,88 @@
+# $Id: Text.pm 1179 2006-08-05 08:30:57Z warly $
+package Youri::Check::Output::File::Format::Text;
+
+=head1 NAME
+
+Youri::Check::Output::File::Format::Text - File text format support
+
+=head1 DESCRIPTION
+
+This format plugin for L<Youri::Check::Output::File> provides text format
+support.
+
+=cut
+
+use warnings;
+use strict;
+use Carp;
+use base 'Youri::Check::Output::File::Format';
+
+sub extension {
+ return 'txt';
+}
+
+sub get_report {
+ my ($self, $time, $title, $iterator, $type, $columns, $links, $maintainer) = @_;
+
+ my $content;
+ $content .= $title;
+ $content .= "\n";
+
+ my $lead_columns = [
+ $maintainer ?
+ qw/package media/ :
+ qw/package media maintainer/
+ ];
+ my @results;
+ $content .= join("\t", @$lead_columns, @$columns) . "\n";
+ while (my $result = $iterator->get_result()) {
+ if (@results && $result->{package} ne $results[0]->{package}) {
+ $content .= $self->_get_formated_results(
+ $lead_columns,
+ $columns,
+ \@results
+ );
+ @results = ();
+ }
+ push(@results, $result);
+ }
+ $content .= $self->_get_formated_results(
+ $lead_columns,
+ $columns,
+ \@results
+ );
+
+ $content .= "\n";
+ $content .= "Page generated $time\n";
+
+ return \$content;
+}
+
+sub _get_formated_results {
+ my ($self, $lead_columns, $columns, $results) = @_;
+
+ my $content;
+ $content .= join(
+ "\t",
+ (map { $results->[0]->{$_} || '' } @$lead_columns),
+ (map { $results->[0]->{$_} || '' } @$columns)
+ ) . "\n";
+ for my $i (1 .. $#$results) {
+ $content .= join(
+ "\t",
+ (map { '' } @$lead_columns),
+ (map { $results->[$i]->{$_} || '' } @$columns)
+ ) . "\n";
+ }
+ return $content;
+}
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2002-2006, YOURI project
+
+This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/lib/Youri/Check/Output/Mail.pm b/lib/Youri/Check/Output/Mail.pm
new file mode 100644
index 0000000..eb9a1f2
--- /dev/null
+++ b/lib/Youri/Check/Output/Mail.pm
@@ -0,0 +1,156 @@
+# $Id: Mail.pm 1179 2006-08-05 08:30:57Z warly $
+package Youri::Check::Output::Mail;
+
+=head1 NAME
+
+Youri::Check::Output::Mail - Report results by mail
+
+=head1 DESCRIPTION
+
+This plugin reports results by mail. Additional subplugins handle specific
+formats.
+
+=cut
+
+use warnings;
+use strict;
+use Carp;
+use MIME::Entity;
+use Youri::Utils;
+use base 'Youri::Check::Output';
+
+sub _init {
+ my $self = shift;
+ my %options = (
+ from => '', # mail from header
+ to => '', # mail to header
+ reply_to => '', # mail reply-to header
+ mta => '', # mta path
+ noempty => 1, # don't generate empty reports
+ formats => {},
+ @_
+ );
+
+ croak "no format defined" unless $options{formats};
+ croak "formats should be an hashref" unless ref $options{formats} eq 'HASH';
+
+ $self->{_from} = $options{from};
+ $self->{_to} = $options{to};
+ $self->{_reply_to} = $options{reply_to};
+ $self->{_mta} = $options{mta};
+ $self->{_noempty} = $options{noempty};
+
+ foreach my $id (keys %{$options{formats}}) {
+ print "Creating format $id\n" if $options{verbose};
+ eval {
+ push(
+ @{$self->{_formats}},
+ create_instance(
+ 'Youri::Check::Output::Mail::Format',
+ id => $id,
+ test => $options{test},
+ verbose => $options{verbose},
+ %{$options{formats}->{$id}}
+ )
+ );
+ };
+ print STDERR "Failed to create format $id: $@\n" if $@;
+ }
+
+ croak "no formats created" unless @{$self->{_formats}};
+}
+
+sub _global_report {
+ my ($self, $resultset, $type, $columns, $links) = @_;
+
+ foreach my $format (@{$self->{_formats}}) {
+ my $iterator = $resultset->get_iterator(
+ $type,
+ [ 'package' ]
+ );
+
+ return if $self->{_noempty} && ! $iterator->has_results();
+
+ my $content = $format->get_report(
+ $self->{_time},
+ "$type global report",
+ $iterator,
+ $type,
+ $columns,
+ $links,
+ undef
+ );
+
+ $self->_send_mail(
+ $format->type(),
+ $self->{_to},
+ "$type global report",
+ $content,
+ );
+ }
+}
+
+sub _individual_report {
+ my ($self, $resultset, $type, $columns, $links, $maintainer) = @_;
+
+ foreach my $format (@{$self->{_formats}}) {
+ my $iterator = $resultset->get_iterator(
+ $type,
+ [ 'package' ],
+ { maintainer => [ $maintainer ] }
+ );
+
+ return if $self->{_noempty} && ! $iterator->has_results();
+
+ my $content = $format->get_report(
+ $self->{_time},
+ "$type individual report for $maintainer",
+ $iterator,
+ $type,
+ $columns,
+ $links,
+ $maintainer
+ );
+
+ $self->_send_mail(
+ $format->type(),
+ $maintainer,
+ "$type individual report for $maintainer",
+ $content,
+ );
+ }
+
+}
+
+sub _send_mail {
+ my ($self, $type, $to, $subject, $content) = @_;
+
+ return unless $content;
+
+ my $mail = MIME::Entity->build(
+ 'Type' => $type,
+ 'From' => $self->{_from},
+ 'Reply-To' => $self->{_reply_to},
+ 'To' => $to,
+ 'Subject' => $subject,
+ 'Data' => $$content
+ );
+
+ if ($self->{_test}) {
+ $mail->print(\*STDOUT);
+ } else {
+ open(MAIL, "| $self->{_mta} -t -oi -oem") or die "Can't open MTA program: $!";
+ $mail->print(\*MAIL);
+ close MAIL;
+ }
+}
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2002-2006, YOURI project
+
+This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/lib/Youri/Check/Output/Mail/Format.pm b/lib/Youri/Check/Output/Mail/Format.pm
new file mode 100644
index 0000000..dee269e
--- /dev/null
+++ b/lib/Youri/Check/Output/Mail/Format.pm
@@ -0,0 +1,66 @@
+# $Id: Base.pm 579 2006-01-09 21:17:54Z guillomovitch $
+package Youri::Check::Output::Mail::Format;
+
+=head1 NAME
+
+Youri::Check::Output::Mail::Format - Abstract mail format support
+
+=head1 DESCRIPTION
+
+This abstract class defines the format support interface for
+L<Youri::Check::Output::Mail>.
+
+=cut
+
+use warnings;
+use strict;
+use Carp;
+
+sub new {
+ my $class = shift;
+ croak "Abstract class" if $class eq __PACKAGE__;
+
+ my %options = (
+ id => '',
+ test => 0,
+ verbose => 0,
+ @_
+ );
+
+ my $self = bless {
+ _id => $options{id},
+ _test => $options{test},
+ _verbose => $options{verbose},
+ }, $class;
+
+ $self->_init(%options);
+
+ return $self;
+}
+
+sub _init {
+ # do nothing
+}
+
+=head2 get_id()
+
+Returns format handler identity.
+
+=cut
+
+sub get_id {
+ my ($self) = @_;
+ croak "Not a class method" unless ref $self;
+
+ return $self->{_id};
+}
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2002-2006, YOURI project
+
+This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/lib/Youri/Check/Output/Mail/Format/HTML.pm b/lib/Youri/Check/Output/Mail/Format/HTML.pm
new file mode 100644
index 0000000..8ed4b28
--- /dev/null
+++ b/lib/Youri/Check/Output/Mail/Format/HTML.pm
@@ -0,0 +1,158 @@
+# $Id: Mail.pm 580 2006-01-11 22:59:36Z guillomovitch $
+package Youri::Check::Output::Mail::Format::HTML;
+
+=head1 NAME
+
+Youri::Check::Output::Mail::Format::HTML - Mail HTML format support
+
+=head1 DESCRIPTION
+
+This format plugin for L<Youri::Check::Output::Mail> provides HTML format
+support.
+
+=cut
+
+use warnings;
+use strict;
+use Carp;
+use CGI;
+use base 'Youri::Check::Output::Mail::Format';
+
+sub type {
+ return 'text/html';
+}
+
+sub _init {
+ my $self = shift;
+ my %options = (
+ style => <<EOF, # css style
+h1 {
+ text-align:center;
+}
+table {
+ border-style:solid;
+ border-width:1px;
+ border-color:black;
+ width:100%;
+}
+tr.odd {
+ background-color:white;
+}
+tr.even {
+ background-color:silver;
+}
+p.footer {
+ font-size:smaller;
+ text-align:center;
+}
+EOF
+ @_
+ );
+
+ $self->{_style} = $options{style};
+ $self->{_cgi} = CGI->new();
+}
+
+sub get_report {
+ my ($self, $time, $title, $iterator, $type, $columns, $links, $maintainer) = @_;
+
+ my $body;
+ my $lead_columns = [
+ $maintainer ?
+ qw/package media/ :
+ qw/package media maintainer/
+ ];
+ my $line;
+ my @results;
+ $body .= $self->{_cgi}->start_table();
+ $body .= $self->{_cgi}->Tr([
+ $self->{_cgi}->th([
+ @$lead_columns,
+ @$columns
+ ])
+ ]);
+ while (my $result = $iterator->get_result()) {
+ if (@results && $result->{package} ne $results[0]->{package}) {
+ $body .= $self->_get_formated_results(
+ $lead_columns,
+ $columns,
+ $links,
+ $line++ % 2 ? 'odd' : 'even',
+ \@results
+ );
+ @results = ();
+ }
+ push(@results, $result);
+ }
+ $body .= $self->_get_formated_results(
+ $lead_columns,
+ $columns,
+ $links,
+ $line++ % 2 ? 'odd' : 'even',
+ \@results
+ );
+ $body .= $self->{_cgi}->end_table();
+
+ my $content;
+ $content .= $self->{_cgi}->start_html(
+ -title => $title,
+ -style => { code => $self->{_style} }
+ );
+ $content .= $self->{_cgi}->h1($title);
+ $content .= $body;
+ $content .= $self->{_cgi}->hr();
+ $content .= $self->{_cgi}->p(
+ { class => 'footer' },
+ "Page generated $time"
+ );
+ $content .= $self->{_cgi}->end_html();
+
+ return \$content;
+}
+
+sub _get_formated_results {
+ my ($self, $lead_columns, $columns, $links, $class, $results) = @_;
+
+ my $content;
+ $content .= $self->{_cgi}->end_Tr();
+ for my $i (0 .. $#$results) {
+ $content .= $self->{_cgi}->start_Tr(
+ { class => $class }
+ );
+ if ($i == 0) {
+ # first line contains spanned cells
+ $content .= $self->{_cgi}->td(
+ { rowspan => scalar @$results },
+ [
+ map { $results->[$i]->{$_} }
+ @$lead_columns
+ ]
+ );
+ }
+ $content .= $self->{_cgi}->td(
+ [
+ map {
+ $links->{$_} && $results->[$i]->{$links->{$_}} ?
+ $self->{_cgi}->a(
+ { href => $results->[$i]->{$links->{$_}} },
+ $self->{_cgi}->escapeHTML($results->[$i]->{$_})
+ ) :
+ $self->{_cgi}->escapeHTML($results->[$i]->{$_})
+ } @$columns
+ ]
+ );
+ $content .= $self->{_cgi}->end_Tr();
+ }
+
+ return $content;
+}
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2002-2006, YOURI project
+
+This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/lib/Youri/Check/Output/Mail/Format/Text.pm b/lib/Youri/Check/Output/Mail/Format/Text.pm
new file mode 100644
index 0000000..f08e840
--- /dev/null
+++ b/lib/Youri/Check/Output/Mail/Format/Text.pm
@@ -0,0 +1,83 @@
+# $Id: Mail.pm 580 2006-01-11 22:59:36Z guillomovitch $
+package Youri::Check::Output::Mail::Format::Text;
+
+=head1 NAME
+
+Youri::Check::Output::Mail::Format::Text - Mail text format support
+
+=head1 DESCRIPTION
+
+This format plugin for L<Youri::Check::Output::Mail> provides text format
+support.
+
+=cut
+
+use warnings;
+use strict;
+use Carp;
+use base 'Youri::Check::Output::Mail::Format';
+
+sub type {
+ return 'text/plain';
+}
+
+sub get_report {
+ my ($self, $time, $title, $iterator, $type, $columns, $links, $maintainer) = @_;
+
+ my $content;
+ my $lead_columns = [
+ $maintainer ?
+ qw/package media/ :
+ qw/package media maintainer/
+ ];
+ my @results;
+ $content .= join("\t", @$lead_columns, @$columns) . "\n";
+ while (my $result = $iterator->get_result()) {
+ if (@results && $result->{package} ne $results[0]->{package}) {
+ $content .= $self->_get_formated_results(
+ $lead_columns,
+ $columns,
+ \@results
+ );
+ @results = ();
+ }
+ push(@results, $result);
+ }
+
+ $content .= $self->_get_formated_results(
+ $lead_columns,
+ $columns,
+ \@results
+ );
+
+ return \$content;
+}
+
+sub _get_formated_results {
+ my ($self, $lead_columns, $columns, $results) = @_;
+
+ my $content;
+ $content .= join(
+ "\t",
+ (map { $results->[0]->{$_} || '' } @$lead_columns),
+ (map { $results->[0]->{$_} || '' } @$columns)
+ ) . "\n";
+ for my $i (1 .. $#$results) {
+ $content .= join(
+ "\t",
+ (map { '' } @$lead_columns),
+ (map { $results->[$i]->{$_} || '' } @$columns)
+ ) . "\n";
+ }
+ return $content;
+}
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2002-2006, YOURI project
+
+This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+1;