|
|
|
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 $hidden = $self->req->param('hidden') || 0;
|
|
|
|
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,
|
|
|
|
hidden => $hidden,
|
|
|
|
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}, hidden => 0}, {-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;
|