diff --git a/CHANGELOG b/CHANGELOG
index 33413d9..8c34dab 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,12 @@
Revision history for Lutim
+0.10.0 2018-04-07
+ - PostgreSQL performance improvments
+ - Move some tasks to recurring instead of being in after_dispatch hook
+ - Built-in image cache system \o/
+ - Disable logs option
+ - Disable images' counter option
+
0.9.6 2018-03-12
- Update translations
diff --git a/cpanfile b/cpanfile
index 12b1cd9..b02cd39 100644
--- a/cpanfile
+++ b/cpanfile
@@ -27,3 +27,5 @@ requires 'Image::ExifTool';
requires 'Data::Entropy';
requires 'List::MoreUtils', '> 0.33';
requires 'Archive::Zip';
+requires 'CHI';
+requires 'Data::Serializer';
diff --git a/cpanfile.snapshot b/cpanfile.snapshot
index 52123ab..5fc2f20 100644
--- a/cpanfile.snapshot
+++ b/cpanfile.snapshot
@@ -44,12 +44,65 @@ DISTRIBUTIONS
perl 5.008001
strict 0
warnings 0
+ CHI-0.60
+ pathname: J/JS/JSWARTZ/CHI-0.60.tar.gz
+ provides:
+ CHI 0.60
+ CHI::CacheObject 0.60
+ CHI::Driver 0.60
+ CHI::Driver::Base::CacheContainer 0.60
+ CHI::Driver::CacheCache 0.60
+ CHI::Driver::FastMmap 0.60
+ CHI::Driver::File 0.60
+ CHI::Driver::Memory 0.60
+ CHI::Driver::Metacache 0.60
+ CHI::Driver::Null 0.60
+ CHI::Driver::RawMemory 0.60
+ CHI::Driver::Role::HasSubcaches 0.60
+ CHI::Driver::Role::IsSizeAware 0.60
+ CHI::Driver::Role::IsSubcache 0.60
+ CHI::Stats 0.60
+ requirements:
+ Carp::Assert 0.20
+ Class::Load 0
+ Data::UUID 0
+ Digest::JHash 0
+ Digest::MD5 0
+ ExtUtils::MakeMaker 0
+ File::Spec 0.80
+ Hash::MoreUtils 0
+ JSON::MaybeXS 1.003003
+ List::MoreUtils 0.13
+ Log::Any 0.08
+ Moo 1.003
+ MooX::Types::MooseLike 0.23
+ MooX::Types::MooseLike::Base 0
+ MooX::Types::MooseLike::Numeric 0
+ Storable 0
+ String::RewritePrefix 0
+ Task::Weaken 0
+ Time::Duration 1.06
+ Time::Duration::Parse 0.03
+ Time::HiRes 1.30
+ Try::Tiny 0.05
Canary-Stability-2012
pathname: M/ML/MLEHMANN/Canary-Stability-2012.tar.gz
provides:
Canary::Stability 2012
requirements:
ExtUtils::MakeMaker 0
+ Carp-Assert-0.21
+ pathname: N/NE/NEILB/Carp-Assert-0.21.tar.gz
+ provides:
+ Carp::Assert 0.21
+ requirements:
+ Carp 0
+ Exporter 0
+ ExtUtils::MakeMaker 0
+ perl 5.006
+ strict 0
+ vars 0
+ warnings 0
Class-Data-Inheritable-0.08
pathname: T/TM/TMTM/Class-Data-Inheritable-0.08.tar.gz
provides:
@@ -65,6 +118,25 @@ DISTRIBUTIONS
ExtUtils::MakeMaker 0
File::Spec 0.80
perl 5.006
+ Class-Load-0.24
+ pathname: E/ET/ETHER/Class-Load-0.24.tar.gz
+ provides:
+ Class::Load 0.24
+ Class::Load::PP 0.24
+ requirements:
+ Carp 0
+ Data::OptList 0
+ Exporter 0
+ ExtUtils::MakeMaker 0
+ Module::Implementation 0.04
+ Module::Runtime 0.012
+ Package::Stash 0.14
+ Scalar::Util 0
+ Try::Tiny 0
+ base 0
+ perl 5.006
+ strict 0
+ warnings 0
Class-Method-Modifiers-2.12
pathname: E/ET/ETHER/Class-Method-Modifiers-2.12.tar.gz
provides:
@@ -287,6 +359,55 @@ DISTRIBUTIONS
perl 5.006
strict 0
warnings 0
+ Data-OptList-0.110
+ pathname: R/RJ/RJBS/Data-OptList-0.110.tar.gz
+ provides:
+ Data::OptList 0.110
+ requirements:
+ ExtUtils::MakeMaker 0
+ List::Util 0
+ Params::Util 0
+ Sub::Install 0.921
+ strict 0
+ warnings 0
+ Data-Serializer-0.60
+ pathname: N/NE/NEELY/Data-Serializer-0.60.tar.gz
+ provides:
+ Data::Serializer 0.60
+ Data::Serializer::Bencode 0.03
+ Data::Serializer::Config::General 0.02
+ Data::Serializer::Convert::Bencode 0.03
+ Data::Serializer::Convert::Bencode_XS 0.03
+ Data::Serializer::Cookbook 0.05
+ Data::Serializer::Data::Denter 0.02
+ Data::Serializer::Data::Dumper 0.05
+ Data::Serializer::Data::Taxi 0.02
+ Data::Serializer::FreezeThaw 0.02
+ Data::Serializer::JSON 0.04
+ Data::Serializer::JSON::Syck 0.02
+ Data::Serializer::PHP::Serialization 0.02
+ Data::Serializer::Persistent 0.01
+ Data::Serializer::Raw 0.02
+ Data::Serializer::Storable 0.03
+ Data::Serializer::XML::Dumper 0.02
+ Data::Serializer::XML::Simple 0.03
+ Data::Serializer::YAML 0.02
+ Data::Serializer::YAML::Syck 0.02
+ requirements:
+ AutoLoader 0
+ Data::Dumper 2.08
+ Digest::SHA 0
+ Exporter 0
+ File::Spec 0
+ IO::File 0
+ Test::More 0
+ Data-UUID-1.221
+ pathname: R/RJ/RJBS/Data-UUID-1.221.tar.gz
+ provides:
+ Data::UUID 1.221
+ requirements:
+ Digest::MD5 0
+ ExtUtils::MakeMaker 0
Data-Validate-Domain-0.14
pathname: D/DR/DROLSKY/Data-Validate-Domain-0.14.tar.gz
provides:
@@ -797,6 +918,18 @@ DISTRIBUTIONS
perl 5.006
strict 0
warnings 0
+ Digest-JHash-0.10
+ pathname: S/SH/SHLOMIF/Digest-JHash-0.10.tar.gz
+ provides:
+ Digest::JHash 0.10
+ requirements:
+ DynaLoader 0
+ Exporter 0
+ ExtUtils::MakeMaker 0
+ perl 5.008
+ strict 0
+ vars 0
+ warnings 0
Dist-CheckConflicts-0.11
pathname: D/DO/DOY/Dist-CheckConflicts-0.11.tar.gz
provides:
@@ -846,6 +979,16 @@ DISTRIBUTIONS
perl 5.008001
strict 0
warnings 0
+ Exporter-Lite-0.08
+ pathname: N/NE/NEILB/Exporter-Lite-0.08.tar.gz
+ provides:
+ Exporter::Lite 0.08
+ requirements:
+ Carp 0
+ ExtUtils::MakeMaker 6.3
+ perl 5.006
+ strict 0
+ warnings 0
Exporter-Tiny-1.000000
pathname: T/TO/TOBYINK/Exporter-Tiny-1.000000.tar.gz
provides:
@@ -992,15 +1135,21 @@ DISTRIBUTIONS
perl 5.005
strict 0
warnings 0
- Hash-Merge-0.299
- pathname: H/HE/HERMES/Hash-Merge-0.299.tar.gz
+ Hash-Merge-0.300
+ pathname: R/RE/REHSACK/Hash-Merge-0.300.tar.gz
provides:
- Hash::Merge 0.299
+ Hash::Merge 0.300
requirements:
Clone::Choose 0.008
- ExtUtils::MakeMaker 0
+ ExtUtils::MakeMaker 6.64
Scalar::Util 0
perl 5.008001
+ Hash-MoreUtils-0.05
+ pathname: R/RE/REHSACK/Hash-MoreUtils-0.05.tar.gz
+ provides:
+ Hash::MoreUtils 0.05
+ requirements:
+ Test::More 0.90
IO-Socket-SSL-2.056
pathname: S/SU/SULLR/IO-Socket-SSL-2.056.tar.gz
provides:
@@ -1215,6 +1364,16 @@ DISTRIBUTIONS
requirements:
ExtUtils::MakeMaker 0
perl 5.004
+ JSON-MaybeXS-1.003010
+ pathname: H/HA/HAARG/JSON-MaybeXS-1.003010.tar.gz
+ provides:
+ JSON::MaybeXS 1.003010
+ requirements:
+ Carp 0
+ ExtUtils::MakeMaker 0
+ JSON::PP 2.27300
+ Scalar::Util 0
+ perl 5.006
List-MoreUtils-0.428
pathname: R/RE/REHSACK/List-MoreUtils-0.428.tar.gz
provides:
@@ -1266,6 +1425,40 @@ DISTRIBUTIONS
requirements:
ExtUtils::MakeMaker 6.30
Locale::Maketext 1.17
+ Log-Any-1.705
+ pathname: P/PR/PREACTION/Log-Any-1.705.tar.gz
+ provides:
+ Log::Any 1.705
+ Log::Any::Adapter 1.705
+ Log::Any::Adapter::Base 1.705
+ Log::Any::Adapter::File 1.705
+ Log::Any::Adapter::Null 1.705
+ Log::Any::Adapter::Stderr 1.705
+ Log::Any::Adapter::Stdout 1.705
+ Log::Any::Adapter::Syslog 1.705
+ Log::Any::Adapter::Test 1.705
+ Log::Any::Adapter::Util 1.705
+ Log::Any::Manager 1.705
+ Log::Any::Proxy 1.705
+ Log::Any::Proxy::Null 1.705
+ Log::Any::Proxy::Test 1.705
+ Log::Any::Test 1.705
+ requirements:
+ B 0
+ Carp 0
+ Data::Dumper 0
+ Exporter 0
+ ExtUtils::MakeMaker 0
+ Fcntl 0
+ File::Basename 0
+ FindBin 0
+ IO::File 0
+ Storable 0
+ Sys::Syslog 0
+ Test::Builder 0
+ constant 0
+ strict 0
+ warnings 0
MRO-Compat-0.13
pathname: H/HA/HAARG/MRO-Compat-0.13.tar.gz
provides:
@@ -1436,8 +1629,8 @@ DISTRIBUTIONS
URI::db 0.15
URI::file 4.21
perl 5.010001
- Mojolicious-7.70
- pathname: S/SR/SRI/Mojolicious-7.70.tar.gz
+ Mojolicious-7.71
+ pathname: S/SR/SRI/Mojolicious-7.71.tar.gz
provides:
Mojo undef
Mojo::Asset undef
@@ -1506,7 +1699,7 @@ DISTRIBUTIONS
Mojo::UserAgent::Transactor undef
Mojo::Util undef
Mojo::WebSocket undef
- Mojolicious 7.70
+ Mojolicious 7.71
Mojolicious::Command undef
Mojolicious::Command::cgi undef
Mojolicious::Command::cpanify undef
@@ -1619,6 +1812,24 @@ DISTRIBUTIONS
Sub::Defer 2.003001
Sub::Quote 2.003001
perl 5.006
+ MooX-Types-MooseLike-0.29
+ pathname: M/MA/MATEU/MooX-Types-MooseLike-0.29.tar.gz
+ provides:
+ MooX::Types::MooseLike 0.29
+ MooX::Types::MooseLike::Base 0.29
+ requirements:
+ ExtUtils::MakeMaker 0
+ Module::Runtime 0.014
+ MooX-Types-MooseLike-Numeric-1.03
+ pathname: M/MA/MATEU/MooX-Types-MooseLike-Numeric-1.03.tar.gz
+ provides:
+ MooX::Types::MooseLike::Numeric 1.03
+ requirements:
+ ExtUtils::MakeMaker 0
+ Moo 1.004002
+ MooX::Types::MooseLike 0.23
+ Test::Fatal 0.003
+ Test::More 0.96
Mozilla-CA-20180117
pathname: A/AB/ABH/Mozilla-CA-20180117.tar.gz
provides:
@@ -1635,10 +1846,10 @@ DISTRIBUTIONS
Carp 0
ExtUtils::MakeMaker 0
Storable 0
- Net-SSLeay-1.84
- pathname: M/MI/MIKEM/Net-SSLeay-1.84.tar.gz
+ Net-SSLeay-1.85
+ pathname: M/MI/MIKEM/Net-SSLeay-1.85.tar.gz
provides:
- Net::SSLeay 1.84
+ Net::SSLeay 1.85
Net::SSLeay::Handle 0.61
requirements:
ExtUtils::MakeMaker 6.36
@@ -1701,6 +1912,17 @@ DISTRIBUTIONS
perl 5.006001
strict 0
warnings 0
+ Params-Util-1.07
+ pathname: A/AD/ADAMK/Params-Util-1.07.tar.gz
+ provides:
+ Params::Util 1.07
+ requirements:
+ ExtUtils::CBuilder 0.27
+ ExtUtils::MakeMaker 6.52
+ File::Spec 0.80
+ Scalar::Util 1.18
+ Test::More 0.42
+ perl 5.00503
Params-ValidationCompiler-0.27
pathname: D/DR/DROLSKY/Params-ValidationCompiler-0.27.tar.gz
provides:
@@ -1824,6 +2046,29 @@ DISTRIBUTIONS
strict 0
version 0.83
warnings 0
+ String-RewritePrefix-0.007
+ pathname: R/RJ/RJBS/String-RewritePrefix-0.007.tar.gz
+ provides:
+ String::RewritePrefix 0.007
+ requirements:
+ Carp 0
+ ExtUtils::MakeMaker 6.30
+ Sub::Exporter 0.972
+ strict 0
+ warnings 0
+ Sub-Exporter-0.987
+ pathname: R/RJ/RJBS/Sub-Exporter-0.987.tar.gz
+ provides:
+ Sub::Exporter 0.987
+ Sub::Exporter::Util 0.987
+ requirements:
+ Carp 0
+ Data::OptList 0.100
+ ExtUtils::MakeMaker 6.30
+ Params::Util 0.14
+ Sub::Install 0.92
+ strict 0
+ warnings 0
Sub-Exporter-Progressive-0.001013
pathname: F/FR/FREW/Sub-Exporter-Progressive-0.001013.tar.gz
provides:
@@ -1837,6 +2082,17 @@ DISTRIBUTIONS
requirements:
ExtUtils::MakeMaker 0
Test::More 0
+ Sub-Install-0.928
+ pathname: R/RJ/RJBS/Sub-Install-0.928.tar.gz
+ provides:
+ Sub::Install 0.928
+ requirements:
+ B 0
+ Carp 0
+ ExtUtils::MakeMaker 6.30
+ Scalar::Util 0
+ strict 0
+ warnings 0
Sub-Quote-2.005000
pathname: H/HA/HAARG/Sub-Quote-2.005000.tar.gz
provides:
@@ -1867,6 +2123,17 @@ DISTRIBUTIONS
Text::Balanced 2
if 0
perl 5.005
+ Task-Weaken-1.05
+ pathname: E/ET/ETHER/Task-Weaken-1.05.tar.gz
+ provides:
+ Task::Weaken 1.05
+ requirements:
+ Config 0
+ ExtUtils::MakeMaker 0
+ File::Spec 0
+ Scalar::Util 1.14
+ perl 5.006
+ strict 0
Test-Fatal-0.014
pathname: R/RJ/RJBS/Test-Fatal-0.014.tar.gz
provides:
@@ -1898,6 +2165,28 @@ DISTRIBUTIONS
requirements:
ExtUtils::MakeMaker 0
perl 5.008
+ Time-Duration-1.20
+ pathname: N/NE/NEILB/Time-Duration-1.20.tar.gz
+ provides:
+ Time::Duration 1.20
+ requirements:
+ Exporter 0
+ ExtUtils::MakeMaker 0
+ constant 0
+ perl 5.006
+ strict 0
+ warnings 0
+ Time-Duration-Parse-0.13
+ pathname: N/NE/NEILB/Time-Duration-Parse-0.13.tar.gz
+ provides:
+ Time::Duration::Parse 0.13
+ requirements:
+ Carp 0
+ Exporter::Lite 0
+ ExtUtils::MakeMaker 0
+ perl 5.006
+ strict 0
+ warnings 0
Try-Tiny-0.30
pathname: E/ET/ETHER/Try-Tiny-0.30.tar.gz
provides:
diff --git a/lib/Lutim.pm b/lib/Lutim.pm
index ab58ba0..9d264fa 100644
--- a/lib/Lutim.pm
+++ b/lib/Lutim.pm
@@ -1,7 +1,9 @@
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
package Lutim;
use Mojo::Base 'Mojolicious';
+use Mojo::IOLoop;
use Lutim::DB::Image;
+use CHI;
use vars qw($im_loaded);
BEGIN {
@@ -51,9 +53,21 @@ sub startup {
dbtype => 'sqlite',
db_path => 'minion.db'
},
+ cache_max_size => 0,
+ quiet_logs => 0,
+ disable_img_stats => 0,
}
});
+ my $cache_max_size = ($config->{cache_max_size} > 0) ? 8 * 1024 * 1024 * $config->{cache_max_size} : 1;
+ $self->{images_cache} = CHI->new(
+ driver => 'Memory',
+ global => 1,
+ is_size_aware => 1,
+ max_size => $cache_max_size,
+ expires_in => '1 day'
+ );
+
die "You need to provide a contact information in lutim.conf !" unless (defined($config->{contact}));
$ENV{MOJO_MAX_MESSAGE_SIZE} = $config->{max_file_size};
@@ -131,16 +145,16 @@ sub startup {
}
);
- $self->hook(
- after_dispatch => sub {
- my $c = shift;
- $c->provisioning();
+ # Recurrent tasks
+ Mojo::IOLoop->recurring(5 => sub {
+ my $loop = shift;
- # Purge expired anti-flood protection
- my $wait_for_it = $c->app->{wait_for_it};
- delete @{$wait_for_it}{grep { time - $wait_for_it->{$_} > $c->config->{anti_flood_delay} } keys %{$wait_for_it}} if (defined($wait_for_it));
- }
- );
+ $self->provisioning();
+
+ # Purge expired anti-flood protection
+ my $wait_for_it = $self->{wait_for_it};
+ delete @{$wait_for_it}{grep { time - $wait_for_it->{$_} > $self->config->{anti_flood_delay} } keys %{$wait_for_it}} if (defined($wait_for_it));
+ });
$self->defaults(layout => 'default');
diff --git a/lib/Lutim/Controller.pm b/lib/Lutim/Controller.pm
index b2303bc..cf13b6c 100644
--- a/lib/Lutim/Controller.pm
+++ b/lib/Lutim/Controller.pm
@@ -36,7 +36,7 @@ sub home {
$c->on(finish => sub {
my $c = shift;
- $c->app->log->info('[HIT] someone visited site index');
+ $c->app->log->info('[HIT] someone visited site index') unless $c->config('quiet_logs');
}
);
}
@@ -157,7 +157,7 @@ sub modify {
if ($image->mod_token ne $token || $token eq '') {
$msg = $c->l('The delete token is invalid.');
} else {
- $c->app->log->info('[MODIFICATION] someone modify '.$image->filename.' with token method (path: '.$image->path.')');
+ $c->app->log->info('[MODIFICATION] someone modify '.$image->filename.' with token method (path: '.$image->path.')') unless $c->config('quiet_logs');
$image->delete_at_day(($c->param('delete-day') && ($c->param('delete-day') <= $c->max_delay || $c->max_delay == 0)) ? $c->param('delete-day') : $c->max_delay);
$image->delete_at_first_view(($c->param('first-view')) ? 1 : 0);
@@ -194,7 +194,7 @@ sub modify {
return $c->redirect_to('/');
}
} else {
- $c->app->log->info('[UNSUCCESSFUL] someone tried to modify '.$short.' but it does\'nt exist.');
+ $c->app->log->info('[UNSUCCESSFUL] someone tried to modify '.$short.' but it does\'nt exist.') unless $c->config('quiet_logs');
# Image never existed
my $msg = $c->l('Unable to find the image %1.', $short);
@@ -227,7 +227,7 @@ sub delete {
} elsif ($image->enabled() == 0) {
$msg = $c->l('The image %1 has already been deleted.', $image->filename);
} else {
- $c->app->log->info('[DELETION] someone made '.$image->filename.' removed with token method (path: '.$image->path.')');
+ $c->app->log->info('[DELETION] someone made '.$image->filename.' removed with token method (path: '.$image->path.')') unless $c->config('quiet_logs');
$c->delete_image($image);
return $c->respond_to(
@@ -261,7 +261,7 @@ sub delete {
}
);
} else {
- $c->app->log->info('[UNSUCCESSFUL] someone tried to delete '.$short.' but it does\'nt exist.');
+ $c->app->log->info('[UNSUCCESSFUL] someone tried to delete '.$short.' but it does\'nt exist.') unless $c->config('quiet_logs');
# Image never existed
return $c->respond_to(
@@ -465,7 +465,7 @@ sub add {
->write;
# Log image creation
- $c->app->log->info('[CREATION] '.$ip.' pushed '.$filename.' (path: '.$path.')');
+ $c->app->log->info('[CREATION] '.$ip.' pushed '.$filename.' (path: '.$path.')') unless $c->config('quiet_logs');
# Give url to user
$short = $record->short;
@@ -562,7 +562,7 @@ sub short {
if ($image->enabled && $image->path) {
if($image->delete_at_day && $image->created_at + $image->delete_at_day * 86400 <= time()) {
# Log deletion
- $c->app->log->info('[DELETION] someone tried to view '.$image->filename.' but it has been removed by expiration (path: '.$image->path.')');
+ $c->app->log->info('[DELETION] someone tried to view '.$image->filename.' but it has been removed by expiration (path: '.$image->path.')') unless $c->config('quiet_logs');
# Delete image
$c->delete_image($image);
@@ -608,7 +608,7 @@ sub short {
# Delete image if needed
if ($image->delete_at_first_view && $image->counter >= 1) {
# Log deletion
- $c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')');
+ $c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')') unless $c->config('quiet_logs');
# Delete image
$c->delete_image($image);
@@ -626,19 +626,21 @@ sub short {
# Update counter
$c->on(finish => sub {
# Log access
- $c->app->log->info('[VIEW] someone viewed '.$image->filename.' (path: '.$image->path.')');
+ $c->app->log->info('[VIEW] someone viewed '.$image->filename.' (path: '.$image->path.')') unless $c->config('quiet_logs');
# Update record
- if ($c->config('minion')->{enabled}) {
- $c->app->minion->enqueue(accessed => [$image->short, time]);
- } else {
- $image->accessed(time);
+ unless ($c->config('disable_img_stats')) {
+ if ($c->config('minion')->{enabled}) {
+ $c->app->minion->enqueue(accessed => [$image->short, time]);
+ } else {
+ $image->accessed(time);
+ }
}
# Delete image if needed
if ($image->delete_at_first_view) {
# Log deletion
- $c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')');
+ $c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')') unless $c->config('quiet_logs');
# Delete image
$c->delete_image($image);
@@ -647,7 +649,7 @@ sub short {
}
} elsif ($image->path && !$image->enabled) {
# Log access try
- $c->app->log->info('[NOT FOUND] someone tried to view '.$short.' but it does\'nt exist anymore.');
+ $c->app->log->info('[NOT FOUND] someone tried to view '.$short.' but it does\'nt exist anymore.') unless $c->config('quiet_logs');
# Warn user
$c->flash(
@@ -688,7 +690,7 @@ sub zip {
my $filename = $image->filename;
if($image->delete_at_day && $image->created_at + $image->delete_at_day * 86400 <= time()) {
# Log deletion
- $c->app->log->info('[DELETION] someone tried to view '.$image->filename.' but it has been removed by expiration (path: '.$image->path.')');
+ $c->app->log->info('[DELETION] someone tried to view '.$image->filename.' but it has been removed by expiration (path: '.$image->path.')') unless $c->config('quiet_logs');
# Delete image
$c->delete_image($image);
@@ -701,7 +703,7 @@ sub zip {
# Delete image if needed
if ($image->delete_at_first_view && $image->counter >= 1) {
# Log deletion
- $c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')');
+ $c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')') unless $c->config('quiet_logs');
# Delete image
$c->delete_image($image);
@@ -728,18 +730,20 @@ sub zip {
}
# Log access
- $c->app->log->info('[VIEW] someone viewed '.$image->filename.' (path: '.$image->path.')');
+ $c->app->log->info('[VIEW] someone viewed '.$image->filename.' (path: '.$image->path.')') unless $c->config('quiet_logs');
# Update counter and record
- if ($c->config('minion')->{enabled}) {
- $c->app->minion->enqueue(accessed => [$image->short, time]);
- } else {
- $image->accessed(time);
+ unless ($c->config('disable_img_stats')) {
+ if ($c->config('minion')->{enabled}) {
+ $c->app->minion->enqueue(accessed => [$image->short, time]);
+ } else {
+ $image->accessed(time);
+ }
}
}
} elsif ($image->path && !$image->enabled) {
# Log access try
- $c->app->log->info('[NOT FOUND] someone tried to view '.$short.' but it does\'nt exist anymore.');
+ $c->app->log->info('[NOT FOUND] someone tried to view '.$short.' but it does\'nt exist anymore.') unless $c->config('quiet_logs');
# Warn user
$zip->addString(encode('UTF-8', $c->l('Unable to find the image: it has been deleted.')), 'images/'.$image->filename.'.txt');
diff --git a/lib/Lutim/Plugin/Helpers.pm b/lib/Lutim/Plugin/Helpers.pm
index 8c65680..4d5977b 100644
--- a/lib/Lutim/Plugin/Helpers.pm
+++ b/lib/Lutim/Plugin/Helpers.pm
@@ -2,6 +2,7 @@
package Lutim::Plugin::Helpers;
use Mojo::Base 'Mojolicious::Plugin';
use Mojo::Util qw(quote);
+use Mojo::File;
use Crypt::CBC;
use Data::Entropy qw(entropy_source);
use DateTime;
@@ -18,9 +19,9 @@ sub register {
# Database migration
my $migrations = Mojo::Pg::Migrations->new(pg => $app->pg);
if ($app->mode eq 'development' && $ENV{LUTIM_DEBUG}) {
- $migrations->from_file('utilities/migrations/postgresql.sql')->migrate(0)->migrate(2);
+ $migrations->from_file('utilities/migrations/postgresql.sql')->migrate(0)->migrate(3);
} else {
- $migrations->from_file('utilities/migrations/postgresql.sql')->migrate(2);
+ $migrations->from_file('utilities/migrations/postgresql.sql')->migrate(3);
}
} elsif ($app->config('dbtype') eq 'sqlite') {
# SQLite database migration if needed
@@ -77,7 +78,6 @@ sub _render_file {
$dl = 'attachment' if ($mediatype =~ m/svg/);
$filename = quote($filename);
- my $asset;
unless (-f $path && -r $path) {
$c->app->log->error("Cannot read file [$path]. error [$!]");
$c->flash(
@@ -98,11 +98,30 @@ sub _render_file {
$headers->add('Content-Disposition' => $dl.';filename='.$filename);
$c->res->content->headers($headers);
- if ($key) {
- $asset = $c->decrypt($key, $path, $iv);
- } else {
- $asset = Mojo::Asset::File->new(path => $path);
+ my $cache = $c->app->{images_cache}->compute($img->short, undef, sub {
+ if ($key) {
+ return {
+ asset => $c->decrypt($key, $path, $iv),
+ key => $key
+ };
+ } else {
+ return {
+ asset => Mojo::File->new($path)->slurp,
+ };
+ }
+ });
+ if ($key && $key ne $cache->{key}) {
+ $c->app->{images_cache}->replace(
+ $img->short,
+ {
+ asset => $c->decrypt($key, $path, $iv),
+ key => $key
+ },
+ );
}
+ # Extend expiration time
+ my $asset = Mojo::Asset::Memory->new;
+ $asset->add_chunk($cache->{asset});
if (defined $thumb && $im_loaded && $mediatype ne 'image/svg+xml' && $mediatype !~ m#image/(x-)?xcf# && $mediatype ne 'image/webp') { # ImageMagick don't work in Debian with svg (for now?)
my $im = Image::Magick->new;
@@ -261,17 +280,20 @@ sub _decrypt {
open(my $f, "<",$file) or die "Unable to read encrypted file: $!";
binmode $f;
- while (read($f, my $buffer,1024)) {
+ while (read($f, my $buffer, 1024)) {
$decrypt_asset->add_chunk($cipher->crypt($buffer));
}
$decrypt_asset->add_chunk($cipher->finish) ;
- return $decrypt_asset;
+ return $decrypt_asset->slurp;
}
sub _delete_image {
my $c = shift;
my $img = shift;
+ if ($c->app->{images_cache}) {
+ $c->app->{images_cache}->remove($img->short);
+ }
unlink $img->path or warn "Could not unlink ".$img->path.": $!";
$img->disable();
}
diff --git a/lib/Mounter.pm b/lib/Mounter.pm
index 748f6a2..7c9da6f 100644
--- a/lib/Mounter.pm
+++ b/lib/Mounter.pm
@@ -46,6 +46,9 @@ sub startup {
dbtype => 'sqlite',
db_path => 'minion.db'
},
+ cache_max_size => 0,
+ quiet_logs => 0,
+ disable_img_stats => 0,
}
}
);
diff --git a/lutim.conf.template b/lutim.conf.template
index 46eb95f..a7d4a17 100644
--- a/lutim.conf.template
+++ b/lutim.conf.template
@@ -92,7 +92,7 @@
# comma-separated values proposed for delays
# optional, default is '0,1,7,30,365'
#proposed_delays => '0,1,7,30,365',
-
+
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
# a warning message will be displayed on homepage
# optional, default is 0 (no limit)
@@ -159,6 +159,11 @@
# }
#},
+ # disable counters of images
+ # set to 1 to disable counters
+ # optional, counters are enabled by default
+ #disable_img_stats => 0,
+
# define the height of the thumbnails generated at users' will
# this is not the height of the thumbnails send after upload,
# we're talking about thumbnails generated when someone asked for
@@ -175,6 +180,22 @@
# optional, default is 15
#max_files_in_zip => 15,
+ # maximum size (in MB) of memory allowed for the image cache
+ # Lutim has a built-in memory-based image cache to accelerate responses to often-viewed images.
+ # This setting makes the cache remove oldest viewed image if the cache size is over it.
+ # WARNING: a cache is created for each hypnotoad worker, which by default is twice the number of
+ # CPUs you have. See http://mojolicious.org/perldoc/Mojo/Server/Hypnotoad#workers for details
+ # So, if you have 4 workers and set cache_max_size to 100, the real maximum size of RAM used for
+ # cache is 400MB.
+ # If set to 0, the cache is disabled
+ # optional, default is 0
+ #cache_max_size => 0,
+
+ # enable or disable Lutim built-in logs
+ # set to 1 to disable logs
+ # optional, default is 0
+ #quiet_logs => 0,
+
##########################
# Lutim cron jobs settings
##########################
diff --git a/t/postgresql1.conf b/t/postgresql1.conf
index 9d7fe63..62f0d1a 100644
--- a/t/postgresql1.conf
+++ b/t/postgresql1.conf
@@ -89,6 +89,10 @@
# optional, default is 0 (no limit)
default_delay => 30,
+ # comma-separated values proposed for delays
+ # optional, default is '0,1,7,30,365'
+ #proposed_delays => '0,1,7,30,365',
+
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
# a warning message will be displayed on homepage
# optional, default is 0 (no limit)
@@ -171,6 +175,13 @@
# optional, default is 15
#max_files_in_zip => 15,
+ # maximum size (in MB) of memory allowed for the image cache
+ # Lutim has a built-in memory-based image cache to accelerate responses to often-viewed images.
+ # This setting makes the cache remove oldest viewed image if the cache size is over it.
+ # If set to 0, the cache is disabled
+ # optional, default is 0
+ #cache_max_size => 0,
+
##########################
# Lutim cron jobs settings
##########################
diff --git a/t/postgresql2.conf b/t/postgresql2.conf
index 452e6ca..008d01d 100644
--- a/t/postgresql2.conf
+++ b/t/postgresql2.conf
@@ -89,6 +89,10 @@
# optional, default is 0 (no limit)
default_delay => 30,
+ # comma-separated values proposed for delays
+ # optional, default is '0,1,7,30,365'
+ #proposed_delays => '0,1,7,30,365',
+
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
# a warning message will be displayed on homepage
# optional, default is 0 (no limit)
@@ -171,6 +175,13 @@
# optional, default is 15
#max_files_in_zip => 15,
+ # maximum size (in MB) of memory allowed for the image cache
+ # Lutim has a built-in memory-based image cache to accelerate responses to often-viewed images.
+ # This setting makes the cache remove oldest viewed image if the cache size is over it.
+ # If set to 0, the cache is disabled
+ # optional, default is 0
+ #cache_max_size => 0,
+
##########################
# Lutim cron jobs settings
##########################
diff --git a/t/postgresql3.conf b/t/postgresql3.conf
index a8a5810..dd81819 100644
--- a/t/postgresql3.conf
+++ b/t/postgresql3.conf
@@ -89,6 +89,10 @@
# optional, default is 0 (no limit)
default_delay => 30,
+ # comma-separated values proposed for delays
+ # optional, default is '0,1,7,30,365'
+ #proposed_delays => '0,1,7,30,365',
+
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
# a warning message will be displayed on homepage
# optional, default is 0 (no limit)
@@ -171,6 +175,13 @@
# optional, default is 15
#max_files_in_zip => 15,
+ # maximum size (in MB) of memory allowed for the image cache
+ # Lutim has a built-in memory-based image cache to accelerate responses to often-viewed images.
+ # This setting makes the cache remove oldest viewed image if the cache size is over it.
+ # If set to 0, the cache is disabled
+ # optional, default is 0
+ #cache_max_size => 0,
+
##########################
# Lutim cron jobs settings
##########################
diff --git a/t/sqlite1.conf b/t/sqlite1.conf
index 53348e7..1b555e7 100644
--- a/t/sqlite1.conf
+++ b/t/sqlite1.conf
@@ -89,6 +89,10 @@
# optional, default is 0 (no limit)
default_delay => 30,
+ # comma-separated values proposed for delays
+ # optional, default is '0,1,7,30,365'
+ #proposed_delays => '0,1,7,30,365',
+
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
# a warning message will be displayed on homepage
# optional, default is 0 (no limit)
@@ -171,6 +175,13 @@
# optional, default is 15
#max_files_in_zip => 15,
+ # maximum size (in MB) of memory allowed for the image cache
+ # Lutim has a built-in memory-based image cache to accelerate responses to often-viewed images.
+ # This setting makes the cache remove oldest viewed image if the cache size is over it.
+ # If set to 0, the cache is disabled
+ # optional, default is 0
+ #cache_max_size => 0,
+
##########################
# Lutim cron jobs settings
##########################
diff --git a/t/sqlite2.conf b/t/sqlite2.conf
index e4c6a12..e80a1f0 100644
--- a/t/sqlite2.conf
+++ b/t/sqlite2.conf
@@ -89,6 +89,10 @@
# optional, default is 0 (no limit)
default_delay => 30,
+ # comma-separated values proposed for delays
+ # optional, default is '0,1,7,30,365'
+ #proposed_delays => '0,1,7,30,365',
+
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
# a warning message will be displayed on homepage
# optional, default is 0 (no limit)
@@ -171,6 +175,13 @@
# optional, default is 15
#max_files_in_zip => 15,
+ # maximum size (in MB) of memory allowed for the image cache
+ # Lutim has a built-in memory-based image cache to accelerate responses to often-viewed images.
+ # This setting makes the cache remove oldest viewed image if the cache size is over it.
+ # If set to 0, the cache is disabled
+ # optional, default is 0
+ #cache_max_size => 0,
+
##########################
# Lutim cron jobs settings
##########################
diff --git a/t/sqlite3.conf b/t/sqlite3.conf
index dea2e0b..65d142a 100644
--- a/t/sqlite3.conf
+++ b/t/sqlite3.conf
@@ -89,6 +89,10 @@
# optional, default is 0 (no limit)
default_delay => 30,
+ # comma-separated values proposed for delays
+ # optional, default is '0,1,7,30,365'
+ #proposed_delays => '0,1,7,30,365',
+
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
# a warning message will be displayed on homepage
# optional, default is 0 (no limit)
@@ -171,6 +175,13 @@
# optional, default is 15
#max_files_in_zip => 15,
+ # maximum size (in MB) of memory allowed for the image cache
+ # Lutim has a built-in memory-based image cache to accelerate responses to often-viewed images.
+ # This setting makes the cache remove oldest viewed image if the cache size is over it.
+ # If set to 0, the cache is disabled
+ # optional, default is 0
+ #cache_max_size => 0,
+
##########################
# Lutim cron jobs settings
##########################
diff --git a/t/test.t b/t/test.t
index 83aee73..8c37ae1 100644
--- a/t/test.t
+++ b/t/test.t
@@ -26,12 +26,35 @@ BEGIN {
{
file => $cfile->to_abs->to_string,
default => {
- dbtype => 'sqlite'
+ provisioning => 100,
+ provis_step => 5,
+ length => 8,
+ always_encrypt => 0,
+ anti_flood_delay => 5,
+ tweet_card_via => '@framasky',
+ max_file_size => 10*1024*1024,
+ https => 0,
+ proposed_delays => '0,1,7,30,365',
+ default_delay => 0,
+ max_delay => 0,
+ token_length => 24,
+ crypto_key_length => 8,
+ thumbnail_size => 100,
+ theme => 'default',
+ dbtype => 'sqlite',
+ db_path => 'lutim.db',
+ max_files_in_zip => 15,
+ prefix => '/',
+ minion => {
+ enabled => 0,
+ dbtype => 'sqlite',
+ db_path => 'minion.db'
+ },
+ cache_max_size => 0,
}
}
);
$m->plugin('Lutim::Plugin::Helpers');
- $m->plugin('DebugDumperHelper');
}
# Home page
diff --git a/themes/default/lib/Lutim/I18N/lutim.pot b/themes/default/lib/Lutim/I18N/lutim.pot
index 9842998..f56937e 100644
--- a/themes/default/lib/Lutim/I18N/lutim.pot
+++ b/themes/default/lib/Lutim/I18N/lutim.pot
@@ -32,11 +32,11 @@ msgstr ""
msgid "-or-"
msgstr ""
-#: lib/Lutim.pm:187 lib/Lutim/Command/cron/stats.pm:151 lib/Lutim/Command/cron/stats.pm:162 lib/Lutim/Command/cron/stats.pm:179 themes/default/templates/index.html.ep:5 themes/default/templates/raw.html.ep:10 themes/default/templates/raw.html.ep:21 themes/default/templates/raw.html.ep:38
+#: lib/Lutim.pm:201 lib/Lutim/Command/cron/stats.pm:151 lib/Lutim/Command/cron/stats.pm:162 lib/Lutim/Command/cron/stats.pm:179 themes/default/templates/index.html.ep:5 themes/default/templates/raw.html.ep:10 themes/default/templates/raw.html.ep:21 themes/default/templates/raw.html.ep:38
msgid "1 year"
msgstr ""
-#: lib/Lutim.pm:186 lib/Lutim/Command/cron/stats.pm:148 lib/Lutim/Command/cron/stats.pm:159 lib/Lutim/Command/cron/stats.pm:176 themes/default/templates/index.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/lutim.js.ep:151 themes/default/templates/raw.html.ep:18 themes/default/templates/raw.html.ep:35 themes/default/templates/raw.html.ep:7
+#: lib/Lutim.pm:200 lib/Lutim/Command/cron/stats.pm:148 lib/Lutim/Command/cron/stats.pm:159 lib/Lutim/Command/cron/stats.pm:176 themes/default/templates/index.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/lutim.js.ep:151 themes/default/templates/raw.html.ep:18 themes/default/templates/raw.html.ep:35 themes/default/templates/raw.html.ep:7
msgid "24 hours"
msgstr ""
@@ -44,7 +44,7 @@ msgstr ""
msgid ": Error while trying to get the counter."
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:77
+#: themes/default/templates/partial/navbar.html.ep:79
msgid "About"
msgstr ""
@@ -156,7 +156,7 @@ msgstr ""
msgid "For more details, see the homepage of the project."
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:80
+#: themes/default/templates/partial/navbar.html.ep:82
msgid "Fork me!"
msgstr ""
@@ -196,19 +196,19 @@ msgstr ""
msgid "Image delay"
msgstr ""
-#: lib/Lutim/Controller.pm:748
+#: lib/Lutim/Controller.pm:752
msgid "Image not found."
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:69
+#: themes/default/templates/partial/navbar.html.ep:71
msgid "Informations"
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:33
+#: themes/default/templates/partial/navbar.html.ep:35
msgid "Install webapp"
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:29
+#: themes/default/templates/partial/navbar.html.ep:31
msgid "Instance's statistics"
msgstr ""
@@ -228,7 +228,7 @@ msgstr ""
msgid "Keep EXIF tags"
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:40
+#: themes/default/templates/partial/navbar.html.ep:42
msgid "Language"
msgstr ""
@@ -236,7 +236,7 @@ msgstr ""
msgid "Let's go!"
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:74
+#: themes/default/templates/partial/navbar.html.ep:76
msgid "License:"
msgstr ""
@@ -260,7 +260,7 @@ msgstr ""
msgid "Markdown syntax"
msgstr ""
-#: themes/default/templates/myfiles.html.ep:2 themes/default/templates/partial/navbar.html.ep:26
+#: themes/default/templates/myfiles.html.ep:2 themes/default/templates/partial/navbar.html.ep:28
msgid "My images"
msgstr ""
@@ -314,23 +314,23 @@ msgid "Something bad happened"
msgstr ""
#. ($c->config('contact')
-#: lib/Lutim/Controller.pm:755
+#: lib/Lutim/Controller.pm:759
msgid "Something went wrong when creating the zip file. Try again later or contact the administrator (%1)."
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:52
+#: themes/default/templates/partial/navbar.html.ep:54
msgid "Support the author"
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:60
+#: themes/default/templates/partial/navbar.html.ep:62
msgid "Support the author on Liberapay"
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:57
+#: themes/default/templates/partial/navbar.html.ep:59
msgid "Support the author on Tipeee"
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:63
+#: themes/default/templates/partial/navbar.html.ep:65
msgid "Support the author with bitcoins"
msgstr ""
@@ -401,7 +401,7 @@ msgstr ""
msgid "Toggle fullscreen"
msgstr ""
-#: themes/default/templates/partial/navbar.html.ep:16
+#: themes/default/templates/partial/navbar.html.ep:18
msgid "Toggle navigation"
msgstr ""
@@ -418,7 +418,7 @@ msgstr ""
msgid "Unable to find the image %1."
msgstr ""
-#: lib/Lutim/Controller.pm:572 lib/Lutim/Controller.pm:617 lib/Lutim/Controller.pm:654 lib/Lutim/Controller.pm:697 lib/Lutim/Controller.pm:709 lib/Lutim/Controller.pm:720 lib/Lutim/Controller.pm:745 lib/Lutim/Plugin/Helpers.pm:84
+#: lib/Lutim/Controller.pm:572 lib/Lutim/Controller.pm:617 lib/Lutim/Controller.pm:656 lib/Lutim/Controller.pm:699 lib/Lutim/Controller.pm:711 lib/Lutim/Controller.pm:722 lib/Lutim/Controller.pm:749 lib/Lutim/Plugin/Helpers.pm:84
msgid "Unable to find the image: it has been deleted."
msgstr ""
@@ -443,7 +443,7 @@ msgid "Uploaded files by days"
msgstr ""
#. ($c->app->config('contact')
-#: lib/Lutim/Plugin/Helpers.pm:183
+#: lib/Lutim/Plugin/Helpers.pm:202
msgid "Uploading is currently disabled, please try later or contact the administrator (%1)."
msgstr ""
@@ -495,7 +495,7 @@ msgstr ""
msgid "core developer"
msgstr ""
-#: lib/Lutim.pm:185 lib/Lutim/Command/cron/stats.pm:147 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:175 themes/default/templates/index.html.ep:3 themes/default/templates/raw.html.ep:17 themes/default/templates/raw.html.ep:34 themes/default/templates/raw.html.ep:6
+#: lib/Lutim.pm:199 lib/Lutim/Command/cron/stats.pm:147 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:175 themes/default/templates/index.html.ep:3 themes/default/templates/raw.html.ep:17 themes/default/templates/raw.html.ep:34 themes/default/templates/raw.html.ep:6
msgid "no time limit"
msgstr ""
diff --git a/themes/default/templates/partial/for_my_delay.html.ep b/themes/default/templates/partial/for_my_delay.html.ep
index c3b5f0a..f622a85 100644
--- a/themes/default/templates/partial/for_my_delay.html.ep
+++ b/themes/default/templates/partial/for_my_delay.html.ep
@@ -1,7 +1,7 @@
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
% my @delays = split(',', $self->config('proposed_delays'));
% for my $delay (@delays) {
-% my $text = ($delay == 7 || $delay == 30) ? l('%1 days', $delay) : $d->{'delay_'.$delay};
+% my $text = (defined($d->{'delay_'.$delay})) ? $d->{'delay_'.$delay} : l('%1 days', $delay);
% if (config('max_delay')) {
% if ($delay) {
% if ($delay < config('max_delay')) {
diff --git a/themes/default/templates/partial/lutim.js.ep b/themes/default/templates/partial/lutim.js.ep
index ffeb3aa..73ac394 100644
--- a/themes/default/templates/partial/lutim.js.ep
+++ b/themes/default/templates/partial/lutim.js.ep
@@ -139,7 +139,7 @@ function buildMessage(success, msg) {
'