You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
4.8 KiB
180 lines
4.8 KiB
package LDV::Filebin; |
|
|
|
use strict; |
|
use warnings; |
|
use utf8; |
|
|
|
use Mojo::Base 'Mojolicious::Controller'; |
|
use Mojo::Asset::File; |
|
|
|
use File::MimeInfo::Magic qw(mimetype); |
|
use Imager; |
|
|
|
sub _file_path { |
|
my ($self, $fname, $fext, $full) = @_; |
|
|
|
my $path = sprintf "/files/%s.%s", $fname, $fext; |
|
return $full ? $self->app->home->rel_file("public/$path") : $path; |
|
} |
|
|
|
sub create { |
|
my ($self) = @_; |
|
|
|
$self->access_allowed($self->app->config->{filebin}->{access}) |
|
or return; |
|
|
|
$self->render; |
|
} |
|
|
|
sub view { |
|
my ($self) = @_; |
|
my $time = $self->stash('time') || 0; |
|
|
|
eval { |
|
my $now = time(); |
|
my $file = $self->app->db->select('filebin', '*', {created => $time, expire => {'>=' => $now}})->hash |
|
or die "file not found\n"; |
|
$file->{path} = $self->_file_path($time, $file->{fext}); |
|
|
|
$self->stash({file => $file}); 1; |
|
$self->render; 1; |
|
} or do { |
|
chomp $@; |
|
$self->flash({error => $@}); |
|
$self->app->log->error($@); |
|
$self->redirect_to('/filebin'); |
|
}; |
|
|
|
$self->rendered; |
|
} |
|
|
|
sub save { |
|
my ($self) = @_; |
|
|
|
$self->access_allowed($self->app->config->{filebin}->{access}) |
|
or return; |
|
|
|
eval { |
|
my $time = time(); |
|
my $conf = $self->app->config->{filebin}; |
|
|
|
die "request too large\n" |
|
if $self->req->is_limit_exceeded; |
|
|
|
my $expire = $self->req->param('expire') || 7; # days |
|
my $upload = $self->req->upload('file'); |
|
die "no file uploaded\n" unless ($upload and $upload->size > 0); |
|
die "file too large\n" if ($upload->size > $conf->{file_maxsize}); |
|
|
|
{ # hack: don't use memory backend |
|
my $path = POSIX::tmpnam; |
|
$upload->move_to($path); |
|
$upload->asset(Mojo::Asset::File->new(path => $path)); |
|
$upload->asset->cleanup(1); # rearm self-destruction |
|
} |
|
|
|
my $file = { |
|
created => $time, expire => $time + $expire * 86400, |
|
ftype => 'b', # default -- generic binary |
|
fsize => $upload->size, |
|
fname => $upload->filename, |
|
fmime => mimetype($upload->asset->path), |
|
fext => '', |
|
res_w => 0, |
|
res_h => 0, |
|
}; |
|
|
|
if ($file->{fname} =~ m<\.([a-z0-9]{1,5})$>oi) { |
|
$file->{fext} = lc($1); |
|
} |
|
if ($file->{fmime} =~ m{^image/}o) { |
|
my ($max_w, $max_h) = ($conf->{image_maxres} =~ m/(\d+)x(\d+)/oi); |
|
Imager->set_file_limits( |
|
width => $max_w, height => $max_h, |
|
bytes => $conf->{image_maxmem}, |
|
); |
|
# query image |
|
my $image = Imager->new(file => $upload->asset->path) |
|
or die(Imager->errstr() . "\n"); |
|
$file->{ftype} = 'i'; |
|
$file->{fext} = $image->tags(name => 'i_format'), |
|
$file->{res_w} = $image->getwidth, |
|
$file->{res_h} = $image->getheight, |
|
# make thumb |
|
my ($th_w, $th_h) = ($conf->{thumbs_size} =~ m/(\d+)x(\d+)/oi); |
|
my $thumb = $image->scale(xpixels => $th_w, ypixels => $th_h, type => 'min'); |
|
my $path = $self->_file_path("${time}_tn", $conf->{thumbs_ext}, 'fullpath'); |
|
$thumb->write(file => $path) |
|
or die $thumb->errstr; |
|
} elsif ($file->{fmime} =~ m{^video/}o) { |
|
$file->{ftype} = 'v'; |
|
} elsif ($file->{fmime} =~ m{^audio/}o) { |
|
$file->{ftype} = 'a'; |
|
} elsif ($file->{fmime} =~ m{^text/}o) { |
|
$file->{ftype} = 't'; |
|
} |
|
|
|
$upload->move_to($self->_file_path($time, $file->{fext}, 'fullpath')); |
|
$self->app->db->insert('filebin', $file); |
|
|
|
$self->redirect_to("/filebin/$time"); |
|
} or do { |
|
chomp $@; |
|
$self->app->log->error($@); |
|
$@ =~ s/\s+ at \s+ .+ \s+ line \s+ \d+//oxi; |
|
$self->flash({error => $@}); |
|
$self->redirect_to('/filebin'); |
|
}; |
|
|
|
$self->rendered; |
|
} |
|
|
|
sub latest { |
|
my ($self) = @_; |
|
|
|
eval { |
|
my $now = time(); |
|
my @files = $self->app->db->select('filebin', '*', {expire => {'>=' => $now}}, {-desc => 'created'})->hashes; |
|
splice(@files, 15); # first 15 elements |
|
foreach my $file (@files) { |
|
$file->{thumb} = $self->_file_path($file->{created}, $file->{fext}); |
|
$file->{url} = sprintf '/filebin/%d', $file->{created}; |
|
} |
|
$self->stash(files => \@files); |
|
$self->render; |
|
} or do { |
|
chomp $@; |
|
$self->flash({error => $@}); |
|
$self->app->log->error($@); |
|
$self->redirect_to('/filebin'); |
|
}; |
|
} |
|
|
|
sub prune { |
|
my ($self) = @_; |
|
|
|
$self->access_allowed($self->app->config->{filebin}->{access}) |
|
or return; |
|
|
|
eval { |
|
my $now = time(); |
|
my $conf = $self->app->config->{filebin}; |
|
my @files = $self->app->db->select('filebin', '*', {expire => {'<=' => $now}})->hashes; |
|
foreach my $file (@files) { |
|
unlink $self->_file_path($file->{created}, $file->{fext}, 1); |
|
if ($file->{ftype} eq 'i') { |
|
unlink $self->_file_path("$file->{created}_tn", $conf->{thumbs_ext}, 1); |
|
} |
|
$self->app->db->delete('filebin', {id => $file->{id}}); |
|
} 1; |
|
} or do { |
|
chomp $@; |
|
$self->flash({error => $@}); |
|
$self->app->log->error($@); |
|
}; |
|
|
|
$self->redirect_to('/filebin'); |
|
$self->rendered; |
|
} |
|
|
|
1;
|
|
|