#!/usr/bin/perl -w # # mirror_list.pl -- generate various Debian mirror lists # Copyright (C) 1998 James Treacy # Copyright (C) 2000-2002, 2007-2008 Josip Rodin # Copyright (C) 2005 Joey Hess # Copyright (C) 2016 Peter Palfrader use strict; use English; use HTML::Entities; binmode(STDOUT => ':utf8'); require 5.001; my @filter_arches=qw(); # Architectures not to list. my $officialsiteregex = q{^ftp\d?(?:\.wa)?\...\.debian\.org$}; my $internalsiteregex = q{^((ftp|security)-master|ftp)\.debian\.org$}; my $encode = '<>&"\''; use Getopt::Long; my ($mirror_source, $output_type, $help); my %opthash = ( "mirror|m=s" => \$mirror_source, "type|t=s" => \$output_type, "help|h!" => \$help, ); Getopt::Long::config('no_getopt_compat', 'no_auto_abbrev'); GetOptions(%opthash) or die "error parsing options"; $output_type = 'html' if (! defined $output_type); $mirror_source = 'Mirrors.masterlist' if (! defined $mirror_source); my $last_modify = gmtime((stat($mirror_source))[9]); my (@mirror, %countries, %countries_sorted, %countries_sponsors, %longest); my ($count, $cdimagecount); my (%code_of_country, %plain_name_of_country); my %includedsites; my $globalsite; sub process_line { my ($lno, $line) = @_; my $field = ''; if ($line =~ /^Site:\s*(.+)\s*$/i) { my $site = $1; $globalsite = $site; $count++; unless ($site =~ /$internalsiteregex/) { if (!defined($longest{site}) || length($site)+1 > $longest{site}) { $longest{site} = length($site)+1; # warn "increasing longest site to " . length($site) . " because of " . $site . "\n"; } } $mirror[$count-1]{site} = $site; $mirror[$count-1]{_lno} = $lno; return; } elsif ($line =~ /^Alias(?:es)?:\s*(.+)\s*$/is) { push @{ $mirror[$count-1]{aliases} }, $_ foreach (split("\n", $1)); } elsif ($line =~ /^(\w+)-architecture:\s*(.+)\s*$/i && length $2) { my $key = "$1"."-architecture"; my @arches=split(' ', $2); foreach my $f (@filter_arches) { @arches=grep { ! /^$f$/ } @arches; } if (! @arches) { # Mirror only carries filtered architectures. $mirror[$count-1]{filtered}=1; } foreach my $f (@filter_arches) { @arches=grep { ! /^\!$f$/ } @arches; } if (@arches) { $mirror[$count-1]{$key}=\@arches; } } elsif ($line=~ /^((Archive|Security|CDimage|Jigdo|Old)-(\w*)):\s*(.*)\s*$/i) { my $type = lc $1; my $value = $4; $mirror[$count-1]{method}{$type} = $value; if (!defined($longest{$type}) || length($value)+1 > $longest{$type}) { $longest{$type} = length($value)+1; # warn "increasing longest $type to " . length($value) . " because of " . $value . " at " . $globalsite . "\n" if (defined($type) && $type =~ /archive-(f|ht)tp/); } } elsif ($line =~ /^Includes:\s*(.+)\s*$/i) { push @{ $mirror[$count-1]{includes} }, $_ foreach (split(" ", $1)); } elsif ($line =~ /^Sponsor:\s*(.+)\s*$/i) { push @{ $mirror[$count-1]{sponsor} }, $1; } elsif ($line =~ /^([\w-]+):\s*(.+)\s*$/s) { $field = lc $1; my $value = $2; # no need for all private data in the %mirror hash # XXX modified to include x-archive-architecture because # the nsupdate thingy needs it for included-in sites - another # possible solution would be to convert those particular ones to # e.g. -archive-architecture? if ($field !~ /^x-/ || $field =~ /^x-archive-architecture/) { $mirror[$count-1]{$field} = $value; } if ($field eq 'country') { if ($value =~ /^(\w\w) (.+)$/) { $code_of_country{$value} = $1; $plain_name_of_country{$value} = $2; } else { die "strangely formatted Country field value: $value"; } } } else { die "Error: incorrect line format\n\"$line\"\n"; } } sub aptlines { foreach my $country (sort keys %countries) { print "\n$country\n"; print "-" x length($country); # underline print "\n"; foreach my $id (@{ $countries{$country} }) { my $archcomm=""; if ($mirror[$id]{'Archive-architecture'}) { $archcomm=" # ".join(" ", sort @{$mirror[$id]{'Archive-architecture'}})."\n"; } if (defined $mirror[$id]{method}{'archive-http'}) { print "deb http://$mirror[$id]{site}$mirror[$id]{method}{'archive-http'} stable main contrib non-free$archcomm\n"; } print "\n"; } } } sub secondary_mirrors { # TODO make the text version not have such long lines. my $format = shift; die "must get format for secondary_mirrors()" unless $format; my $html = 1 if ($format eq 'html'); my $text = 1 if ($format eq 'text'); my $wml = 1 if ($format eq 'wml'); my $formatstring; if ($html || $text) { print "

