3 # download.pl -- CGI interface for downloading files on packages.debian.org
5 # Copyright (C) 1998 (?) James Treacy
6 # Copyright (C) 2001 Josip Rodin
7 # Copyright (C) 2004 Frank Lichtenheld
9 # Licensed under the GPL or something.
21 use Packages::HTML ();
22 use Packages::Search qw( :all );
23 use Packages::Config qw( $HOME $DBDIR @SUITES @ARCHIVES @SECTIONS @ARCHITECTURES );
27 &Packages::CGI::reset;
29 &Packages::Config::init( '../' );
30 &Packages::DB::init();
32 # TODO: find a way to get the U.S. mirror list from a more authoritive
33 # location automatically. might not be overly smart to automatize it
34 # completely, since I hand pick sites that are up-to-date, fast, and
35 # have HTTP on a reasonably short URL
39 # grep-dctrl -F Site,Alias -e '(udel|bigfoot|kernel|crosslink|internap|cerias|lcs.mit|progeny)' Mirrors.masterlist | timestamps/archive_mirror_check.py
40 my @north_american_sites = (
41 "ftp.us.debian.org/debian",
42 "http.us.debian.org/debian",
43 "ftp.debian.org/debian",
44 # "ftp.ca.debian.org/debian",
45 "ftp.egr.msu.edu/debian",
46 "mirrors.kernel.org/debian",
47 "archive.progeny.com/debian",
48 "debian.crosslink.net/debian",
49 "ftp-mirror.internap.com/pub/debian",
50 "ftp.cerias.purdue.edu/pub/os/debian",
51 "ftp.lug.udel.edu/debian",
52 "debian.lcs.mit.edu/debian",
53 "debian.teleglobe.net",
55 "debian.oregonstate.edu/debian",
57 my @european_sites = (
58 "ftp.de.debian.org/debian",
59 "ftp.at.debian.org/debian",
60 "ftp.bg.debian.org/debian",
61 "ftp.cz.debian.org/debian",
62 "ftp.dk.debian.org/debian",
63 "ftp.ee.debian.org/debian",
64 "ftp.fi.debian.org/debian",
65 "ftp.fr.debian.org/debian",
66 "ftp.hr.debian.org/debian",
67 "ftp.hu.debian.org/debian",
68 "ftp.ie.debian.org/debian",
69 "ftp.is.debian.org/debian",
70 "ftp.it.debian.org/debian",
71 "ftp.nl.debian.org/debian",
72 "ftp.no.debian.org/debian",
73 "ftp.pl.debian.org/debian",
74 "ftp.si.debian.org/debian",
75 "ftp.es.debian.org/debian",
76 "ftp.se.debian.org/debian",
77 "ftp.tr.debian.org/debian",
78 "ftp.uk.debian.org/debian",
80 my @south_american_sites = (
81 "ftp.br.debian.org/debian",
82 "ftp.cl.debian.org/debian",
84 my @australian_sites = (
85 "ftp.au.debian.org/debian",
86 "ftp.wa.au.debian.org/debian",
87 "ftp.nz.debian.org/debian",
90 "ftp.jp.debian.org/debian",
91 # "ftp.kr.debian.org/debian",
92 "linux.csie.nctu.edu.tw/debian",
93 "debian.linux.org.tw/debian",
94 "linux.cdpa.nsysu.edu.tw/debian",
97 my @volatile_european_sites = (
98 "volatile.debian.net/debian-volatile",
99 "ftp2.de.debian.org/debian-volatile",
100 "ftp.sk.debian.org/debian-volatile",
102 my @backports_european_sites = (
103 "www.backports.org/debian",
104 "debian.sil.at/backports.org/",
105 "backports.debian.or.at/backports.org",
106 "mirror.realroute.net/backports.org",
107 "backports.cisbg.com",
108 "backports.linuxdediziert.de/backports.org",
109 "debian.netcologne.de/debian-backports",
110 "ftp.de.debian.org/backports.org",
111 "mirror.buildd.net/backports.org",
112 "ftp.estpak.ee/backports.org",
113 "debian.acantho.net/backports.org",
114 "backports.essentkabel.com/backports.org",
118 my @backports_asian_sites = (
119 "backports.mithril-linux.org",
121 my @backports_australian_sites = (
122 "mirror.linux.org.au/backports.org",
124 my @amd64_european_sites = (
125 "amd64.debian.net/debian",
126 "ftp.de.debian.org/debian-amd64/debian",
127 "bach.hpc2n.umu.se/debian-amd64/debian",
128 "bytekeeper.as28747.net/debian-amd64/debian",
129 "mirror.switch.ch/debian-amd64/debian",
130 "ftp.nl.debian.org/debian-amd64/debian",
132 my @amd64_asian_sites = (
133 "hanzubon.jp/debian-amd64/debian",
135 my @amd64_north_american_sites = (
136 "mirror.espri.arizona.edu/debian-amd64/debian",
138 my @kfreebsd_north_american_sites = (
139 "www.gtlib.gatech.edu/pub/gnuab/debian",
141 my @kfreebsd_european_sites = (
142 # master site, aka ftp.gnuab.org
143 "kfreebsd-gnu.debian.net/debian",
144 "ftp.easynet.be/ftp/gnuab/debian",
145 "ftp.de.debian.org/debian-kfreebsd",
147 my @nonus_north_american_sites = (
148 # "ftp.ca.debian.org/debian-non-US",
149 "debian.yorku.ca/debian/non-US",
150 "mirror.direct.ca/linux/debian-non-US",
152 my @nonus_european_sites = (
153 "non-us.debian.org/debian-non-US",
154 "ftp.de.debian.org/debian-non-US",
155 "ftp.at.debian.org/debian-non-US",
156 "ftp.bg.debian.org/debian-non-US",
157 "ftp.cz.debian.org/debian-non-US",
158 "ftp.fi.debian.org/debian-non-US",
159 "ftp.fr.debian.org/debian-non-US",
160 "ftp.hr.debian.org/debian-non-US",
161 "ftp.hu.debian.org/debian-non-US",
162 "ftp.ie.debian.org/debian-non-US",
163 "ftp.is.debian.org/debian-non-US",
164 "ftp.it.debian.org/debian-non-US",
165 "ftp.nl.debian.org/debian-non-US",
166 "ftp.no.debian.org/debian-non-US",
167 "ftp.pl.debian.org/debian/non-US",
168 "ftp.si.debian.org/debian-non-US",
169 "ftp.es.debian.org/debian-non-US",
170 "ftp.se.debian.org/debian-non-US",
171 "ftp.tr.debian.org/debian-non-US",
172 "ftp.uk.debian.org/debian/non-US",
174 my @nonus_australian_sites = (
175 "ftp.au.debian.org/debian-non-US",
176 "ftp.wa.au.debian.org/debian-non-US",
177 "ftp.nz.debian.org/debian-non-US",
179 my @nonus_asian_sites = (
180 "ftp.jp.debian.org/debian-non-US",
181 # "ftp.kr.debian.org/debian-non-US",
182 "linux.csie.nctu.edu.tw/debian-non-US",
183 "debian.linux.org.tw/debian-non-US",
184 "linux.cdpa.nsysu.edu.tw/debian-non-US",
186 my @nonus_south_american_sites = (
187 "ftp.br.debian.org/debian-non-US",
188 "ftp.cl.debian.org/debian-non-US",
191 # list of architectures
194 m68k => 'Motorola 680x0',
197 powerpc => 'PowerPC',
199 hppa => 'HP PA-RISC',
200 ia64 => 'Intel IA-64',
202 mipsel => 'MIPS (DEC)',
204 "hurd-i386" => 'Hurd (i386)',
206 "kfreebsd-i386" => 'GNU/kFreeBSD (i386)'
209 $ENV{PATH} = "/bin:/usr/bin";
210 # Read in all the variables set by the form
212 if ($ARGV[0] && ($ARGV[0] eq 'php')) {
213 $input = new CGI(\*STDIN);
218 my $pet0 = new Benchmark;
219 my $tet0 = new Benchmark;
220 # use this to disable debugging in production mode completly
221 my $debug_allowed = 1;
222 my $debug = $debug_allowed && $input->param("debug");
223 $debug = 0 if !defined($debug) || $debug !~ /^\d+$/o;
224 $Packages::CGI::debug = $debug;
226 if (my $path = $input->param('path')) {
227 my @components = map { lc $_ } split /\//, $path;
229 my %SUITES = map { $_ => 1 } @SUITES;
230 my %ARCHIVES = map { $_ => 1 } @ARCHIVES;
231 my %ARCHITECTURES = map { $_ => 1 } @ARCHITECTURES;
233 foreach (@components) {
235 $input->param('suite', $_);
236 } elsif ($ARCHIVES{$_}) {
237 $input->param('archive', $_);
238 } elsif ($ARCHITECTURES{$_}) {
239 $input->param('arch', $_);
240 } elsif ($_ eq 'source') {
241 $input->param('source', 1);
246 my ( $pkg, $suite, @sections, $arch, @archives, $format );
247 my %params_def = ( package => { default => undef, match => '^([a-z0-9.+-]+)$',
249 suite => { default => undef, match => '^(\w+)$',
251 archive => { default => 'all', match => '^(\w+)$',
252 array => ', ', var => \@archives,
253 replace => { all => [qw(us security non-US)] } },
254 arch => { default => undef, match => '^(\w+)$',
256 format => { default => 'html', match => '^(\w+)$',
260 my %params = Packages::Search::parse_params( $input, \%params_def, \%opts );
262 #XXX: Don't use alternative output formats yet
264 if ($format eq 'html') {
265 print $input->header( -charset => 'utf-8' );
268 if ($params{errors}{package}) {
269 fatal_error( "package not valid or not specified" );
272 if ($params{errors}{suite}) {
273 fatal_error( "suite not valid or not specified" );
276 if ($params{errors}{arch}) {
277 fatal_error( "arch not valid or not specified" );
281 $opts{h_suites} = { $suite => 1 };
282 $opts{h_archs} = { $arch => 1 };
283 $opts{h_sections} = { map { $_ => 1 } @SECTIONS };
284 $opts{h_archives} = { map { $_ => 1 } @archives };
288 my ($final_result, $file, $filen, $md5sum, @file_components, $archive) = ("")x5;
290 sub gettext { return $_[0]; };
292 my $st0 = new Benchmark;
293 unless (@Packages::CGI::fatal_errors) {
294 tie %packages_all, 'DB_File', "$DBDIR/packages_all_$suite.db",
295 O_RDONLY, 0666, $DB_BTREE
296 or die "couldn't tie DB $DBDIR/packages_all_$suite.db: $!";
298 read_entry( \%packages, $pkg, \@results, \%opts );
301 fatal_error( "No such package".
302 "{insert link to search page with substring search}" );
305 my $final_result = shift @results;
307 if (version_cmp( $_->[7], $final_result->[7] ) > 0) {
312 $archive = $final_result->[1];
313 my %data = split /\000/, $packages_all{"$pkg $arch $final_result->[7]"};
314 $file = $data{filename};
315 @file_components = split('/', $file);
316 $filen = pop(@file_components);
318 $md5sum = $data{md5sum};
322 my $arch_string = $arch ne 'all' ? "on $arches{$arch} machines" : "";
324 print Packages::HTML::header( title => "Package Download Selection",
326 print_title_above => 1 );
335 print "<h2>Download Page for <kbd>$filen</kbd> $arch_string</h2>\n".
336 "<p>You can download the requested file from the <tt>";
337 print join( '/', @file_components).'/';
338 print "</tt> subdirectory at";
339 print $archive ne 'security' ? " any of these sites:" : ":";
342 if ($archive eq 'security') {
346 <li><a href="http://security.debian.org/debian-security/$file">security.debian.org/debian-security</a></li>
349 <p>Debian security updates are currently officially distributed only via
350 security.debian.org.</p>
353 } elsif ($arch eq 'amd64') {
355 print_links( "North America", $file, @amd64_north_american_sites );
356 print_links( "Europe", $file, @amd64_european_sites );
357 # print_links( "Australia and New Zealand", $file,
358 # @nonus_australian_sites );
359 print_links( "Asia", $file, @amd64_asian_sites );
360 # print_links( "South America", $file, @nonus_south_american_sites );
363 <p>Note that AMD64 is not officialy included in the Debian archive
364 yet, but the AMD64 porter group keeps their archive in sync with
365 the official archive as close as possible. See the
366 <a href="http://www.debian.org/ports/amd64/">AMD64 ports page</a> for
367 current information.</p>
370 } elsif ($arch eq 'kfreebsd-i386') {
372 print_links( "North America", $file, @kfreebsd_north_american_sites );
373 print_links( "Europe", $file, @kfreebsd_european_sites );
374 # print_links( "Australia and New Zealand", $file,
375 # @nonus_australian_sites );
376 # print_links( "Asia", $file, @amd64_asian_sites );
377 # print_links( "South America", $file, @nonus_south_american_sites );
380 <p>Note that GNU/kFreeBSD is not officialy included in the Debian archive
381 yet, but the GNU/kFreeBSD porter group keeps their archive in sync with
382 the official archive as close as possible. See the
383 <a href="http://www.debian.org/ports/kfreebsd-gnu/">GNU/kFreeBSD ports page</a> for
384 current information.</p>
387 } elsif ($archive eq 'non-US') {
389 print_links( "North America", $file, @nonus_north_american_sites );
390 print_links( "Europe", $file, @nonus_european_sites );
391 print_links( "Australia and New Zealand", $file,
392 @nonus_australian_sites );
393 print_links( "Asia", $file, @nonus_asian_sites );
394 print_links( "South America", $file, @nonus_south_american_sites );
397 <p>If none of the above sites are fast enough for you, please see our
398 <a href="http://www.debian.org/mirror/list-non-US">complete mirror list</a>.</p>
401 } elsif ($archive eq 'backports') {
403 # print_links( "North America", $file, @nonus_north_american_sites );
404 print '<div class="cardleft">';
405 print_links( "Europe", $file, @backports_european_sites );
406 print '</div><div class="cardright">';
407 print_links( "Australia and New Zealand", $file,
408 @backports_australian_sites );
409 print_links( "Asia", $file, @backports_asian_sites );
410 # print_links( "South America", $file, @nonus_south_american_sites );
414 <p style="clear:both">If none of the above sites are fast enough for you, please see our
415 <a href="http://www.backports.org/debian/README.mirrors.html">complete mirror list</a>.</p>
418 } elsif ($archive eq 'volatile') {
420 # print_links( "North America", $file, @nonus_north_american_sites );
421 print_links( "Europe", $file, @volatile_european_sites );
422 # print_links( "Australia and New Zealand", $file,
423 # @nonus_australian_sites );
424 # print_links( "Asia", $file, @nonus_asian_sites );
425 # print_links( "South America", $file, @nonus_south_american_sites );
428 <p>If none of the above sites are fast enough for you, please see our
429 <a href="http://volatile.debian.net/mirrors.html">complete mirror list</a>.</p>
432 } elsif ($archive eq 'us') {
434 print '<div class="cardleft">';
435 print_links( "North America", $file, @north_american_sites );
436 print '</div><div class="cardright">';
437 print_links( "Europe", $file, @european_sites );
438 print '</div><div class="cardleft">';
439 print_links( "Australia and New Zealand", $file, @australian_sites );
440 print '</div><div class="cardright">';
441 print_links( "Asia", $file, @asian_sites );
442 print '</div><div class="cardleft">';
443 print_links( "South America", $file, @south_american_sites );
447 <p style="clear:both">If none of the above sites are fast enough for you, please see our
448 <a href="http://www.debian.org/mirror/list">complete mirror list</a>.</p>
454 <p>Note that in some browsers you will need to tell your browser you want
455 the file saved to a file. For example, in Netscape or Mozilla, you should
456 hold the Shift key when you click on the URL.</p>
459 print "<p>The MD5sum for <tt>$filen</tt> is <strong>$md5sum</strong></p>\n"
463 my $trailer = Packages::HTML::trailer( ".." );
464 $trailer =~ s/LAST_MODIFIED_DATE/gmtime()/e;
470 my ( $title, $file, @servers ) = @_;
472 print "<p><em>$title</em></p>";
475 print "<li><a href=\"http://$_/$file\">$_</a></li>\n";
476 # print "<li><a href=\"ftp://$_/$file\">$_</a></li>\n";