From d73b713c08ea5d6f542776da07af0e7c6f451b42 Mon Sep 17 00:00:00 2001 From: Alex 'AdUser' Z Date: Thu, 24 Dec 2015 23:43:26 +1000 Subject: [PATCH] * LDV::Zerobin : separate content from metadata --- conf/ldv.conf.sample | 1 - lib/LDV/Zerobin.pm | 117 +++++++++++++++++++++++++++++-------------- 2 files changed, 79 insertions(+), 39 deletions(-) diff --git a/conf/ldv.conf.sample b/conf/ldv.conf.sample index a47f927..aaf16d2 100644 --- a/conf/ldv.conf.sample +++ b/conf/ldv.conf.sample @@ -39,7 +39,6 @@ }, zerobin => { - root => 'data/zerobin', syntax => ['bash', 'c', 'css', 'html', 'perl', 'php', 'python', 'other'], maxsize => 10 * 1024 * 1024, }, diff --git a/lib/LDV/Zerobin.pm b/lib/LDV/Zerobin.pm index 25b5dc4..4adc386 100644 --- a/lib/LDV/Zerobin.pm +++ b/lib/LDV/Zerobin.pm @@ -10,11 +10,63 @@ use Mojo::Base 'Mojolicious::Controller'; use Mojo::Asset::File; use Mojo::Util qw(b64_encode b64_decode decode encode); -sub _paste_path { +sub _metadata_path { my ($self, $time) = @_; - my $root ||= $self->app->config->{zerobin}->{root}; - return $self->app->home->rel_file("$root/$time.json"); + return $self->app->home->rel_file("data/zerobin/$time.json"); +} + +sub _metadata_save { + my ($self, $time, $data) = @_; + + my $path = $self->_metadata_path($time); + my $asset = Mojo::Asset::File->new; + $asset->add_chunk(encode_json($data)); + $asset->move_to($path); + + return 1; +} + +sub _metadata_load { + my ($self, $time) = @_; + + my $path = $self->_metadata_path($time); + die("paste metadata not found\n") unless (-f $path); + my $asset = Mojo::Asset::File->new(path => $path); + $asset->cleanup(0); + + return decode_json($asset->slurp); +} + +sub _content_path { + my ($self, $time) = @_; + + return $self->app->home->rel_file("public/zerobin/$time.txt"); +} + +sub _content_save { + my ($self, $time, $content) = @_; + + unless (ref $content) { + my $asset = Mojo::Asset::File->new; + $asset->add_chunk($content); + $content = $asset; # wrap plaintext to Mojo::Asset + } + my $path = $self->_content_path($time); + $content->move_to($path); + + return 1; +} + +sub _content_load { + my ($self, $time) = @_; + + my $path = $self->_content_path($time); + die("paste content not found\n") unless (-f $path); + my $asset = Mojo::Asset::File->new(path => $path); + $asset->cleanup(0); + + return $asset->slurp; } sub create { @@ -26,7 +78,7 @@ sub create { if (ref($langs) eq 'ARRAY'); $self->stash({syntax => \@syntax}); - $self->render(); + $self->render; } sub view { @@ -34,17 +86,13 @@ sub view { 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 = decode_json($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}); + die("paste not found\n") unless $time; + my $paste = $self->_metadata_load($time); + $paste->{data} = $self->_content_load($time); + $paste->{time} = $time; + utf8::decode($paste->{data}); + $self->stash({paste => $paste}); + 1; } or do { chomp $@; $self->app->log->error($@); @@ -54,7 +102,7 @@ sub view { return; }; - $self->render(); + $self->render; } sub save { @@ -62,7 +110,7 @@ sub save { eval { my $source = $self->req->param('source') || '-'; - my $expire = $self->req->param('expire') || 30; # 1 month + my $expire = $self->req->param('expire') || 30; # 30 days or 1 month my $syntax = $self->req->param('syntax') || ''; my $paste; if ($source eq 'form') { @@ -83,7 +131,7 @@ sub save { my $mime = File::MimeInfo::Magic::mimetype($tmpfile); die("uploaded file not looks like text\n") unless $mime =~ m{^text/}; - $paste = $upload->asset->slurp; + $paste = $upload->asset; unlink $tmpfile; } else { die("unknown 'source'\n"); @@ -92,14 +140,11 @@ sub save { $syntax = 'auto' unless ($syntax =~ m|^[a-z0-9]+$|oi); my $time = time(); - my $json = { + $self->_metadata_save($time, { expire => $time + ($expire * 86400), syntax => $syntax, - data => b64_encode(encode('UTF-8', $paste)), - }; - my $asset = Mojo::Asset::File->new; - $asset->add_chunk(encode_json($json)); - $asset->move_to($self->_paste_path($time)); + }); + $self->_content_save($time, $paste); $self->redirect_to("/zerobin2/$time"); 1; } or do { chomp $@; @@ -109,38 +154,34 @@ sub save { $self->redirect_to("/zerobin2"); }; - $self->rendered(); - return 1; + $self->rendered; } sub prune { my ($self) = @_; eval { - my $time = time(); - my $storage = $self->app->config->{zerobin}->{root}; - my $files = $self->app->home->list_files($storage); - foreach my $file (@$files) { + my $currtime = time(); + my $files = $self->app->home->list_files("data/zerobin"); + foreach my $file (@{ $files }) { next unless $file =~ m/^(\d+)\.json$/oi; my $time = $1; - my $path = $self->app->home->rel_file("$storage/$file"); - my $asset = Mojo::Asset::File->new(path => $path); - my $data = decode_json($asset->slurp); - next if ($data->{expire} > $time); # not yet + my $data = $self->_metadata_load($time); + 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 $path; + unlink $self->_metadata_path($time); + unlink $self->_content_path($time); } 1; } or do { chomp $@; $self->app->log->error($@); $@ = "internal error" if ($@ =~ m|at \S+ line \d+|oi); - $self->stash({'result' => $@}); + $self->stash({result => $@}); }; $self->redirect_to("/zerobin2"); - $self->rendered(); - return 1; + $self->rendered; } 1;