" if $html; print "\n\n " if $text; print "Secondary mirrors of the Debian archive"; print "\n ---------------------------------------\n\n" if $text; print "

\n\n" if $html; if ($html) { print < Host name HTTP Architectures END } else { my $formatstring = "%-$longest{site}s %-$longest{'archive-http'}s%s\n"; printf $formatstring, "HOST NAME", "HTTP", "ARCHITECTURES"; printf $formatstring, "---------", "----", "-------------"; } } elsif ($wml) { print "\n"; } foreach my $country (sort keys %countries) { my $countryplain = $plain_name_of_country{$country}; my $countrycode = $code_of_country{$country}; my %our_mirrors; foreach my $id (@{ $countries{$country} }) { if (defined $mirror[$id]{method}{'archive-http'}) { $our_mirrors{$id} = 1; } } next unless (keys %our_mirrors); print "\n"; if ($html) { print "
\n"; print "$country\n"; } elsif ($text) { print "$country"; } print "\n"; if ($text) { print "-" x length($country); # underline print "\n"; } foreach my $id (@{ $countries_sorted{$country} }) { next unless defined $mirror[$id]{method}{'archive-http'}; my $aliaslist; if (exists $mirror[$id]{'aliases'}) { if (!exists $mirror[$id]{includes}) { # we want to display aliases in the main list for official mirrors # but for others, it's just clutter, so skip them if ($mirror[$id]{site} =~ /$officialsiteregex/) { my $truename = @{$mirror[$id]{'aliases'}}[0]; if ($truename =~ /^ftp.+\.debian\.org$/) { $truename = @{$mirror[$id]{'aliases'}}[1]; } $aliaslist .= " (" . $truename . ")"; } } } if (exists $mirror[$id]{includes}) { $aliaslist .= " ("; my @tmparray = @{$mirror[$id]{includes}}; my $notalldone = $#tmparray + 1; SUBSITE: foreach my $subsite (@{ $mirror[$id]{includes} }) { # this is basically a sanity check my $subsite_id; SUBSITEID: foreach my $mid (0 .. $#mirror) { if ($mirror[$mid]{site} eq $subsite) { $subsite_id = $mid; last SUBSITEID; } } die $subsite ." included in " . $mirror[$id]{site} . " does not exist\n" unless defined $subsite_id; # must be an error # this prints the canonical name of the included site rather than its reference - should be in sync, but might actually vary $aliaslist .= $mirror[$subsite_id]{site}; $notalldone--; $aliaslist .= ", " if ($notalldone); } $aliaslist .= ")"; } if ($html) { print "\n"; print "$mirror[$id]{site}"; print "
$aliaslist" if ($aliaslist); print "\n"; } elsif ($text) { my $formatstring = "%-$longest{site}s "; printf $formatstring, $mirror[$id]{site}; } if (defined $mirror[$id]{method}{'archive-http'}) { my $rest = $longest{'archive-http'} - length($mirror[$id]{method}{'archive-http'}); if ($html) { print <$mirror[$id]{method}{'archive-http'} END } elsif ($text) { my $formatstring = "%s%${rest}s"; printf $formatstring, $mirror[$id]{method}{'archive-http'}, ''; } elsif ($wml) { print <"}{"$mirror[$id]{site}"} }, "$mirror[$id]{method}{'archive-http'}"; EOF } } else { if ($html) { print "\n"; } elsif ($text) { my $formatstring = "%-$longest{'archive-http'}s"; printf $formatstring, " "; } elsif ($wml) { print <"}{"$mirror[$id]{site}"} }, ""; EOF } } my $archlistsorted = join(" ", sort @{$mirror[$id]{'Archive-architecture'}}); if ($html) { print "$archlistsorted\n"; } elsif ($text) { print $archlistsorted; print "\n"; } elsif ($wml) { print <"}{"$mirror[$id]{site}"} }, "$archlistsorted"; EOF } if ($aliaslist) { if ($text) { print $aliaslist . "\n"; } elsif ($wml) { print <"}{"$mirror[$id]{site}"} }, "$aliaslist"; EOF } } if ($html) { print "\n"; } } } if ($wml) { # in our WML templates there is a langcmp comparison method, # which sorts alphabetically depending on the language print <
\$country EOM } \$sawcountry{\$country} = 1; sub officialfirst { (\$b =~ /^ftp\\d?(?:\\.wa)?\\...\\.debian\\.org\$/) <=> (\$a =~ /^ftp\\d?(?:\\.wa)?\\...\\.debian\\.org\$/) || \$a cmp \$b; } foreach my \$countrysite (sort officialfirst keys \%{\$secondaries{\$country}}) { my \@elems = \@{\$secondaries{\$country}{\$countrysite}}; print < \$countrysite EOM if (\$elems[3]) { my \$extraname = \$elems[3]; \$extraname =~ s% %\ \;\ \;%; print < \$extraname EOM } print < \$elems[0] \$elems[1] EOM } }
EOF } print "\n" if ($html); } sub intro { my $format = shift; die "must get format for intro()" unless $format; my $html = 1 if ($format eq 'html'); my $text = 1 if ($format eq 'text'); print "

" if $html; print " " if $text; print "Debian worldwide mirror sites"; print "

" if $html; print "\n -----------------------------\n" if $text; print "\n"; print "

" if $html; print "Debian is distributed ("; print $html ? "mirrored" : "mirrored"; print ") on hundreds of servers on the Internet.\n"; print <" if $html; print < A primary mirror site has good bandwidth, is available 24 hours a day, and has an easy to remember name of the form ftp.<country>.debian.org.
END } else { print <.debian.org. END } print <\n" if $html; if ($html) { print < A secondary mirror site may have restrictions on what they mirror (due to END } else { print <\n" if $html; print "

