The Big, the Fat and the Ugly commit ;)
authorFrank Lichtenheld <frank@lichtenheld.de>
Tue, 21 Nov 2006 23:46:55 +0000 (23:46 +0000)
committerFrank Lichtenheld <frank@lichtenheld.de>
Tue, 21 Nov 2006 23:46:55 +0000 (23:46 +0000)
 - Make output via Template Toolkit (libtemplate-perl) and
   not "manual". This should seperate the logic of data
   retrieval and data display and make adding new output
   formats and styles easier. Lets see how this turns out :)
 - While doing this I also reworked most of the site designs
   and added a lot of new information and hopefully structure
   to the output
Currently broken:
 - Most of the l10n stuff since I need to find
   a good way to feed the templates to gettext first.
   (this is not "RC" for an use on p.d.o)
 - RSS feed of new packages. Didn't came around yet to convert
   this one.
   (this one is "RC")
 - probably a lot of minor things

35 files changed:
bin/create_index_pages
bin/newpkg_info
cgi-bin/dispatcher.pl
config.sh.sed.in
cron.d/050checkinst
lib/Packages/CGI.pm
lib/Packages/Config.pm
lib/Packages/DoDownload.pm
lib/Packages/DoFilelist.pm
lib/Packages/DoIndex.pm
lib/Packages/DoNewPkg.pm
lib/Packages/DoSearch.pm
lib/Packages/DoSearchContents.pm
lib/Packages/DoShow.pm
lib/Packages/HTML.pm [deleted file]
lib/Packages/Template.pm [new file with mode: 0644]
static/packages.css.sed.in
templates/config.tmpl [new file with mode: 0644]
templates/config/architectures.tmpl [new file with mode: 0644]
templates/config/archive_layout.tmpl [new file with mode: 0644]
templates/config/mirrors.tmpl [new file with mode: 0644]
templates/html/download.tmpl [new file with mode: 0644]
templates/html/error.tmpl [new file with mode: 0644]
templates/html/filelist.tmpl [new file with mode: 0644]
templates/html/foot.tmpl [new file with mode: 0644]
templates/html/head.tmpl [new file with mode: 0644]
templates/html/index.tmpl [new file with mode: 0644]
templates/html/menu.inc [new file with mode: 0644]
templates/html/messages.tmpl [new file with mode: 0644]
templates/html/newpkg.tmpl [new file with mode: 0644]
templates/html/search.tmpl [new file with mode: 0644]
templates/html/search_contents.tmpl [new file with mode: 0644]
templates/html/show.tmpl [new file with mode: 0644]
templates/html/suite_index.tmpl [new file with mode: 0644]
templates/txt/index.tmpl [new file with mode: 0644]

index 2d6e47285b7d0145e950a656addbc7c1a6fabec9..69b60a28b26ddf866b92f18446a5a560ddc4581d 100755 (executable)
@@ -8,15 +8,17 @@ use File::Path;
 use DB_File;
 use Storable;
 use HTML::Entities;
+use URI::Escape;
 use Locale::gettext;
 use Compress::Zlib;
 
 use lib './lib';
 
 use Packages::Config qw( $TOPDIR $DBDIR @ARCHIVES @SUITES @LANGUAGES $LOCALES);
-use Packages::HTML;
+use Packages::Template;
 use Packages::I18N::Locale;
 use Packages::Page;
+use Packages::SrcPage;
 use Packages::Sections;
 &Packages::Config::init( './' );
 
@@ -33,6 +35,12 @@ my $wwwdir = "$TOPDIR/www";
 tie my %packages, 'DB_File', "$DBDIR/packages_small.db",
     O_RDONLY, 0666, $DB_BTREE
     or die "couldn't tie DB $DBDIR/packages_small.db: $!";
+tie my %src_packages, 'DB_File', "$DBDIR/sources_small.db",
+    O_RDONLY, 0666, $DB_BTREE
+    or die "couldn't tie DB $DBDIR/sources_small.db: $!";
+tie my %src2bin, 'DB_File', "$DBDIR/sources_packages.db",
+    O_RDONLY, 0666, $DB_BTREE
+    or die "couldn't open $DBDIR/sources_packages.db: $!";
 
 my $sections = retrieve "$DBDIR/sections.info";
 my $subsections = retrieve "$DBDIR/subsections.info";
@@ -45,42 +53,45 @@ my $priorities = retrieve "$DBDIR/priorities.info";
 
 my (%pages);
 
