package YadProxy; # Выдаёт листинг каталогов в стиле nginx и редиректы для файлов use 5.018; use strict; use warnings; use utf8; use open qw (:std :utf8); use English qw ( -no_match_vars ); use CHI; use CHI::Driver::BerkeleyDB; use File::Basename qw (basename dirname); use List::SomeUtils qw (any); use YadProxy::Conf qw (LoadConf); use version; our $VERSION = qw (1.0); use Exporter qw (import); our @EXPORT_OK = qw (DirList); my $c = LoadConf (); my $index_dir = $c->{index_dir}; my $url_prefix = $c->{url_prefix}; sub DirList { my $requested_path = shift; if ((! defined $requested_path) || $requested_path eq '') { $requested_path = '/'; } else { while (substr ($requested_path, -1) eq '/') { chop $requested_path; } if ((! defined $requested_path) || $requested_path eq '') { $requested_path = '/'; } } my @output; my @found; my $status = '200'; my $content_type = 'text/plain'; my $index_url = CHI->new ( driver => 'BerkeleyDB', root_dir => $index_dir, namespace => 'url' ); # прежде чем строить индекс, проверим-ка мы запрос на вшивость, вдруг, с нас запрашивают файл? # в этом случае нам надо отдать 302 if (my $url = $index_url->get ($requested_path)) { return ('302', 'text/plain', $url); } my $index_size = CHI->new ( driver => 'BerkeleyDB', root_dir => $index_dir, namespace => 'size' ); my $index_md5 = CHI->new ( driver => 'BerkeleyDB', root_dir => $index_dir, namespace => 'md5' ); my $index_sha256 = CHI->new ( driver => 'BerkeleyDB', root_dir => $index_dir, namespace => 'sha256' ); my $index_dirs = CHI->new ( driver => 'BerkeleyDB', root_dir => $index_dir, namespace => 'dirs' ); my $index_mtime = CHI->new ( driver => 'BerkeleyDB', root_dir => $index_dir, namespace => 'mtime' ); my $index_of; if ($requested_path eq '/') { $index_of = $url_prefix; } else { $index_of = $url_prefix . '/' . $requested_path; } if (substr ($url_prefix, 0, 1) ne '/') { $index_of = '/' . $index_of; } push @output, ''; push @output, sprintf '
../', $index_of;
# попробуем отловить все каталоги, начинающиеся с запрошенного пути
foreach my $key (sort ($index_dirs->get_keys ())) {
if (
(
(defined $key) &&
(length ($key) > length ($requested_path)) &&
(substr ($key, 0, length ($requested_path)) eq $requested_path)
) ||
$requested_path eq '/'
) {
my @dirs;
if ($requested_path eq '/') {
@dirs = split /\//, $key;
} else {
@dirs = split /\//, substr ($key, 1 + length ($requested_path));
}
if (defined $dirs[0] && (! any {$_ eq $dirs[0]} @found)) {
# у каталогов нету ctime или mtime, так что поставим 01-Jan-1970 00:00
push @found, $dirs[0];
my $str = $dirs[0];
my $len = 50 - (1 + length ($str));
if ($len < 0) {
$str = substr ($str, 0, 47);
$str .= '...';
$len = 0;
}
# there is no way to get dir mtime from yandex.disk
push @output, sprintf (
"%s/% ${len}s 01-Jan-1970 00:00 -",
$dirs[0],
$str,
''
);
}
}
}
# попробуем отловить все файлы, начинающиеся с запрошенного пути
foreach my $key (sort ($index_url->get_keys())) {
if (
(
(defined $key) &&
(length ($key) > length ($requested_path)) &&
(substr ($key, 0, length ($requested_path)) eq $requested_path)
) ||
$requested_path eq '/'
) {
my $str;
my @urls;
if ($requested_path eq '/') {
@urls = split /\//, $key;
} else {
@urls = split /\//, substr ($key, 1 + length ($requested_path));
}
if (defined $urls[0] && (! any {$_ eq $urls[0]} @found)) {
push @found, $urls[0];
$str = $urls[0];
}
if ($#urls < 1) {
my $len = 50 - length ($str);
if ($len < 0) {
$str = substr ($str, 0, 47);
$str .= '...';
$len = 0;
}
push @output, sprintf (
"%s% ${len}s %s % 19s",
$index_url->get ($key),
$str,
'',
$index_mtime->get ($key),
$index_size->get ($key)
);
}
}
}
push @output, '