" if $html; print < netselect can be used to\n"; } else { print "a primary or secondary site. The program `netselect' can be used to\n"; } print < wget or rsync for determining the site with the most throughput.\n"; } else { print "`wget' or `rsync' for determining the site with the most throughput.\n"; } print <" if $html; print "The authoritative copy of the following list can always be found at:\n"; print "" if $html; print " https://www.debian.org/mirror/list"; print ".
" if $html; print "\n"; print <" if $html; print " https://www.debian.org/mirror/submit"; print ".
" if $html; print "\n"; print <" if $html; print " https://www.debian.org/mirror/"; print ".
" if $html; print "\n"; } sub primary_mirrors { my $format = shift; die "must get format for primary_mirrors()" unless $format; my $html = 1 if ($format eq 'html'); my $text = 1 if ($format eq 'text'); my $wml = 1 if ($format eq 'wml'); my %primaries = (); if ($html) { print <Primary Debian mirror sites END } elsif ($text) { print < END } foreach my $country (sort keys %countries) { foreach my $id (sort @{ $countries{$country} }) { next unless ($mirror[$id]{site} =~ /$officialsiteregex/); my $countryplain = $plain_name_of_country{$country}; my $countrycode = $code_of_country{$country}; unless (exists $mirror[$id]{method}{'archive-http'}) { warn "official mirror " . $mirror[$id]{site} . " does not have archive-http?!"; next; } my $arches = join(" ", sort @{$mirror[$id]{'Archive-architecture'}}); if ($html) { $countryplain =~ s/ / /; print < END } elsif ($text) { printf " %-14s %-20s %-14s %s\n", $countryplain, $mirror[$id]{site}, $mirror[$id]{method}{'archive-http'}, $arches; } elsif ($wml) { # this creates a hash of with keys like # later this gets expanded by WML into forms like # Germany or Deutschland # the next-level key is the site name, because countries # can have more than one site print <"}{"$mirror[$id]{site}"} }, ( "$mirror[$id]{method}{'archive-http'}", "$arches", ); EOF } } } if ($wml) { # in our WML templates there is a langcmp comparison method, # which sorts alphabetically depending on the language print < EOM } } EOF } print "
Country Site Architectures
$countryplain $mirror[$id]{site}$mirror[$id]{method}{'archive-http'} $arches
\$country \$countrysite\$elems[0] \$elems[1]
\n" if ($html); } # meant to be output into a file which is then included into a .wml file # and processed by WML sub primary_mirror_sponsors { print <


END foreach my $country (sort keys %countries) { foreach my $id (sort @{ $countries{$country} }) { next unless ($mirror[$id]{site} =~ /$officialsiteregex/); my $countrycode = $code_of_country{$country}; print < <${countrycode}c> $mirror[$id]{site} END if (exists $mirror[$id]{includes}) { my $numsubsites = @{ $mirror[$id]{includes} }; my $snum = 0; foreach my $subsite (@{ $mirror[$id]{includes} }) { # XXX Note this is a little bit wrong; if there is more than one id # for a subsite, it just takes the first one. This problem # could occur if a subsite begins mirroring some other arch, # like amd64. my $subsite_id; foreach my $mid (0..$#mirror) { if ($mirror[$mid]{site} eq $subsite) { $subsite_id=$mid; last; } } die "can't find $subsite, wtf?!" unless defined $subsite_id; # must be an error die "can't find sponsor for $subsite, wtf?!" unless defined $mirror[$subsite_id]{sponsor}; # must be an error my $numsponsors = @{ $mirror[$subsite_id]{sponsor} }; my $num = 0; my ($sponsorname, $sponsorurl); foreach my $sponsor (@{ $mirror[$subsite_id]{sponsor} }) { if ($sponsor =~ /^(.+) (https?:.*)$/) { $sponsorname = $1; $sponsorurl = $2; } else { warn "can't find sponsor URL for sponsor $sponsor of $subsite"; $sponsorname = $sponsor; } encode_entities($sponsorname, $encode); if ($sponsorurl) { print "$sponsorname"; } else { print "$sponsorname"; } $num++; print ", " unless ($num >= $numsponsors); } $snum++; print ", " unless ($snum >= $numsubsites); } } else { die "$mirror[$id]{site} has no sponsor\n" unless exists $mirror[$id]{sponsor}; # must be an error my $numsponsors = @{ $mirror[$id]{sponsor} }; my $num = 0; my ($sponsorname, $sponsorurl); foreach my $sponsor (@{ $mirror[$id]{sponsor} }) { if ($sponsor =~ /^(.+) (http:.*)$/) { $sponsorname = $1; $sponsorurl = $2; } else { warn "can't find sponsor URL for sponsor $sponsor of $mirror[$id]{site}"; $sponsorname = $sponsor; } encode_entities($sponsorname, $encode); if ($sponsorurl) { print "$sponsorname"; } else { print "$sponsorname"; } $num++; print ", " unless ($num >= $numsponsors); } } print < END } } print "\n"; } # meant to be output into a file which is then included into a .wml file # and processed by WML sub mirror_sponsors { print <
END foreach my $country (sort keys %countries) { next unless $countries_sponsors{$country}; foreach my $id (sort @{ $countries_sponsors{$country} }) { # sites which have Includes don't have to have Sponsor, the included ones # have it; and those are looped over separately anyway, so no need to repeat next if (exists $mirror[$id]{includes}); my $countrycode = $code_of_country{$country}; print < ${countrycode} <${countrycode}c> $mirror[$id]{site} END if (exists $mirror[$id]{'included-in'}) { print "
("; print join (", ", @{ $mirror[$id]{'included-in'} }); print ")"; } print < END my $numsponsors = @{ $mirror[$id]{sponsor} }; my $num = 0; my ($sponsorname, $sponsorurl); foreach my $sponsor (@{ $mirror[$id]{sponsor} }) { if ($sponsor =~ /^(.+) (https?:.*)$/) { $sponsorname = $1; $sponsorurl = $2; } else { warn "can't find sponsor URL for sponsor $sponsor of $mirror[$id]{site}"; $sponsorname = $sponsor; } encode_entities($sponsorname, $encode); if ($sponsorurl) { print "$sponsorname"; } else { print "$sponsorname"; } $num++; print ",\n" unless ($num >= $numsponsors); } print "\n"; print < END } } } # meant to be output into a file which is then included into a .wml file # and processed by WML sub cdimage_mirrors($) { my $which = shift; die unless $which; print "#use wml::debian::languages\n\n\nmy \@cdmirrors = (\n"; foreach my $country (keys %countries) { foreach my $id (sort @{ $countries{$country} }) { my $countrycode = $code_of_country{$country}; if ($which eq "httpftp") { if (defined $mirror[$id]{method}{'cdimage-ftp'} || defined $mirror[$id]{method}{'cdimage-http'}) { print " '<${countrycode}c>: $mirror[$id]{site}:"; if (defined $mirror[$id]{method}{'cdimage-ftp'}) { print qq( FTP); } if (defined $mirror[$id]{method}{'cdimage-http'}) { print qq( HTTP); } print "',\n"; } } elsif ($which eq "rsync") { if (defined $mirror[$id]{method}{'cdimage-rsync'}) { print qq( '<${countrycode}c>: $mirror[$id]{site}: rsync $mirror[$id]{site}\:\:$mirror[$id]{method}{'cdimage-rsync'}',\n); END } } } } print ");\n\n"; # Write some code to sort the list alphabetically (the ordering is # language-dependent) print <<'EOM'; print "
    \n"; foreach $line (sort langcmp @cdmirrors) { print "
  • $line
  • \n"; } print "
\n";
EOM } sub header { print < Debian worldwide mirror sites END } sub trailer { print "\n\n"; } # this is likely obsolete sub access_methods { print <Debian worldwide mirror sites

This is a complete list of mirrors of Debian. For each site, the different types of material available are listed, along with the access method for each type.

The following things are mirrored:

Packages
The Debian package pool.
CD Images
Official Debian CD Images. See https://www.debian.org/CD/ for details.
Old releases
The archive of old released versions of Debian.
Some of the old releases also included the so-called debian-non-US archive, with sections for Debian packages that could not be distributed in the US due to software patents or use of encryption. The debian-non-US updates were discontinued with Debian 3.1.

The following access methods are possible:

HTTP
Standard web access, but it can be used for downloading files.
FTP
The file transfer protocol.
rsync
An efficient means of mirroring.
NFS
Network file system (if you don't know what it is, you don't need it).

The 'Type' entry is one of:

leaf
These comprise the bulk of the mirrors.
Push-Secondary
These sites mirror directly from a Push-Primary site, using push mirroring.
Push-Primary
These sites mirror directly from the master archive site (which is not publicly accessible), using push mirroring.
(See the page about push mirroring for details on that.)

The authoritative copy of the following list can always be found at: https://www.debian.org/mirror/list-full.
Everything else you want to know about Debian mirrors: https://www.debian.org/mirror/.
END } sub full_listing { # TODO: fix the html mode to output actual normal HTML, rather than

  my $format = shift;
  die "must get format for full_listing()" unless $format;
  my $html = 1 if ($format eq 'html');
  my $text = 1 if ($format eq 'text');
  my $wml = 1 if ($format eq 'wml');

  if ($html) {
    print "\n
\n"; print "

Jump directly to a country on the list:
\n"; } if ($html) { my $linelength = 0; foreach my $country (sort keys %countries) { my $countryplain = $plain_name_of_country{$country}; my $countrycode = $code_of_country{$country}; print " ["; print $countryplain; print "]"; $linelength += length($countryplain) + 3; if ($linelength >= 75) { print "
\n"; $linelength = 0; } } } elsif ($wml) { # in our WML templates there is a langcmp comparison method, # which sorts alphabetically depending on the language print <"} = $countrycode; EOF } print <' . "\$country]"; \$linelength += length(\$country) + 3; if (\$linelength >= 75) { print "
\n"; \$linelength = 0; } } :> EOF } if ($html || $wml) { print "\n


\n"; } print "
\n" if $html;
  foreach my $country (sort keys %countries) {
    my $countryplain = $plain_name_of_country{$country};
    my $countrycode = $code_of_country{$country};
    print "\n";
    if ($html) {
      print "$country\n";
    } elsif ($text) {
      print "$country\n";
    } elsif ($wml) {
      print "

<${countrycode}c>

\n"; } if ($html || $text) { print "-" x length($country); # underline } elsif ($wml) { print "\n"; } print "\n"; foreach my $id (@{ $countries_sorted{$country} }) { next unless keys %{$mirror[$id]{'method'}}; print "Site: "; print "" if $wml; print $mirror[$id]{site}; if (exists $mirror[$id]{'aliases'}) { print ", ".join(", ", @{ $mirror[$id]{'aliases'} }); } print "" if $wml; print "
" if $wml; print "\n"; warn "undefined type for $mirror[$id]{site}!\n" unless defined $mirror[$id]{'type'}; $mirror[$id]{'type'} ||= 'leaf'; print "Type: $mirror[$id]{'type'}\n"; print "
" if $wml; foreach my $method ( sort keys %{ $mirror[$id]{method} } ) { my $display = $method; $display =~ s/archive-/Packages /; $display =~ s/security-/Security updates /; $display =~ s/cdimage-/CD Images /; $display =~ s/jigdo-/Jigdo files /; $display =~ s/old-/Old releases /; $display =~ s/ftp/over FTP/; $display =~ s/http/over HTTP/; $display =~ s/nfs/over NFS/; $display =~ s/rsync/over rsync/; if ($method =~ /http/) { print $display.": "; print "" if $wml; print "$mirror[$id]{method}{$method}\n"; print "" if $wml; } elsif ($method =~ /ftp/) { print $display.": "; print "" if $wml; print "$mirror[$id]{method}{$method}\n"; print "" if $wml; } else { print $display.": "; print "" if $wml; print $mirror[$id]{method}{$method}."\n"; print "" if $wml; } print "
" if $wml; } if (exists $mirror[$id]{'Archive-architecture'}) { print "Includes architectures: ".join(" ", sort @{$mirror[$id]{'Archive-architecture'}})."\n"; print "
" if $wml; } print "Update frequency: "; if ($mirror[$id]{'type'} =~ /push/i) { print "whenever there are updates (push-triggered)"; } elsif (exists $mirror[$id]{'updates'} and $mirror[$id]{'updates'} =~ /^(?:once|daily)(.*)$/) { print "once a day"; print " $1" if $1; } elsif (exists $mirror[$id]{'updates'} and $mirror[$id]{'updates'} =~ /^(?:twice)(.*)$/) { print "twice a day"; print " $1" if $1; } elsif (exists $mirror[$id]{'updates'} and $mirror[$id]{'updates'} =~ /^(?:four)(.*)$/) { print "four times a day"; print " $1" if $1; } elsif (exists $mirror[$id]{'updates'} and $mirror[$id]{'updates'} ne '') { print $mirror[$id]{'updates'}; } else { print "unknown"; } print "\n"; print "
" if $wml; if (exists $mirror[$id]{'comment'}) { print "Comment: "; print "" if $wml; print $mirror[$id]{comment}; print "" if $wml; print "\n"; print "
" if $wml; } print "
" if $wml; print "\n"; } } print "
\n" if $html; } sub compact_list($$) { my $whichtype = shift; die "must get type for compact_list()" unless $whichtype; my $ordering = shift; die "must get ordering for compact_list()" unless $ordering; sub printhtmlftprsync($$$$) { my ($site, $http, $ftp, $rsync) = @_; print "HTTP " if (defined $http); print "FTP " if (defined $ftp); print "rsync ". $site . "::" . $rsync if (defined $rsync); } if ($ordering eq 'countrysite') { foreach my $country (sort keys %countries) { my %our_mirrors; foreach my $id (@{ $countries{$country} }) { if ( defined($mirror[$id]{method}{$whichtype.'-ftp'}) or defined($mirror[$id]{method}{$whichtype.'-http'}) or defined($mirror[$id]{method}{$whichtype.'-rsync'}) ) { $our_mirrors{$id} = 1; } } next unless (keys %our_mirrors); my $countryplain = $plain_name_of_country{$country}; my $countrycode = $code_of_country{$country}; foreach my $id (@{ $countries_sorted{$country} }) { next unless (exists $our_mirrors{$id}); print "
  • <".$countrycode."c>: " . $mirror[$id]{site} . ": "; printhtmlftprsync($mirror[$id]{site}, $mirror[$id]{method}{$whichtype.'-http'}, $mirror[$id]{method}{$whichtype.'-ftp'}, $mirror[$id]{method}{$whichtype.'-rsync'}); print "
  • \n"; } } } elsif ($ordering eq 'sitecountry') { my %our_mirrors; foreach my $id (0..$#mirror) { if ( defined($mirror[$id]{method}{$whichtype.'-ftp'}) or defined($mirror[$id]{method}{$whichtype.'-http'}) or defined($mirror[$id]{method}{$whichtype.'-rsync'}) ) { $our_mirrors{ $mirror[$id]{site} } = $id; } } foreach my $site (sort keys %our_mirrors) { my $id = $our_mirrors{$site}; my $countryplain = $plain_name_of_country{ $mirror[$id]{country} }; my $countrycode = $code_of_country{ $mirror[$id]{country} }; print "
  • " . $mirror[$id]{site}; if ($countrycode ne ''){print " (<".$countrycode."c>)"} print ": "; printhtmlftprsync($mirror[$id]{site}, $mirror[$id]{method}{$whichtype.'-http'}, $mirror[$id]{method}{$whichtype.'-ftp'}, $mirror[$id]{method}{$whichtype.'-rsync'}); print "
  • \n"; } } } sub footer_stuff($$) { my $format = shift; die "must get format for footer_stuff()" unless $format; my $html = 1 if ($format eq 'html'); my $text = 1 if ($format eq 'text'); my $wml = 1 if ($format eq 'wml'); my $whichcount = shift; die "must get count for footer_stuff()" unless $whichcount; if ($html || $wml) { print <
    Last modified: $last_modify Number of sites listed: $whichcount
    END } elsif ($text) { print "\n"; print "-" x 79 . "\n"; # expecting $last_modify like: Mon Jan 1 00:00:00 0000 - 24 characters wide # expecting $whichcount to be less than 1k :) printf "%-14s %-24s %-11s %-23s %-3d\n", 'Last modified:', $last_modify, '', 'Number of sites listed:', $whichcount; } } # fork of secondary_mirrors sub generate_html_matrix { my $archive_name = $_[0]; my $archive_name_lc = lc($archive_name); print "

    Mirrors of the Debian-".$archive_name_lc." archive

    \n"; print "\n"; print "\n\n"; print "\n\n"; foreach my $country (sort keys %countries) { my %our_mirrors; foreach my $id (@{ $countries{$country} }) { if (defined $mirror[$id]{method}{"$archive_name_lc-ftp"} || defined $mirror[$id]{method}{"$archive_name_lc-http"} || defined $mirror[$id]{method}{"$archive_name_lc-rsync"}) { $our_mirrors{$id} = 1; } } next unless (keys %our_mirrors); print "\n"; foreach my $id (@{ $countries_sorted{$country} }) { next unless (exists $our_mirrors{$id}); print ""; print "\n"; print "\n"; print "\n"; print "\n\n"; } } print "\n
    HOST NAMEFTPHTTPRSYNCARCHITECTURES
    $country
    $mirror[$id]{site}"; if (defined $mirror[$id]{method}{"$archive_name_lc-ftp"}) { print ""; print $mirror[$id]{method}{"$archive_name_lc-ftp"}; print "\n"; } print ""; if (defined $mirror[$id]{method}{"$archive_name_lc-http"}) { print ""; print $mirror[$id]{method}{"$archive_name_lc-http"}; print "\n"; } print ""; if (defined $mirror[$id]{method}{"$archive_name_lc-rsync"}) { print ""; print $mirror[$id]{method}{"$archive_name_lc-rsync"}; print "\n"; } print ""; if (exists $mirror[$id]{"$archive_name"}) { print join(" ", sort @{$mirror[$id]{$archive_name}}); } else { print " all"; } print "
    \n"; } ######### Begin main routine ########################### if (defined $help) { print_help(); exit; } open SRC, "<:utf8", $mirror_source or die "Error: problem opening mirror source file, $mirror_source\n" ."Use the -m option?\n"; my $current = ''; while () { chomp; if (/^$/ && $current eq '') { next; } elsif (/^$/) { process_line($INPUT_LINE_NUMBER, $current); $current = ''; next; } elsif (/^\s+(.*)$/) { # add line to current entry $current .= "\n$1"; } elsif (/^[\w-]+:\s/) { if ($current ne "") { # need to process previous line process_line($INPUT_LINE_NUMBER, $current); } $current = $_; } else { die "Error: unknown format on line $INPUT_LINE_NUMBER:\n$_\n"; } } if ($current ne "") { process_line($INPUT_LINE_NUMBER, $current); } # Remove filtered mirrors. my @filtered; foreach my $id (0..$#mirror) { if ($mirror[$id]{filtered}) { push @filtered, $id; } } foreach my $id (reverse @filtered) { # reverse order so indexes are valid splice(@mirror, $id, 1); } # count the number of mirrors # the masterlist parser's $count included the filtered sites $count = @mirror; # Create arrays of countries, with their mirrors. foreach my $id (0..$#mirror) { if (exists $mirror[$id]{country}) { push @{ $countries{ $mirror[$id]{country} } }, $id; if (exists $mirror[$id]{sponsor} && keys %{$mirror[$id]{method}}) { push @{ $countries_sponsors{ $mirror[$id]{country} } }, $id; } } elsif ($mirror[$id]{type} =~/^(GeoDNS|RoundRobinDNS)$/i) { # TODO these are not currently displayed anywhere } else { warn "found a mirror without a country, wtf? " . $mirror[$id]{site} .", defined at line ". $mirror[$id]{_lno}; } # we'll also use this opportunity to help create a references # between sites which are connected with Includes: if (exists $mirror[$id]{includes}) { foreach my $includedsite (@{ $mirror[$id]{includes} }) { $includedsites{$includedsite} = $mirror[$id]{site}; } } } # Sort the country info arrays to first list the official sites, # then the unofficial sites, but exclude special Debian sites foreach my $country (sort keys %countries) { my %countries_sorted_o; my %countries_sorted_u; foreach my $id (@{ $countries{$country} }) { if ($mirror[$id]{site} =~ /$officialsiteregex/) { push @{ $countries_sorted_o{$country} }, $id; } elsif ($mirror[$id]{site} !~ /$internalsiteregex/) { push @{ $countries_sorted_u{$country} }, $id; } # using the opportunity to add the Included-in: back-reference if (exists $includedsites{ $mirror[$id]{site} }) { push @{ $mirror[$id]{'included-in'} }, $includedsites{ $mirror[$id]{site} }; } } # merge the reordered lists into %countries_sorted # (there's got to be a cleaner way to do this, but hey) foreach my $id (@{ $countries_sorted_o{$country} }) { push @{ $countries_sorted{$country} }, $id; } undef %countries_sorted_o; foreach my $id (@{ $countries_sorted_u{$country} }) { push @{ $countries_sorted{$country} }, $id; } undef %countries_sorted_u; } if ($output_type eq 'html') { header(); intro('html'); primary_mirrors('html'); secondary_mirrors('html'); footer_stuff('html', $count); trailer(); } elsif ($output_type eq 'text') { intro('text'); primary_mirrors('text'); secondary_mirrors('text'); footer_stuff('text', $count); } elsif ($output_type eq 'wml-primary') { primary_mirrors('wml'); } elsif ($output_type eq 'wml-secondary') { secondary_mirrors('wml'); } elsif ($output_type eq 'wml-footer') { footer_stuff('wml', $count); } elsif ($output_type eq 'apt') { header(); print "
    \n";
      aptlines();
      print "
    \n"; trailer(); } elsif ($output_type eq 'fullmethods') { # this is likely obsolete header(); access_methods(); full_listing('html'); footer_stuff('html', $count); trailer(); } elsif ($output_type eq 'wml-full') { full_listing('wml'); footer_stuff('wml', $count); } elsif ($output_type eq 'compact-old') { compact_list('old', 'sitecountry'); } elsif ($output_type eq 'officialsponsors') { primary_mirror_sponsors(); } elsif ($output_type eq 'sponsors') { mirror_sponsors(); } elsif ($output_type eq 'cdimages-httpftp') { cdimage_mirrors("httpftp"); } elsif ($output_type eq 'cdimages-rsync') { cdimage_mirrors("rsync"); } else { die "Error: unknown output type requested, $output_type\n"; } sub print_help { print <