+my $template = new Packages::Template( "$TOPDIR/templates", 'html', {} );
+
 print "write suite index files ...\n";
 foreach my $s (@SUITES) {
     my $key = $s;
     mkpath ( "$wwwdir/$key" );
     foreach my $lang (@LANGUAGES) {
        my $locale = get_locale( $lang );
+       my $charset = get_locale( $lang );
        setlocale ( LC_ALL, $locale ) or do {
            warn "couldn't set locale ($lang/$locale)\n";
            next;
        };
+       print "writing $key/index (lang=$lang)...\n";
        open $pages{$key}{$lang}{index}{fh}, '>', "$wwwdir/$key/index.$lang.html.new"
            or die "can't open index file for output: $!";
-       my $index_title = sprintf( _g( "List of sections in \"%s\"" ),
-                                  $key );
-       print {$pages{$key}{$lang}{index}{fh}} header( title => $index_title,
-                                                      title_keywords => "debian, $s",
-                                                      desc => encode_entities( $index_title, '"' ),
-                                                      lang => $lang ),
-       title( $index_title ), '<div id="lefthalfcol"><dl>';
-       my $i = 0; my $num_sections = keys %{$subsections->{$s}};
+
+       my %content = ( subsections => [], suite => $s,
+                       lang => $lang, charset => $charset );
+       $content{make_search_url} = sub { return &Packages::CGI::make_search_url(@_) };
+       $content{make_url} = sub { return &Packages::CGI::make_url(@_) };
+        # needed to work around the limitations of the the FILTER syntax
+       $content{html_encode} = sub { return HTML::Entities::encode_entities(@_,'<>&"') };
+       $content{uri_escape} = sub { return URI::Escape::uri_escape(@_) };
+       $content{quotemeta} = sub { return quotemeta($_[0]) };
+
        foreach my $ssec ((keys %{$subsections->{$s}}, 'virtual')) {
            next if $ssec eq '-';
            if ($sections_descs{$ssec}) {
-               print {$pages{$key}{$lang}{index}{fh}} "<dt><a href=\"$ssec/\">".dgettext( 'sections', $sections_descs{$ssec}[0] )."</a></dt><dd>".dgettext( 'sections', $sections_descs{$ssec}[1] )."</dd>\n";
-               $i++;
-               if ($i eq ceil($num_sections/2)) {
-                   print {$pages{$key}{$lang}{index}{fh}} "</dl>\n</div> <!-- end lefthalfcol -->\n<div id=\"righthalfcol\">\n<dl>\n";
-               }
+               push @{$content{subsections}}, {
+                   id => $ssec,
+                   name => dgettext( 'sections', $sections_descs{$ssec}[0] ),
+                   desc => dgettext( 'sections', $sections_descs{$ssec}[1] ),
+               };
            }
        }
        
-       print {$pages{$key}{$lang}{index}{fh}} '</dl></div>',
-       "<p class=\"psmallcenter\"><a href=\"allpackages\" title=\""._g( "List of all packages" )."\">".
-           _g( "All packages" ) ."</a><br>(<a href=\"allpackages?format=txt.gz\">".
-           _g( "compact compressed textlist" )."</a>)</p>\n";
-       print {$pages{$key}{$lang}{index}{fh}} trailer( "../", 'index', $lang, @LANGUAGES );
+       print {$pages{$key}{$lang}{index}{fh}} $template->page( 'suite_index', \%content );
+       print {$pages{$key}{$lang}{index}{fh}} $template->trailer( 'index', $lang, \@LANGUAGES );
        close $pages{$key}{$lang}{index}{fh} or
            warn "can't close index file $wwwdir/$key/index.$lang.html.new: $!";
        rename( "$wwwdir/$key/index.$lang.html.new",
@@ -90,70 +101,8 @@ foreach my $s (@SUITES) {
 }
 setlocale( LC_ALL, 'C' ) or die "couldn't reset locale";
 
-print "opening files ...\n";
-foreach my $s (@SUITES) {
-    my $key = $s;
-    mkpath ( "$wwwdir/$key" );
-    open $pages{$key}{fh}, '>', "$wwwdir/$key/allpackages.en.html.new"
-       or die "can't open index file for output: $!";
-    $pages{$key}{textgz} = gzopen("$wwwdir/$key/allpackages.en.txt.gz.new",
-                                 'wb9')
-       or die "can't open text index file for output: $!";
-
-    my $title = sprintf( _g( "Software Packages in \"%s\"" ),
-                        $key );
-    print {$pages{$key}{fh}} header( title => $title,
-                                    title_keywords => "debian, $s",
-                                    desc => encode_entities( $title, '"' ),
-                                    lang => 'en' ),
-    title( $title ), '<dl>';
-    my $title_txt = sprintf( _g( "All Debian Packages in \"%s\"" ),
-                            $key )."\n\n";
-    $title_txt .= _g( "Last Modified: " ).gmtime()."\n".
-       sprintf(_g( "Copyright (C) 1997-%d SPI;\nSee <URL:http://www.debian.org/license> for the license terms."), (gmtime)[5]+1900 )."\n\n";
-   $pages{$key}{textgz}->gzwrite($title_txt);
-
-    foreach my $sec (keys %{$sections->{$s}}) {
-       mkpath ( "$wwwdir/$key/$sec" );
-       open $pages{$key}{$sec}{fh}, '>', "$wwwdir/$key/$sec/index.en.html.new"
-           or die "can't open index file for output: $!";
-       $title = sprintf( _g( "Software Packages in \"%s\", section %s" ),
-                         $key, $sec );
-       print {$pages{$key}{$sec}{fh}} header( title => $title,
-                                              title_keywords => "debian, $s, $sec",
-                                              desc => encode_entities( $title, '"' ),
-                                              lang => 'en' ),
-       title( $title ), '<dl>';
-    }
-    foreach my $ssec ((keys %{$subsections->{$s}}, 'virtual')) {
-       next if $ssec eq '-';
-       mkpath ( "$wwwdir/$key/$ssec" );
-       open $pages{$key}{$ssec}{fh}, '>', "$wwwdir/$key/$ssec/index.en.html.new"
-           or die "can't open index file for output: $!";
-       $title = sprintf( _g( "Software Packages in \"%s\", subsection %s" ),
-                         $key, $ssec );
-       print {$pages{$key}{$ssec}{fh}} header( title => $title,
-                                               title_keywords => "debian, $s, $ssec",
-                                               desc => encode_entities( $title, '"' ),
-                                               lang => 'en' ),
-       title( $title ), '<dl>';
-    }
-    foreach my $prio (keys %{$priorities->{$s}}) {
-       next if $prio eq '-';
-       mkpath ( "$wwwdir/$key/$prio" );
-       open $pages{$key}{$prio}{fh}, '>', "$wwwdir/$key/$prio/index.en.html.new"
-           or die "can't open index file for output: $!";
-       $title = sprintf( _g( "Software Packages in \"%s\", priority %s" ),
-                         $key, $prio );
-       print {$pages{$key}{$prio}{fh}} header( title => $title,
-                                               title_keywords => "debian, $s, $prio",
-                                               desc => encode_entities( $title, '"' ),
-                                               lang => 'en' ),
-       title( $title ), '<dl>';
-    }
-}
-
-print "writing package info ...\n";
+print "collecting package info ...\n";
+my %allpkgs;
 while (my ($pkg, $data) = each %packages) {
     my (%pkg,%virt);
     my ($virt, $p_data) = split /\000/o, $data, 2;
@@ -176,87 +125,135 @@ while (my ($pkg, $data) = each %packages) {
        $pkg{$_} ||= new Packages::Page( $pkg );
        $pkg{$_}->add_provided_by([split /\s+/, $virt{$_}]);
     }
-    
+
     while (my ($key, $entry) = each %pkg) {
+       $allpkgs{$key} ||= [];
+
+       my %p = ( name => $pkg, providers => [], versions => '' );
        if (my $provided_by = $entry->{provided_by}) {
-           my $str = "<dt><a href=\"$pkg\">$pkg</a> ".
-               "</dt>\n     <dd>virtual package provided by ".
-               join( ', ',map { "<a href=\"../$_\">$_</a>" } @$provided_by)."</dd>\n";
-           my $txt_str = "$pkg\tvirtual package provided by ".join(', ', @$provided_by)."\n";
-           print {$pages{$key}{virtual}{fh}} $str
-               or die "couldn't write to output file: $!";
-       }
-       next if $entry->is_virtual;
-       my (undef, $v_str) = $entry->get_version_string;
-       my $subsection = $entry->get_newest( 'subsection' );
-       my $section = $entry->get_newest( 'section' );
-       my $archive = $entry->get_newest( 'archive' );
-       my $short_desc_txt = $entry->get_newest( 'description' );
-       my $short_desc = encode_entities( $short_desc_txt, "<>&\"" );
-       my $priority = $entry->get_newest( 'priority' );
-       
-       my $str = "<dt><a href=\"$pkg\">$pkg</a> ($v_str) ";
-       my $txt_str = "$pkg ($v_str)";
-       if ($section ne 'main') {
-           $str .= marker( $section );
-           $txt_str .= " [$section]";
-       }
-       if ($archive ne 'us') {
-           $str .= marker( $archive );
-           $txt_str .= " [$archive]";
-       }
-       $str .= "</dt>\n     <dd>$short_desc</dd>\n";
-       $txt_str .= " $short_desc_txt\n";
-       print {$pages{$key}{fh}} $str
-           or die "couldn't write to output file: $!";
-       $pages{$key}{textgz}->gzwrite($txt_str)
-           or die "couldn't write to output file: ".$pages{$key}{textgz}->gzerror;
-       print {$pages{$key}{$section}{fh}} $str
-           or die "couldn't write to output file: $!";
-       if ($subsection ne '-') {
-           print {$pages{$key}{$subsection}{fh}} $str
-               or die "couldn't write to output file: $!";
-       }
-       if ($priority ne '-') {
-           print {$pages{$key}{$priority}{fh}} $str
-               or die "couldn't write to output file: $!";
+           $p{providers} = $provided_by;
+       }
+       $p{subsection} = $p{section} = $p{archive} = $p{desc} = $p{priority} = '';
+       unless ($entry->is_virtual) {
+           (undef, $p{versions}) = $entry->get_version_string;
+           $p{subsection} = $entry->get_newest( 'subsection' );
+           $p{section} = $entry->get_newest( 'section' );
+           $p{archive} = $entry->get_newest( 'archive' );
+           $p{desc} = $entry->get_newest( 'description' );
+           $p{priority} = $entry->get_newest( 'priority' );
        }
+       push @{$allpkgs{$key}}, \%p;
     }
 }
 
-print "closing files ...\n";
-foreach my $s (@SUITES) {
-    my $key = $s;
-    print {$pages{$key}{fh}} '</dl>', trailer( "../" );
-    ($pages{$key}{textgz}->gzclose == Z_OK) or
-       warn "can't close text index file $wwwdir/$key/allpackages.en.txt.gz.new: ".$pages{$key}{textgz}->gzerror;
-    close $pages{$key}{fh} or
-       warn "can't close index file $wwwdir/$key/allpackages.en.html.new: $!";
-    rename( "$wwwdir/$key/allpackages.en.html.new",
-           "$wwwdir/$key/allpackages.en.html" );
-    rename( "$wwwdir/$key/allpackages.en.txt.gz.new",
-           "$wwwdir/$key/allpackages.en.txt.gz" );
-    foreach my $sec (keys %{$sections->{$s}{'us'}}) {
-       print {$pages{$key}{$sec}{fh}} '</dl>', trailer( "../../" );
-       close $pages{$key}{$sec}{fh} or
-           warn "can't close index file $wwwdir/$key/$sec/index.en.html.new: $!";
-       rename( "$wwwdir/$key/$sec/index.en.html.new",
-               "$wwwdir/$key/$sec/index.en.html" );
+write_files(\%allpkgs);
+
+print "collecting source package info ...\n";
+my %allsrcpkgs;
+while (my ($pkg, $data) = each %src_packages) {
+    my %pkg;    
+    foreach (split /\000/o, $data||'') {
+       my @data = split ( /\s/o, $_ );
+       $pkg{$data[1]} ||= new Packages::SrcPage( $pkg );
+       $pkg{$data[1]}->merge_package( { package => $pkg,
+                                        archive => $data[0],
+                                        suite => $data[1],
+                                        section => $data[2],
+                                        subsection => $data[3],
+                                        priority => $data[4],
+                                        version => $data[5],
+                                        } );
+    }
+
+    while (my ($key, $entry) = each %pkg) {
+       $allsrcpkgs{$key} ||= [];
+
+       my %p = ( name => $pkg, providers => [], versions => '' );
+       $p{versions} = $entry->{version};
+       $p{subsection} = $entry->get_newest( 'subsection' );
+       $p{section} = $entry->get_newest( 'section' );
+       $p{archive} = $entry->get_newest( 'archive' );
+       $p{priority} = $entry->get_newest( 'priority' );
+       
+       $p{desc} = '';
+       $p{binaries} = [];
+#      my $binaries = find_binaries( $pkg, $p{archive}, $p{suite}, \%src2bin );
+#      if ($binaries && @$binaries) {
+#          pkg_list( \%packages, $opts, $binaries, 'en', $contents{binaries} );
+#      }
+
+       push @{$allsrcpkgs{$key}}, \%p;
     }
-    foreach my $ssec ((keys %{$subsections->{$s}}, 'virtual')) {
-       next if $ssec eq '-';
-       print {$pages{$key}{$ssec}{fh}} '</dl>', trailer( "../../" );
-       close $pages{$key}{$ssec}{fh} or
-           warn "can't close index file $wwwdir/$key/$ssec/index.en.html.new: $!";
-       rename( "$wwwdir/$key/$ssec/index.en.html.new",
-               "$wwwdir/$key/$ssec/index.en.html" );
+}
+
+write_files(\%allsrcpkgs, 1);
+
+sub write_files {
+    my ($pkgs, $source) = @_;
+
+    $source = $source ? 'source/' : '';
+    print "writing files ...\n";
+    foreach my $s (@SUITES) {
+       my $key = $s;
+       mkpath ( "$wwwdir/$source$key" );
+       print "writing $source$s/allpackages...\n";
+       $template->process( 'html/index.tmpl', { packages => $pkgs->{$key}, suite => $s, lang => 'en', is_source => $source  },
+                           "$wwwdir/$source$key/allpackages.en.html.new" )
+           or die "error writing allpackages for $key: ".$template->error();
+       print "writing $source$s/allpackages (txt)...\n";
+       my $gzfh = gzopen("$wwwdir/$source$key/allpackages.en.txt.gz.new",
+                     'wb9')
+           or die "can't open text index file for output: $!";
+       my $gztxt;
+       $template->process( 'txt/index.tmpl', { packages => $pkgs->{$key}, suite => $s, lang => 'en', is_source => $source  },
+                           \$gztxt )
+           or die "error writing allpackages txt for $key: ".$template->error();    
+       $gzfh->gzwrite($gztxt);
+       ($gzfh->gzclose == Z_OK) or
+           warn "can't close text index file $wwwdir/$source$key/allpackages.en.txt.gz.new: ".$gzfh->gzerror;
+
+       rename( "$wwwdir/$source$key/allpackages.en.html.new",
+               "$wwwdir/$source$key/allpackages.en.html" );
+       rename( "$wwwdir/$source$key/allpackages.en.txt.gz.new",
+               "$wwwdir/$source$key/allpackages.en.txt.gz" );
+       
+       foreach my $sec (keys %{$sections->{$s}}) {
+           mkpath ( "$wwwdir/$source$key/$sec" );
+
+           print "writing $source$s/$sec/index...\n";
+           $template->process( 'html/index.tmpl', { packages => [ grep { $_->{section} eq $sec } @{$pkgs->{$key}} ],
+                                                    suite => $s, lang => 'en', is_source => $source,
+                                                    category => { id => 'section', name => $sec } },
+                               "$wwwdir/$source$key/$sec/index.en.html.new" )
+               or die "error writing section index for $key/$sec: ".$template->error();
+           rename( "$wwwdir/$source$key/$sec/index.en.html.new",
+                   "$wwwdir/$source$key/$sec/index.en.html" );
     }
-    foreach my $prio (keys %{$priorities->{$s}}) {
-       next if $prio eq '-';
-       print {$pages{$key}{$prio}{fh}} '</dl>', trailer( "../../" );
-       close $pages{$key}{$prio}{fh} or
-           warn "can't close index file $wwwdir/$key/$prio/index.en.html.new: $!";
-       rename( "$wwwdir/$key/$prio/index.en.html.new",
-               "$wwwdir/$key/$prio/index.en.html" );
+       foreach my $ssec ((keys %{$subsections->{$s}}, 'virtual')) {
+           next if $ssec eq '-';
+           mkpath ( "$wwwdir/$source$key/$ssec" );
+
+           print "writing $source$s/$ssec/index...\n";
+           $template->process( 'html/index.tmpl', { packages => [ grep { $_->{subsection} eq $ssec } @{$pkgs->{$key}} ],
+                                                    suite => $s, lang => 'en', is_source => $source,
+                                                    category => { id => 'subsection', name => $ssec } },
+                               "$wwwdir/$source$key/$ssec/index.en.html.new" )
+           or die "error writing subsection index for $key/$ssec: ".$template->error();
+       rename( "$wwwdir/$source$key/$ssec/index.en.html.new",
+               "$wwwdir/$source$key/$ssec/index.en.html" );
+       }
+       foreach my $prio (keys %{$priorities->{$s}}) {
+           next if $prio eq '-';
+           mkpath ( "$wwwdir/$source$key/$prio" );
+           
+           print "writing $source$s/$prio/index...\n";
+           $template->process( 'html/index.tmpl', { packages => [ grep { $_->{priority} eq $prio } @{$pkgs->{$key}} ],
+                                                    suite => $s, lang => 'en', is_source => $source,
+                                                    category => { id => 'priority', name => $prio } },
+                               "$wwwdir/$source$key/$prio/index.en.html.new" )
+               or die "error writing priority index for $key/$prio: ".$template->error();
+           rename( "$wwwdir/$source$key/$prio/index.en.html.new",
+                   "$wwwdir/$source$key/$prio/index.en.html" );
+       }
     }
 }
index 175119aa6b82b7471d8c9015f60b7837aa33e730..e2f36aef9790dcd4d7ec14136a9abb6d8fec73ac 100755 (executable)
@@ -11,12 +11,12 @@ use Packages::Config qw( $TOPDIR $DBDIR );
 use Packages::Search qw( :all );
 &Packages::Config::init( './' );
 
-my $suite = $ARGV[0] or die "No suite given";
+my $suite = $ARGV[0] or die "Fatal Error: No suite given";
 my $start_time = time;
 
 tie my %packages, 'DB_File', "$DBDIR/packages_small.db",
     O_RDONLY, 0666, $DB_BTREE
-    or die "couldn't tie DB $DBDIR/packages_small.db: $!\n";
+    or die "Fatal Error: Couldn't tie DB $DBDIR/packages_small.db: $!\n";
 
 sub get_iso_date {
     my ($age) = @_;
@@ -28,23 +28,26 @@ sub get_iso_date {
 }
 
 open CHANGES, '>', "$TOPDIR/files/packages/newpkg_info.new"
-    or die "Couldn't open CHANGES file: $!";
+    or die "Fatal Error: Couldn't open CHANGES file: $!";
 for (my $age = 0; $age < 7; $age++) {
     my (%old, %changes);
     my $newday = get_iso_date( $age );
     my $oldday = get_iso_date( $age+1 );
     open OLD, '<', "$TOPDIR/files/packages/package_names_$suite.$oldday"
        or do {
-           warn"Couldn't open OLD file $TOPDIR/files/packages/package_names_$suite.$oldday: $!\n";
-           last;
+           warn "Warning: Couldn't open OLD file $TOPDIR/files/packages/package_names_$suite.$oldday: $!\n";
+           next;
+       };
+    open NEW, '<', "$TOPDIR/files/packages/package_names_$suite.$newday"
+       or do {
+           warn "Warning: Couldn't open NEW file $TOPDIR/files/packages/package_names_$suite.$newday: $!\n";
+           next;
        };
     while (<OLD>) {
        chomp;
        $old{$_} = 1;
     }
     close OLD;
-    open NEW, '<', "$TOPDIR/files/packages/package_names_$suite.$newday"
-       or die "Couldn't open NEW file $TOPDIR/files/packages/package_names_$suite.$newday: $!\n";
     while (<NEW>) {
        chomp;
        if ($old{$_}) {
@@ -62,7 +65,7 @@ for (my $age = 0; $age < 7; $age++) {
     my %archives = map { $_ => 1 } qw( us security non-US );
     foreach (sort keys %changes) {
        my $entry = read_entry_simple( \%packages, $_, \%archives, $suite)
-           or die "Can't find entry for package $_\n";
+           or die "Fatal Error: Can't find entry for package $_\n";
        shift @$entry; # remove virtual pkg info
        print CHANGES join(" ", $_, $age, @$entry)."\n";
        print "Wrote entry: ".join(" ", $_, $age, @$entry)."\n";
index 04d5acb74273f5aabc30a916d9cce450a8f84558..45d1b463154539b9c20dc63c71e3b5eb40285650 100755 (executable)
@@ -13,19 +13,23 @@ use warnings;
 use lib '../lib';
 use CGI;
 use POSIX;
+use File::Basename;
 use URI::Escape;
 use HTML::Entities;
+use Template;
 use DB_File;
 use Benchmark ':hireswallclock';
 use I18N::AcceptLanguage;
 use Locale::gettext;
 
 use Deb::Versions;
-use Packages::Config qw( $DBDIR $ROOT @SUITES @SECTIONS @ARCHIVES @ARCHITECTURES @LANGUAGES $LOCALES );
-use Packages::CGI;
+use Packages::Config qw( $DBDIR $ROOT $TEMPLATEDIR $CACHEDIR
+                        @SUITES @SECTIONS @ARCHIVES @ARCHITECTURES @PRIORITIES
+                        @LANGUAGES $LOCALES );
+use Packages::CGI qw( :DEFAULT get_all_messages );
 use Packages::DB;
 use Packages::Search qw( :all );
-use Packages::HTML ();
+use Packages::Template ();
 use Packages::Sections;
 use Packages::I18N::Locale;
 
@@ -38,6 +42,7 @@ use Packages::DoDownload;
 use Packages::DoFilelist;
 
 &Packages::CGI::reset;
+$Packages::Search::too_many_hits = 0;
 
 # clean up env
 $ENV{PATH} = "/bin:/usr/bin";
@@ -60,7 +65,8 @@ my $debug = DEBUG && $input->param("debug");
 $debug = 0 if !defined($debug) || $debug !~ /^\d+$/o;
 $Packages::CGI::debug = $debug;
 
-&Packages::Config::init( '../' );
+my $homedir = dirname($ENV{SCRIPT_FILENAME}).'/../';
+&Packages::Config::init( $homedir );
 &Packages::DB::init();
 
 my $acc = I18N::AcceptLanguage->new();
@@ -115,6 +121,7 @@ if (my $path = $input->path_info() || $input->param('PATH_INFO')) {
        my %SECTIONS = map { $_ => 1 } @SECTIONS;
        my %ARCHIVES = map { $_ => 1 } @ARCHIVES;
        my %ARCHITECTURES = map { $_ => 1 } (@ARCHITECTURES, 'all');
+       my %PRIORITIES = map { $_ => 1 } @PRIORITIES;
        my %params_set;
        sub set_param_once {
            my ($cgi, $params_set, $key, $val) = @_;
@@ -147,6 +154,8 @@ if (my $path = $input->path_info() || $input->param('PATH_INFO')) {
                set_param_once( $input, \%params_set, 'source', 1);
            } elsif ($ARCHITECTURES{$_}) {
                set_param_once( $input, \%params_set, 'arch', $_);
+           } elsif ($PRIORITIES{$_}) {
+               set_param_once( $input, \%params_set, 'priority', $_);
            } else {
                push @pkg, $_;
            }
@@ -195,11 +204,15 @@ my %params_def = ( keywords => { default => undef,
                   subsection => { default => 'default', match => '^([\w-]+)$',
                                   array => ',', var => \@subsections,
                                   replace => { default => [] } },
+                  priority => { default => 'default', match => '^([\w-]+)$',
+                                array => ',',
+                                replace => { default => [] } },
                   arch => { default => 'any', match => '^([\w-]+)$',
                             array => ',', var => \@archs, replace =>
                             { any => \@ARCHITECTURES } },
                   format => { default => 'html', match => '^([\w.]+)$',  },
                   mode => { default => undef, match => '^(\w+)$',  },
+                  sort_by => { default => 'file', match => '^(\w+)$', },
                   );
 my %opts;
 my %params = Packages::CGI::parse_params( $input, \%params_def, \%opts );
@@ -238,50 +251,40 @@ my $pet1 = new Benchmark;
 my $petd = timediff($pet1, $pet0);
 debug( "Parameter evaluation took ".timestr($petd) ) if DEBUG;
 
-my (%html_header, $menu, $page_content);
+my $template = new Packages::Template( $TEMPLATEDIR, $opts{format}, { lang => $opts{lang}, charset => $charset, debug => ( DEBUG ? $opts{debug} : 0 ) }, ( $CACHEDIR ? { COMPILE_DIR => $CACHEDIR } : {} ) );
+
+my (%html_header, %page_content);
 unless (@Packages::CGI::fatal_errors) {
     no strict 'refs';
     &{"do_$what_to_do"}( \%params, \%opts, \%html_header,
-                        \$menu, \$page_content );
-} else {
-    %html_header = ( title => _g('Error'),
-                    lang => $opts{lang},
-                    print_title => 1,
-                    print_search_field => 'packages',
-                    search_field_values => { 
-                        keywords => _g('search for a package'),
-                        searchon => 'default',
-                        arch => 'any',
-                        suite => 'all',
-                        section => 'all',
-                        exact => 1,
-                        debug => $debug,
-                    },
-                    );
+                        \%page_content );
 }
 
-print $input->header( -charset => $charset );
+$page_content{opts} = \%opts;
+$page_content{params} = \%params;
 
-print Packages::HTML::header( %html_header );
+$page_content{make_search_url} = sub { return &Packages::CGI::make_search_url(@_) };
+$page_content{make_url} = sub { return &Packages::CGI::make_url(@_) };
+# needed to work around the limitations of the the FILTER syntax
+$page_content{html_encode} = sub { return HTML::Entities::encode_entities(@_,'<>&"') };
+$page_content{uri_escape} = sub { return URI::Escape::uri_escape(@_) };
+$page_content{quotemeta} = sub { return quotemeta($_[0]) };
 
-print $menu||'';
-print_errors();
-print_hints();
-print_msgs();
-print_debug() if DEBUG;
-print_notes();
+print $input->header( -charset => $charset );
+
+#use Data::Dumper;
+#print '<pre>'.Dumper(\%ENV, \%html_header, \%page_content, get_all_messages()).'</pre>';
 
 unless (@Packages::CGI::fatal_errors) {
-    print $page_content;
+print $template->page( $what_to_do, { %page_content, %{ get_all_messages() } } );
+} else {
+print $template->error_page( get_all_messages() );
 }
 
 my $tet1 = new Benchmark;
 my $tetd = timediff($tet1, $tet0);
-print "Total page evaluation took ".timestr($tetd)."<br>"
-    if DEBUG;
 
-my $trailer = Packages::HTML::trailer( $ROOT );
+my $trailer = $template->trailer( undef, undef, undef, $tetd );
 print $trailer;
 
 # vim: ts=8 sw=4
-
index ea6703a4d3169cbea48a5f746c42a3bf0b67628b..d5d84988a0f6c01b9b1723311ebb0db0eeb8ba8c 100644 (file)
@@ -14,14 +14,16 @@ podir=${topdir}/po
 localedir=%TOPDIR%/locale
 staticdir=${topdir}/static
 configdir=${topdir}/conf
+templatedir=${topdir}/templates
+cachedir=${topdir}/cache
 
 # unset this if %SITE% moves somewhere where the packages files
 # cannot be obtained locally
 #
-localdir=/org/ftp.debian.org/ftp
+#localdir=/org/ftp.debian.org/ftp
 
 # path to private ftp directory
-ftproot=/org/ftp.root
+#ftproot=/org/ftp.root
 
 ftpsite=http://ftp.debian.org/debian
 nonus_ftpsite=http://ftp.uk.debian.org/debian-non-US
@@ -41,6 +43,7 @@ archives="us non-US security amd64 kfreebsd backports volatile"
 sections="main contrib non-free"
 parts="$sections"
 suites="oldstable stable stable-volatile stable-backports testing unstable experimental"
+priorities="required important standard optional extra"
 dists="$suites"
 architectures="alpha amd64 arm hppa hurd-i386 i386 ia64 kfreebsd-i386 kfreebsd-amd64 m68k mips mipsel powerpc s390 sparc"
 arch_oldstable="alpha arm hppa i386 ia64 m68k mips mipsel powerpc s390 sparc"
@@ -53,4 +56,4 @@ arch_stable_proposed_updates="${arch_stable}"
 
 # Miscellaneous
 #
-admin_email="djpig@debian.org,joey@infodrom.org"
+admin_email="djpig@debian.org"
index ad6397a20526e8d32047dc4724c182f036fa558d..7f054cb8ca152da1876b655588102213d72e6b0f 100755 (executable)
@@ -16,6 +16,7 @@ locales="de_DE.UTF-8 en_US.UTF-8 nl_NL fr_FR.UTF-8"
 
 packages=`tempfile`
 locs=`tempfile`
+cache=`tempfile`
 trap "rm -f $packages $locs" INT EXIT
 
 for p in $required
@@ -36,7 +37,22 @@ do
     fi
 done
 
-if [ -s $packages -o -s $locs ]
+if [ -n "$cachedir" ]
+then
+    if [ ! -d "$cachedir" ]
+    then
+       echo "cachedir missing." >> $cache
+    else
+       perm=$(ls -ld "$cachedir" | perl -ne 'print "ok" if /^drwxrws--- \d+ www-data/')
+        if [ -z "$perm" ]
+       then
+           echo "cachedir has wrong permissions." >> $cache
+           echo "make sure it is writable by the web server." >> $cache
+       fi
+    fi
+fi
+
+if [ -s $packages -o -s $locs -o -s $cache ]
 then
     (
        echo "Subject: Problem packages.debian.org on `hostname -s`"
@@ -56,6 +72,12 @@ then
            echo
            cat $locs
        fi
+       if [ -s $cache ]
+       then
+           echo "Problems with cachedir:"
+           echo
+           cat $cache
+       fi
     ) | /usr/sbin/sendmail -t
 fi
 
index 236dd8df3b1e976341af46b8ba91d06f14473dc1..9a8584fe6bd51b4cf784ad1dc37d522215ab4e33 100644 (file)
@@ -7,9 +7,10 @@ use Exporter;
 use Packages::Config;
 
 our @ISA = qw( Exporter );
-our @EXPORT = qw( fatal_error error hint debug msg note
-                 print_errors print_hints print_debug print_msgs
-                 print_notes DEBUG make_url make_search_url );
+our @EXPORT = qw( DEBUG debug fatal_error );
+our @EXPORT_OK = qw( error hint msg note get_all_messages
+                    make_url make_search_url );
+
 
 # define this to 0 in production mode
 use constant DEBUG => 1;
@@ -40,50 +41,22 @@ sub msg {
 sub note {
     push @notes, [ @_ ];
 }
-sub print_errors {
-    return unless @fatal_errors || @errors;
-    print '<div class="perror">';
-    foreach ((@fatal_errors, @errors)) {
-       print "<p>ERROR: $_</p>";
-    }
-    print '</div>';
-}
-sub print_debug {
+sub get_errors { (@fatal_errors, @errors) }
+sub get_debug {
     return unless $debug && @debug;
-    print '<div class="pdebug">';
-    print '<h2>Debugging:</h2><pre>';
-    foreach (@debug) {
-       print "$_\n";
-    }
-    print '</pre></div>';
-}
-sub print_hints {
-    return unless @hints;
-    print '<div class="phints">';
-    foreach (@hints) {
-       print "<p>$_</p>";
-    }
-    print '</div>';
-}
-sub print_msgs {
-    print '<div class="pmsgs">';
-    foreach (@msgs) {
-       print "<p>$_</p>";
-    }
-    print '</div>';
+    return @debug;
 }
-sub print_notes {
-    foreach (@notes) {
-       my ( $title, $note ) = @$_;
-
-       print '<div class="pnotes">';
-       if ($note) {
-           print "<h2>$title</h2>";
-       } else {
-           $note = $title;
-       }
-       print "<p>$note</p></div>";
-    }
+sub get_msgs { @msgs };
+sub get_hints { @hints };
+sub get_notes { @notes };
+sub get_all_messages {
+    return {
+       errors => [ @fatal_errors, @errors ],
+       debugs => $debug ? \@debug : [],
+       msgs => \@msgs,
+       hints => \@hints,
+       notes => \@notes,
+    };
 }
 
 our $USE_PAGED_MODE = 1;
@@ -400,9 +373,14 @@ sub init_url {
 }
 
 sub make_url {
-    my ($add_path, $add_query, $override) = @_;
+    my ($add_path, $add_query, @override) = @_;
     my (@path, @query_string) = ()x2;
-    $override ||= {};
+    my $override = {};
+    if (ref $override[0]) { 
+       $override = $override[0];
+    } elsif (@override) {
+       $override = { @override };
+    }
 
     push @path, $Packages::Config::ROOT;
     foreach my $p (qw(lang source suite archive arch)) {
@@ -428,9 +406,14 @@ sub make_url {
 }
 
 sub make_search_url {
-    my ($add_path, $add_query, $override) = @_;
+    my ($add_path, $add_query, @override) = @_;
     my (@path, @query_string) = ()x2;
-    $override ||= {};
+    my $override ||= {};
+    if (ref $override[0]) { 
+       $override = $override[0];
+    } elsif (@override) {
+       $override = { @override };
+    }
 
     push @path, $Packages::Config::SEARCH_URL
        if $Packages::Config::SEARCH_URL;
index e749735c3ae4229c46420d8c4b04bf0337ebddda..8252a1b132271d8f1c49159d4a0c7ec914c15140 100644 (file)
@@ -4,23 +4,18 @@ use strict;
 use warnings;
 
 use Exporter;
-use Packages::CGI;
+use Packages::CGI qw( :DEFAULT error );
 
 our @ISA = qw( Exporter );
 
-our ( $TOPDIR, $DBDIR, $ROOT, $HOSTNAME, $HOME, $CONTACT_MAIL, $WEBMASTER_MAIL,
-      $SEARCH_PAGE, $SEARCH_URL, @LANGUAGES, $LOCALES,
-      $SRC_SEARCH_URL, $CONTENTS_SEARCH_CGI,
-      $CN_HELP_URL, $BUG_URL, $SRC_BUG_URL, $QA_URL, $DDPO_URL,
+our ( $TOPDIR, $DBDIR, $TEMPLATEDIR, $CACHEDIR, $ROOT,
+      @LANGUAGES, $LOCALES,
       @SUITES, @SECTIONS, @ARCHIVES, @ARCHITECTURES,
-      %FTP_SITES );
-our @EXPORT_OK = qw( $TOPDIR $DBDIR $ROOT $HOSTNAME $HOME $CONTACT_MAIL
-                    $WEBMASTER_MAIL @LANGUAGES $LOCALES
-                    $SEARCH_PAGE $SEARCH_URL
-                    $SRC_SEARCH_URL $CONTENTS_SEARCH_CGI
-                    $CN_HELP_URL $BUG_URL $SRC_BUG_URL $QA_URL $DDPO_URL
+      @PRIORITIES, %FTP_SITES );
+our @EXPORT_OK = qw( $TOPDIR $DBDIR $TEMPLATEDIR $CACHEDIR $ROOT
+                    @LANGUAGES $LOCALES
                     @SUITES @SECTIONS @ARCHIVES @ARCHITECTURES
-                    %FTP_SITES  );
+                    @PRIORITIES %FTP_SITES  );
 our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] );
 
 our $config_read_time;
@@ -37,21 +32,10 @@ sub init {
            next if /^\s*\#/o;
            chomp;
            $TOPDIR = $1 if /^\s*topdir="?([^\"]*)"?\s*$/o;
+           $TEMPLATEDIR = $1 if /^\s*templatedir="?([^\"]*)"?\s*$/o;
+           $CACHEDIR = $1 if /^\s*cachedir="?([^\"]*)"?\s*$/o;
            $ROOT = $1 if /^\s*root="?([^\"]*)"?\s*$/o;
-           $HOSTNAME = $1 if /^\s*hostname="?([^\"]*)"?\s*$/o;
-           $HOME = $1 if /^\s*home="?([^\"]*)"?\s*$/o;
            $LOCALES = $1 if /^\s*localedir="?([^\"]*)"?\s*$/o;
-#          $SEARCH_CGI = $1 if /^\s*search_cgi="?([^\"]*)"?\s*$/o;
-           $SEARCH_PAGE = $1 if /^\s*search_page="?([^\"]*)"?\s*$/o;
-           $SEARCH_URL = $1 if /^\s*search_url="?([^\"]*)"?\s*$/o;
-           $SRC_SEARCH_URL = $1 if /^\s*search_src_url="?([^\"]*)"?\s*$/o;
-           $WEBMASTER_MAIL = $1 if /^\s*webmaster="?([^\"]*)"?\s*$/o;
-           $CONTACT_MAIL = $1 if /^\s*contact="?([^\"]*)"?\s*$/o;
-           $BUG_URL = $1 if /^\s*bug_url="?([^\"]*)"?\s*$/o;
-           $SRC_BUG_URL = $1 if /^\s*src_bug_url="?([^\"]*)"?\s*$/o;
-           $QA_URL = $1 if /^\s*qa_url="?([^\"]*)"?\s*$/o;
-           $DDPO_URL = $1 if /^\s*ddpo_url="?([^\"]*)"?\s*$/o;
-           $CN_HELP_URL = $1 if /^\s*cn_help_url="?([^\"]*)"?\s*$/o;
            $FTP_SITES{us} = $1 if /^\s*ftpsite="?([^\"]*)"?\s*$/o;
            $FTP_SITES{$1} = $2 if /^\s*(\w+)_ftpsite="?([^\"]*)"?\s*$/o;
            @LANGUAGES = split(/\s+/, $1) if /^\s*polangs="?([^\"]*)"?\s*$/o;
@@ -59,6 +43,10 @@ sub init {
            @SECTIONS = split(/\s+/, $1) if /^\s*sections="?([^\"]*)"?\s*$/o;
            @ARCHIVES = split(/\s+/, $1) if /^\s*archives="?([^\"]*)"?\s*$/o;
            @ARCHITECTURES = split(/\s+/, $1) if /^\s*architectures="?([^\"]*)"?\s*$/o;
+           @PRIORITIES = split(/\s+/, $1) if /^\s*priorities="?([^\"]*)"?\s*$/o;
+       }
+       foreach (($TEMPLATEDIR, $CACHEDIR, $LOCALES)) {
+           s/\$\{?topdir\}?/$TOPDIR/g;
        }
        close (C);
        debug( "read config ($modtime > $config_read_time)" ) if DEBUG;
index 89da639639cad7ced9e5f9352b2e191aeb6856a4..bd7f8e1660bb5d68b6a0d0233e6c34ffcecdc6fb 100644 (file)
@@ -3,6 +3,7 @@ package Packages::DoDownload;
 use strict;
 use warnings;
 
+use POSIX;
 use CGI ();
 use DB_File;
 use Benchmark ':hireswallclock';
@@ -10,200 +11,17 @@ use Exporter;
 
 use Deb::Versions;
 use Packages::I18N::Locale;
-use Packages::HTML ();
 use Packages::Search qw( :all );
-use Packages::Config qw( $HOME $DBDIR @SUITES @ARCHIVES @SECTIONS @ARCHITECTURES $SEARCH_URL );
+use Packages::Config qw( $DBDIR @SUITES @ARCHIVES @SECTIONS @ARCHITECTURES );
 use Packages::CGI;
 use Packages::DB;
 
 our @ISA = qw( Exporter );
 our @EXPORT = qw( do_download );
 
-# TODO: find a way to get the U.S. mirror list from a more authoritive
-# location automatically. might not be overly smart to automatize it
-# completely, since I hand pick sites that are up-to-date, fast, and
-# have HTTP on a reasonably short URL
-#   -- Joy
-
-# hint:
-# grep-dctrl -F Site,Alias -e '(udel|bigfoot|kernel|crosslink|internap|cerias|lcs.mit|progeny)' Mirrors.masterlist | timestamps/archive_mirror_check.py
-our @north_american_sites = (
-       "ftp.us.debian.org/debian",
-       "http.us.debian.org/debian",
-       "ftp.debian.org/debian",
-#      "ftp.ca.debian.org/debian",
-       "ftp.egr.msu.edu/debian",
-       "mirrors.kernel.org/debian",
-       "archive.progeny.com/debian",
-       "debian.crosslink.net/debian",
-       "ftp-mirror.internap.com/pub/debian",
-       "ftp.cerias.purdue.edu/pub/os/debian",
-       "ftp.lug.udel.edu/debian",
-       "debian.lcs.mit.edu/debian",
-       "debian.teleglobe.net",
-       "debian.rutgers.edu",
-       "debian.oregonstate.edu/debian",
-       );
-our @european_sites = (
-       "ftp.de.debian.org/debian",
-       "ftp.at.debian.org/debian",
-       "ftp.bg.debian.org/debian",
-       "ftp.cz.debian.org/debian",
-       "ftp.dk.debian.org/debian",
-       "ftp.ee.debian.org/debian",
-       "ftp.fi.debian.org/debian",
-       "ftp.fr.debian.org/debian",
-       "ftp.hr.debian.org/debian",
-       "ftp.hu.debian.org/debian",
-       "ftp.ie.debian.org/debian",
-       "ftp.is.debian.org/debian",
-       "ftp.it.debian.org/debian",
-       "ftp.nl.debian.org/debian",
-       "ftp.no.debian.org/debian",
-       "ftp.pl.debian.org/debian",
-       "ftp.si.debian.org/debian",
-       "ftp.es.debian.org/debian",
-       "ftp.se.debian.org/debian",
-       "ftp.tr.debian.org/debian",
-       "ftp.uk.debian.org/debian",
-       );
-our @south_american_sites = (
-       "ftp.br.debian.org/debian",
-       "ftp.cl.debian.org/debian",
-       );
-our @australian_sites = (
-       "ftp.au.debian.org/debian",
-       "ftp.wa.au.debian.org/debian",
-       "ftp.nz.debian.org/debian",
-       );
-our @asian_sites = (
-       "ftp.jp.debian.org/debian",
-#      "ftp.kr.debian.org/debian",
-       "linux.csie.nctu.edu.tw/debian",
-       "debian.linux.org.tw/debian",
-       "linux.cdpa.nsysu.edu.tw/debian",
-       ); 
-
-our @volatile_european_sites = (
-        "volatile.debian.net/debian-volatile",
-        "ftp2.de.debian.org/debian-volatile",
-        "ftp.sk.debian.org/debian-volatile",
-                              );
-our @backports_european_sites = (
-        "www.backports.org/debian",
-       "debian.sil.at/backports.org/",
-        "backports.debian.or.at/backports.org",
-        "mirror.realroute.net/backports.org",
-        "backports.cisbg.com",
-        "backports.linuxdediziert.de/backports.org",
-        "debian.netcologne.de/debian-backports",
-        "ftp.de.debian.org/backports.org",
-        "mirror.buildd.net/backports.org",
-        "ftp.estpak.ee/backports.org",
-        "debian.acantho.net/backports.org",
-        "backports.essentkabel.com/backports.org",
-        "backports.sipo.nl",
-        "ftp.tuke.sk",
-                              );
-our @backports_asian_sites = (
-        "backports.mithril-linux.org",
-                            );
-our @backports_australian_sites = (
-        "mirror.linux.org.au/backports.org",
-                                 );
-our @amd64_european_sites = (
-        "amd64.debian.net/debian",
-        "ftp.de.debian.org/debian-amd64/debian",
-        "bach.hpc2n.umu.se/debian-amd64/debian",
-        "bytekeeper.as28747.net/debian-amd64/debian",
-       "mirror.switch.ch/debian-amd64/debian",
-        "ftp.nl.debian.org/debian-amd64/debian",
-                           );
-our @amd64_asian_sites = (
-        "hanzubon.jp/debian-amd64/debian",
-                        );
-our @amd64_north_american_sites = (
-        "mirror.espri.arizona.edu/debian-amd64/debian",
-                                 );
-our @kfreebsd_north_american_sites = (
-       "www.gtlib.gatech.edu/pub/gnuab/debian",
-                                    );
-our @kfreebsd_european_sites = (
-        # master site, aka ftp.gnuab.org
-        "kfreebsd-gnu.debian.net/debian",
-        "ftp.easynet.be/ftp/gnuab/debian",
-       "ftp.de.debian.org/debian-kfreebsd",
-       "ftp.sh.cvut.cz/MIRRORS/debian-non-linux",
-       "ftp.eila.jussieu.fr/pub/Debian-gnuab",
-                              );
-my @kfreebsd_asian_sites = (
-       "ftp.citkit.ru/pub/HURD/debian",
-                           );
-our @nonus_north_american_sites = (
-#      "ftp.ca.debian.org/debian-non-US",
-       "debian.yorku.ca/debian/non-US",
-       "mirror.direct.ca/linux/debian-non-US",
-       );
-our @nonus_european_sites = (
-       "non-us.debian.org/debian-non-US",
-       "ftp.de.debian.org/debian-non-US",
-       "ftp.at.debian.org/debian-non-US",
-       "ftp.bg.debian.org/debian-non-US",
-       "ftp.cz.debian.org/debian-non-US",
-       "ftp.fi.debian.org/debian-non-US",
-       "ftp.fr.debian.org/debian-non-US",
-       "ftp.hr.debian.org/debian-non-US",
-       "ftp.hu.debian.org/debian-non-US",
-       "ftp.ie.debian.org/debian-non-US",
-       "ftp.is.debian.org/debian-non-US",
-       "ftp.it.debian.org/debian-non-US",
-       "ftp.nl.debian.org/debian-non-US",
-       "ftp.no.debian.org/debian-non-US",
-       "ftp.pl.debian.org/debian/non-US",
-       "ftp.si.debian.org/debian-non-US",
-       "ftp.es.debian.org/debian-non-US",
-       "ftp.se.debian.org/debian-non-US",
-       "ftp.tr.debian.org/debian-non-US",
-       "ftp.uk.debian.org/debian/non-US",
-       );
-our @nonus_australian_sites = (
-       "ftp.au.debian.org/debian-non-US",
-       "ftp.wa.au.debian.org/debian-non-US",
-       "ftp.nz.debian.org/debian-non-US",
-       );
-our @nonus_asian_sites = (
-       "ftp.jp.debian.org/debian-non-US",
-#      "ftp.kr.debian.org/debian-non-US",
-       "linux.csie.nctu.edu.tw/debian-non-US",
-       "debian.linux.org.tw/debian-non-US",
-       "linux.cdpa.nsysu.edu.tw/debian-non-US",
-       );
-our @nonus_south_american_sites = (
-       "ftp.br.debian.org/debian-non-US",
-       "ftp.cl.debian.org/debian-non-US",
-       );
-
-# list of architectures
-our %arches = (
-        i386    => 'Intel x86',
-        m68k    => 'Motorola 680x0',
-        sparc   => 'SPARC',
-        alpha   => 'Alpha',
-        powerpc => 'PowerPC',
-        arm     => 'ARM',
-        hppa    => 'HP PA-RISC',
-        ia64    => 'Intel IA-64',
-        mips    => 'MIPS',
-        mipsel  => 'MIPS (DEC)',
-        s390    => 'IBM S/390',
-       "hurd-i386" => 'Hurd (i386)',
-       amd64   => 'AMD64',
-       "kfreebsd-i386" => 'GNU/kFreeBSD (i386)',
-       "kfreebsd-amd64" => 'GNU/kFreeBSD (amd64)'
-);
 
 sub do_download {
-    my ($params, $opts, $html_header, $menu, $page_content) = @_;
+    my ($params, $opts, $html_header, $page_content) = @_;
 
     if ($params->{errors}{package}) {
        fatal_error( _g( "package not valid or not specified" ) );
@@ -228,7 +46,7 @@ sub do_download {
 
     our (%packages_all);
     my (@results);
-    my ($final_result, $file, $filen, $md5sum, @file_components, $archive) = ("")x5;
+    my ($final_result, $filename, $directory, @file_components, $archive) = ("")x5;
 
     my $st0 = new Benchmark;
     unless (@Packages::CGI::fatal_errors) {
@@ -240,8 +58,8 @@ sub do_download {
 
        @results = grep { $_->[7] ne 'v' } @results;
        unless (@results) {
-           fatal_error( _g( "No such package." )."<br>".
-                        sprintf( _g( '<a href="%s">Search for the package</a>' ), "$SEARCH_URL/$pkg" ) );
+#          fatal_error( _g( "No such package." )."<br>".
+#                       sprintf( _g( '<a href="%s">Search for the package</a>' ), "$SEARCH_URL/$pkg" ) );
        } else {
            my $final_result = shift @results;
            foreach (@results) {
@@ -253,120 +71,38 @@ sub do_download {
            debug( "final_result=@$final_result", 1 );
            $archive = $final_result->[1];
            my %data = split /\000/, $packages_all{"$pkg $arch $final_result->[7]"};
-           $file = $data{filename};
-           @file_components = split('/', $file);
-           $filen = pop(@file_components);
-           
-           $md5sum = $data{md5sum};
-       }
-    }
-
-    %$html_header = ( title => _g( "Package Download Selection" ),
-                     lang => $opts->{lang},
-                     print_title => 1 );
-
-    if ($file) {
-       if ($arch ne 'all') {
-           $$page_content .= '<h2>'.sprintf( _g('Download Page for <kbd>%s</kbd> on %s machines'), $filen, $arches{$arch} ).'</h2>';
-       } else {
-           $$page_content .= '<h2>'.sprintf( _g('Download Page for <kbd>%s</kbd>'), $filen ).'</h2>';
-       }
-       my $directory = join( '/', @file_components).'/';
-       if ($archive ne 'security' ) {
-           $$page_content .= "<p>".sprintf( _g( 'You can download the requested file from the <tt>%s</tt> subdirectory at any of these sites:' ), $directory )."</p>\n";
-       } else {
-           $$page_content .= "<p>".sprintf( _g( 'You can download the requested file from the <tt>%s</tt> subdirectory at:' ), $directory )."</p>\n";
-       }
-
-       hint(sprintf(_g("If you are running Debian, it's strongly suggested to use a
-           package manager like <a href=\"%s\">aptitude</a> or <a
-           href=\"%s\">synaptic</a> to download and install
-           packages, instead of doing so manually via this website."),
-                    make_url('aptitude','',{arch=>undef}), 
-                    make_url('synaptic','',{arch=>undef}) ) );
-       
-       if ($archive eq 'security') {
-           
-           $$page_content .= "<ul><li><a href=\"http://security.debian.org/debian-security/$file\">security.debian.org/debian-security</a></li></ul>";
-           $$page_content .= '<p>'._g( 'Debian security updates are currently officially distributed only via <tt>security.debian.org</tt>.' ).'</p>';
-       } elsif ($archive eq 'amd64') {
-
-           $$page_content .= print_links( _g( "North America" ), $file, @amd64_north_american_sites );
-           $$page_content .= print_links( _g( "Europe" ), $file, @amd64_european_sites );
-           $$page_content .= print_links( _g( "Asia" ), $file, @amd64_asian_sites );
-
-           $$page_content .= '<p>'._g( 'Note that AMD64 is not officialy included in the Debian archive yet, but the AMD64 porter group keeps their archive in sync with the official archive as close as possible. See the <a href="http://www.debian.org/ports/amd64/">AMD64 ports page</a> for current information.' ).'</p>';
-       } elsif ($archive eq 'kfreebsd') {
-
-           $$page_content .= print_links( _g( "North America" ), $file, @kfreebsd_north_american_sites );
-           $$page_content .= print_links( _g( "Europe" ), $file, @kfreebsd_european_sites );
-           $$page_content .= print_links( _g( "Asia" ), $file, @kfreebsd_asian_sites );
-       
-           $$page_content .= '<p>'._g( 'Note that GNU/kFreeBSD is not officialy included in the Debian archive yet, but the GNU/kFreeBSD porter group keeps their archive in sync with the official archive as close as possible. See the <a href="http://www.debian.org/ports/kfreebsd-gnu/">GNU/kFreeBSD ports page</a> for current information.' ).'</p>';
-       } elsif ($archive eq 'non-US') {
-
-           $$page_content .= '<div class="cardleft">';
-           $$page_content .= print_links( _g( "North America" ), $file, @nonus_north_american_sites );
-           $$page_content .= print_links( _g( "Australia and New Zealand" ), $file,
-                                          @nonus_australian_sites );
-           $$page_content .= print_links( _g( "Asia" ), $file, @nonus_asian_sites );
-           $$page_content .= print_links( _g( "South America" ), $file, @nonus_south_american_sites );
-           $$page_content .= '</div><div class="cardright">';
-           $$page_content .= print_links( _g( "Europe" ), $file, @nonus_european_sites );
-           $$page_content .= '</div>';
-
-           $$page_content .= '<p style="clear:both">'.sprintf( _g('If none of the above sites are fast enough for you, please see our <a href="%s">complete mirror list</a>.' ), 'http://www.debian.org/mirror/list-non-US' ).'</p>';
-       } elsif ($archive eq 'backports') {
-       
-           $$page_content .= '<div class="cardleft">';
-           $$page_content .= print_links( _g( "Europe" ), $file, @backports_european_sites );
-           $$page_content .= '</div><div class="cardright">';
-           $$page_content .= print_links( _g( "Australia and New Zealand" ), $file,
-                                          @backports_australian_sites );
-           $$page_content .= print_links( _g( "Asia" ), $file, @backports_asian_sites );
-           $$page_content .= '</div>';
-           
-           $$page_content .= '<p style="clear:both">'.sprintf( _g( 'If none of the above sites are fast enough for you, please see our <a href="%s">complete mirror list</a>.'), 'http://www.backports.org/debian/README.mirrors.html' ).'</p>';
-       } elsif ($archive eq 'volatile') {
-           
-           $$page_content .= print_links( _g( "Europe" ), $file, @volatile_european_sites );
+           if (!%data && $arch ne 'all' && $final_result->[3] eq 'all') {
+               %data = split /\000/, $packages_all{"$pkg all $final_result->[7]"};
+               $arch = 'all';
+               debug( "choosing arch 'all' instead of requested arch $arch", 1 );
+#              fatal_error( _g( "No such package." )."<br>".
+#                           sprintf( _g( '<a href="%s">Search for the package</a>' ), "$SEARCH_URL/$pkg" ) ) unless %data;
+           }
+           @file_components = split('/', $data{filename});
+           $filename = pop(@file_components);
+           $directory = join( '/', @file_components).'/';
+
+           $page_content->{archive} = $archive;
+           $page_content->{suite} = $suite;
+           $page_content->{pkg} = $pkg;
+           $page_content->{pkgsize} = sprintf( '%.1f', floor(($data{size}/102.4)+0.5)/10 );
+           $page_content->{pkgsize_unit} = _g( 'kByte' );
+           if ($page_content->{pkgsize} > 1024) {
+               $page_content->{pkgsize} = sprintf( '%.1f', floor(($data{size}/(102.4*102.4))+0.5)/100 );
+               $page_content->{pkgsize_unit} = _g( 'MByte' );
+           }
+           $page_content->{architecture} = $arch;
+           foreach (keys %data) {
+               $page_content->{$_} = $data{$_};
+           }
+           $page_content->{filename} = { file => $filename,
+                                         directory => $directory,
+                                         full => $data{filename},
+                                     };
 
-           $$page_content .= '<p>'.sprintf( _g( 'If none of the above sites are fast enough for you, please see our <a href="%s">complete mirror list</a>.' ), 'http://volatile.debian.net/mirrors.html' ).'</p>';
-       } elsif ($archive eq 'us') {
-           
-           $$page_content .= '<div class="cardleft">';
-           $$page_content .= print_links( _g( "North America" ), $file, @north_american_sites );
-           $$page_content .= '</div><div class="cardright">';
-           $$page_content .= print_links( _g( "Europe" ), $file, @european_sites );
-           $$page_content .= '</div><div class="cardleft">';
-           $$page_content .= print_links( _g( "Australia and New Zealand" ), $file, @australian_sites );
-           $$page_content .= '</div><div class="cardright">';
-           $$page_content .= print_links( _g( "Asia" ), $file, @asian_sites );
-           $$page_content .= '</div><div class="cardleft">';
-           $$page_content .= print_links( _g( "South America" ), $file, @south_american_sites );
-           $$page_content .= '</div>';
-           
-           $$page_content .= '<p style="clear:both">'.sprintf( _g( 'If none of the above sites are fast enough for you, please see our <a href="%s">complete mirror list</a>.' ), 'http://www.debian.org/mirror/list' ).'</p>';
        }
-    
-    $$page_content .= '<p>'._g( 'Note that in some browsers you will need to tell your browser you want the file saved to a file. For example, in Firefox or Mozilla, you should hold the Shift key when you click on the URL.' ).'</p>';
-    $$page_content .= "<p>".sprintf( _g( 'The MD5sum for <tt>%s</tt> is <strong>%s</strong>' ), $filen, $md5sum ).'</p>'
-       if $md5sum;
-    }
-}
-
-sub print_links {
-    my ( $title, $file, @servers ) = @_;
-
-    my $str = "<p><em>$title</em></p>";
-    $str .= "<ul>";
-    foreach (@servers) {
-       $str .= "<li><a href=\"http://$_/$file\">$_</a></li>\n";
-       # $str .= "<li><a href=\"ftp://$_/$file\">$_</a></li>\n";
     }
-    $str .= "</ul>";
-
-    return $str;
+       
 }
 
 1;
index a1dda56b95d01904096438c2b448ed828b39a37c..97e9f013bea2db584800accdc1c87bbfde3c41ca 100644 (file)
@@ -17,7 +17,6 @@ use Packages::I18N::Locale;
 use Packages::CGI;
 use Packages::DB;
 use Packages::Search qw( :all );
-use Packages::HTML;
 use Packages::Page ();
 use Packages::SrcPage ();
 
@@ -25,7 +24,7 @@ our @ISA = qw( Exporter );
 our @EXPORT = qw( do_filelist );
 
 sub do_filelist {
-    my ($params, $opts, $html_header, $menu, $page_content) = @_;
+    my ($params, $opts, $html_header, $page_content) = @_;
 
     if ($params->{errors}{package}) {
        fatal_error( _g( "package not valid or not specified" ) );
@@ -37,17 +36,12 @@ sub do_filelist {
        fatal_error( _g( "architecture not valid or not specified" ) );
     }
 
-    $$menu = '';
     my $pkg = $opts->{package};
     my $suite = $opts->{suite}[0];
     my $arch = $opts->{arch}[0] ||'';
-
-    %$html_header = ( title => sprintf( _g( "Filelist of package <em>%s</em> in <em>%s</em> of architecture <em>%s</em>" ), $pkg, $suite, $arch ),
-                     title_tag => sprintf( _g( "Filelist of package %s/%s/%s" ), $pkg, $suite, $arch ),
-                     lang => $opts->{lang},
-                     keywords => "debian, $suite, $arch, filelist",
-                     print_title => 1,
-                     );
+    $page_content->{pkg} = $pkg;
+    $page_content->{suite} = $suite;
+    $page_content->{arch} = $arch;
 
     unless (@Packages::CGI::fatal_errors) {
        if (tie my %contents, 'DB_File', "$DBDIR/contents/filelists_${suite}_${arch}.db",
@@ -57,13 +51,13 @@ sub do_filelist {
                fatal_error( _g( "No such package in this suite on this architecture." ) );
            } else {
                my @files = unpack "L/(CC/a)", $contents{$pkg};
-               my $file = "";
-               $$page_content .= '<div id="pfilelist"><pre>';
+               my $file;
+
+               $page_content->{files} = [];
                for (my $i=0; $i<scalar @files;) {
                    $file = substr($file, 0, $files[$i++]).$files[$i++];
-                   $$page_content .= "/$file\n";
+                   push @{$page_content->{files}}, "/$file";
                }
-               $$page_content .= '</pre></div>';
            }
        } else {
            fatal_error( _g( "Invalid suite/architecture combination" ) );
index 064a18ad2aa4b386c336dccc3d01af144ca25a0e..0ed874a24ce31a4dcf5865a3036c0cd25330fe58 100644 (file)
@@ -44,9 +44,12 @@ sub send_file {
     }
 
     my $wwwdir = "$TOPDIR/www";
-    my $path = "$opts->{suite}[0]/";
+    my $path = "";
+    $path .= "source/" if $opts->{source};
+    $path .= "$opts->{suite}[0]/";
     $path .= "$opts->{archive}[0]/" if @{$opts->{archive}} == 1;
     $path .= "$opts->{subsection}[0]/" if @{$opts->{subsection}};
+    $path .= "$opts->{priority}[0]/" if @{$opts->{priority}};
     # we don't have translated index pages for subsections yet
     $opts->{lang} = 'en' if @{$opts->{subsection}} or $file eq 'allpackages';
     $path .= "$file.$opts->{lang}.$opts->{format}";
@@ -71,21 +74,6 @@ sub send_file {
                                  $path, $! ) );
        }
     }
-
-    %$html_header = ( title => _g('Error'),
-                     lang => $opts->{lang},
-                     print_title => 1,
-                     print_search_field => 'packages',
-                     search_field_values => { 
-                         keywords => _g('search for a package'),
-                         searchon => 'default',
-                         arch => 'any',
-                         suite => 'all',
-                         section => 'all',
-                         exact => 1,
-                         debug => $Packages::CGI::debug,
-                     },
-                     );
 }
 
 1;
index 059d5a33fa5e859d3dad1c6bc07d884547ac3ff6..7ee921a3975ee6c14f689d0ccd10dfbca029177a 100644 (file)
@@ -16,10 +16,10 @@ use Packages::I18N::Locale;
 use Packages::Search qw( :all );
 use Packages::CGI;
 use Packages::DB;
-use Packages::Config qw( $TOPDIR @SECTIONS $HOSTNAME $ROOT );
+use Packages::Config qw( $TOPDIR @SECTIONS $ROOT );
 
 sub do_newpkg {
-    my ($params, $opts, $html_header, $menu, $page_content) = @_;
+    my ($params, $opts, $html_header, $page_content) = @_;
 
     if ($params->{errors}{suite}) {
        fatal_error( _g( "suite not valid or not specified" ) );
@@ -38,10 +38,6 @@ sub do_newpkg {
     my $one_section = @{$opts->{section}} == 1 ?
        $opts->{section}[0] : undef;
 
-    my @full_path = ($HOSTNAME, $ROOT, $suite);
-    push @full_path, $one_archive if $one_archive;
-    my $full_path = join( '/', @full_path );
-
     my @new_pkgs;
     #FIXME: move to Packages::DB?
     open NEWPKG, '<', "$TOPDIR/files/packages/newpkg_info"
@@ -63,90 +59,60 @@ sub do_newpkg {
     my $now_time = strftime ("%B %d, %Y", @date);
     my $rss_time = strftime ("%Y-%m-%dT%H:%M+00:00", @date);
 
-    unless ($opts->{format} eq 'rss') {
-       my $title = sprintf( _g( "New Packages in \"%s\"" ), 
-                            $suite );
-       %$html_header = ( title => $title,
-                         title_keywords => "debian, "._g('new packages').", $suite, @{$opts->{section}}",
-                         meta => "<link rel=\"alternate\" type=\"application/rss+xml\" title=\"RSS\" href=\"newpkg?format=rss\">",
-                         lang => $opts->{lang},
-                         print_title => 1 );
-       
-       $$page_content .= "<p>"
-           . sprintf(_g( "The following packages were added to suite <em>%s</em>%s in the Debian archive during the last 7 days."), $suite,
-                     $one_section ? sprintf(_g(" (section %s)"),$one_section):'')."</p>"
-           . "<p>".sprintf( _g( "This information is also available as an <a href=\"%s\">RSS feed</a>." ), "newpkg?format=rss" )
-           ." <a href=\"newpkg?format=rss\"><img src=\"http://planet.debian.org/rss10.png\" alt=\"[RSS 1.0 Feed]\"></a></p>";
-
-       if (@new_pkgs) {
-           $$page_content .= "\n<ul>\n";
-           
-           foreach my $pkg (sort { &$sort_func($a,$b) } @new_pkgs) {
-               $$page_content .= sprintf ("<li><a href=\"%s\">%s</a>\n    -- %s%s",
-                                          $pkg->[0], $pkg->[0],
-                                          encode_entities($pkg->[-1], '"&<>'),
-                                          $pkg->[1] ?
-                                          sprintf(_g(" <em>(%s days old)</em>"),$pkg->[1]):
-                                          '');
-           }
-           $$page_content .= "\n</ul>\n" if @new_pkgs;
-       }
-
-       my $slist = '';
-       if ($one_section) {
-           foreach my $s (@SECTIONS) {
-               $slist .= ", " if $slist;
-               $slist .= $one_section eq $s ? $s :
-                   "<a href=\"../$s/newpkg\">$s</a>";
-           }
-       }
-
-       $$page_content .= '<p class="psmallcenter"><a href="'.make_url('allpackages','').'" title="'.
-           _g( "List of all packages" ) ."\">".
-           _g( "All packages" ) ."</a><br>(<a href=\"".make_url('allpackages','',{format=>'txt.gz'})."\">".
-           _g( "compact compressed textlist" )."</a>)<br>".
-           ($slist ? sprintf(_g( "New packages in %s" ), $slist ):'').
-           "</p>\n";
-
-    } else { # unless ($opts->{format} eq 'rss')
-       my ( $rss_link, $rss_description, $rss_date );
-
-       $rss_description = sprintf(_g( "The following packages were added to suite %s%s in the Debian archive during the last 7 days."), $suite,
-                                  $one_section ? sprintf(_g(" (section %s)"),$one_section):'');
-
-       my $rss = new XML::RSS (version => '1.0');
-       $rss_link = "$full_path".($one_section?"$one_section/":'')."/newpkg?format=rss";
-       $rss->channel(
-                     title        => _g("New Debian Packages"),
-                     link         => $rss_link,
-                     description  => $rss_description,
-                     dc => {
-                         date       => $rss_time,
-                         publisher  => 'debian-www@lists.debian.org',
-                         rights     => 'Copyright '.($date[5]+1900).', SPI Inc.',
-                         language   => $opts->{lang},
-                     },
-                     syn => {
-                         updatePeriod     => "daily",
-                         updateFrequency  => "2",
-#                    updateBase       => "1901-01-01T00:00+00:00",
-                     } );
-
-       foreach my $pkg (sort { &$sort_func($a,$b) } @new_pkgs) {
-           $rss->add_item(
-                          title       => $pkg->[0],
-                          link        => "$full_path/$pkg->[0]",
-                          description => $pkg->[-1],
-                          dc => {
-                              subject  => $pkg->[6],
-                          } );
-       }
-       my $charset = get_charset( $opts->{lang} );
-       print &CGI::header( -type => 'application/rss+xml',
-                           -charset => $charset );
-       print $rss->as_string;
-       exit;
+    $page_content->{make_url} = sub { return &Packages::CGI::make_url(@_) };
+
+    if (@new_pkgs) {
+       $page_content->{new_packages} = [ sort { &$sort_func($a,$b) } @new_pkgs ];
     }
+
+    $page_content->{suite} = $suite;
+    $page_content->{section} = $one_section if $one_section;
+    $page_content->{archive} = $one_archive if $one_archive;
+    $page_content->{sections} = \@SECTIONS;
+
+#    my @full_path = ($HOSTNAME, $ROOT, $suite);
+#    push @full_path, $one_archive if $one_archive;
+#    my $full_path = join( '/', @full_path );
+
+#     } else { # unless ($opts->{format} eq 'rss')
+#      my ( $rss_link, $rss_description, $rss_date );
+
+#      $rss_description = sprintf(_g( "The following packages were added to suite %s%s in the Debian archive during the last 7 days."), $suite,
+#                                 $one_section ? sprintf(_g(" (section %s)"),$one_section):'');
+
+#      my $rss = new XML::RSS (version => '1.0');
+#      $rss_link = "$full_path".($one_section?"$one_section/":'')."/newpkg?format=rss";
+#      $rss->channel(
+#                    title        => _g("New Debian Packages"),
+#                    link         => $rss_link,
+#                    description  => $rss_description,
+#                    dc => {
+#                        date       => $rss_time,
+#                        publisher  => 'debian-www@lists.debian.org',
+#                        rights     => 'Copyright '.($date[5]+1900).', SPI Inc.',
+#                        language   => $opts->{lang},
+#                    },
+#                    syn => {
+#                        updatePeriod     => "daily",
+#                        updateFrequency  => "2",
+# #                  updateBase       => "1901-01-01T00:00+00:00",
+#                    } );
+
+#      foreach my $pkg (sort { &$sort_func($a,$b) } @new_pkgs) {
+#          $rss->add_item(
+#                         title       => $pkg->[0],
+#                         link        => "$full_path/$pkg->[0]",
+#                         description => $pkg->[-1],
+#                         dc => {
+#                             subject  => $pkg->[6],
+#                         } );
+#      }
+#      my $charset = get_charset( $opts->{lang} );
+#      print &CGI::header( -type => 'application/rss+xml',
+#                          -charset => $charset );
+#      print $rss->as_string;
+#      exit;
+#     }
 }
 
 1;
index f8782b1e5bd96fe65deccfba0dd2866cd493eec1..df9a91d0b266e891d02094401505b2fc72fa7adf 100644 (file)
@@ -14,15 +14,12 @@ our @EXPORT = qw( do_search );
 use Deb::Versions;
 use Packages::I18N::Locale;
 use Packages::Search qw( :all );
-use Packages::CGI;
+use Packages::CGI qw( :DEFAULT msg );
 use Packages::DB;
-use Packages::HTML qw(marker);
-use Packages::Config qw( $DBDIR $SEARCH_URL $SEARCH_PAGE
-                        @SUITES @ARCHIVES $ROOT );
-use Packages::HTML;
+use Packages::Config qw( $DBDIR @SUITES @ARCHIVES $ROOT );
 
 sub do_search {
-    my ($params, $opts, $html_header, $menu, $page_content) = @_;
+    my ($params, $opts, $html_header, $page_content) = @_;
 
     $Params::Search::too_many_hits = 0;
 
@@ -33,8 +30,6 @@ sub do_search {
        fatal_error( _g( "keyword too short (keywords need to have at least two characters)" ) );
     }
 
-    $$menu = "";
-    
     my @keywords = @{$opts->{keywords}};
     my $searchon = $opts->{searchon};
 
@@ -56,19 +51,19 @@ sub do_search {
 
        if ($searchon eq 'names') {
            if ($opts->{source}) {
-               do_names_search( \@keywords, \%sources, $sp_obj,
+               do_names_search( [ @keywords ], \%sources, $sp_obj,
                                 \&read_src_entry_all, $opts,
                                 \@results, \@non_results );
            } else {
-               do_names_search( \@keywords, \%packages, $p_obj,
+               do_names_search( [ @keywords ], \%packages, $p_obj,
                                 \&read_entry_all, $opts,
                                 \@results, \@non_results );
            }
        } else {
-           do_names_search( \@keywords, \%packages, $p_obj,
+           do_names_search( [ @keywords ], \%packages, $p_obj,
                             \&read_entry_all, $opts,
                             \@results, \@non_results );
-           do_fulltext_search( \@keywords, "$DBDIR/descriptions.txt",
+           do_fulltext_search( [ @keywords ], "$DBDIR/descriptions.txt",
                                \%did2pkg, \%packages,
                                \&read_entry_all, $opts,
                                \@results, \@non_results );
@@ -110,11 +105,11 @@ sub do_search {
            unless (@non_results) {
                error( _g( "Can't find that package." ) );
            } else {
-               hint( _g( "Can't find that package." )." ".
-                     sprintf( _g( '<a href="%s">%s</a>'.
-                     " results have not been displayed due to the".
-                     " search parameters." ), "$SEARCH_URL/$keyword_esc" ,
-                     $#non_results+1 ) );
+#              hint( _g( "Can't find that package." )." ".
+#                    sprintf( _g( '<a href="%s">%s</a>'.
+#                    " results have not been displayed due to the".
+#                    " search parameters." ), "$SEARCH_URL/$keyword_esc" ,
+#                    $#non_results+1 ) );
            }
            
        } else {
@@ -132,27 +127,23 @@ sub do_search {
                               encode_entities(make_search_url('',"keywords=$keyword_esc",{exact => 0})) ) );
            }
        }
-       hint( sprintf( _g( 'You can try a different search on the <a href="%s">Packages search page</a>.' ), "$SEARCH_PAGE#search_packages" ) );
+#      hint( sprintf( _g( 'You can try a different search on the <a href="%s">Packages search page</a>.' ), "$SEARCH_PAGE#search_packages" ) );
        
     }
 
-    %$html_header = ( title => _g( 'Package Search Results' ) ,
-                     lang => $opts->{lang},
-                     title_tag => _g( 'Debian Package Search Results' ),
-                     print_title => 1,
-                     print_search_field => 'packages',
-                     search_field_values => { 
-                         keywords => $keyword_enc,
-                         searchon => $opts->{searchon_form},
-                         arch => $archs_enc,
-                         suite => $suites_enc,
-                         section => $sections_enc,
-                         exact => $opts->{exact},
-                         debug => $opts->{debug},
-                     },
-                     );
-
-    $$page_content = '';
+    $page_content->{make_url} = sub { return &Packages::CGI::make_url(@_) };
+    $page_content->{make_search_url} = sub { return &Packages::CGI::make_search_url(@_) };
+
+    $page_content->{search_field_values} = { 
+       keywords => $keyword_enc,
+       searchon => $opts->{searchon_form},
+       arch => $archs_enc,
+       suite => $suites_enc,
+       section => $sections_enc,
+       exact => $opts->{exact},
+       debug => $opts->{debug},
+    };
+
     if (@results) {
        my (%pkgs, %subsect, %sect, %archives, %desc, %binaries, %provided_by);
 
@@ -177,10 +168,10 @@ sub do_search {
 
            my %uniq_pkgs = map { $_ => 1 } (keys %pkgs, keys %provided_by);
            my @pkgs = sort keys %uniq_pkgs;
-           $$page_content .= print_packages( \%pkgs, \@pkgs, $opts, \@keywords,
-                                             \&print_package, \%provided_by,
-                                             \%archives, \%sect, \%subsect,
-                                             \%desc );
+           process_packages( $page_content, 'packages', \%pkgs, \@pkgs, $opts, \@keywords,
+                             \&process_package, \%provided_by,
+                             \%archives, \%sect, \%subsect,
+                             \%desc );
 
        } else { # unless $opts->{source}
            foreach (@results) {
@@ -208,134 +199,112 @@ sub do_search {
            }
 
            my @pkgs = sort keys %pkgs;
-           $$page_content .= print_packages( \%pkgs, \@pkgs, $opts, \@keywords,
-                                             \&print_src_package, \%archives,
-                                             \%sect, \%subsect, \%binaries );
+           process_packages( $page_content, 'src_packages', \%pkgs, \@pkgs, $opts, \@keywords,
+                             \&process_src_package, \%archives,
+                             \%sect, \%subsect, \%binaries );
        } # else unless $opts->{source}
     } # if @results
 } # sub do_search
 
-sub print_packages {
-    my ($pkgs, $pkgs_list, $opts, $keywords, $print_func, @func_args) = @_;
+sub process_packages {
+    my ($content, $target, $pkgs, $pkgs_list, $opts, $keywords, $print_func, @func_args) = @_;
+
+    my @categories;
+    $content->{results} = scalar @$pkgs_list;
 
-    #my ($start, $end) = multipageheader( $input, scalar @pkgs, \%opts );
-    my $str = '<div id="psearchres">';
-    $str .= "<p>".sprintf( _g( "Found <em>%s</em> matching packages." ),
-                          scalar @$pkgs_list )."</p>";
-    #my $count = 0;
     my $keyword;
     $keyword = $keywords->[0] if @$keywords == 1;
            
     my $have_exact;
     if ($keyword && grep { $_ eq $keyword } @$pkgs_list) {
        $have_exact = 1;
-       $str .= '<h2>'._g( "Exact hits" ).'</h2>';
-       $str .= &$print_func( $keyword, $pkgs->{$keyword}||{},
-                             map { $_->{$keyword}||{} } @func_args );
+       $categories[0]{name} = _g( "Exact hits" );
+
+       $categories[0]{$target} = [ &$print_func( $keyword, $pkgs->{$keyword}||{},
+                                                  map { $_->{$keyword}||{} } @func_args ) ];
        @$pkgs_list = grep { $_ ne $keyword } @$pkgs_list;
     }
            
     if (@$pkgs_list && (($opts->{searchon} ne 'names') || !$opts->{exact})) {
-       $str .= '<h2>'._g( 'Other hits' ).'</h2>'
-           if $have_exact;
+       my %cat;
+       $cat{name} = _g( 'Other hits' ) if $have_exact;
        
+       $cat{packages} = [];
        foreach my $pkg (@$pkgs_list) {
-           #$count++;
-           #next if $count < $start or $count > $end;
-           $str .= &$print_func( $pkg, $pkgs->{$pkg}||{},
-                                 map { $_->{$pkg}||{} } @func_args );
+           push @{$cat{$target}}, &$print_func( $pkg, $pkgs->{$pkg}||{},
+                                                map { $_->{$pkg}||{} } @func_args );
        }
+       push @categories, \%cat;
     } elsif (@$pkgs_list) {
-       $str .= "<p>".sprintf( _g( '<a href="%s">%s</a> results have not been displayed because you requested only exact matches.' ),
-                              encode_entities(make_search_url('',"keywords=$opts->{keyword_esc}",{exact => 0})),
-                              scalar @$pkgs_list )."</p>";
+       $content->{skipped} = scalar @$pkgs_list;
     }
-    $str .= '</div>';
 
-    return $str;
+    $content->{categories} = \@categories;
 }
 
-sub print_package {
+sub process_package {
     my ($pkg, $pkgs, $provided_by, $archives, $sect, $subsect, $desc) = @_;
 
-    my $str = '<h3>'.sprintf( _g( 'Package %s' ), $pkg ).'</h3>';
-    $str .= '<ul>';
+    my %pkg = ( pkg => $pkg,
+               suites => [] );
+
     foreach my $suite (@SUITES) {
-           my $override = { suite => $suite };
-           if (exists $pkgs->{$suite}) {
-               my %archs_printed;
-               my @versions = version_sort keys %{$pkgs->{$suite}};
-               my $origin_str = "";
-               if ($sect->{$suite}{$versions[0]}) {
-                   $origin_str .= " ".marker($sect->{$suite}{$versions[0]});
-               }
-               $str .= sprintf( "<li><a href=\"%s\">%s</a> (%s): %s   %s\n",
-                                make_url($pkg,'',$override), $suite, $subsect->{$suite}{$versions[0]},
-                                $desc->{$suite}{$versions[0]}, $origin_str );
+       my %suite = ( suite => $suite );
+       if (exists $pkgs->{$suite}) {
+           my %archs_printed;
+           my @versions = version_sort keys %{$pkgs->{$suite}};
+           $suite{section} = $sect->{$suite}{$versions[0]};
+           $suite{subsection} = $subsect->{$suite}{$versions[0]};
+           $suite{desc} = $desc->{$suite}{$versions[0]};
+           $suite{versions} = [];
                
-               foreach my $v (@versions) {
-                   my $archive_str = "";
-                   if ($archives->{$suite}{$v} ne 'us') {
-                       $archive_str .= " ".marker($archives->{$suite}{$v});
-                   }
+           foreach my $v (@versions) {
+               my %version;
+               $version{version} = $v;
+               $version{archive} = $archives->{$suite}{$v};
                    
-                   my @archs_to_print = grep { !$archs_printed{$_} } sort keys %{$pkgs->{$suite}{$v}};
-                   $str .= sprintf( "<br>%s$archive_str: %s\n",
-                                    $v, join (" ", @archs_to_print ))
-                       if @archs_to_print;
-                   $archs_printed{$_}++ foreach @archs_to_print;
-               }
-               if (my $p =  $provided_by->{$suite}) {
-                   $str .= '<br>'._g( 'also provided by: ' ).
-                       join( ', ', map { "<a href=\"".
-                                             make_url($_,'',$override)."\">$_</a>"  } @$p);
-               }
-               $str .= "</li>\n";
-           } elsif (my $p =  $provided_by->{$suite}) {
-               $str .= sprintf( "<li><a href=\"%s\">%s</a>: "._g('Virtual package').'<br>',
-                                make_url($pkg,'',$override), $suite );
-               $str .= _g( 'provided by: ' ).
-                   join( ', ', map { "<a href=\"".
-                                         make_url($_,'',$override)."\">$_</a>"  } @$p);
+               $version{architectures} = [ grep { !$archs_printed{$_} } sort keys %{$pkgs->{$suite}{$v}} ];
+               push @{$suite{versions}}, \%version if @{$version{architectures}};
+
+               $archs_printed{$_}++ foreach @{$version{architectures}};
            }
+           if (my $p =  $provided_by->{$suite}) {
+               $suite{providers} = $p;
+           }
+       } elsif (my $p =  $provided_by->{$suite}) {
+           $suite{desc} = _g('Virtual package');
+           $suite{providers} = $p;
+       }
+       push @{$pkg{suites}}, \%suite if $suite{versions} || $suite{providers};
     }
-    $str .= "</ul>\n";
-    return $str;
+
+    return \%pkg;
 }
 
-sub print_src_package {
+sub process_src_package {
     my ($pkg, $pkgs, $archives, $sect, $subsect, $binaries) = @_;
 
-    my $str = '<h3>'.sprintf( _g( 'Source package %s' ), $pkg ).'</h3>';
-    $str .= "<ul>\n";
+    my %pkg = ( pkg => $pkg,
+               origins => [] );
+
     foreach my $suite (@SUITES) {
        foreach my $archive (@ARCHIVES) {
            if (exists $pkgs->{$suite}{$archive}) {
-               my $origin_str = "";
-               if ($sect->{$suite}{$archive}{source}) {
-                   $origin_str .= " ".marker($sect->{$suite}{$archive}{source});
-               }
-               if ($archives->{$suite}{$archive}{source}) {
-                   $origin_str .= " ".marker($archives->{$suite}{$archive}{source});
-               }
-               $str .= sprintf( "<li><a href=\"$ROOT/%s/source/%s\">%s</a> (%s): %s   %s",
-                                $suite.(($archive ne 'us')?"/$archive":''), $pkg, $suite.(($archive ne 'us')?"/$archive":''), $subsect->{$suite}{$archive}{source},
-                                $pkgs->{$suite}{$archive}, $origin_str );
-               
-               $str .= "<br>"._g( 'Binary packages: ' );
-               my @bp_links;
-               foreach my $bp (@{$binaries->{$suite}{$archive}}) {
-                   my $bp_link = sprintf( "<a href=\"$ROOT/%s/%s\">%s</a>",
-                                          $suite.(($archive ne 'us')?"/$archive":''), uri_escape( $bp ),  $bp );
-                   push @bp_links, $bp_link;
-               }
-               $str .= join( ", ", @bp_links );
-               $str .= "</li>\n";
+               my %origin;
+               $origin{version} = $pkgs->{$suite}{$archive};
+               $origin{suite} = $suite;
+               $origin{archive} = $archive; 
+               $origin{section} = $sect->{$suite}{$archive}{source};
+               $origin{subsection} = $subsect->{$suite}{$archive}{source};
+               $origin{real_archive} = $archives->{$suite}{$archive}{source};
+
+               $origin{binaries} = $binaries->{$suite}{$archive};
+               push @{$pkg{origins}}, \%origin;
            }
        }
     }
-    $str .= "</ul>\n";
-    return $str;
+
+    return \%pkg;
 }
 
 1;
index 1a51ba3d445eb28c2f697ce5dd80a46e06e61d83..f512ec4618334a3a007cd0492b8350e4ba7f8892 100644 (file)
@@ -16,11 +16,10 @@ use Packages::I18N::Locale;
 use Packages::Search qw( :all );
 use Packages::CGI;
 use Packages::DB;
-use Packages::Config qw( $DBDIR $SEARCH_URL $SEARCH_PAGE
-                        @SUITES @ARCHIVES @ARCHITECTURES $ROOT );
+use Packages::Config qw( $DBDIR @SUITES @ARCHIVES @ARCHITECTURES $ROOT );
 
 sub do_search_contents {
-    my ($params, $opts, $html_header, $menu, $page_content) = @_;
+    my ($params, $opts, $html_header, $page_content) = @_;
 
     if ($params->{errors}{keywords}) {
        fatal_error( _g( "keyword not valid or missing" ) );
@@ -42,26 +41,12 @@ sub do_search_contents {
        fatal_error( sprintf( _g( "more than one suite specified for contents search (%s)" ), "@{$opts->{suite}}" ) );
     }
 
-    $$menu = "";
-    
     my @keywords = @{$opts->{keywords}};
     my $mode = $opts->{mode} || '';
     my $suite = $opts->{suite}[0];
     my $archive = $opts->{archive}[0] ||'';
     $Packages::Search::too_many_hits = 0;
 
-    # for URL construction
-    my $keyword_esc = uri_escape( "@keywords" );
-    my $suites_param = join ',', @{$params->{values}{suite}{no_replace}};
-    my $sections_param = join ',', @{$params->{values}{section}{no_replace}};
-    my $archs_param = join ',', @{$params->{values}{arch}{no_replace}};
-
-    # for output
-    my $keyword_enc = encode_entities "@keywords" || '';
-    my $suites_enc = encode_entities( join( ', ', @{$params->{values}{suite}{no_replace}} ), '&<>"' );
-    my $sections_enc = encode_entities( join( ', ', @{$params->{values}{section}{no_replace}} ), '&<>"' );
-    my $archs_enc = encode_entities( join( ', ',  @{$params->{values}{arch}{no_replace}} ), '&<>"' );
-    
     my $st0 = new Benchmark;
     my (@results);
 
@@ -110,61 +95,8 @@ sub do_search_contents {
        my $st1 = new Benchmark;
        my $std = timediff($st1, $st0);
        debug( "Search took ".timestr($std) ) if DEBUG;
-    }
-    
-    my $suite_wording = sprintf(_g("suite <em>%s</em>"), $suites_enc );
-    my $section_wording = $sections_enc eq 'all' ? _g("all sections")
-       : sprintf(_g("section(s) <em>%s</em>"), $sections_enc );
-    my $arch_wording = $archs_enc eq 'any' ? _g("all architectures")
-       : sprintf(_g("architecture(s) <em>%s</em>"), $archs_enc );
-    my $wording = _g("paths that end with");
-    if ($mode eq 'filename') {
-       $wording =  _g("files named");
-    } elsif ($mode eq 'exactfilename') {
-       $wording = _g("filenames that contain");
-    }
-    msg( sprintf( _g("You have searched for %s <em>%s</em> in %s, %s, and %s." ),
-                 $wording, $keyword_enc,
-                 $suite_wording, $section_wording, $arch_wording ) );
-
-    if ($mode ne 'filename') {
-       msg( '<a href="'.make_search_url('',"keywords=$keyword_esc",{mode=>'filename'}).
-             "\">"._g("Search within filenames")."</a>");
-    }
-    if ($mode ne 'exactfilename') {
-       msg( '<a href="'.make_search_url('',"keywords=$keyword_esc",{mode=>'exactfilename'}).
-             "\">"._g("Search exact filename")."</a>");
-    }
-    if ($mode eq 'exactfilename' || $mode eq 'filename') {
-       msg( '<a href="'.make_search_url('',"keywords=$keyword_esc",{mode=>undef}).
-             "\">"._g("Search for paths ending with")."</a>");
-    }
-
-    msg( _g("Search in other suite:")." ".
-        join( ' ', map { '[<a href="'.make_search_url('',"keywords=$keyword_esc",{suite=>$_}).
-                             "\">$_</a>]" } @SUITES ) );
-
-    if ($Packages::Search::too_many_hits) {
-       error( _g( "Your search was too wide so we will only display only the first about 100 matches. Please consider using a longer keyword or more keywords." ) );
-    }
-    
-    %$html_header = ( title => _g( 'Package Contents Search Results' ),
-                     lang => $opts->{lang},
-                     title_tag => _g( 'Debian Package Contents Search Results' ),
-                     print_title => 1,
-                     print_search_field => 'packages',
-                     search_field_values => { 
-                         keywords => $keyword_enc,
-                         searchon => 'contents',
-                         arch => $archs_enc,
-                         suite => $suites_enc,
-                         section => $sections_enc,
-                         exact => $opts->{exact},
-                         debug => $opts->{debug},
-                     },
-                     );
+    }    
 
-    $$page_content = '';
     my (%results,%archs);
     foreach my $result (sort { $a->[0] cmp $b->[0] } @results) {
        my $file = shift @$result;
@@ -180,52 +112,47 @@ sub do_search_contents {
     }
     my @all_archs = keys %archs;
     @all_archs = @ARCHITECTURES unless @all_archs;
-    debug( "all_archs = @all_archs", 1 ) if DEBUG;
-    msg(_g("Limit search to a specific architecture:")." ".
-       join( ' ', map { '[<a href="'.make_search_url('',"keywords=$keyword_esc",{arch=>$_}).
-                            "\">$_</a>]" } @all_archs ) )
-       unless (@{$opts->{arch}} == 1) || (@all_archs == 1);
-    msg(sprintf(_g('Search in <a href="%s">all architectures</a>'),
-               make_search_url('',"keywords=$keyword_esc",{arch=>undef})))
-       if @{$opts->{arch}} == 1;
+    $page_content->{suite} = $suite;
+    $page_content->{archive} = $archive;
+    $page_content->{all_architectures} = \@all_archs;
+    $page_content->{all_suites} = \@SUITES;
+    $page_content->{mode} = $mode;
+    $page_content->{search_architectures} = $opts->{arch};
+    $page_content->{search_keywords} = $opts->{keywords};
+    $page_content->{sections} = $opts->{section};
+    $page_content->{too_many_hits} = $Packages::Search::too_many_hits;
 
-    if (!@Packages::CGI::fatal_errors && !keys(%results)) {
-       error( _g( "Nothing found" ) );
-    }
+    debug( "all_archs = @all_archs", 1 ) if DEBUG;
 
     if (keys %results) {
-       $$page_content .= "<p>".sprintf( _g( 'Found %s results' ),
-                                        scalar keys %results )."</p>";
-       $$page_content .= '<div
-       id="pcontentsres"><table><colgroup><col><col></colgroup><tr><th>'._g('File').'</th><th>'._g('Packages')
-           ."</th></tr>\n";
-       foreach my $file (sort keys %results) {
-               my $file_enc = encode_entities($file);
-               foreach my $kw (@{$opts->{keywords}}) {
-                   my $kw_enc = encode_entities($kw);
-                   $file_enc =~ s#(\Q$kw_enc\E)#<span class="keyword">$1</span>#g;
-               }
-           $$page_content .= "<tr><td class=\"file\">/$file_enc</td><td>";
-           my @pkgs;
+       my $sort_func = sub { $_[0] cmp $_[1] };
+       $sort_func = sub { (sort keys %{$results{$_[0]}})[0]
+                          cmp
+                          (sort keys %{$results{$_[1]}})[0]
+                        } if $opts->{sort_by} eq 'pkg';
+
+       $page_content->{results} = [];
+       foreach my $file (sort {&$sort_func($a,$b)} keys %results) {
+           my %result;
+           $result{file} = "/$file";
+           $result{packages} = [];
            foreach my $pkg (sort keys %{$results{$file}}) {
                my $arch_str = '';
                my @archs = keys %{$results{$file}{$pkg}};
+               my $arch_neg = 0;
                unless ($results{$file}{$pkg}{all} ||
                        (@archs == @all_archs)) {
-                   if (@archs < @all_archs/2) {
-                       $arch_str = ' ['.join(' ',sort @archs).']';
-                   } else {
-                       $arch_str = ' ['._g('not').' '.
-                           join(' ', grep { !$results{$file}{$pkg}{$_} } @all_archs).']';
+                   if (@archs >= @all_archs/2) {
+                       @archs = grep { !$results{$file}{$pkg}{$_} } @all_archs;
+                       $arch_neg = 1;
                    }
+               } else {
+                   @archs = ();
                }
-               push @pkgs, "<a href=\"".make_url($pkg,'',{suite=>$suite})."\">$pkg</a>$arch_str";
+               push @{$result{packages}}, { pkg => $pkg, architectures => \@archs, architectures_are_rev => $arch_neg };
            }
-           $$page_content .= join( ", ", @pkgs);
-           $$page_content .= "</td></tr>\n";
+           push @{$page_content->{results}}, \%result;
        }
-       $$page_content .= '<tr><th>'._g('File').'</th><th>'._g('Packages')."</th></tr>\n" if @results > 20;
-       $$page_content .= '</table></div>';
     }
 } # sub do_search_contents
 
index 5b22552f348a79906045128eb63ab589df46c331..62324a7c0ff682f91e51eec10f06aac948ab07e4 100644 (file)
@@ -11,13 +11,12 @@ use Benchmark ':hireswallclock';
 use Exporter;
 
 use Deb::Versions;
-use Packages::Config qw( $DBDIR $ROOT @SUITES @ARCHIVES @SECTIONS
-                        @ARCHITECTURES %FTP_SITES $SEARCH_URL );
+use Packages::Config qw( $DBDIR @SUITES @ARCHIVES @SECTIONS
+                        @ARCHITECTURES %FTP_SITES );
 use Packages::I18N::Locale;
-use Packages::CGI;
+use Packages::CGI qw( :DEFAULT make_url make_search_url note );
 use Packages::DB;
 use Packages::Search qw( :all );
-use Packages::HTML;
 use Packages::Page ();
 use Packages::SrcPage ();
 
@@ -25,7 +24,7 @@ our @ISA = qw( Exporter );
 our @EXPORT = qw( do_show );
 
 sub do_show {
-    my ($params, $opts, $html_header, $menu, $page_content) = @_;
+    my ($params, $opts, $html_header, $page_contents) = @_;
 
     if ($params->{errors}{package}) {
        fatal_error( _g( "package not valid or not specified" ) );
@@ -37,20 +36,20 @@ sub do_show {
        fatal_error( sprintf( _g( "more than one suite specified for show (%s)" ), "@{$opts->{suite}}" ) );
     }
 
+    my %contents;
+    $contents{make_url} = sub { return &Packages::CGI::make_url(@_) };
+
     my $pkg = $opts->{package};
-    my $encodedpkg = uri_escape( $pkg );
+    $contents{pkg} = $pkg;
     my $suite = $opts->{suite}[0];
+    $contents{suite} = $suite;
     my $archive = $opts->{archive}[0] ||'';
     
-    my $DL_URL = "$pkg/download";
-    my $FILELIST_URL = "$pkg/files";
-
     our (%packages_all, %sources_all);
     my (@results, @non_results);
     my $page = $opts->{source} ?
        new Packages::SrcPage( $pkg ) :
        new Packages::Page( $pkg );
-    my $package_page = "";
     my ($short_desc, $version, $section, $subsection) = ("")x5;
     
     my $st0 = new Benchmark;
@@ -78,19 +77,13 @@ sub do_show {
                my $s = $_->[2];
                $all_suites{$s}++;
            }
-           foreach (suites_sort(keys %all_suites)) {
-               if ($suite eq $_) {
-                   $$menu .= "[ <strong>$_</strong> ] ";
-               } else {
-                   $$menu .= "[ <a href=\"".make_url($encodedpkg,'',{suite=>$_})."\">$_</a> ] ";
-               }
-           }
-           $$menu .= '<br>';
+           $contents{suites} = [ suites_sort(keys %all_suites) ];
            
            unless (@results) {
                fatal_error( _g( "Package not available in this suite." ) );
            } else {
                unless ($opts->{source}) {
+
                    for my $entry (@results) {
                        debug( join(":", @$entry), 1 ) if DEBUG;
                        my (undef, $archive, undef, $arch, $section, $subsection,
@@ -110,8 +103,11 @@ sub do_show {
                    
                    unless ($page->is_virtual()) {
                        $version = $page->{newest};
+                       $contents{version} = $version;
                        my $source = $page->get_newest( 'source' );
                        $archive = $page->get_newest( 'archive' );
+                       $contents{archive} = $archive;
+
                        debug( "find source package: source=$source", 1) if DEBUG;
                        my $src_data = $sources_all{"$archive $suite $source"};
                        $page->add_src_data( $source, $src_data )
@@ -123,10 +119,13 @@ sub do_show {
 
                        my $did = $page->get_newest( 'description' );
                        my @tags = split(/, /, $page->get_newest( 'tag' ));
+                       $contents{tags} = \@tags;
+
                        $section = $page->get_newest( 'section' );
+                       $contents{section} = $section;
                        $subsection = $page->get_newest( 'subsection' );
-                       my $filenames = $page->get_arch_field( 'filename' );
-                       my $file_md5sums = $page->get_arch_field( 'md5sum' );
+                       $contents{subsection} = $subsection;
+
                        my $archives = $page->get_arch_field( 'archive' );
                        my $versions = $page->get_arch_field( 'version' );
                        my $sizes_inst = $page->get_arch_field( 'installed-size' );
@@ -145,149 +144,77 @@ sub do_show {
                        $long_desc =~ s/\n /\n/sgo;
                        $long_desc =~ s/\n.\n/\n<p>\n/go;
                        $long_desc =~ s/(((\n|\A) [^\n]*)+)/\n<pre>$1\n<\/pre>/sgo;
-                       my @menu = ( [ _g( "Distribution:" ),
-                                      _g( "Overview over this suite" ),
-                                      make_url("/",''),
-                                      $suite ],
-                                    [ _g( "Section:" ),
-                                      _g( "All packages in this section" ),
-                                      make_url("$subsection/",''),
-                                      $subsection ], );
-                       push @menu, [ _g( "Source:" ),
-                                     _g( "Source package building this package" ),
-                                     make_url($source,'',{source=>'source'}),
-                                     $source ] if $source;
-                       $$menu .= simple_menu( @menu );
+
+                       $contents{desc} = { short => $short_desc,
+                                           long => $long_desc, };
 
                        my $v_str = $version;
                        my $multiple_versions = grep { $_ ne $version } values %$versions;
                        $v_str .= _g(" and others") if $multiple_versions;
-                       my $title .= sprintf( _g( "Package: %s (%s)" ), $pkg, $v_str );
-                       $title .=  " ".marker( $archive ) if $archive ne 'us';
-                       $title .=  " ".marker( $subsection ) if $subsection eq 'non-US'
-                           and $archive ne 'non-US'; # non-US/security
-                       $title .=  " ".marker( $section ) if $section ne 'main';
-                       $package_page .= title( $title );
-                       
-                       if (my $provided_by = $page->{provided_by}) {
-                           note( _g( "This is also a virtual package provided by ").join( ', ', map { "<a href=\"".make_url($_,'')."\">$_</a>"  } @$provided_by) );
-                       }
-                       
-                       if ($suite eq "experimental") {
-                           note( _g( "Experimental package"),
-                                 _g( "Warning: This package is from the <strong>experimental</strong> distribution. That means it is likely unstable or buggy, and it may even cause data loss. If you ignore this warning and install it nevertheless, you do it on your own risk.")."</p>"
-                                 );
-                       }
-                       if ($subsection eq "debian-installer") {
-                           note( _g( "debian-installer udeb package"),
-                                 _g( 'Warning: This package is intended for the use in building <a href="http://www.debian.org/devel/debian-installer">debian-installer</a> images only. Do not install it on a normal Debian system.' )
-                                 );
-                       }
-                       $package_page .= pdesc( $short_desc, $long_desc );
-                       $package_page .= ptags( $pkg, @tags ) if @tags;
+                       $contents{versions} = { short => $v_str,
+                                               multiple => $multiple_versions };
+
+                       my $provided_by = $page->{provided_by};
+                       $contents{providers} = [];
+                       pkg_list( \%packages, $opts, $provided_by, 'en', $contents{providers} ) if $provided_by;
 
                        #
                        # display dependencies
                        #
-                       my $dep_list;
-                       $dep_list = print_deps( \%packages, $opts, $pkg,
-                                               $page->get_dep_field('depends'),
-                                               'depends' );
-                       $dep_list .= print_deps( \%packages, $opts, $pkg,
-                                                $page->get_dep_field('recommends'),
-                                                'recommends' );
-                       $dep_list .= print_deps( \%packages, $opts, $pkg,
-                                                $page->get_dep_field('suggests'),
-                                                'suggests' );
-
-                       if ( $dep_list ) {
-                           $package_page .= "<div id=\"pdeps\">\n";
-                           $package_page .= sprintf( "<h2>"._g( "Other Packages Related to %s" )."</h2>\n", $pkg );
-                           
-                           $package_page .= pdeplegend( [ 'dep',  _g( 'depends' ) ],
-                                                        [ 'rec',  _g( 'recommends' ) ],
-                                                        [ 'sug',  _g( 'suggests' ) ], );
-                           
-                           $package_page .= $dep_list;
-                           $package_page .= "</div> <!-- end pdeps -->\n";
-                       }
+                       build_deps( \%packages, $opts, $pkg,
+                                   $page->get_dep_field('depends'),
+                                   'depends', \%contents );
+                       build_deps( \%packages, $opts, $pkg,
+                                   $page->get_dep_field('recommends'),
+                                   'recommends', \%contents );
+                       build_deps( \%packages, $opts, $pkg,
+                                   $page->get_dep_field('suggests'),
+                                   'suggests', \%contents );
 
                        #
                        # Download package
                        #
-                       my $encodedpack = uri_escape( $pkg );
-                       $package_page .= "<div id=\"pdownload\">";
-                       $package_page .= sprintf( "<h2>"._g( "Download %s\n" )."</h2>",
-                                                 $pkg ) ;
-                       $package_page .= "<table summary=\""._g("The download table links to the download of the package and a file overview. In addition it gives information about the package size and the installed size.")."\">\n";
-                       $package_page .= "<caption class=\"hidecss\">"._g("Download for all available architectures")."</caption>\n";
-                       $package_page .= "<tr>\n";
-                       $package_page .= "<th>"._g("Architecture")."</th>";
-                       $package_page .= "<th>"._g("Version")."</th>"
-                           if $multiple_versions;
-                       $package_page .= "<th>"._g( "Package Size")."</th><th>"._g("Installed Size")."</th><th>"._g("Files")."</th></tr>\n";
+                       my @downloads;
                        foreach my $a ( @archs ) {
-                           $package_page .= "<tr>\n";
-                           $package_page .=  "<th><a href=\"".make_url("$encodedpkg/$a/download",'');
-                           $package_page .=  "\">$a</a></th>\n";
-                           $package_page .= "<td>".$versions->{$a}."</td>"
-                               if $multiple_versions;
-                           $package_page .= '<td class="size">';
-                           # package size
-                           $package_page .=  sprintf(_g('%.1f&nbsp;kB'),
-                                                     floor(($sizes_deb->{$a}/102.4)+0.5)/10);
-                           $package_page .= '</td><td class="size">';
-                           # installed size
-                           $package_page .=  sprintf(_g('%d&nbsp;kB'),
-                                                     $sizes_inst->{$a});
-                           $package_page .= "</td>\n<td>";
+                           my %d = ( arch => $a,
+                                     pkgsize => sprintf( '%.1f', floor(($sizes_deb->{$a}/102.4)+0.5)/10 ),
+                                     instsize => $sizes_inst->{$a}, );
+
+                           $d{version} = $versions->{$a} if $multiple_versions;
                            if ( ($suite ne "experimental")
                                 && ($subsection ne 'debian-installer')) {
-                               $package_page .= sprintf( "[<a href=\"%s\">"._g( "list of files" )."</a>]\n",
-                                                         make_url("$encodedpkg/$a/filelist",''), $pkg );
-                           } else {
-                               $package_page .= _g( "no current information" );
+                               $d{contents_avail} = 1;
                            }
-                           $package_page .= "</td>\n</tr>";
+                           push @downloads, \%d;
                        }
-                       $package_page .= "</table>\n";
-                       $package_page .= "</div> <!-- end pdownload -->\n";
+                       $contents{downloads} = \@downloads;
                        
                        #
                        # more information
                        #
-                       $package_page .= pmoreinfo( name => $pkg, data => $page,
-                                                   opts => $opts,
-                                                   env => \%FTP_SITES,
-                                                   bugreports => 1, sourcedownload => 1,
-                                                   changesandcopy => 1, maintainers => 1,
-                                                   search => 1 );
+                       moreinfo( name => $pkg, data => $page, vars => \%contents,
+                                 opts => $opts,
+                                 env => \%FTP_SITES,
+                                 bugreports => 1, sourcedownload => 1,
+                                 changesandcopy => 1, maintainers => 1,
+                                 search => 1 );
                    } else { # unless $page->is_virtual
-                       $short_desc = _g( "virtual package" );
-
-                       $$menu .= simple_menu( [ _g( "Distribution:" ),
-                                                _g( "Overview over this distribution" ),
-                                                make_url('/',''),
-                                                $suite ],
-                                              [ _g( "Section:" ),
-                                                _g( "All packages in this section" ),
-                                                make_url("virtual/",''),
-                                                
-                                                'virtual' ], );
-
-                       $package_page .= title( sprintf( _g( "Virtual Package: %s" ),
-                                                        $pkg ) );
+                       $contents{is_virtual} = 1;
+                       $contents{desc}{short} = _g( "virtual package" );
+                       $contents{subsection} = 'virtual';
 
                        my $policy_url = 'http://www.debian.org/doc/debian-policy/';
                        note( sprintf( _g( 'This is a <em>virtual package</em>. See the <a href="%s">Debian policy</a> for a <a href="%sch-binary.html#s-virtual_pkg">definition of virtual packages</a>.' ),
                                       $policy_url, $policy_url ));
 
-                       $package_page .= sprintf( "<h2>"._g( "Packages providing %s" )."</h2>",                              $pkg );
                        my $provided_by = $page->{provided_by};
-                       $package_page .= pkg_list( \%packages, $opts, $provided_by, 'en');
+                       $contents{providers} = [];
+                       pkg_list( \%packages, $opts, $provided_by, 'en', $contents{providers} );
 
                    } # else (unless $page->is_virtual)
                } else { # unless $opts->{source}
+                   $contents{is_source} = 1;
+
                    for my $entry (@results) {
                        debug( join(":", @$entry), 1 ) if DEBUG;
                        my (undef, $archive, undef, $section, $subsection,
@@ -298,114 +225,64 @@ sub do_show {
                            or debug( "Merging $pkg $version FAILED", 2 ) if DEBUG;
                    }
                    $version = $page->{version};
+                   $contents{version} = $version;
 
                    my $st1 = new Benchmark;
                    my $std = timediff($st1, $st0);
                    debug( "Data search and merging took ".timestr($std) ) if DEBUG;
 
                    $archive = $page->get_newest( 'archive' );
+                   $contents{archive} = $archive;
                    $section = $page->get_newest( 'section' );
+                   $contents{section} = $section;
                    $subsection = $page->get_newest( 'subsection' );
-
-                   $$menu .= simple_menu( [ _g( "Distribution:" ),
-                                            _g( "Overview over this suite" ),
-                                            make_url('/',''),
-                                            $suite ],
-                                          [ _g( "Section:" ),
-                                            _g( "All packages in this section" ),
-                                            make_url("$subsection/",''),
-                                            $subsection ],
-                                          );
+                   $contents{subsection} = $subsection;
                    
-                   my $title .= sprintf( _g( "Source Package: %s (%s)" ),
-                                         $pkg, $version );
-                   $title .=  " ".marker( $archive ) if $archive ne 'us';
-                   $title .=  " ".marker( $subsection ) if $subsection eq 'non-US'
-                       and $archive ne 'non-US'; # non-US/security
-                   $title .=  " ".marker( $section ) if $section ne 'main';
-                   $package_page .= title( $title );
-                   
-                   if ($suite eq "experimental") {
-                       note( _g( "Experimental package"),
-                             _g( "Warning: This package is from the <strong>experimental</strong> distribution. That means it is likely unstable or buggy, and it may even cause data loss. If you ignore this warning and install it nevertheless, you do it on your own risk.")."</p>"
-                             );
-                   }
-                   if ($subsection eq "debian-installer") {
-                       note( _g( "debian-installer udeb package"),
-                             _g( 'Warning: This package is intended for the use in building <a href="http://www.debian.org/devel/debian-installer">debian-installer</a> images only. Do not install it on a normal Debian system.' )
-                             );
-                   }
-
                    my $binaries = find_binaries( $pkg, $archive, $suite, \%src2bin );
                    if ($binaries && @$binaries) {
-                       $package_page .= '<div class="pdesc">';
-                       $package_page .= _g( "The following binary packages are built from this source package:" );
-                       $package_page .= pkg_list( \%packages, $opts, $binaries, 'en' );
-                       $package_page .= '</div> <!-- end pdesc -->';
+                       $contents{binaries} = [];
+                       pkg_list( \%packages, $opts, $binaries, 'en', $contents{binaries} );
                    }
                    
                    #
                    # display dependencies
                    #
-                   my $dep_list;
-                   $dep_list = print_deps( \%packages, $opts, $pkg,
-                                           $page->get_dep_field('build-depends'),
-                                           'build-depends' );
-                   $dep_list .= print_deps( \%packages, $opts, $pkg,
-                                            $page->get_dep_field('build-depends-indep'),
-                                            'build-depends-indep' );
-
-                   if ( $dep_list ) {
-                       $package_page .= "<div id=\"pdeps\">\n";
-                       $package_page .= sprintf( "<h2>"._g( "Other Packages Related to %s" )."</h2>\n", $pkg );
-                       
-                       $package_page .= pdeplegend( [ 'adep',  _g( 'build-depends' ) ],
-                                                    [ 'idep',  _g( 'build-depends-indep' ) ],
-                                                    );
-                       
-                       $package_page .= $dep_list;
-                       $package_page .= "</div> <!-- end pdeps -->\n";
-                   }
+                   build_deps( \%packages, $opts, $pkg,
+                               $page->get_dep_field('build-depends'),
+                               'build-depends', \%contents );
+                   build_deps( \%packages, $opts, $pkg,
+                               $page->get_dep_field('build-depends-indep'),
+                               'build-depends-indep', \%contents );
 
                    #
                    # Source package download
                    #
-                   $package_page .= "<div id=\"pdownload\">\n";
-                   $package_page .= sprintf( "<h2>"._g( "Download %s" )."</h2>\n",
-                                             $pkg ) ;
-
                    my $source_files = $page->get_src( 'files' );
                    my $source_dir = $page->get_src( 'directory' );
                    
-                   $package_page .= sprintf( '<table summary="'._g('Download information for the files of this source package' ).'">'.
-                                             "<tr><th>%s</th><th>%s</th><th>%s</th>",
-                                             _g("File"),
-                                             _g("Size (in kB)"),
-                                             _g("md5sum") );
+                   $contents{srcfiles} = [];
                    foreach( @$source_files ) {
                        my ($src_file_md5, $src_file_size, $src_file_name)
                            = split /\s+/, $_;
                        (my $server = lc $archive) =~ s/-//go; # non-US hack
-                       my $src_url = $FTP_SITES{$server}
+                       $server = $FTP_SITES{$server}
                            || $FTP_SITES{us};
-                       $src_url .= "/$source_dir/$src_file_name";
+                       my $path = "/$source_dir/$src_file_name";
                        
-                       $package_page .= "<tr><td><a href=\"$src_url\">$src_file_name</a></td>\n"
-                           ."<td>".sprintf("%.1f", (floor(($src_file_size/102.4)+0.5)/10))."</td>\n"
-                           ."<td class=\"md5sum\">$src_file_md5</td></tr>";
+                       push @{$contents{srcfiles}}, { server => $server, path => $path, filename => $src_file_name,
+                                                      size => sprintf("%.1f", (floor(($src_file_size/102.4)+0.5)/10)),
+                                                      md5sum => $src_file_md5 };
                    }
-                   $package_page .= "</table>\n";
-                   $package_page .= "</div> <!-- end pdownload -->\n";
 
                    #
                    # more information
                    #
-                   $package_page .= pmoreinfo( name => $pkg, data => $page,
-                                               opts => $opts,
-                                               env => \%FTP_SITES,
-                                               bugreports => 1,
-                                               changesandcopy => 1, maintainers => 1,
-                                               search => 1, is_source => 1 );
+                   moreinfo( name => $pkg, data => $page, vars => \%contents,
+                             opts => $opts,
+                             env => \%FTP_SITES,
+                             bugreports => 1,
+                             changesandcopy => 1, maintainers => 1,
+                             search => 1, is_source => 1 );
                    
                } # else (unless $opts->{source})
            } # else (unless @results)
@@ -413,33 +290,174 @@ sub do_show {
     }
 
 #    use Data::Dumper;
-#    debug( "Final page object:\n".Dumper($page), 3 ) if DEBUG;
-
-    my $title = $opts->{source} ?
-       _g( "Details of source package <em>%s</em> in %s" ) :
-       _g( "Details of package <em>%s</em> in %s" ) ;
-    my $title_tag = $opts->{source} ?
-       _g( "Details of source package %s in %s" ) :
-       _g( "Details of package %s in %s" ) ;
-    %$html_header = ( title => sprintf( $title, $pkg, $suite ) ,
-                     lang => $opts->{lang},
-                     desc => $short_desc,
-                     keywords => "$suite, $archive, $section, $subsection, $version",
-                     title_tag => sprintf( $title_tag, $pkg, $suite ),
-                     print_search_field => 'packages',
-                     search_field_values => { 
-                         keywords => '',
-                         searchon => $opts->{source} ? 'sourcenames' : 'names',
-                         arch => 'any',
-                         suite => 'all',
-                         section => 'all',
-                         exact => 0,
-                         debug => $opts->{debug},
-                     },
-                     );
-
-    $$page_content = $package_page;
+#    debug( "Final page object:\n".Dumper(\%contents), 3 ) if DEBUG;
+
+    %$page_contents = %contents;
+}
+
+sub moreinfo {
+    my %info = @_;
+    
+    my $name = $info{name} or return;
+    my $env = $info{env} or return;
+    my $opts = $info{opts} or return;
+    my $page = $info{data} or return;
+    my $contents = $info{vars} or return;
+    my $is_source = $info{is_source};
+    my $suite = $opts->{suite}[0];
+
+    my $source = $page->get_src( 'package' );
+    my $source_version = $page->get_src( 'version' );
+    my $src_dir = $page->get_src('directory');
+    if ($info{sourcedownload}) {
+       $contents->{src}{url} = make_url($source,'',{source=>'source'});
+       $contents->{src}{pkg} = $source;
+
+       my @downloads;
+       my $files = $page->get_src( 'files' );
+       if (defined($files) and @$files) {
+           foreach( @$files ) {
+               my ($src_file_md5, $src_file_size, $src_file_name) = split /\s/o, $_;
+               my ($name, $server, $path);
+               # non-US hack
+               ($server = lc $page->get_newest('archive')) =~ s/-//go;
+               $server = $env->{$server}||$env->{us};
+               $path = "$src_dir/$src_file_name";
+               if ($src_file_name =~ /dsc$/) {
+                   $name = 'dsc'
+               } else {
+                   $name = $src_file_name;
+               }
+               push @downloads, { name => $name, server => $server, path => $path };
+           }
+       }
+       $contents->{src}{downloads} = \@downloads;
+    }
+
+    if ($info{changesandcopy}) {
+       if ( $src_dir ) {
+           (my $src_basename = $source_version) =~ s,^\d+:,,; # strip epoche
+           $src_basename = "${source}_$src_basename";
+           $src_dir =~ s,pool/updates,pool,o;
+           $src_dir =~ s,pool/non-US,pool,o;
+
+           $contents->{files}{changelog}{path} = "$src_dir/$src_basename/changelog";
+           $contents->{files}{copyright}{path} = "$src_dir/$src_basename/".( $is_source ? 'copyright' : "$name.copyright" );
+       }
+   }
+
+    if ($info{maintainers}) {
+       my $uploaders = $page->get_src( 'uploaders' );
+       if ($uploaders && @$uploaders) {
+           my @maintainers = map { { name => $_->[0], mail => $_->[1] } } @$uploaders;
+           $contents->{maintainers} = \@maintainers;
+       }
+    }
+
+}
+
+sub providers {
+    my ($suite, $entry, $also) = @_;
+    my %tmp = map { $_ => 1 } split /\s/, $entry;
+    my @provided_by = keys %tmp; # weed out duplicates
+    my %out = ( also => $also,
+               pkgs => \@provided_by );
+    return \%out;
+}
+
+sub build_deps {
+    my ( $packages, $opts, $pkg, $relations, $type, $contents) = @_;
+    my %dep_type = ('depends' => 'dep', 'recommends' => 'rec', 
+                   'suggests' => 'sug', 'build-depends' => 'adep',
+                   'build-depends-indep' => 'idep' );
+    my $suite = $opts->{suite}[0];
+
+    my %out = ( id => $dep_type{$type}, terms => [] );
+
+#    use Data::Dumper;
+#    debug( "print_deps called:\n".Dumper( $pkg, $relations, \$type ), 3 ) if DEBUG;
+
+    foreach my $rel (@$relations) {
+       my %rel_out;
+       $rel_out{is_old_pkgs} = $rel->[0];
+       $rel_out{alternatives} = [];
+
+       foreach my $rel_alt ( @$rel ) {
+           next unless ref($rel_alt);
+           my ( $p_name, $pkg_version, $arch_neg,
+                $arch_str, $subsection, $available ) = @$rel_alt;
+
+           if ($arch_str ||= '') {
+               if ($arch_neg) {
+                   $arch_str = _g("not")." $arch_str";
+               } else {
+                   $arch_str = $arch_str;
+               }
+           }
+
+           my %rel_alt_out = ( name => $p_name,
+                               version => $pkg_version,
+                               arch_str => $arch_str,
+                               arch_neg => $arch_neg );
+                            
+           my @results;
+           my %entries;
+           my $entry = $entries{$p_name} ||
+               read_entry_simple( $packages, $p_name, $opts->{h_archives}, $suite);
+           my $short_desc = $entry->[-1];
+           my $arch = $entry->[3];
+           my $archive = $entry->[1];
+           my $p_suite = $entry->[2];
+           if ( $short_desc ) {
+               $rel_alt_out{desc} = $short_desc;
+               $rel_alt_out{suite} = $p_suite;
+               if ( $rel_out{is_old_pkgs} ) {
+               } elsif (defined $entry->[1]) {
+                   $entries{$p_name} ||= $entry;
+                   $rel_alt_out{providers} = providers( $p_suite,
+                                                       $entry->[0],
+                                                       1 ) if defined $entry->[0];
+               } elsif (defined $entry->[0]) {
+                    $rel_alt_out{desc} = undef;
+                   $rel_alt_out{providers} = providers( $p_suite,
+                                                       $entry->[0] );
+                   #FIXME: we don't handle virtual packages from
+                   # the fallback suite correctly here
+                   $rel_alt_out{suite} = $suite;
+               }
+           } elsif ( $rel_out{is_old_pkgs} ) {
+           } else {
+               $rel_alt_out{desc} = _g( "Package not available" );
+               $rel_alt_out{suite} = '';
+           }
+           push @{$rel_out{alternatives}}, \%rel_alt_out;
+       }
+
+       push @{$out{terms}}, \%rel_out;
+    }
+
+    $contents->{relations} ||= [];
+    push @{$contents->{relations}}, \%out if @{$out{terms}};
+} # end print_deps
+
+sub pkg_list {
+    my ( $packages, $opts, $pkgs, $lang, $list ) = @_;
+    my $suite = $opts->{suite}[0];
+
+    foreach my $p ( sort @$pkgs ) {
+
+       # we don't deal with virtual packages here because for the
+       # current uses of this function this isn't needed
+       my $short_desc = (read_entry_simple( $packages, $p, $opts->{h_archives}, $suite))->[-1];
+
+       if ( $short_desc ) {
+           push @$list, { name => $p, desc => $short_desc, available => 1 };
+       } else {
+           push @$list, { name => $p, desc => _g("Not available") };
+       }
+    }
 }
 
+
 1;
 
diff --git a/lib/Packages/HTML.pm b/lib/Packages/HTML.pm
deleted file mode 100644 (file)
index e0814a7..0000000
+++ /dev/null
@@ -1,593 +0,0 @@
-package Packages::HTML;
-
-use strict;
-use warnings;
-
-use Exporter;
-use URI::Escape;
-use HTML::Entities;
-use Locale::gettext;
-
-use Packages::CGI qw(make_url make_search_url);
-use Packages::Search qw( read_entry_simple );
-use Packages::Config qw( :all );
-
-#use Packages::Util;
-use Packages::I18N::Locale;
-use Packages::I18N::Languages;
-use Packages::I18N::LanguageNames;
-#use Generated::Strings qw( gettext dgettext );
-
-our @ISA = qw( Exporter );
-our @EXPORT = qw( header title trailer file_changed time_stamp
-                 read_md5_hash write_md5_hash simple_menu
-                 ds_begin ds_item ds_end title marker pdesc ptags
-                 pdeplegend pkg_list pmoreinfo print_deps print_src_deps );
-
-our $CHANGELOG_URL = '/changelogs';
-
-sub img {
-    my ( $root, $url, $src, $alt, %attr ) = @_; 
-    my @attr;
-
-    foreach my $a ( keys %attr ) {
-       push @attr, "$a=\"$attr{$a}\"";
-    }
-
-    return "<a href=\"$root$url\"><img src=\"$root$src\" alt=\"$alt\" @attr></a>";
-}
-
-sub simple_menu {
-    my $str = "";
-    foreach my $entry (@_) {
-       $str .= "[&nbsp;$entry->[0] <a title=\"$entry->[1]\" href=\"$entry->[2]\">$entry->[3]</a>&nbsp;]\n";
-    }
-    return $str;
-}
-
-sub title {
-    return "<h1>$_[0]</h1>\n";
-}
-
-sub marker {
-    return "[<strong class=\"pmarker\">$_[0]</strong>]";
-}
-
-sub pdesc {
-    my ( $short_desc, $long_desc ) = @_;
-    my $str = "";
-
-    $str .= "<div id=\"pdesc\">\n";
-    $str .= "<h2>$short_desc</h2>\n";
-
-    $str .= "<p>$long_desc\n";
-    $str .= "</div> <!-- end pdesc -->\n";
-
-    return $str;
-}
-
-sub ptags {
-    my ( $package, @tags ) = @_;
-    my $str = "";
-
-    $str .= "<div id=\"ptags\">\n<p>";
-    $str .= "<a href=\"http://debtags.alioth.debian.org/cgi-bin/edit.cgi?pkg=".uri_escape($package)."\">Tags</a>:\n";
-    foreach my $tag (@tags) {
-        $str .= "<a href=\"http://debtags.alioth.debian.org/cgi-bin/index.cgi?tags=".uri_escape($tag)."\">$tag</a>\n";
-    }
-    $str .= "</p>\n</div> <!-- end ptags -->\n";
-
-    return $str;
-}
-
-sub pdeplegend {
-    my $str = "<table id=\"pdeplegend\" summary=\"legend\"><tr>\n";
-
-    foreach my $entry (@_) {
-       $str .= "<td><img src=\"$ROOT/Pics/$entry->[0].gif\" alt=\"[$entry->[0]]\" width=\"16\" height=\"16\">= $entry->[1]</td>";
-    }
-
-    $str .= "\n</tr></table>\n";
-    return $str;
-}
-
-sub pkg_list {
-    my ( $packages, $opts, $pkgs, $lang ) = @_;
-    my $suite = $opts->{suite}[0];
-
-    my $str = "";
-    foreach my $p ( sort @$pkgs ) {
-
-       # we don't deal with virtual packages here because for the
-       # current uses of this function this isn't needed
-       my $short_desc = (read_entry_simple( $packages, $p, $opts->{h_archives}, $suite))->[-1];
-
-       if ( $short_desc ) {
-           $str .= "<dt><a href=\"".make_url($p,'',{source=>undef})."\">$p</a></dt>\n".
-                   "\t<dd>$short_desc</dd>\n";
-       } else {
-           $str .= "<dt>$p</dt>\n\t<dd>"._g("Not available")."</dd>\n";
-       }
-    }
-    if ($str) {
-       $str = "<dl>$str</dl>\n";
-    }
-
-    return $str;
-}
-
-sub pmoreinfo {
-    my %info = @_;
-    
-    my $name = $info{name} or return;
-    my $env = $info{env} or return;
-    my $opts = $info{opts} or return;
-    my $page = $info{data} or return;
-    my $is_source = $info{is_source};
-    my $suite = $opts->{suite}[0];
-
-    my $str = "<div id=\"pmoreinfo\">";
-    $str .= sprintf( "<h2>"._g( "More Information on %s" )."</h2>",
-                    $name );
-    
-    if ($info{bugreports}) {
-       my $bug_url = $is_source ? $SRC_BUG_URL : $BUG_URL; 
-       $str .= "<p>\n".sprintf( _g( "Check for <a href=\"%s\">Bug Reports</a> about %s." )."<br>\n",
-                        $bug_url.$name, $name );
-    }
-       
-    my $source = $page->get_src( 'package' );
-    my $source_version = $page->get_src( 'version' );
-    my $src_dir = $page->get_src('directory');
-    if ($info{sourcedownload}) {
-       my $files = $page->get_src( 'files' );
-       $str .= _g( "Source Package:" );
-       $str .= " <a href=\"".make_url($source,'',{source=>'source'})."\">$source</a>, ".
-           _g( "Download" ).":\n";
-
-       unless (defined($files) and @$files) {
-           $str .= _g( "Not found" );
-       } else {
-           foreach( @$files ) {
-               my ($src_file_md5, $src_file_size, $src_file_name) = split /\s/o, $_;
-               # non-US hack
-               (my $server = lc $page->get_newest('archive')) =~ s/-//go;
-               $str .= sprintf("<a href=\"%s/$src_dir/$src_file_name\">[",
-                               $env->{$server}||$env->{us});
-               if ($src_file_name =~ /dsc$/) {
-                   $str .= "dsc";
-               } else {
-                   $str .= $src_file_name;
-               }
-               $str .= "]</a>\n";
-           }
-       }
-#          $package_page .= sprintf( _g( " (These sources are for version %s)\n" ), $src_version )
-#              if ($src_version ne $version) && !$src_version_given_in_control;
-    }
-
-    if ($info{changesandcopy}) {
-       if ( $src_dir ) {
-           (my $src_basename = $source_version) =~ s,^\d+:,,; # strip epoche
-           $src_basename = "${source}_$src_basename";
-           $src_dir =~ s,pool/updates,pool,o;
-           $src_dir =~ s,pool/non-US,pool,o;
-           $str .= "<br>".sprintf( _g( 'View the <a href="%s">Debian changelog</a>' ),
-                                   "$CHANGELOG_URL/$src_dir/$src_basename/changelog" )."<br>\n";
-           my $copyright_url = "$CHANGELOG_URL/$src_dir/$src_basename/";
-           $copyright_url .= ( $is_source ? 'copyright' : "$name.copyright" );
-
-           $str .= sprintf( _g( 'View the <a href="%s">copyright file</a>' ),
-                            $copyright_url )."</p>";
-       }
-   }
-
-    if ($info{maintainers}) {
-       my $uploaders = $page->get_src( 'uploaders' );
-       if ($uploaders && @$uploaders) {
-           foreach (@$uploaders) {
-               $_->[0] = encode_entities( $_->[0], '&<>' );
-           }
-           my ($maint_name, $maint_mail) = @{shift @$uploaders}; 
-           unless (@$uploaders) {
-               $str .= "<p>\n".sprintf( _g( "%s is responsible for this Debian package." ).
-                                        "\n",
-                                        "<a href=\"mailto:$maint_mail\">$maint_name</a>" 
-                                        );
-           } else {
-               my $up_str = "<a href=\"mailto:$maint_mail\">$maint_name</a>";
-               my @uploaders_str;
-               foreach (@$uploaders) {
-                   push @uploaders_str, "<a href=\"mailto:$_->[1]\">$_->[0]</a>";
-               }
-               my $last_up = pop @uploaders_str;
-               $up_str .= ", ".join ", ", @uploaders_str if @uploaders_str;
-               $up_str .= sprintf( _g( " and %s are responsible for this Debian package." ), $last_up );
-               $str .= "<p>\n$up_str ";
-           }
-       }
-
-       $str .= sprintf( _g( "See the <a href=\"%s\">developer information for %s</a>." )."</p>", $QA_URL.$source, $name ) if $source;
-    }
-
-    if ($info{search}) {
-       my $encodedname = uri_escape( $name );
-       my $search_url = $is_source ? "$ROOT/source" : $ROOT;
-       $str .= "<p>".sprintf( _g( "Search for <a href=\"%s\">other versions of %s</a>" ),
-           "$search_url/$encodedname", $name )."</p>\n";
-    }
-
-    $str .= "</div> <!-- end pmoreinfo -->\n";
-    return $str;
-}
-
-sub dep_item {
-    my ( $suite, $name, $info, $desc ) = @_;
-    my ($link, $post_link) = ('', '');
-    if ($suite) {
-       $link = "<a href=\"".make_url($name,'',{suite=>$suite,source=>undef})."\">";
-       $post_link = '</a>';
-    }
-    if ($info) {
-       $info = " $info";
-    } else {
-       $info = '';
-    }
-    if ($desc) {
-       $desc = "</dt><dd>$desc</dd>";
-    } else {
-       $desc = '</dt>';
-    }
-
-    return "$link$name$post_link$info$desc";
-} # end dep_item
-
-sub provides_string {
-    my ($suite, $entry, $also) = @_;
-    my %tmp = map { $_ => 1 } split /\s/, $entry;
-    my @provided_by = keys %tmp; # weed out duplicates
-    my $short_desc = $also ? _g("also a virtual package provided by ")
-       : _g("virtual package provided by ");
-    if (@provided_by < 10) {
-       $short_desc .= join( ', ',map { "<a href=\"".make_url($_,'',{suite=>$suite,source=>undef})."\">$_</a>" } @provided_by);
-    } else {
-       $short_desc .= sprintf( _g("%s packages"), scalar(@provided_by));
-    }
-    return $short_desc;
-}
-
-sub print_deps {
-    my ( $packages, $opts, $pkg, $relations, $type) = @_;
-    my %dep_type = ('depends' => 'dep', 'recommends' => 'rec', 
-                   'suggests' => 'sug', 'build-depends' => 'adep',
-                   'build-depends-indep' => 'idep' );
-    my $res = "<ul class=\"ul$dep_type{$type}\">\n";
-    my $first = 1;
-    my $suite = $opts->{suite}[0];
-
-#    use Data::Dumper;
-#    debug( "print_deps called:\n".Dumper( $pkg, $relations, \$type ), 3 ) if DEBUG;
-
-    foreach my $rel (@$relations) {
-       my $is_old_pkgs = $rel->[0];
-       my @res_pkgs = ();
-
-       if ($is_old_pkgs)  {
-           $res .= "<dt>";
-       } else {
-           if ($first) {
-               $res .= "<li>";
-               $first = 0;
-           } else {
-               $res .= "</dl></li>\n<li>";
-           }
-           $res .= "<dl><dt><img class=\"hidecss\" src=\"$ROOT/Pics/$dep_type{$type}.gif\" alt=\"[$dep_type{$type}]\"> ";
-       }
-
-       foreach my $rel_alt ( @$rel ) {
-           next unless ref($rel_alt);
-           my ( $p_name, $pkg_version, $arch_neg,
-                $arch_str, $subsection, $available ) = @$rel_alt;
-
-           if ($arch_str ||= '') {
-               if ($arch_neg) {
-                   $arch_str = " ["._g("not")." $arch_str]";
-               } else {
-                   $arch_str = " [$arch_str]";
-               }
-           }
-           $pkg_version = "($pkg_version)" if $pkg_version ||= '';
-           
-           my @results;
-           my %entries;
-           my $entry = $entries{$p_name} ||
-               read_entry_simple( $packages, $p_name, $opts->{h_archives}, $suite);
-           my $short_desc = $entry->[-1];
-           my $arch = $entry->[3];
-           my $archive = $entry->[1];
-           my $p_suite = $entry->[2];
-           if ( $short_desc ) {
-               if ( $is_old_pkgs ) {
-                   push @res_pkgs, dep_item( $p_suite,
-                                             $p_name, "$pkg_version$arch_str" );
-               } elsif (defined $entry->[1]) {
-                   $entries{$p_name} ||= $entry;
-                   $short_desc = encode_entities( $short_desc, "<>&\"" );
-                   $short_desc .= "<br>".provides_string( $p_suite,
-                                                          $entry->[0],
-                                                          1 )
-                       if defined $entry->[0];
-                   push @res_pkgs, dep_item( $p_suite,
-                                             $p_name, "$pkg_version$arch_str", $short_desc );
-               } elsif (defined $entry->[0]) {
-                   $short_desc = provides_string( $p_suite,
-                                                  $entry->[0] );
-                   #FIXME: we don't handle virtual packages from
-                   # the fallback suite correctly here
-                   push @res_pkgs, dep_item( $suite,
-                                             $p_name, "$pkg_version$arch_str", $short_desc );
-               }
-           } elsif ( $is_old_pkgs ) {
-               push @res_pkgs, dep_item( undef, $p_name, "$pkg_version$arch_str" );
-           } else {
-               my $short_desc = _g( "Package not available" );
-               push @res_pkgs, dep_item( undef, $p_name, "$pkg_version$arch_str", $short_desc );
-           }
-           
-       }
-       
-       $res .= "\n".join( "<dt>"._g( "or" )." ", @res_pkgs )."\n";
-    }
-    if (@$relations) {
-       $res .= "</dl></li>\n";
-       $res .= "</ul>\n";
-    } else {
-       $res = "";
-    }
-    return $res;
-} # end print_deps
-
-my $ds_begin = '<dl>';
-my $ds_item_desc  = '<dt>';
-my $ds_item = ':</dt><dd>';
-my $ds_item_end = '</dd>';
-my $ds_end = '</dl>';
-#          my $ds_begin = '<table><tbody>';
-#          my $ds_item_desc  = '<tr><td>';
-#          my $ds_item = '</td><td>';
-#          my $ds_item_end = '</td></tr>';
-#          my $ds_end = '</tbody></table>';
-
-sub ds_begin {
-    return $ds_begin;
-}
-sub ds_item {
-    return "$ds_item_desc$_[0]$ds_item$_[1]$ds_item_end\n";
-}
-sub ds_end {
-    return $ds_end;
-}
-
-sub header {
-    my (%params) = @_;
-
-    my $DESC_LINE;
-    if (defined $params{desc}) {
-       $DESC_LINE = "<meta name=\"Description\" content=\"$params{desc}\">";
-    }
-    else {
-       $DESC_LINE = '';
-    }
-
-    my $title_keywords = $params{title_keywords} || $params{title} || '';
-    my $title_tag = $params{title_tag} || $params{title} || '';
-    my $title_in_header = $params{page_title} || $params{title} || '';
-    my $page_title = $params{page_title} || $params{title} || '';
-    my $meta = $params{meta} || '';
-
-    my $search_in_header = '';
-    $params{print_search_field} ||= "";
-    if ($params{print_search_field} eq 'packages') {
-       my %values = %{$params{search_field_values}};
-       my %checked_searchon = ( names => "",
-                                all => "",
-                                sourcenames => "",
-                                contents => "");
-       $checked_searchon{$values{searchon}} = "checked=\"checked\"";
-       $checked_searchon{names} = "checked=\"checked\""
-               if $values{searchon} eq 'default';
-       $search_in_header = <<MENU;
-<form method="GET" action="$SEARCH_URL">
-<div id="hpacketsearch">
-<input type="text" size="30" name="keywords" value="" id="kw">
-<input type="submit" value="%s">
-<span style="font-size: 60%%"><a href="$SEARCH_PAGE#search_packages">%s</a></span>
-<br>
-<div style="font-size: 80%%">%s
-<input type="radio" name="searchon" value="names" id="onlynames" $checked_searchon{names}>
-<label for="onlynames">%s</label>&nbsp;&nbsp;
-<input type="radio" name="searchon" value="all" id="descs" $checked_searchon{all}>
-<label for="descs">%s</label>
-<br>
-<input type="radio" name="searchon" value="sourcenames" id="src" $checked_searchon{sourcenames}>
-<label for="src">%s</label>
-<input type="radio" name="searchon" value="contents" id="conts" $checked_searchon{contents}>
-<label for="conts">%s</label>
-</div>
-</div> <!-- end hpacketsearch -->
-</form>
-MENU
-;
-       $search_in_header = sprintf( $search_in_header,
-                                    _g( 'Search' ),
-                                    _g( 'Full options' ),
-                                    _g( 'Search on:'),
-                                    _g( 'Package Names' ),
-                                    _g( 'Descriptions' ),
-                                    _g( 'Source package names' ),
-                                    _g( 'Package contents' ));
-#     } elsif ($params{print_search_field} eq 'contents') {
-#      my %values = %{$params{search_field_values}};
-#      my %checked_searchmode = ( searchfiles => "",
-#                                 searchfilesanddirs => "",
-#                                 searchword => "",
-#                                 filelist => "", );
-#      $checked_searchmode{$values{searchmode}} = "checked=\"checked\"";
-#      $search_in_header = <<MENU;
-# <form method="GET" action="$CONTENTS_SEARCH_CGI">
-# <div id="hpacketsearch">
-# <input type="hidden" name="debug" value="$values{debug}" />
-# <input type="hidden" name="version" value="$values{version}" />
-# <input type="hidden" name="arch" value="$values{arch}" />
-# <input type="hidden" name="case" value="$values{case}" />
-# <input type="text" size="30" name="word" id="keyword" value="$values{keyword}">&nbsp;
-# <input type="submit" value="Search">
-# <span style="font-size: 60%"><a href="$SEARCH_PAGE#search_contents">Full options</a></span>
-# <br>
-# <div style="font-size: 80%">Display:
-# <input type=radio name="searchmode" value="searchfiles" id="searchfiles" $checked_searchmode{searchfiles}>
-# <label for="searchfiles">files</label>
-# <input type=radio name="searchmode" value="searchfilesanddirs" id="searchfilesanddirs" $checked_searchmode{searchfilesanddirs}>
-# <label for="searchfilesanddirs">files &amp; directories</label>
-# <br>
-# <input type=radio name="searchmode" value="searchword" id="searchword" $checked_searchmode{searchword}>
-# <label for="searchword">subword matching</label>
-# <input type=radio name="searchmode" value="filelist" id="filelist" $checked_searchmode{filelist}>
-# <label for="filelist">content list</label>
-# </div>
-# </div> <!-- end hpacketsearch -->
-# </form>
-# MENU
-# ;
-    }
-
-    my $keywords = $params{keywords} || '';
-    my $KEYWORDS_LINE = "<meta name=\"Keywords\" content=\"debian, $keywords $title_keywords\">";
-    
-    my $LANG = $params{lang};
-    my $charset = get_charset($LANG);
-    my $txt = <<HEAD;
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html lang="$LANG">
-<head>
-<title>Debian -- $title_tag</title>
-<link rev="made" href="mailto:$WEBMASTER_MAIL">
-<meta http-equiv="Content-Type" content="text/html; charset=$charset">
-<meta name="Author" content="Debian Webmaster, $WEBMASTER_MAIL">
-$KEYWORDS_LINE
-$DESC_LINE
-$meta
-<link href="$ROOT/debian.css" rel="stylesheet" type="text/css" media="all">
-<link href="$ROOT/packages.css" rel="stylesheet" type="text/css" media="all">
-</head>
-<body>
-<div id="header">
-   <div id="upperheader">
-   <div id="logo">
-  <a href="$HOME/"><img src="$HOME/logos/openlogo-nd-50.png" alt="" /></a>
-HEAD
-;
-
-    $txt .= img( "$HOME/", "", "Pics/debian.png", _g( "Debian Project" ),
-                width => 179, height => 61 );
-    $txt .= <<HEADEND;
-
-</div> <!-- end logo -->
-HEADEND
-;
-
-    $txt .= <<NAVBEGIN;
-$search_in_header
-</div> <!-- end upperheader -->
-
-NAVBEGIN
-;
-    $txt .= "<p class=\"hidecss\"><a href=\"\#inner\">" . _g("Skip Site Navigation")."</a></p>\n";
-    $txt .= "<div id=\"navbar\">\n<ul>".
-       "<li><a href=\"$HOME/intro/about\">"._g( "About&nbsp;Debian" )."</a></li>\n".
-       "<li><a href=\"$HOME/News/\">"._g( "News" )."</a></li>\n".
-       "<li><a href=\"$HOME/distrib/\">"._g( "Getting&nbsp;Debian" )."</a></li>\n".
-       "<li><a href=\"$HOME/support\">"._g( "Support" )."</a></li>\n".
-       "<li><a href=\"$HOME/devel/\">"._g( "Development" )."</a></li>\n".
-       "<li><a href=\"$HOME/sitemap\">"._g( "Site map" )."</a></li>\n".
-       "<li><a href=\"http://search.debian.org/\">"._g( "Search" )."</a></li>\n";
-    $txt .= "</ul>\n";
-    $txt .= <<ENDNAV;
-</div> <!-- end navbar -->
-</div> <!-- end header -->
-ENDNAV
-;
-    $txt .= <<BEGINCONTENT;
-<div id="outer">
-<div id="inner">
-
-BEGINCONTENT
-;
-    if ($params{print_title}) {
-       $txt .= "<h1>$page_title</h1>\n";
-    }
-
-    return $txt;
-}
-
-sub trailer {
-    my ($ROOT, $NAME, $LANG, @USED_LANGS) = @_;
-    my $txt = "</div> <!-- end inner -->\n<div id=\"footer\">\n";
-    my $langs = languages( $NAME, $LANG, @USED_LANGS );
-    my $bl_class = $langs ? ' class="bordertop"' : "";
-    $txt .=
-       $langs.
-       "\n<hr class=\"hidecss\">\n" .
-       "<p$bl_class>".
-       sprintf( _g( "Back to: <a href=\"%s/\">Debian Project homepage</a> || <a href=\"%s/\">Packages search page</a>" ), $HOME, $ROOT ).
-       "</p>\n<hr class=\"hidecss\">\n".
-       "<div id=\"fineprint\" class=\"bordertop\"><p>".
-       sprintf( _g( "To report a problem with the web site, e-mail <a href=\"mailto:%s\">%s</a>. For other contact information, see the Debian <a href=\"%s/contact\">contact page</a>." ), $CONTACT_MAIL, $CONTACT_MAIL, $HOME).
-       "</p>\n".
-       "<p>". _g( "Last Modified: " ). gmtime().
-       "<br>\n".
-       sprintf( _g( "Copyright &copy; 1997-2005 <a href=\"http://www.spi-inc.org\">SPI</a>; See <a href=\"%s/license\">license terms</a>." ), "$HOME/" )."<br>\n".
-       _g( "Debian is a registered trademark of Software in the Public Interest, Inc." ).
-       "</div> <!-- end fineprint -->\n".
-       "</div> <!-- end footer -->\n".
-       "</div> <!-- end outer -->\n".
-       "</body>\n</html>\n";
-
-    return $txt;
-}
-
-sub languages {
-    my ( $name, $lang, @used_langs ) = @_;
-    
-    my $str = "";
-    
-    if (@used_langs) {
-       $str .= "<hr class=\"hidecss\">\n";
-       $str .= "<!--UdmComment-->\n<p>\n";
-       $str .= _g( "This page is also available in the following languages:\n" );
-       $str .= "</p><p class=\"navpara\">\n";
-       
-       my @printed_langs = ();
-       foreach (@used_langs) {
-           next if $_ eq $lang; # Never print the current language
-           unless (get_selfname($_)) { warn "missing language $_"; next } #DEBUG
-           push @printed_langs, $_;
-       }
-       return "" unless scalar @printed_langs;
-       # Sort on uppercase to work with languages which use lowercase initial
-       # letters.
-       foreach my $cur_lang (sort langcmp @printed_langs) {
-           my $tooltip = dgettext( "langs", get_language_name($cur_lang) );
-           $str .= "<a href=\"$name.$cur_lang.html\" title=\"$tooltip\" hreflang=\"$cur_lang\" lang=\"$cur_lang\" rel=\"alternate\">".get_selfname($cur_lang);
-           $str .= " (".get_transliteration($cur_lang).")" if defined get_transliteration($cur_lang);
-           $str .= "</a>\n";
-       }
-       $str .= "\n</p><p>\n";
-       $str .= sprintf( _g( "How to set <a href=\"%s\">the default document language</a>" ), $CN_HELP_URL )."</p>";
-       $str .= "\n<!--/UdmComment-->\n";
-    }
-    
-    return $str;
-}
-
-1;
diff --git a/lib/Packages/Template.pm b/lib/Packages/Template.pm
new file mode 100644 (file)
index 0000000..9912cd7
--- /dev/null
@@ -0,0 +1,121 @@
+package Packages::Template;
+
+use strict;
+use warnings;
+
+use Template;
+use Locale::gettext;
+use Benchmark ':hireswallclock';
+
+use Packages::CGI;
+use Packages::I18N::Locale;
+use Packages::I18N::Languages;
+use Packages::I18N::LanguageNames;
+
+our @ISA = qw( Exporter );
+#our @EXPORT = qw( head );
+
+use constant COMPILE => 1;
+
+sub new {
+    my ($classname, $include, $format, $vars, $options) = @_;
+    $options ||= {};
+
+    my $self = {};
+    bless( $self, $classname );
+
+    my @timestamp = gmtime;
+    $vars->{timestamp} = {
+       year => $timestamp[5]+1900,
+       string => scalar gmtime() .' UTC',
+    };
+
+    $self->{template} = Template->new( {
+       PRE_PROCESS => [ 'config.tmpl' ],
+       INCLUDE_PATH => $include,
+       VARIABLES => $vars,
+       COMPILE_EXT => '.ttc',
+       %$options,
+    } ) or fatal_error( sprintf( _g( "Initialization of Template Engine failed: %s" ), $Template::ERROR ) );
+    $self->{format} = $format;
+
+    return $self;
+}
+
+sub process {
+    my $self = shift;
+    return $self->{template}->process(@_);
+}
+sub error {
+    my $self = shift;
+    return $self->{template}->error(@_);
+}
+
+sub page {
+    my ($self, $action, $page_content) = @_;
+
+    #use Data::Dumper;
+    #die Dumper($self, $action, $page_content);
+
+    my $txt;
+    $self->process("$self->{format}/$action.tmpl", $page_content, \$txt)
+       or die sprintf( "template error: %s", $self->error ); # too late for reporting on-line
+
+    return $txt;
+}
+
+sub error_page {
+    my ($self, $page_content) = @_;
+
+#    use Data::Dumper;
+#    warn Dumper($page_content);
+
+    my $txt;
+    $self->process("$self->{format}/error.tmpl", $page_content, \$txt)
+       or die sprintf( "template error: %s", $self->error ); # too late for reporting on-line
+
+    return $txt;
+}
+
+sub trailer {
+    my ($self, $NAME, $LANG, $USED_LANGS, $timediff) = @_;
+
+    my $langs = languages( $LANG, @$USED_LANGS );
+
+    my $txt;
+    $self->process("$self->{format}/foot.tmpl", { langs => $langs, name => $NAME, benchmark => $timediff ? timestr($timediff) : '' }, \$txt)
+       or die sprintf( "template error: %s", $self->error ); # too late for reporting on-line
+
+    return $txt;
+}
+
+sub languages {
+    my ( $lang, @used_langs ) = @_;
+    
+    my @langs;
+
+    if (@used_langs) {
+       
+       my @printed_langs = ();
+       foreach (@used_langs) {
+           next if $_ eq $lang; # Never print the current language
+           unless (get_selfname($_)) { warn "missing language $_"; next } #DEBUG
+           push @printed_langs, $_;
+       }
+       return [] unless scalar @printed_langs;
+       # Sort on uppercase to work with languages which use lowercase initial
+       # letters.
+       foreach my $cur_lang (sort langcmp @printed_langs) {
+           my %lang;
+           $lang{lang} = $cur_lang;
+           $lang{tooltip} = dgettext( "langs", get_language_name($cur_lang) );
+            $lang{selfname} = get_selfname($cur_lang);
+           $lang{transliteration} = get_transliteration($cur_lang) if defined get_transliteration($cur_lang);
+           push @langs, \%lang;
+       }
+    }
+    
+    return \@langs;
+}
+
+1;
index 00ab1b5a36e842ea3cab3ff203129a649236e2d3..082abba78112397ac8701632cb659dd0536b642d 100644 (file)
        font-size: 88%;
 }
 
-/* classes and div names for package pages */
+h1 {
+       clear: both;
+}
 
 #pdesc, #ptags, #pdeps, #pdownload, #pmoreinfo {
        margin-left: 1em;
        margin-right: 1em;
 }
+#pmoreinfo p {
+       font-size: 0.85em;
+}
+
+/*
+
+  DESCRIPTIONS
+
+*/
 
 #pdesc p {
        text-align: justify;
+       max-width: 60em;
 }
 
 .pdescshort {
        font-weight: bold;
 }
 
+/*
+
+  DEPENDENCIES
+
+*/
+
 #pdeps table tr td {
-       font-size: 0.9em;
+       font-size: smaller;
 }
 
 #pdeps ul {
@@ -50,9 +68,9 @@
        padding-left: 2em;
 }
 
-#pdeps li {
+/* #pdeps li {
        text-indent: -2em;
-}
+} */
 
 #pdeps ul.uldep, #pdeps ul.uladep {
        list-style-type: disc;
 }
 
 #pdeps ul.uldep li, #pdeps ul.ulrec li, #pdeps ul.ulsug li, #pdeps ul.uladep li, #pdeps ul.ulidep li {
-       padding-left: 2em;
+       padding-left: 1em;
 }
 #pdeps dl {
        margin: 0;
 }
 
-#pdownload p {
-       display: inline;
-}
-
+/*
 
-#pmoreinfo p {
-       font-size: 0.85em;
-}
+  MESSAGES
 
+*/
 .pmarker {
        color: red;
+       clear: both;
 }
 .perror {
        margin: .2em;
        font-weight: bold;
        padding: 0.5em;
        margin: 0;
+       clear: both;
 }
 .pdebug {
        margin: .2em;
        font-size: 80%;
        border: solid thin gray;
+       clear: both;
 }
 .phints {
        background-color: #FF9;
        padding: 0.5em;
        margin: 0;
+       clear: both;
 }
 .pnotes {
        margin: .2em;
+       padding: .5em;
        border: solid thin black;
        background-color: #bdf;
+       clear: both;
 }
 .pnotes h2 {
        color: red;
 }
+.pconstantnag {
+       max-width: 60em;
+       border: dotted thin red;
+       padding: .5em;
+       font-size: smaller;
+}
+.pconstantnag h2 {
+       text-align: center;
+}
+.pconstantnag strong {
+       color: red;
+}
 
 table#pdeplegend, #pdownload table {
        border-width: 4px;
@@ -122,8 +154,49 @@ table#pdeplegend, #pdownload table {
        border-collapse: collapse;
 }
 
+
+/*
+
+  DOWNLOAD
+
+*/
+#pdownload td {
+       font-size: 0.85em;
+       text-align: center;
+}
+#pdownload td.size {
+       text-align: right;
+}
+#pdownload td.md5sum {
+       font-family: monospace;
+}
+#pdownload p {
+       display: inline;
+}
+
+#pdownloadnotes {
+       font-size: smaller;
+       max-width: 60em;
+}
+#pdownloadmeta tr {
+       text-align: left;
+}
+
+/*
+
+  CONTENTS SEARCH
+
+*/
+#pcontentsres {
+       margin-left: 1em;
+       margin-top: 2em;
+}
+#pcontentsres p {
+       margin-top: .1em;
+       margin-bottom: .25em;
+}
 #pcontentsres table {
-       margin: 0 1em 1em 1em;
+       margin: 1em 1em 1em 0;
        min-width: 50%;
        border: 2px gray;
        border-style: ridge;
@@ -138,17 +211,6 @@ table#pdeplegend, #pdownload table {
 #pcontentsres td.file {
        font-family: monospace;
 }
-#pdownload td {
-       font-size: 0.85em;
-       text-align: center;
-}
-
-#pdownload td.size {
-       text-align: right;
-}
-#pdownload td.md5sum {
-       font-family: monospace;
-}
 #pcontentsres td {
 /*     font-size: smaller;*/
        padding: .4em;
@@ -156,16 +218,105 @@ table#pdeplegend, #pdownload table {
 #pcontentsres th {
        text-align: center;
 }
+#pcontentsres h1 {
+       text-align: left;
+       margin-bottom: .25em;
+}
+#pfilelist pre {
+       border-top: solid #BFC3DC thin;
+       padding: .5em;
+}
+
+/*
+
+  PACKAGES SEARCH
+  AND COMMON STUFF
+  FOR SEARCHES
+
+*/
 #psearchres h2 {
        padding: .3em;
        border-top: solid gray thin;
        border-bottom: solid gray thin;
        background-color: #bdf;
 }
-#pfilelist pre {
-       border-top: solid #BFC3DC thin;
-       padding: .5em;
+#psearchres li {
+       margin-top: 1em;
+}
+#psearchres .resultlink {
+       font-weight: bold;
+}
+#psearchres .binaries {
+       font-size: smaller;
+}
+#psearchsug {
+       font-size: smaller;
+}
+#psearchsug ul.linklist {
+       display: inline;
+       margin-top: .1em;
+       margin-bottom: 0;
+       padding: 0;
+}
+#psearchsug .linklist li {
+       display: inline;        
+       margin-top: 0;
+       margin-bottom: 0;
+       margin-right: 1em;
+       margin-left: 0;
+}
+#psearchsug p {
+       margin-top: .1em;
+       margin-bottom: 0;
+}
+#psearchnoresult, #psearchtoomanyhits {
+       font-size: larger;
+       font-weight: bold;
+       max-width: 60em;
 }
 .keyword {
        font-weight: bold;
 }
+
+#pothers {
+       float: right;
+       text-align: right;
+}
+
+#pnavbar {
+       clear: both;
+       margin-bottom: .25em;
+       padding-left: 1em;
+       padding-top: 6px;
+       padding-bottom: 4px;
+       width: 100%;
+       height: auto;
+       text-align: left;
+       background: #DF0451;
+       color: yellow;
+       font-size: smaller;
+       font-weight: bold;
+}
+#pnavbar ul {
+       display: inline;
+       list-style-type: none; 
+       padding-left:  0px;
+       line-height: 1.5em;
+}
+#pnavbar ul li {
+       display: inline;
+       margin: 0;
+       white-space: nowrap;
+}
+#pnavbar a {
+       color: yellow;
+       text-decoration: none;
+}
+#pnavbar a:hover {
+}
+
+#pnavbar, .pconstantnag {
+       -moz-border-radius: 15px;
+       /* this goes to the end as the css validator does not like it
+       will be replaced by border-radius with css3 */
+}
diff --git a/templates/config.tmpl b/templates/config.tmpl
new file mode 100644 (file)
index 0000000..bb5f7b8
--- /dev/null
@@ -0,0 +1,39 @@
+[%- DEFAULT
+   charset = 'UTF-8'
+   lang = 'en'
+
+   organisation = 'Debian'
+   homepage = 'http://www.debian.org/'
+   packages_homepage = 'http://packages.debian.org/'
+   searchformurl = packages_homepage
+   search_url = '/'
+   tags_url = 'http://debtags.alioth.debian.org/'
+   bugs_url = 'http://bugs.debian.org/'
+   src_bugs_url = bugs_url _ 'src:'
+   mirror_url = 'http://ftp.debian.org/'
+   changelogs_url = '/changelogs/'
+   cn_help_url = homepage _ 'intro/cn'
+   logo = {
+       url => homepage,
+        src => '/Pics/openlogo-nd-50.png',
+        alt => organisation,
+   }
+   copyright = {
+       url => 'http://www.spi-inc.org/',
+        name => 'SPI Inc.',
+        years => '1997 - ' _ timestamp.year,
+   }
+   license = {
+       url => homepage _ 'license'
+   }
+   contact = {
+       name => 'Debian Web Mailinglist',
+       mail => 'debian-www@lists.debian.org',
+        url => homepage _ 'contact',
+   }
+   admin = {
+       name => 'Debian Webmaster',
+       mail => 'webmaster@debian.org',
+   }
+   trademarknotes = organisation _ ' is a trademark of ' _ copyright.name
+-%]
diff --git a/templates/config/architectures.tmpl b/templates/config/architectures.tmpl
new file mode 100644 (file)
index 0000000..c15e8be
--- /dev/null
@@ -0,0 +1,21 @@
+[%
+# list of architectures
+architectures = {
+        i386    => 'Intel x86',
+        m68k    => 'Motorola 680x0',
+        sparc   => 'SPARC',
+        alpha   => 'Alpha',
+        powerpc => 'PowerPC',
+        arm     => 'ARM',
+        hppa    => 'HP PA-RISC',
+        ia64    => 'Intel IA-64',
+        mips    => 'MIPS',
+        mipsel  => 'MIPS (DEC)',
+        s390    => 'IBM S/390',
+       "hurd-i386" => 'Hurd (i386)',
+       amd64   => 'AMD64',
+       "kfreebsd-i386" => 'GNU/kFreeBSD (i386)',
+       "kfreebsd-amd64" => 'GNU/kFreeBSD (amd64)'
+}
+
+%]
\ No newline at end of file
diff --git a/templates/config/archive_layout.tmpl b/templates/config/archive_layout.tmpl
new file mode 100644 (file)
index 0000000..1eacb16
--- /dev/null
@@ -0,0 +1,5 @@
+[%
+   main_section = 'main'
+   main_archive = 'us'
+   standard_priority = 'optional'
+%]
diff --git a/templates/config/mirrors.tmpl b/templates/config/mirrors.tmpl
new file mode 100644 (file)
index 0000000..8842d77
--- /dev/null
@@ -0,0 +1,210 @@
+[%
+
+# TODO: find a way to get the U.S. mirror list from a more authoritive
+# location automatically. might not be overly smart to automatize it
+# completely, since I hand pick sites that are up-to-date, fast, and
+# have HTTP on a reasonably short URL
+#   -- Joy
+
+# hint:
+# grep-dctrl -F Site,Alias -e '(udel|bigfoot|kernel|crosslink|internap|cerias|lcs.mit|progeny)' Mirrors.masterlist | timestamps/archive_mirror_check.py
+mirrors = {
+       us => {
+               mirror_list => 'http://www.debian.org/mirror/list',
+               north_america => [
+                       "ftp.us.debian.org/debian",
+                       "http.us.debian.org/debian",
+                       "ftp.debian.org/debian",
+#                      "ftp.ca.debian.org/debian",
+                       "ftp.egr.msu.edu/debian",
+                       "mirrors.kernel.org/debian",
+                       "archive.progeny.com/debian",
+                       "debian.crosslink.net/debian",
+                       "ftp-mirror.internap.com/pub/debian",
+                       "ftp.cerias.purdue.edu/pub/os/debian",
+                       "ftp.lug.udel.edu/debian",
+                       "debian.lcs.mit.edu/debian",
+                       "debian.teleglobe.net",
+                       "debian.rutgers.edu",
+                       "debian.oregonstate.edu/debian",
+               ],
+               europa => [
+                       "ftp.de.debian.org/debian",
+                       "ftp.at.debian.org/debian",
+                       "ftp.bg.debian.org/debian",
+                       "ftp.cz.debian.org/debian",
+                       "ftp.dk.debian.org/debian",
+                       "ftp.ee.debian.org/debian",
+                       "ftp.fi.debian.org/debian",
+                       "ftp.fr.debian.org/debian",
+                       "ftp.hr.debian.org/debian",
+                       "ftp.hu.debian.org/debian",
+                       "ftp.ie.debian.org/debian",
+                       "ftp.is.debian.org/debian",
+                       "ftp.it.debian.org/debian",
+                       "ftp.nl.debian.org/debian",
+                       "ftp.no.debian.org/debian",
+                       "ftp.pl.debian.org/debian",
+                       "ftp.si.debian.org/debian",
+                       "ftp.es.debian.org/debian",
+                       "ftp.se.debian.org/debian",
+                       "ftp.tr.debian.org/debian",
+                       "ftp.uk.debian.org/debian",
+               ],
+               south_america => [
+                       "ftp.br.debian.org/debian",
+                       "ftp.cl.debian.org/debian",
+               ],
+               australia => [
+                       "ftp.au.debian.org/debian",
+                       "ftp.wa.au.debian.org/debian",
+                       "ftp.nz.debian.org/debian",
+               ],
+               asia => [
+                       "ftp.jp.debian.org/debian",
+#                      "ftp.kr.debian.org/debian",
+                       "linux.csie.nctu.edu.tw/debian",
+                       "debian.linux.org.tw/debian",
+                       "linux.cdpa.nsysu.edu.tw/debian",
+               ],
+       },
+
+       volatile => {
+               mirror_list => 'http://volatile.debian.net/mirrors.html',
+               europa => [
+                       "volatile.debian.net/debian-volatile",
+                       "ftp2.de.debian.org/debian-volatile",
+                       "ftp.sk.debian.org/debian-volatile",
+               ],
+       },
+
+       backports => {
+               mirror_list => 'http://www.backports.org/debian/README.mirrors.html',
+               europa => [
+                       "www.backports.org/debian",
+                       "debian.sil.at/backports.org/",
+                       "backports.debian.or.at/backports.org",
+                       "mirror.realroute.net/backports.org",
+                       "backports.cisbg.com",
+                       "backports.linuxdediziert.de/backports.org",
+                       "debian.netcologne.de/debian-backports",
+                       "ftp.de.debian.org/backports.org",
+                       "mirror.buildd.net/backports.org",
+                       "ftp.estpak.ee/backports.org",
+                       "debian.acantho.net/backports.org",
+                       "backports.essentkabel.com/backports.org",
+                       "backports.sipo.nl",
+                       "ftp.tuke.sk",
+               ],
+               asia => [
+                       "backports.mithril-linux.org",
+               ],
+               australia => [
+                       "mirror.linux.org.au/backports.org",
+               ],
+       },
+
+       amd64 => {
+               unofficial_port => {
+                       url_name => 'amd64',
+                       name => 'AMD64',
+               },
+               europa => [
+                       "amd64.debian.net/debian",
+                       "ftp.de.debian.org/debian-amd64/debian",
+                       "bach.hpc2n.umu.se/debian-amd64/debian",
+                       "bytekeeper.as28747.net/debian-amd64/debian",
+                       "mirror.switch.ch/debian-amd64/debian",
+                       "ftp.nl.debian.org/debian-amd64/debian",
+               ],
+               asia => [
+                       "hanzubon.jp/debian-amd64/debian",
+               ],
+               north_america => [
+                       "mirror.espri.arizona.edu/debian-amd64/debian",
+               ],
+       },
+
+       kfreebsd => {
+               unofficial_port => {
+                       url_name => 'kfreebsd-gnu',
+                       name => 'GNU/kFreeBSD',
+               },
+               north_america => [
+                       "www.gtlib.gatech.edu/pub/gnuab/debian",
+               ],
+               europa => [
+                       # master site, aka ftp.gnuab.org
+                       "kfreebsd-gnu.debian.net/debian",
+                       "ftp.easynet.be/ftp/gnuab/debian",
+                       "ftp.de.debian.org/debian-kfreebsd",
+                       "ftp.sh.cvut.cz/MIRRORS/debian-non-linux",
+                       "ftp.eila.jussieu.fr/pub/Debian-gnuab",
+               ],
+               asia => [
+                       "ftp.citkit.ru/pub/HURD/debian",
+               ],
+       },
+
+       nonus => {
+               mirror_list => 'http://www.debian.org/mirror/list-non-US',
+               north_america => [
+#                      "ftp.ca.debian.org/debian-non-US",
+                       "debian.yorku.ca/debian/non-US",
+                       "mirror.direct.ca/linux/debian-non-US",
+               ],
+               europa => [
+                       "non-us.debian.org/debian-non-US",
+                       "ftp.de.debian.org/debian-non-US",
+                       "ftp.at.debian.org/debian-non-US",
+                       "ftp.bg.debian.org/debian-non-US",
+                       "ftp.cz.debian.org/debian-non-US",
+                       "ftp.fi.debian.org/debian-non-US",
+                       "ftp.fr.debian.org/debian-non-US",
+                       "ftp.hr.debian.org/debian-non-US",
+                       "ftp.hu.debian.org/debian-non-US",
+                       "ftp.ie.debian.org/debian-non-US",
+                       "ftp.is.debian.org/debian-non-US",
+                       "ftp.it.debian.org/debian-non-US",
+                       "ftp.nl.debian.org/debian-non-US",
+                       "ftp.no.debian.org/debian-non-US",
+                       "ftp.pl.debian.org/debian/non-US",
+                       "ftp.si.debian.org/debian-non-US",
+                       "ftp.es.debian.org/debian-non-US",
+                       "ftp.se.debian.org/debian-non-US",
+                       "ftp.tr.debian.org/debian-non-US",
+                       "ftp.uk.debian.org/debian/non-US",
+               ],
+               australia => [
+                       "ftp.au.debian.org/debian-non-US",
+                       "ftp.wa.au.debian.org/debian-non-US",
+                       "ftp.nz.debian.org/debian-non-US",
+               ],
+               asia => [
+                       "ftp.jp.debian.org/debian-non-US",
+#                      "ftp.kr.debian.org/debian-non-US",
+                       "linux.csie.nctu.edu.tw/debian-non-US",
+                       "debian.linux.org.tw/debian-non-US",
+                       "linux.cdpa.nsysu.edu.tw/debian-non-US",
+               ],
+               south_america => [
+                       "ftp.br.debian.org/debian-non-US",
+                       "ftp.cl.debian.org/debian-non-US",
+               ],
+       },
+}
+
+ports_url = 'http://www.debian.org/ports/'
+
+continents = {
+               north_america => 'North America',
+               south_america => 'South America',
+               asia          => 'Asia',
+               australia     => 'Australia and New Zealand',
+               europa        => 'Europa',
+               africa        => 'Africa',
+       }
+
+%]
+
diff --git a/templates/html/download.tmpl b/templates/html/download.tmpl
new file mode 100644 (file)
index 0000000..c59a6e5
--- /dev/null
@@ -0,0 +1,99 @@
+[%- PROCESS 'html/head.tmpl'
+   title_tag = 'Package Download Selection'
+   description = desc
+   keywords = "$suite, $archive, $section, $subsection, $version"
+   navigation = [ { prefix=>'Distribution:', title=>'Overview over this suite', url=>make_url('/'), name=>suite },
+                 { prefix=>'Package:', url=>make_url(pkg,'','arch',undef), name=>pkg },
+                 { url=>make_url(pkg), name=>architecture },
+                 { name => 'Download' },
+               ]
+-%]
+[%- PROCESS 'config/mirrors.tmpl' -%]
+[%- PROCESS 'config/architectures.tmpl' -%]
+[%- PROCESS 'html/messages.tmpl' -%]
+
+[% IF architecture != 'all' %]
+<h2>Download Page for <kbd>[% filename.file %]</kbd> on [% architectures.$architecture %] machines</h2>
+[% ELSE %]
+<h2>Download Page for <kbd>[% filename.file %]</kbd></h2>
+[% END %]
+
+<div class="pconstantnag">
+<p>If you are running Debian, it's strongly suggested to use a
+package manager like <a href="[% make_url('aptitude','','arch','') %]">aptitude</a> or
+<a href="[% make_url('synaptic','','arch','') %]">synaptic</a> to download and install
+packages, instead of doing so manually via this website.</p>
+[% IF suite == "experimental" %]
+<h2>Experimental package</h2>
+<p>Warning: This package is from the <strong>experimental</strong> distribution.
+That means it is likely unstable or buggy, and it may even cause data loss.
+Please be sure to consult the changelog and other possible documentation before
+using it.</p>
+[% END %]
+[% IF subsection == "debian-installer" %]
+<h2>debian-installer udeb package</h2>
+<p>Warning: This package is intended for the use in building
+<a href="http://www.debian.org/devel/debian-installer">debian-installer</a> images only.
+Do not install it on a normal Debian system.</p>
+[% END %]
+</div>
+
+[%- SET a = mirrors.$archive -%]
+
+[% IF archive != 'security' %]
+  <p>You can download the requested file from the <tt>[% filename.directory %]</tt> subdirectory at any of these sites:</p>
+  <div class="cardleft">
+  [% FOREACH continent IN [ 'north_america', 'south_america', 'asia', 'africa' ] %]
+    [% IF a.$continent %]
+       <p><em>[% continents.$continent %]</em></p>
+       <ul>
+       [% FOREACH m IN a.$continent %]
+         <li><a href="http://[% m %]/[% filename.full %]">[% m %]</a></li>
+       [% END %]
+       </ul>
+    [% END %]
+  [% END %]
+  </div><div class="cardright">
+  [% FOREACH continent IN [ 'europa','australia' ] %]
+    [% IF a.$continent %]
+       <p><em>[% continents.$continent %]</em></p>
+       <ul>
+       [% FOREACH m IN a.$continent %]
+         <li><a href="http://[% m %]/[% filename.full %]">[% m %]</a></li>
+       [% END %]
+       </ul>
+    [% END %]
+  [% END %]
+  </div>
+[% ELSE %]
+<p>You can download the requested file from the <tt>[% filename.directory %]</tt> subdirectory at:</p>
+<ul><li><a href="http://security.debian.org/debian-security/[% filename.full %]">security.debian.org/debian-security</a></li></ul>
+<p>Debian security updates are currently officially distributed only via <tt>security.debian.org</tt></p>
+[% END %]
+
+<div id="pdownloadnotes">
+
+[% IF a.mirror_list %]
+<p style="clear:both">If none of the above sites are fast enough for you,
+please see our <a href="[% a.mirror_list %]">complete mirror list</a>.</p>
+[% END %]
+
+[% IF a.unofficial_port %]
+[% SET port = a.unofficial_port %]
+<p style="clear:both">Note that [% port.name %] is not officially included in the [% organisation %] archive yet,
+but the [% port.name %] porter group keeps their archive in sync with the official archive as close as possible.
+See the <a href="[% ports_url _ port.url_name _ '/' %]">[% port.name %] ports page</a> for current information.</p>
+[% END %]
+
+<p>Note that in some browsers you will need to tell your browser you want the file saved to a file.
+For example, in Firefox or Mozilla, you should hold the Shift key when you click on the URL.</p>
+
+</div>
+
+<h3>More information on <kbd>[% filename.file %]</kbd>:</h3>
+<table id="pdownloadmeta">
+<tr><th>Exact Size</th>                <td class="size">[% size %] Byte ([% pkgsize %] [% pkgsize_unit %])</td>
+<tr><th>MD5 checksum</th>              <td><tt>[% md5sum %]</tt></td>
+<tr><th>SHA1 checksum</th>             <td><tt>[% sha1 || 'Not Available' %]</tt></td>
+<tr><th>SHA256 checksum</th>           <td><tt>[% sha256  || 'Not Available' %]</tt></td>
+</table>
diff --git a/templates/html/error.tmpl b/templates/html/error.tmpl
new file mode 100644 (file)
index 0000000..72c4fd4
--- /dev/null
@@ -0,0 +1,4 @@
+[%- PROCESS 'html/head.tmpl'
+   title_tag = 'Error'
+   page_title = 'Error'
+-%]
diff --git a/templates/html/filelist.tmpl b/templates/html/filelist.tmpl
new file mode 100644 (file)
index 0000000..be74cc3
--- /dev/null
@@ -0,0 +1,17 @@
+[%- PROCESS 'html/head.tmpl'
+   title_tag = "Filelist of package $pkg/$suite/$arch"
+   page_title = "Filelist of package <em>$pkg</em> in <em>$suite</em> of architecture <em>$arch</em>"
+   keywords = "$suite, $arch, filelist"
+   navigation = [ { prefix=>'Distribution:', title=>'Overview over this suite', url=>make_url('/'), name=>suite },
+                 { prefix=>'Package:', url=>make_url(pkg,'','arch',undef), name=>pkg },
+                 { url=>make_url(pkg), name=>arch },
+                 { name => 'Filelist' },
+               ]
+-%]
+<h1></h1>
+
+[% FOREACH file IN files %]
+[%- '<div id="pfilelist"><pre>' IF loop.first -%]
+[% file %]
+[% '</pre></div>' IF loop.last -%]
+[% END %]
diff --git a/templates/html/foot.tmpl b/templates/html/foot.tmpl
new file mode 100644 (file)
index 0000000..fa44e87
--- /dev/null
@@ -0,0 +1,37 @@
+[%- IF benchmark && debug -%]
+Total page evaluation took [% benchmark %]<br>
+[%- END -%]
+</div> <!-- end inner -->
+
+<div id="footer">
+
+[% IF langs.size > 0 %]
+<hr class="hidecss">
+<!--UdmComment-->
+<p>This page is also available in the following languages:</p>
+<p class="navpara">
+[% FOREACH langs %]
+<a href="[% name _ cur_lang _ ".html" %]" title="[% tooltip %]" hreflang="[% cur_lang %]" lang="[% cur_lang %]" rel="alternate">[% selfname %]
+[%- IF transliteration %] ([% transliteration %])[% END %]</a>
+[% END %]
+</p>
+<p>How to set <a href="[% cn_help_url %]">the default document language</a></p>
+<!--/UdmComment-->
+[% END %]
+
+<hr class="hidecss">
+<p [%- ' class="bordertop"' IF langs.count > 0 %]>Back to: <a href="[% homepage %]">[% organisation %] homepage</a> || <a href="[% searchformurl %]">Packages search page</a></p>
+
+<hr class="hidecss">
+<div id="fineprint" class="bordertop">
+<p>To report a problem with the web site, e-mail <a href="mailto:[% contact.mail %]">[% contact.mail %]</a>. For other contact information, see the [% organisation %] <a href="[% contact.url %]">contact page</a>.</p>
+<p>Generated: [% timestamp.string %]<br>
+Copyright &copy; [% copyright.years %] <a href="[% copyright.url %]">[% copyright.name %]</a>; See <a href="[% license.url %]">license terms</a>.
+[% IF trademarknotes -%]
+ <br>[% trademarknotes %]
+[%- END %]
+</div> <!-- end fineprint -->
+</div> <!-- end footer -->
+</div> <!-- end outer -->
+</body>
+</html>
diff --git a/templates/html/head.tmpl b/templates/html/head.tmpl
new file mode 100644 (file)
index 0000000..31cc40b
--- /dev/null
@@ -0,0 +1,72 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="[% lang %]">
+<head>
+<title>[% organisation %] -- [% title_tag %]</title>
+<link rev="made" href="[% admin.mail %]">
+<meta http-equiv="Content-Type" content="text/html; charset=[% charset %]">
+<meta name="Author" content="[% admin.name %], [% admin.mail %]">
+<meta name="Description" content="[% description %]">
+<meta name="Keywords" content="[% organisation %],  [% keywords %]">
+[% html_meta %]
+
+<link href="/debian.css" rel="stylesheet" type="text/css" media="all">
+<link href="/packages.css" rel="stylesheet" type="text/css" media="all">
+</head>
+<body>
+<div id="header">
+   <div id="upperheader">
+
+   <div id="logo">
+  <!-- very Debian specific use of the logo stuff -->
+  <a href="[% logo.url %]"><img src="[% logo.src %]" alt="" /></a>
+  <a href="[% logo.url %]"><img src="/Pics/debian.png" alt="[% logo.alt %]" width="179" height="61"></a>
+</div> <!-- end logo -->
+
+[%- IF print_search_field %]
+[% checked = 'checked="checked"' %]
+<form method="GET" action="/search">
+<div id="hpacketsearch">
+[% IF search_field_values.mode %]<input type="hidden" name="mode" value="[% search_field_values.mode %]">[% END %]
+[% IF search_field_values.sort_by %]<input type="hidden" name="sort_by" value="[% search_field_values.sort_by %]">[% END %]
+[% IF search_field_values.suite %]<input type="hidden" name="suite" value="[% search_field_values.suite %]">[% END %]
+[% IF search_field_values.sections %]<input type="hidden" name="section" value="[% search_field_values.sections %]">[% END %]
+[% IF search_field_values.architectures %]<input type="hidden" name="arch" value="[% search_field_values.architectures %]">[% END %]
+<input type="text" size="30" name="keywords" value="[% search_field_values.keywords | html %]" id="kw">
+<input type="submit" value="Search">
+<span style="font-size: 60%"><a href="[% searchformurl %]">all options</a></span>
+<br>
+<div style="font-size: 80%">search in:
+<input type="radio" name="searchon" value="names" id="onlynames" [% checked IF search_field_values.searchon == 'names' || search_field_values.searchon == 'default' %]>
+<label for="onlynames">package names</label>&nbsp;&nbsp;
+
+<input type="radio" name="searchon" value="all" id="descs" [% checked IF search_field_values.searchon == 'all' %]>
+<label for="descs">descriptions</label>
+<br>
+<input type="radio" name="searchon" value="sourcenames" id="src" [% checked IF search_field_values.searchon == 'sourcenames' %]>
+<label for="src">source package names</label>
+<input type="radio" name="searchon" value="contents" id="conts" [% checked IF search_field_values.searchon == 'contents' %]>
+<label for="conts">package contents</label>
+</div>
+</div> <!-- end hpacketsearch -->
+</form>
+[% END %]
+
+</div> <!-- end upperheader -->
+
+<p class="hidecss"><a href="#inner">skip the navigation</a></p>
+<div id="pnavbar">
+ &gt;&gt; <a href="[% homepage %]" title="[% organisation %] Homepage">[% organisation %]</a>
+ &gt;&gt; <a href="[% packages_homepage %]" title="[% organisation %] Packages Homepage">Packages</a>
+[% FOREACH n IN navigation %]
+ &gt;&gt; [% IF n.url %]<a href="[% n.url %]" [% IF n.title %]title="[% n.title %]"[% END %]>[% n.name %]</a>[% ELSE %][% n.name %][% END %] 
+[% END %]
+</div> <!-- end navbar -->
+
+</div> <!-- end header -->
+<div id="outer">
+<div id="inner">
+
+[%- IF page_title %]
+  <h1>[% page_title %]</h1>
+  [%- PROCESS 'html/messages.tmpl' -%]
+[% END -%]
diff --git a/templates/html/index.tmpl b/templates/html/index.tmpl
new file mode 100644 (file)
index 0000000..8985294
--- /dev/null
@@ -0,0 +1,41 @@
+[% PROCESS 'config/archive_layout.tmpl' %]
+[% pkg_type = is_source ? 'Source' : 'Software';
+   title_common = category ? "$pkg_type Packages in \"$suite\", $category.id $category.name"
+       : "$pkg_type Packages in \"$suite\"";
+   IF category;
+       navigation_pre = [ { prefix=>'Distribution:', title=>'Overview over this suite', url=>"../", name=>suite },
+                          { prefix=>"$category.id:", name=>category.name } ];
+   ELSE;
+       navigation_pre = [ { prefix=>'Distribution:', title=>'Overview over this suite', url=>"index", name=>suite },
+                          { name=>'All Packages' } ];
+   END
+%]
+[% PROCESS 'html/head.tmpl' 
+       title_tag = title_common
+       page_title = title_common
+       keywords = "$suite, $category.name"
+       navigation = navigation_pre
+%]
+
+[% FOREACH packages %]
+  [% '<dl>' IF loop.first %]
+
+  [% BLOCK marker %] [<strong class="pmarker">[% text %]</strong>] [%- END %]
+  [% BLOCK markers %]
+    [% PROCESS marker text=section IF section != main_section %]
+    [% PROCESS marker text=archive IF archive != main_archive %]
+  [% END %]
+  [% IF providers.size %]
+    <dt><a href="[% name %]" id="[% name %]">[% name %]</a></dt>
+       <dd>virtual package provided by [% FOREACH provider IN providers %]<a href="../[% provider | uri %]">[% provider %]</a>[% END %]</dd>
+    [% IF versions.length %]
+      <dt><a href="[% name %]">[% name %]</a> ([% versions %])[% PROCESS markers %]</dt>
+         <dd>[% desc | html %]</dd>
+    [% END %]
+  [% ELSE %]
+    <dt><a href="[% name %]" id="[% name %]">[% name %]</a> ([% versions %])[% PROCESS markers %]</dt>
+       <dd>[% desc | html %]</dd>
+  [% END %]
+
+  [% '</dl>' IF loop.last %]
+[% END %]
diff --git a/templates/html/menu.inc b/templates/html/menu.inc
new file mode 100644 (file)
index 0000000..aa9c43d
--- /dev/null
@@ -0,0 +1,10 @@
+[% BLOCK menuitem -%]
+  [&nbsp;[% prefix -%]
+  [%- IF url -%]
+    <a [% 'title="' _ title _ '"' IF title %] href="[% url %]">[% name %]</a>
+  [%- ELSE -%]
+   <strong>[% name %]</strong>
+  [%- END -%]
+  &nbsp;]
+[%- END -%]
+[% BLOCK marker %] [<strong class="pmarker">[% text %]</strong>] [%- END %]
diff --git a/templates/html/messages.tmpl b/templates/html/messages.tmpl
new file mode 100644 (file)
index 0000000..3d8b6a6
--- /dev/null
@@ -0,0 +1,31 @@
+<!-- messages.tmpl -->
+[%- FOREACH error IN errors %]
+[%- '<div class="perror">' IF loop.first %]
+ <p>[% error %]</p>
+[% '</div>' IF loop.last -%]
+[% END -%]
+[%- FOREACH debug IN debugs %]
+[%- '<div class="pdebug"><h2>Debugging:</h2><pre>' IF loop.first -%]
+[% debug %]
+[% '</pre></div>' IF loop.last -%]
+[% END -%]
+[%- FOREACH hint IN hints %]
+[%- '<div class="phints">' IF loop.first %]
+ <p>[% hint %]</p>
+[% '</div>' IF loop.last -%]
+[% END -%]
+[%- FOREACH msg IN msgs %]
+[%- '<div class="pmsgs">' IF loop.first %]
+ <p>[% msg %]</p>
+[% '</div>' IF loop.last -%]
+[% END -%]
+[%- FOREACH note IN notes %]
+[%- '<div class="pnotes">' IF loop.first %]
+[%- IF note.1 %]
+ <h2>[% note.0 %]</h2>
+ <p>[% note.1 %]</p>
+[% ELSE %]
+ <p>[% note.0 %]</p>
+[% END -%]
+[% '</div>' IF loop.last -%]
+[% END -%]
diff --git a/templates/html/newpkg.tmpl b/templates/html/newpkg.tmpl
new file mode 100644 (file)
index 0000000..0586a6e
--- /dev/null
@@ -0,0 +1,31 @@
+[%- PROCESS 'html/head.tmpl'
+   title_tag = "New Packages in \"$suite\""
+   description = desc
+   keywords = "$suite, new packages, $section"
+   html_meta = '<link rel="alternate" type="application/rss+xml" title="RSS" href="newpkg?format=rss">'
+-%]
+<h1>New Packages in "[% suite %]"</h1>
+
+<p>The following packages were added to suite <em>[% suite %]</em>[% " (section $section)" IF section %] in the [% organisation %] archive during the last 7 days.</p>
+<p>This information is also available as an <a href="newpkg?format=rss">RSS feed</a>
+<a href="newpkg?format=rss"><img src="http://planet.debian.org/rss10.png" alt="[RSS 1.0 Feed]"></a></p>
+
+[% FOREACH pkg IN new_packages %]
+       [% '<ul>' IF loop.first %]
+       <li><a href="[% pkg.0 %]">[% pkg.0 %]</a>
+       -- [% pkg.-1 | html %][% " <em>($pkg.1 days old)</em>" IF pkg.1 %]
+       [% '</ul>' IF loop.last %]
+[% END %]
+
+<p class="psmallcenter"><a href="[% make_url('allpackages','') %]" title="List of all packages">All packages</a><br>
+(<a href="[% make_url('allpackages','','format','txt.gz' ) %]">compact compressed textlist</a>)<br>
+  New packages in 
+[% FOREACH s IN sections %]
+  [%- IF s == section -%]
+[% s %]
+  [%- ELSE -%]
+<a href="[% '../' IF section %][% s %]/newpkg">[% s %]</a>
+  [%- END -%]
+[% ', ' UNLESS loop.last %]
+[% END %]
+</p>
\ No newline at end of file
diff --git a/templates/html/search.tmpl b/templates/html/search.tmpl
new file mode 100644 (file)
index 0000000..69c9db0
--- /dev/null
@@ -0,0 +1,51 @@
+[%- PROCESS 'config/archive_layout.tmpl' -%]
+[%- PROCESS 'html/head.tmpl'
+   title_tag = 'Debian Package Search Results'
+   print_search_field = 'packages'
+   navigation = [ { name => 'Package Search Results' } ]
+-%]
+
+[%- PROCESS 'html/messages.tmpl' -%]
+
+<div id="psearchres">
+<p>Found <em>[% results %]</em> matching packages.</p>
+[% FOREACH categories %]
+  [% "<h2>$name</h2>" IF name %]
+
+[% FOREACH packages %]
+  <h3>Package [% pkg %]</h3>
+  <ul>
+  [% FOREACH s IN suites %]
+    <li><a class="resultlink" href="[% make_url(pkg,'','suite',s.suite) %]">[% s.suite %]</a>[% ' (' _ s.subsect _ ')' IF s.subsect %]: [% s.desc %]  [%- IF s.section %] [<strong class="pmarker">[% s.section %]</strong>][% END %]
+    [% FOREACH s.versions %]
+      <br>[% version %] [%- IF archive != main_archive %] [<strong class="pmarker">[% archive %]</strong>][% END %]: [% architectures.join(' ') %]
+    [% END %]
+    [% IF s.providers %]
+       <br>[% 'also ' IF s.versions.size > 0 %]provided by: [% FOREACH provider IN s.providers %]<a href="[% make_url(provider,'','suite',suite) %]">[% provider %]</a>[% ', ' UNLESS loop.last %][% END %]
+    [% END %]
+    </li>
+  [% END %]
+  </ul>
+[% END %]
+
+[% FOREACH src_packages %]
+  <h3>Source Package [% pkg %]</h3>
+  <ul>
+  [% FOREACH origins %]
+     [% origin = (archive == 'us') ? suite : "$suite/$archive" %]
+    <li><a class="resultlink" href="[% make_url(pkg,'','source',source,'suite',origin) %]">[% origin %]</a> ([% subsection %]): [% version %]
+      [%- IF section %] [<strong class="pmarker">[% section %]</strong>][% END %]
+      [%- IF real_archive %] [<strong class="pmarker">[% real_archive %]</strong>][% END %]
+    <br>Binary packages: <span class="binaries">[% FOREACH binary IN binaries %]<a href="[% make_url(binary,'','source',source,'suite',suite,'archive',archive) %]">[% binary %]</a>[% ', ' UNLESS loop.last %][% END %]</span>
+    </li>
+  [% END %]
+  </ul>
+[% END %]
+
+[% END %]
+
+[% IF skipped %]
+  <p><a href="[% make_search_url('',"keywords=$keywords",'exact', 0) %]">[% skipped %]</a> results have not been displayed because you requested only exact matches.
+[% END %]
+
+</div>
diff --git a/templates/html/search_contents.tmpl b/templates/html/search_contents.tmpl
new file mode 100644 (file)
index 0000000..7b794ac
--- /dev/null
@@ -0,0 +1,123 @@
+[%- PROCESS 'html/head.tmpl'
+   title_tag = "$organisation Package Contents Search Results"
+   keywords = "$suite"
+   print_search_field = 'packages'
+   navigation = [ { title => '', name => 'Packages Contents Search Results', url => '' } ]
+   search_field_values = {
+       keywords => search_keywords.join(' '),
+       searchon => 'contents',
+        mode => mode,
+       sort_by => sort_by,
+       suite => suite,
+       architectures => params.values.arch.no_replace.join(','),
+       sections => params.values.section.no_replace.join(','),
+   }
+-%]
+
+[% keyword_str = search_keywords.join(' ');
+   keyword_esc = uri_escape(keyword_str);
+   keyword_enc = html_encode(keyword_str);
+
+   section_str = params.values.section.no_replace.join(', ');
+   section_esc = uri_escape(section_str);
+   section_enc = html_encode(section_str);
+
+   architectures_str = params.values.arch.no_replace.join(', ');
+   architectures_esc = uri_escape(architectures_str);
+   architectures_enc = html_encode(architectures_str);
+%]
+<div id="psearchsug">
+
+<ul class="linklist">
+[% IF mode != 'filename' %]
+<li><a href="[% make_search_url('',"keywords=$keyword_esc",'mode','filename') %]">Search for <em>[% keyword_enc %]</em> within filenames</a>
+[% END %]
+
+[% IF mode != 'exactfilename' %]
+<li><a href="[% make_search_url('',"keywords=$keyword_esc",'mode','exactfilename') %]">Search exact filename <em>[% keyword_enc %]</em></a>
+[% END %]
+
+[% IF mode == 'exactfilename' || mode == 'filename' %]
+<li><a href="[% make_search_url('',"keywords=$keyword_esc",'mode','') %]">Search for paths ending with <em>[% keyword_enc %]</em></a>
+[% END %]
+</ul>
+
+<p>Search in other suite:
+[% FOREACH s IN all_suites %]
+[<a href="[% make_search_url('',"keywords=$keyword_esc",'suite',s) %]">[% s  %]</a>]
+[% END %]
+
+[% UNLESS search_architectures.size == 1 || all_architectures.size == 1 %]
+<p>Limit search to a specific architecture:
+[% FOREACH a IN all_architectures %] [<a href="[% make_search_url('',"keywords=$keyword_esc",'arch',a) %]">[% a %]</a>][% END %]
+[% END %]
+
+[% IF search_architectures.size == 1 %]
+<p>Search in <a href="[% make_search_url('',"keywords=$keyword_esc",arch,'') %]">all architectures</a>
+[% END %]
+
+</div>
+
+[%- PROCESS 'html/messages.tmpl' -%]
+<div id="pcontentsres">
+
+[% suite_wording = "suite <em>$suite</em>";
+   section_wording = ( section_enc == 'all' ? "all sections" : "section(s) <em>$section_enc</em>" );
+   arch_wording = ( architectures_enc == 'any' ? "all architectures" : "architecture(s) <em>$architectures_enc</em>" );
+   wording = "paths that end with";
+   IF mode == 'filename';
+       wording =  "files named";
+   ELSIF mode == 'exactfilename';
+       wording = "filenames that contain";
+   END %]
+<p>You have searched for [% wording %] <em>[% keyword_enc %]</em> in [% suite_wording %], [% section_wording %], and [% arch_wording %].
+
+[% IF results %]
+Found <strong>[% results.size %] results</strong>.
+
+[% IF too_many_hits %]
+<p id="psearchtoomanyhits">Note: Your search was too wide so we will only display only the first about 100 matches.
+Please consider using a longer keyword or more keywords.</p>
+[% END %]
+
+<table>
+       <colgroup>
+       <col>
+       <col>
+       </colgroup>
+<tr>
+       <th><a title="Sort results by filename" href="[% make_search_url('',"keywords=$keyword_esc&amp;sort_by=file") %]">File</a></th>
+       <th><a title="Sort results by package name" href="[% make_search_url('',"keywords=$keyword_esc&amp;sort_by=pkg") %]">Packages</th>
+</tr>
+[% FOREACH results %]
+[% file = html_encode(file);
+   FOREACH k IN search_keywords;
+   k_enc = html_encode(k);
+   k_quo = quotemeta(k);
+   file = file.replace(k_quo, "<span class=\"keyword\">$k_enc</span>");
+   END %]
+<tr>
+       <td class="file">[% file %]</td>
+        <td>
+        [% FOREACH packages %]
+       [% arch_str = architectures.join(', ');
+          SET arch_str = "not $arch_str" IF ( arch_str && architectures_are_rev );
+          SET arch_str = " [$arch_str]" IF arch_str;
+           pkg_esc = uri_escape(pkg)  %]
+       <a href="[% make_url(pkg_esc,'','suite',suite,'arch','') %]">[% pkg | html %]</a>[% arch_str %][% ', ' UNLESS loop.last %]
+       [% END %]
+        </td>
+</tr>
+[% END %]
+
+[% IF results.size > 20 %]
+<tr><th>File</th><th>Packages</th></tr>
+[% END %]
+</table>
+</div>
+
+[% ELSE %]
+
+<p id="psearchnoresult">Sorry, your search gave no results</p>
+
+[% END %]
diff --git a/templates/html/show.tmpl b/templates/html/show.tmpl
new file mode 100644 (file)
index 0000000..4a51464
--- /dev/null
@@ -0,0 +1,246 @@
+[% PROCESS 'config/archive_layout.tmpl' %]
+[%- PROCESS 'html/head.tmpl'
+   title_tag = ( is_source ? "Details of source package $pkg in $suite"
+                          : "Details of package $pkg in $suite" )
+   description = desc
+   keywords = "$suite, $archive, $section, $subsection, $version"
+   print_search_field = 'packages'
+   search_field_values = { 
+                         keywords => '',
+                         searchon => is_source ? 'sourcenames' : 'names',
+                         arch => 'any',
+                         suite => 'all',
+                         section => 'all',
+                         exact => 0
+                         }
+  navigation = [ { prefix=>'Distribution:', title=>'Overview over this suite', url=>make_url('/'), name=>suite },
+                { prefix=>'Section:', title=>'All packages in this section', url=>make_url("$subsection/"), name=>subsection },
+                { prefix=>'Package:', name=>pkg } ]
+-%]
+<!-- show.tmpl -->
+[% PROCESS 'html/menu.inc' %]
+[% FOREACH s IN suites %]
+   [% '<div id="pothers">' IF loop.first %]
+   [%- IF s == suite -%]
+     [% PROCESS menuitem name=s url='' %]
+   [%- ELSE -%]
+     [% PROCESS menuitem name=s url=make_url(pkg,'','suite',s) %]
+   [%- END -%]
+   [%- '</div>' IF loop.last -%]
+[% END %]
+</div>
+
+[% IF src %]
+<div id="psource">
+[% PROCESS menuitem prefix='Source:' title='Source package building this package' url=make_url(src.pkg,'','source','source') name=src.pkg %]
+</div>
+[% END %]
+
+[%- PROCESS 'html/messages.tmpl' -%]
+
+[% IF is_virtual %]
+<h1>Virtual Package: [% pkg %]
+[% ELSIF is_source %]
+<h1>Source Package: [% pkg %] ([% version %])
+[% ELSE %]
+<h1>Package: [% pkg %] ([% versions.short %])
+[% END %]
+[%- PROCESS marker text=archive IF archive && archive != main_archive %]
+[%- PROCESS marker text=subsection IF subsection == 'non-US' and archive != 'non-US' %]
+[%- PROCESS marker text=section IF section && section != main_section %]</h1>
+
+[% IF suite == "experimental" || subsection == "debian-installer" %]
+<div class="pconstantnag">
+[% IF suite == "experimental" %]
+<h2>Experimental package</h2>
+<p>Warning: This package is from the <strong>experimental</strong> distribution.
+That means it is likely unstable or buggy, and it may even cause data loss.
+Please be sure to consult the changelog and other possible documentation before
+using it.</p>
+[% END %]
+[% IF subsection == "debian-installer" %]
+<h2>debian-installer udeb package</h2>
+<p>Warning: This package is intended for the use in building
+<a href="http://www.debian.org/devel/debian-installer">debian-installer</a> images only.
+Do not install it on a normal Debian system.</p>
+[% END %]
+</div>
+[% END %]
+
+[% UNLESS is_virtual %]
+<div id="pdesc">
+<h2>[% desc.short %]</h2>
+<p>[% desc.long %]
+</div> <!-- end pdesc -->
+[% END %]
+
+[% FOREACH tag IN tags %]
+  [% IF loop.first -%]
+    <div id="ptags"><p>
+    <a href="[% tags_url %]edit.html?pkg=[% pkg | uri %]">Tags</a>:
+  [%- END %]
+  [% tag %][% ', ' UNLESS loop.last %]
+  [% IF loop.last -%]
+    </p>
+    </div> <!-- end ptags -->
+  [%- END %]
+[% END %]
+
+[% FOREACH providers %]
+  [% IF loop.first %]<div id="pdeps"><h2>Packages providing [% pkg %]</h2><dl>[% END %]
+    <dt>[% IF available %]<a href="[% make_url(name,'','source','') %]">[% name %]</a>[% ELSE %][% name %][% END %]</dt>
+    <dd>[% desc %]</dd>
+  [% '</dl></div>' IF loop.last %]
+[% END %]
+
+[% FOREACH binaries %]
+  [% IF loop.first %]<div class="pdesc">The following binary packages are built from this source package:<dl>[% END %]
+    <dt>[% IF available %]<a href="[% make_url(name,'','source','') %]">[% name %]</a>[% ELSE %][% name %][% END %]</dt>
+    <dd>[% desc %]</dd>    
+  [% '</dl></div>' IF loop.last %]
+[% END %]
+
+[% FOREACH relations %]
+  [% IF loop.first -%]
+    <div id="pdeps">
+    <h2>Other Packages Related to [% pkg %]</h2>
+
+    <table id="pdeplegend" summary="legend"><tr>
+    [% IF is_source %]
+    <td><img src="/Pics/adep.gif" alt="[adep]" width="16" height="16">= build-depends</td>
+    <td><img src="/Pics/idep.gif" alt="[idep]" width="16" height="16">= build-depends-indep</td>
+    [% ELSE %]
+    <td><img src="/Pics/dep.gif" alt="[dep]" width="16" height="16">= depends</td>
+    <td><img src="/Pics/rec.gif" alt="[rec]" width="16" height="16">= recommends</td>
+    <td><img src="/Pics/sug.gif" alt="[sug]" width="16" height="16">= suggests</td>
+    [% END %]
+    </tr></table>
+  [%- END %]
+
+  <ul class="ul[% id %]">
+  [% FOREACH terms %]
+    [% '<li>' UNLESS is_old_pkgs %]
+    [% FOREACH alternatives %]
+      [% '<dl>' IF loop.first %]
+      <dt>[% IF loop.first %]<img class="hidecss" src="/Pics/[% id %].gif" alt="[[% id %]]">[% ELSE %]or [% END %]
+       [% IF suite %]<a href="[% make_url(name,'','suite',suite,'source','') %]">[% name %]</a>[% ELSE %][% name %][% END %]
+       [% ' (' _ version _ ')' IF version %]
+        [% ' [' _ arch_str _ ']' IF arch_str %]</dt>
+      [%- IF !is_old_pkgs -%]
+        <dd>[% desc -%]
+        [%- IF providers.size > 0 -%]
+          [% '<br>also a ' IF providers.also %]virtual package provided by
+          [%- IF providers.pkgs.size < 11 -%]
+           [% FOREACH provider IN providers.pkgs %]<a href="[% make_url(provider,'','suite',suite,'source','') %]">[% provider %]</a>[% ', ' UNLESS loop.last %][% END %]
+          [%- ELSE -%]
+            <a href="[% make_url(name,'','suite',suite,'source','') %]">[% providers.pkgs.size %] packages</a>
+          [% END %]
+        [% END %]
+        </dd>
+      [% END %]
+      [% '</dl>' IF loop.last %]
+    [% END %]
+  [% END %]
+  </ul>
+
+  [% IF loop.last -%]
+    </div> <!-- end pdeps -->
+  [%- END %]
+[% END %]
+
+[% FOREACH downloads %]
+  [% IF loop.first -%]
+    <div id="pdownload">
+    <h2>Download [% pkg %]</h2>
+    
+    <table summary="The download table links to the download of the package and a file overview. In addition it gives information about the package size and the installed size.">
+    <caption class="hidecss">Download for all available architectures</caption>
+    <tr><th>Architecture</th>[% '<th>Version</th>' IF versions.multiple %]<th>Package Size</th><th>Installed Size</th><th>Files</th></tr>
+  [%- END %]
+
+<tr>
+[% download_url = pkg _ '/' _ arch _ '/download'
+   filelist_url = pkg _ '/' _ arch _ '/filelist' %]
+<th><a href="[% make_url(download_url) | uri %]">[% arch %]</a></th>
+[% '<td>' _ version _ '</td>' IF versions.multiple %]
+<td class="size">[% pkgsize %]&nbsp;kB</td><td class="size">[% instsize %]&nbsp;kB</td>
+<td>
+[% IF contents_avail %]
+  [<a href="[% make_url(filelist_url) | uri %]">list of files</a>]
+[% ELSE %]
+  no current information
+[% END %]
+</td>
+</tr>
+
+  [% IF loop.last -%]
+    </table>
+
+    </div> <!-- end pdownload -->
+  [%- END %]
+[% END %]
+
+[% FOREACH srcfiles %]
+  [% IF loop.first -%]
+    <div id="pdownload">
+    <h2>Download [% pkg %]</h2>
+    
+    <table summary="Download information for the files of this source package">
+    <tr><th>File</th><th>Size (in kB)</th><th>md5sum</th></tr>
+  [%- END %]
+
+<tr>
+<td><a href="[% server _ path %]">[% filename %]</a></td>
+<td>[% size %]</td>
+<td class="md5sum">[% md5sum %]</td>
+</tr>
+
+  [% IF loop.last -%]
+    </table>
+
+    </div> <!-- end pdownload -->
+  [%- END %]
+[% END %]
+
+
+[% UNLESS is_virtual %]
+<div id="pmoreinfo">
+<h2>More Information on [% pkg %]</h2><p>
+Check for <a href="[% (is_source ? src_bugs_url : bugs_url) _ pkg | uri %]">Bug Reports</a> about [% pkg %].<br>
+[% IF src %]
+  Source Package: <a href="[% src.url %]">[% src.pkg %]</a>, Download:
+  [% FOREACH src.downloads %]
+  <a href="[% server _ path %]">[[% name %]]</a>
+  [% END %]
+  [% IF src.downloads.size == 0 %]
+  Not found
+  [% END %]
+[% END %]
+
+[% IF files %]
+<br>View the <a href="[% changelogs_url _ files.changelog.path %]">Debian changelog</a><br>
+View the <a href="[% changelogs_url _ files.copyright.path %]">copyright file</a></p>
+[% END %]
+<p>
+[% IF maintainers.size == 1 -%]
+  [%- FOREACH maintainers -%]
+    <a href="mailto:[% mail %]">[% name | html %]</a> is responsible for this Debian package.
+  [%- END -%]
+[%- ELSE -%]
+  [%- FOREACH maintainers -%]
+    [%- IF loop.first -%]
+<a href="mailto:[% mail %]">[% name | html %]</a>
+    [%- ELSIF loop.last -%]
+ and <a href="mailto:[% mail %]">[% name | html %]</a> are responsible for this Debian package.
+    [%- ELSE -%]
+, <a href="mailto:[% mail %]">[% name | html %]</a>
+    [%- END -%]
+  [%- END -%]
+[%- END %]
+[% IF src -%]
+See the <a href="[% pts_url _ src.pkg | uri %]">developer information for [% pkg %]</a>.
+[%- END %]
+</p>
+<p>Search for <a href="[% (is_source ? src_search_url : search_url) _ pkg | uri %]">other versions of [% pkg %]</a></p>
+</div> <!-- end pmoreinfo -->
+[% END %]
diff --git a/templates/html/suite_index.tmpl b/templates/html/suite_index.tmpl
new file mode 100644 (file)
index 0000000..ed4f901
--- /dev/null
@@ -0,0 +1,28 @@
+[% PROCESS 'html/head.tmpl' 
+       title_tag = "List of sections in \"$suite\""
+       page_title = "List of sections in \"$suite\""
+       keywords = suite
+       navigation = [ { name=> suite },
+                      { name => 'Index' }, ]
+%]
+
+[% FOREACH subsections %]
+  [% '<div id="lefthalfcol"><dl>' IF loop.first %]
+  
+  <dt><a href="[% id %]/">[% name %]</a></dt>
+  <dd>[% desc %]</dd>
+
+  [%- loop_half = loop.size / 2 -%]
+  [%- IF ( loop.count <= loop_half ) && ( loop.count >= ( loop_half - 1 ) ) -%]
+  </dl>
+  </div> <!-- end lefthalfcol -->
+  <div id="righthalfcol">
+  <dl>
+  [%- END -%]
+  [% '</dl></div>' IF loop.last %]
+[% END %]
+
+<p class="psmallcenter">
+       <a href="allpackages" title="List of all packages">All packages</a><br>
+       (<a href="allpackages?format=txt.gz">compact compressed textlist</a>)
+</p>
diff --git a/templates/txt/index.tmpl b/templates/txt/index.tmpl
new file mode 100644 (file)
index 0000000..ab8c473
--- /dev/null
@@ -0,0 +1,20 @@
+[%- PROCESS 'config/archive_layout.tmpl' -%]
+All Debian Packages in "[% suite %]"
+
+Last Modified: [% timestamp.string %]
+Copyright (C) [% copyright.years %] [% copyright.name %];
+See <URL:[% license.url %]> for the license terms.
+
+[% FOREACH packages -%]
+  [%- BLOCK marker %] [[% text %][% END -%]
+  [%- BLOCK markers -%]
+    [%- PROCESS marker text=section IF section != main_section -%]
+    [%- PROCESS marker text=archive IF archive != main_archive -%]
+  [%- END -%]
+  [%- IF providers %]
+[% name %] virtual package provided by [% providers.join(', ') %]
+  [%- END -%]
+  [%- IF versions %]
+[% name %] ([% versions %])[% PROCESS markers %] [% desc %]
+  [%- END -%]
+[%- END %]