|
|
|
package LDV::Zerobin;
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
use utf8;
|
|
|
|
|
|
|
|
use POSIX qw(strftime);
|
|
|
|
use Mojo::Base 'Mojolicious::Controller';
|
|
|
|
use Mojo::JSON;
|
|
|
|
use Mojo::Asset::File;
|
|
|
|
use Mojo::Util qw(b64_encode b64_decode decode encode);
|
|
|
|
|
|
|
|
sub _paste_path {
|
|
|
|
my ($self, $time) = @_;
|
|
|
|
my $root ||= $self->app->config->{zerobin}->{root};
|
|
|
|
|
|
|
|
return $self->app->home->rel_file("$root/$time.json");
|
|
|
|
}
|
|
|
|
|
|
|
|
sub create
|
|
|
|
{
|
|
|
|
my ($self) = @_;
|
|
|
|
|
|
|
|
my @syntax = ('auto');
|
|
|
|
my $langs = $self->app->config->{zerobin}->{syntax};
|
|
|
|
push @syntax, {'-------' => $langs}
|
|
|
|
if (ref($langs) eq 'ARRAY');
|
|
|
|
|
|
|
|
$self->stash({syntax => \@syntax});
|
|
|
|
$self->render();
|
|
|
|
}
|
|
|
|
|
|
|
|
sub view
|
|
|
|
{
|
|
|
|
my ($self) = @_;
|
|
|
|
my $time = $self->stash('time');
|
|
|
|
|
|
|
|
eval {
|
|
|
|
die("paste not found\n") unless ($time);
|
|
|
|
my $path = $self->_paste_path($time);
|
|
|
|
die("paste not found\n") unless (-f $path);
|
|
|
|
my $asset = Mojo::Asset::File->new(path => $path);
|
|
|
|
my $json = Mojo::JSON->new->decode($asset->slurp());
|
|
|
|
$json->{data} = decode('UTF-8', b64_decode($json->{data}));
|
|
|
|
if (time() > $json->{expire}) {
|
|
|
|
unlink($path);
|
|
|
|
die("paste expired\n");
|
|
|
|
}
|
|
|
|
$self->stash({paste => $json});
|
|
|
|
} or do {
|
|
|
|
chomp $@;
|
|
|
|
$self->app->log->error($@);
|
|
|
|
$@ = "internal error" if ($@ =~ m|at \S+ line \d+|oi);
|
|
|
|
$self->flash({'result' => $@});
|
|
|
|
$self->redirect_to("/zerobin2");
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
$self->render();
|
|
|
|
}
|
|
|
|
|
|
|
|
sub save
|
|
|
|
{
|
|
|
|
my ($self) = @_;
|
|
|
|
|
|
|
|
eval {
|
|
|
|
my $expire = $self->req->param('expire') || 30; # 1 month
|
|
|
|
my $syntax = $self->req->param('syntax') || '';
|
|
|
|
my $paste = $self->req->param('paste') || '';
|
|
|
|
die("empty paste\n") unless $paste;
|
|
|
|
$expire = 30 unless ($expire =~ m|^\d+$|o);
|
|
|
|
$syntax = 'auto' unless ($syntax =~ m|^[a-z0-9]+$|oi);
|
|
|
|
|
|
|
|
my $time = time();
|
|
|
|
my $json = {
|
|
|
|
expire => $time + ($expire * 86400),
|
|
|
|
syntax => $syntax,
|
|
|
|
data => b64_encode(encode('UTF-8', $paste)),
|
|
|
|
};
|
|
|
|
my $asset = Mojo::Asset::File->new;
|
|
|
|
$asset->add_chunk(Mojo::JSON->new->encode($json));
|
|
|
|
$asset->move_to($self->_paste_path($time));
|
|
|
|
$self->redirect_to("/zerobin2/$time"); 1;
|
|
|
|
} or do {
|
|
|
|
chomp $@;
|
|
|
|
$self->app->log->error($@);
|
|
|
|
$@ = "internal error" if ($@ =~ m|at \S+ line \d+|oi);
|
|
|
|
$self->flash({'result' => $@});
|
|
|
|
$self->redirect_to("/zerobin2");
|
|
|
|
};
|
|
|
|
|
|
|
|
$self->rendered();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub prune
|
|
|
|
{
|
|
|
|
my ($self) = @_;
|
|
|
|
|
|
|
|
eval {
|
|
|
|
my $time = time();
|
|
|
|
my $storage = $self->app->config->{zerobin}->{root};
|
|
|
|
my $files = $self->app->home->list_files($storage);
|
|
|
|
my $json = Mojo::JSON->new;
|
|
|
|
foreach my $file (@$files) {
|
|
|
|
next unless $file =~ m/^(\d+)\.json$/oi;
|
|
|
|
my $paste_time = $1;
|
|
|
|
my $path = "$storage/$file";
|
|
|
|
my $data = $json->decode($self->app->home->slurp_rel_file("$storage/$file"));
|
|
|
|
next if ($data->{expire} > $time); # not yet
|
|
|
|
my $date = strftime("%Y-%m-%d %H:%M", localtime($data->{expire}));
|
|
|
|
$self->app->log->info("Removing expired paste: $file ($date)");
|
|
|
|
unlink $self->_paste_path($paste_time);
|
|
|
|
} 1;
|
|
|
|
} or do {
|
|
|
|
chomp $@;
|
|
|
|
$self->app->log->error($@);
|
|
|
|
$@ = "internal error" if ($@ =~ m|at \S+ line \d+|oi);
|
|
|
|
$self->stash({'result' => $@});
|
|
|
|
};
|
|
|
|
|
|
|
|
$self->redirect_to("/zerobin2");
|
|
|
|
$self->rendered();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|