diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..381bb22 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,14 @@ +Revision history for Lufi + +0.02 2017-? + - Database abstraction layer + - IE 11 and Edge support + - Fix encoding error (#83) + - Htpassword authentication support + - Ability to add a password to a file + +0.01 2017-01-09 + - Upload files + - Download files + - Preview files in browser depending on mimetype (images and videos) + - LDAP authentication support diff --git a/Makefile b/Makefile index aedffd9..d56ddf4 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,9 @@ locales: $(XGETTEXT) $(EXTRACTDIR) -o $(PT) 2>/dev/null $(XGETTEXT) $(EXTRACTDIR) -o $(NL) 2>/dev/null +podcheck: + podchecker lib/Lufi/DB/File.pm lib/Lufi/DB/Slice.pm + test: $(CARTON) $(REAL_LUFI) test diff --git a/cpanfile b/cpanfile index 421f77b..ed14502 100644 --- a/cpanfile +++ b/cpanfile @@ -1,9 +1,11 @@ requires 'Mojolicious', '>= 7.31'; requires 'ORLite'; requires 'Mojolicious::Plugin::DebugDumperHelper'; +requires 'Mojolicious::Plugin::PgURLHelper'; requires 'Mojolicious::Plugin::I18N'; requires 'Mojolicious::Plugin::Mail'; requires 'Mojolicious::Plugin::Authentication'; +requires 'Mojo::Pg'; requires 'EV'; requires 'Filesys::DiskUsage'; requires 'Switch'; diff --git a/cpanfile.snapshot b/cpanfile.snapshot index 030f516..19226ce 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -51,6 +51,26 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 + Class-Method-Modifiers-2.12 + pathname: E/ET/ETHER/Class-Method-Modifiers-2.12.tar.gz + provides: + Class::Method::Modifiers 2.12 + requirements: + B 0 + Carp 0 + Exporter 0 + ExtUtils::MakeMaker 0 + base 0 + perl 5.006 + strict 0 + warnings 0 + Clone-0.39 + pathname: G/GA/GARU/Clone-0.39.tar.gz + provides: + Clone 0.39 + requirements: + ExtUtils::MakeMaker 0 + Test::More 0 Convert-ASN1-0.27 pathname: G/GB/GBARR/Convert-ASN1-0.27.tar.gz provides: @@ -85,6 +105,17 @@ DISTRIBUTIONS ExtUtils::MakeMaker 6.30 Test::Fatal 0 Test::More 0 + DBD-Pg-3.6.2 + pathname: T/TU/TURNSTEP/DBD-Pg-3.6.2.tar.gz + provides: + Bundle::DBD::Pg v3.6.2 + DBD::Pg v3.6.2 + requirements: + DBI 1.614 + ExtUtils::MakeMaker 6.11 + Test::More 0.88 + Time::HiRes 0 + version 0 DBD-SQLite-1.54 pathname: I/IS/ISHIGAKI/DBD-SQLite-1.54.tar.gz provides: @@ -241,6 +272,14 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 + Devel-GlobalDestruction-0.14 + pathname: H/HA/HAARG/Devel-GlobalDestruction-0.14.tar.gz + provides: + Devel::GlobalDestruction 0.14 + requirements: + ExtUtils::MakeMaker 0 + Sub::Exporter::Progressive 0.001011 + perl 5.006 Digest-HMAC-1.03 pathname: G/GA/GAAS/Digest-HMAC-1.03.tar.gz provides: @@ -454,6 +493,14 @@ DISTRIBUTIONS ExtUtils::MakeMaker 0 HTTP::Headers 6 perl 5.008001 + Hash-Merge-0.200 + pathname: R/RE/REHSACK/Hash-Merge-0.200.tar.gz + provides: + Hash::Merge 0.200 + requirements: + Clone 0 + ExtUtils::MakeMaker 0 + perl 5.008001 IO-HTML-1.001 pathname: C/CJ/CJM/IO-HTML-1.001.tar.gz provides: @@ -571,6 +618,13 @@ DISTRIBUTIONS File::Spec 0 List::Util 0 Test::More 0.47 + MRO-Compat-0.13 + pathname: H/HA/HAARG/MRO-Compat-0.13.tar.gz + provides: + MRO::Compat 0.13 + requirements: + ExtUtils::MakeMaker 0 + perl 5.006 MailTools-2.18 pathname: M/MA/MARKOV/MailTools-2.18.tar.gz provides: @@ -654,6 +708,31 @@ DISTRIBUTIONS Text::ParseWords 0 perl 5.006001 version 0.87 + Module-Runtime-0.015 + pathname: Z/ZE/ZEFRAM/Module-Runtime-0.015.tar.gz + provides: + Module::Runtime 0.015 + requirements: + Module::Build 0 + Test::More 0.41 + perl 5.006 + strict 0 + warnings 0 + Mojo-Pg-4.0 + pathname: S/SR/SRI/Mojo-Pg-4.0.tar.gz + provides: + Mojo::Pg 4.0 + Mojo::Pg::Database undef + Mojo::Pg::Migrations undef + Mojo::Pg::PubSub undef + Mojo::Pg::Results undef + Mojo::Pg::Transaction undef + requirements: + DBD::Pg 3.005001 + ExtUtils::MakeMaker 0 + Mojolicious 7.32 + SQL::Abstract 1.81 + perl 5.010001 Mojolicious-7.36 pathname: S/SR/SRI/Mojolicious-7.36.tar.gz provides: @@ -813,6 +892,43 @@ DISTRIBUTIONS Mojolicious 5 Test::More 0 perl 5.001001 + Mojolicious-Plugin-PgURLHelper-0.03 + pathname: L/LD/LDIDRY/Mojolicious-Plugin-PgURLHelper-0.03.tar.gz + provides: + Mojolicious::Plugin::PgURLHelper 0.03 + requirements: + ExtUtils::MakeMaker 0 + Mojolicious 7.23 + Moo-2.003002 + pathname: H/HA/HAARG/Moo-2.003002.tar.gz + provides: + Method::Generate::Accessor undef + Method::Generate::BuildAll undef + Method::Generate::Constructor undef + Method::Generate::DemolishAll undef + Moo 2.003002 + Moo::HandleMoose undef + Moo::HandleMoose::FakeConstructor undef + Moo::HandleMoose::FakeMetaClass undef + Moo::HandleMoose::_TypeMap undef + Moo::Object undef + Moo::Role 2.003002 + Moo::_Utils undef + Moo::_mro undef + Moo::_strictures undef + Moo::sification undef + oo undef + requirements: + Class::Method::Modifiers 1.1 + Devel::GlobalDestruction 0.11 + Exporter 5.57 + ExtUtils::MakeMaker 0 + Module::Runtime 0.014 + Role::Tiny 2.000004 + Scalar::Util 0 + Sub::Defer 2.003001 + Sub::Quote 2.003001 + perl 5.006 Mozilla-CA-20160104 pathname: A/AB/ABH/Mozilla-CA-20160104.tar.gz provides: @@ -909,6 +1025,45 @@ DISTRIBUTIONS ExtUtils::MakeMaker 6.30 File::Spec 0 strict 0 + Role-Tiny-2.000005 + pathname: H/HA/HAARG/Role-Tiny-2.000005.tar.gz + provides: + Role::Tiny 2.000005 + Role::Tiny::With 2.000005 + requirements: + Exporter 5.57 + perl 5.006 + SQL-Abstract-1.84 + pathname: I/IL/ILMARI/SQL-Abstract-1.84.tar.gz + provides: + SQL::Abstract 1.84 + SQL::Abstract::Test undef + SQL::Abstract::Tree undef + requirements: + Exporter 5.57 + ExtUtils::MakeMaker 0 + Hash::Merge 0.12 + List::Util 0 + MRO::Compat 0.12 + Moo 2.000001 + Scalar::Util 0 + Sub::Quote 2.000001 + Text::Balanced 2.00 + Sub-Exporter-Progressive-0.001013 + pathname: F/FR/FREW/Sub-Exporter-Progressive-0.001013.tar.gz + provides: + Sub::Exporter::Progressive 0.001013 + requirements: + ExtUtils::MakeMaker 0 + Sub-Quote-2.004000 + pathname: H/HA/HAARG/Sub-Quote-2.004000.tar.gz + provides: + Sub::Defer 2.004000 + Sub::Quote 2.004000 + requirements: + ExtUtils::MakeMaker 0 + Scalar::Util 0 + perl 5.006 Sub-Uplevel-0.2800 pathname: D/DA/DAGOLDEN/Sub-Uplevel-0.2800.tar.gz provides: diff --git a/lib/Lufi.pm b/lib/Lufi.pm old mode 100755 new mode 100644 index e48d4ce..e703ec4 --- a/lib/Lufi.pm +++ b/lib/Lufi.pm @@ -1,7 +1,6 @@ # vim:set sw=4 ts=4 sts=4 ft=perl expandtab: package Lufi; use Mojo::Base 'Mojolicious'; -use LufiDB; use Net::LDAP; use Apache::Htpasswd; @@ -29,6 +28,7 @@ sub startup { upload_dir => 'files', session_duration => 3600, allow_pwd_on_files => 0, + dbtype => 'sqlite', } }); diff --git a/lib/Lufi/Command/cron/cleanbdd.pm b/lib/Lufi/Command/cron/cleanbdd.pm index a6c32ca..4a3e326 100644 --- a/lib/Lufi/Command/cron/cleanbdd.pm +++ b/lib/Lufi/Command/cron/cleanbdd.pm @@ -1,9 +1,8 @@ # vim:set sw=4 ts=4 sts=4 ft=perl expandtab: package Lufi::Command::cron::cleanbdd; use Mojo::Base 'Mojolicious::Command'; -use LufiDB; +use Lufi::DB::File; use FindBin qw($Bin); -use File::Spec qw(catfile); has description => 'Delete IP addresses from database after configured delay.'; has usage => sub { shift->extract_usage }; @@ -11,20 +10,24 @@ has usage => sub { shift->extract_usage }; sub run { my $c = shift; + my $cfile = Mojo::File->new($Bin, '..' , 'lufi.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } + } my $config = $c->app->plugin('Config', { - file => File::Spec->catfile($Bin, '..' ,'lufi.conf'), + file => $cfile, default => { + dbtype => 'sqlite', keep_ip_during => 365, } }); my $separation = time() - $config->{keep_ip_during} * 86400; - LufiDB->do( - 'UPDATE files SET created_by = NULL WHERE created_by IS NOT NULL AND created_at < ?', - {}, - $separation - ); + Lufi::DB::File->new(app => $c->app)->delete_creator_before($separation); } =encoding utf8 diff --git a/lib/Lufi/Command/cron/cleanfiles.pm b/lib/Lufi/Command/cron/cleanfiles.pm index 912d715..c9d0ba0 100644 --- a/lib/Lufi/Command/cron/cleanfiles.pm +++ b/lib/Lufi/Command/cron/cleanfiles.pm @@ -1,10 +1,8 @@ # vim:set sw=4 ts=4 sts=4 ft=perl expandtab: package Lufi::Command::cron::cleanfiles; use Mojo::Base 'Mojolicious::Command'; -use LufiDB; -use Lufi::File; +use Lufi::DB::File; use FindBin qw($Bin); -use File::Spec qw(catfile); has description => 'Delete expired files.'; has usage => sub { shift->extract_usage }; @@ -12,28 +10,39 @@ has usage => sub { shift->extract_usage }; sub run { my $c = shift; - my $time = time(); - - ## Select only files expired since two days, to be sure that nobody is still downloading it - my @files = LufiDB::Files->select('WHERE deleted = 0 AND ((delete_at_day + 2) * 86400) < (? - created_at) AND delete_at_day != 0', $time); - - for my $file (@files) { - my $f = Lufi::File->new(record => $file); - $file->delete; + my $cfile = Mojo::File->new($Bin, '..' , 'lufi.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } } - my $config = $c->app->plugin('Config', { - file => File::Spec->catfile($Bin, '..' ,'lufi.conf'), + file => $cfile, + default => { + dbtype => 'sqlite', + } }); - if (defined($config->{delete_no_longer_viewed_files}) && $config->{delete_no_longer_viewed_files} > 0) { - $time = time() - $config->{delete_no_longer_viewed_files} * 86400; - @files = LufiDB::Files->select('WHERE deleted = 0 AND last_access_at < ?', $time); + my $time = time(); - for my $file (@files) { - my $f = Lufi::File->new(record => $file); - $file->delete; + my $ldfile = Lufi::DB::File->new(app => $c->app); + $ldfile->get_expired($time)->each( + sub { + my ($f, $num) = @_; + $f->delete; } + ); + + if (defined($config->{delete_no_longer_viewed_files}) && $config->{delete_no_longer_viewed_files} > 0) { + $time = time() - $config->{delete_no_longer_viewed_files} * 86400; + my $ldfile = Lufi::DB::File->new(app => $c->app); + $ldfile->get_no_longer_viewed($time)->each( + sub { + my ($f, $num) = @_; + $f->delete; + } + ); } } diff --git a/lib/Lufi/Command/cron/watch.pm b/lib/Lufi/Command/cron/watch.pm index ebb2fec..af4134e 100644 --- a/lib/Lufi/Command/cron/watch.pm +++ b/lib/Lufi/Command/cron/watch.pm @@ -1,11 +1,9 @@ package Lufi::Command::cron::watch; use Mojo::Base 'Mojolicious::Command'; use Filesys::DiskUsage qw/du/; -use LufiDB; -use Lufi::File; +use Lufi::DB::File; use Switch; use FindBin qw($Bin); -use File::Spec qw(catfile); has description => 'Watch the files directory and take action when over quota'; has usage => sub { shift->extract_usage }; @@ -13,9 +11,17 @@ has usage => sub { shift->extract_usage }; sub run { my $c = shift; + my $cfile = Mojo::File->new($Bin, '..' , 'lufi.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } + } my $config = $c->app->plugin('Config', { - file => File::Spec->catfile($Bin, '..' ,'lufi.conf'), + file => $cfile, default => { + dbtype => 'sqlite', policy_when_full => 'warn' } }); @@ -36,11 +42,14 @@ sub run { } case 'delete' { say '[Lufi cron job watch] Older files are being deleted'; + my $ldfile = Lufi::DB::File->new(app => $c->app); do { - for my $file (LufiDB::Files->select('WHERE deleted = 0 ORDER BY created_at ASC LIMIT 50')) { - my $f = Lufi::File->new(record => $file); - $file->delete; - } + $ldfile->get_oldest_undeleted_files(50)->each( + sub { + my ($f, $num) = @_; + $f->delete; + } + ); } while (du(qw/files/) > $config->{max_total_size}); } else { diff --git a/lib/Lufi/Controller/Files.pm b/lib/Lufi/Controller/Files.pm index 7a783a8..7841268 100644 --- a/lib/Lufi/Controller/Files.pm +++ b/lib/Lufi/Controller/Files.pm @@ -4,9 +4,8 @@ use Mojo::Base 'Mojolicious::Controller'; use Mojo::JSON qw(encode_json decode_json to_json true false); use Mojo::Util qw(encode decode); use Mojo::File; -use LufiDB; -use Lufi::File; -use Lufi::Slice; +use Lufi::DB::File; +use Lufi::DB::Slice; use File::Spec::Functions; use Number::Bytes::Human qw(format_bytes); use Filesys::DfPortable; @@ -38,47 +37,46 @@ sub upload { # Check if stop_upload file is present if ($c->stop_upload) { $stop = 1; - $c->send(encode_json( + $c->send(decode('UTF-8', encode_json( { success => false, msg => $c->l('Sorry, uploading is disabled.'), sent_delay => $json->{delay}, i => $json->{i} } - )); + ))); } # Check against max_size elsif (defined $c->config('max_file_size')) { if ($json->{size} > $c->config('max_file_size')) { $stop = 1; - $c->send(encode_json( + $c->send(decode('UTF-8', encode_json( { success => false, msg => $c->l('Your file is too big: %1 (maximum size allowed: %2)', format_bytes($json->{size}), format_bytes($c->config('max_file_size'))), sent_delay => $json->{delay}, i => $json->{i} } - )); + ))); } } # Check that we have enough space (multiplying by 2 since it's encrypted, it takes more place that the original file) elsif ($json->{part} == 0 && ($json->{size} * 2) >= dfportable($c->config('upload_dir'))->{bavail}) { $stop = 1; - $c->send(encode_json( + $c->send(decode('UTF-8', encode_json( { success => false, msg => $c->l('No enough space available on the server for this file (size: %1).', format_bytes($json->{size})), sent_delay => $json->{delay}, i => $json->{i} } - )); + ))); } unless ($stop) { my $f; if (defined($json->{id})) { - my @records = LufiDB::Files->select('WHERE short = ?', $json->{id}); - $f = Lufi::File->new(record => $records[0]) if scalar @records; + $f = Lufi::DB::File->new(app => $c->app)->from_short($json->{id}); } else { my $delay; unless (defined $json->{delay}) { @@ -113,19 +111,17 @@ sub upload { if (defined($c->config('ldap')) || defined($c->config('htpasswd'))) { $creator = 'User: '.$c->current_user.', IP: '.$creator; } - $f = Lufi::File->new( - record => $c->get_empty, - created_by => $creator, - delete_at_first_view => ($json->{del_at_first_view}) ? 1 : 0, - delete_at_day => $delay, - mediatype => $json->{type}, - filename => $json->{name}, - filesize => $json->{size}, - nbslices => $json->{total}, - mod_token => $c->shortener($c->config('token_length')), - passwd => $salted_pwd - ); - $f->write; + $f = Lufi::DB::File->new(app => $c->app)->get_empty() + ->created_by($creator) + ->delete_at_first_view(($json->{del_at_first_view}) ? 1 : 0) + ->delete_at_day($delay) + ->mediatype($json->{type}) + ->filename($json->{name}) + ->filesize($json->{size}) + ->nbslices($json->{total}) + ->mod_token($c->shortener($c->config('token_length'))) + ->passwd($salted_pwd) + ->write; } # This check is just in case we didn't succeed to find a corresponding record @@ -140,7 +136,8 @@ sub upload { # Create slice file my $file = catfile($dir, $json->{part}.'.part'); - my $s = Lufi::Slice->new( + my $s = Lufi::DB::Slice->new( + app => $c->app, short => $f->short, j => $json->{part}, path => $file @@ -176,14 +173,14 @@ sub upload { } )); } else { - $ws->send(encode_json( + $ws->send(decode('UTF-8', encode_json( { success => false, msg => $c->l('The server was unable to find the file record to add your file part to. Please, contact the administrator.'), sent_delay => $json->{delay}, i => $json->{i} } - )); + ))); } } } @@ -203,37 +200,35 @@ sub download { $c->inactivity_timeout(300000); $c->app->log->debug('Client connected'); - my @records = LufiDB::Files->select('WHERE short = ?', $short); + my $ldfile = Lufi::DB::File->new(app => $c->app)->from_short($short); # Do we have a file? - if (scalar @records) { - my $record = $records[0]; + if (defined $ldfile) { # Is the file fully uploaded? - if ($record->deleted + if ($ldfile->deleted || ( - $record->delete_at_day != 0 + $ldfile->delete_at_day != 0 && ( - ($record->created_at + $record->delete_at_day * 86400) < time() + ($ldfile->created_at + $ldfile->delete_at_day * 86400) < time() ) ) ) { - unless ($record->deleted) { - my $f = Lufi::File->new(record => $record); - $f->delete; + unless ($ldfile->deleted) { + $ldfile->delete; } $c->on( message => sub { my ($ws, $json) = @_; - $c->send(encode_json( + $c->send(decode('UTF-8', encode_json( { success => false, msg => $c->l('Error: the file existed but was deleted.') } - )); + ))); } ); - } elsif ($record->complete) { - my $f = Lufi::File->new(record => $record); + } elsif ($ldfile->complete) { + my $f = $ldfile; $c->on( message => sub { @@ -273,7 +268,11 @@ sub download { } } } else { - $c->send(encode_json({msg => $c->l('Your password is not valid. Please refresh the page to retry.')})); + $c->send(decode('UTF-8', encode_json( + { + msg => $c->l('Your password is not valid. Please refresh the page to retry.') + } + ))); } } ); @@ -286,22 +285,22 @@ sub download { $c->on( message => sub { my ($ws, $json) = @_; - $c->send(encode_json( + $c->send(decode('UTF-8', encode_json( { success => false, msg => $c->l('Error: the file has not been sent entirely.') } - )); + ))); } ); } } else { - $c->send(encode_json( + $c->send(decode('UTF-8', encode_json( { success => false, msg => $c->l('Error: unable to find the file. Are you sure of your URL?') } - )); + ))); } } @@ -309,13 +308,13 @@ sub r { my $c = shift; my $short = $c->param('short'); - my @records = LufiDB::Files->select('WHERE short = ?', $short); - if (scalar @records) { - my $f = Lufi::File->new(record => $records[0]); + my $ldfile = Lufi::DB::File->new(app => $c->app)->from_short($short); + + if (defined $ldfile) { return $c->render( template => 'render', - f => $f, - file_pwd => ($c->config('allow_pwd_on_files') && defined($records[0]->{passwd})) + f => $ldfile, + file_pwd => ($c->config('allow_pwd_on_files') && defined($ldfile->passwd)) ); } else { return $c->render( @@ -331,15 +330,16 @@ sub get_counter { my $token = $c->param('token'); if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) { - my @records = LufiDB::Files->select('WHERE short = ?', $short); - if (scalar(@records)) { - if ($records[0]->mod_token eq $token) { + my $ldfile = Lufi::DB::File->new(app => $c->app)->from_short($short); + + if (defined $ldfile) { + if ($ldfile->mod_token eq $token) { return $c->render( json => { success => true, short => $short, - counter => $records[0]->counter, - deleted => ($records[0]->deleted) ? true : false + counter => $ldfile->counter, + deleted => ($ldfile->deleted) ? true : false } ); } else { @@ -380,14 +380,16 @@ sub delete { my $token = $c->param('token'); if ((!defined($c->config('ldap')) && !defined($c->config('htpasswd'))) || $c->is_user_authenticated) { - my @records = LufiDB::Files->select('WHERE short = ? AND mod_token = ?', ($short, $token)); - if (scalar(@records)) { - my $f = Lufi::File->new(record => $records[0]); + my $ldfile = Lufi::DB::File->new(app => $c->app)->from_short($short); + + $ldfile = undef unless (defined($ldfile) && $ldfile->mod_token eq $token); + + if (defined $ldfile) { my $msg; - if ($f->deleted) { + if ($ldfile->deleted) { $msg = $c->l('The file has already been deleted'); } else { - $f->delete; + $ldfile->delete; $msg = $c->l('File deleted'); } return $c->respond_to( @@ -400,7 +402,7 @@ sub delete { any => sub { $c->render( template => 'msg', - f => $f, + f => $ldfile, msg => $msg ); } diff --git a/lib/Lufi/Controller/Misc.pm b/lib/Lufi/Controller/Misc.pm index a688559..1783d61 100644 --- a/lib/Lufi/Controller/Misc.pm +++ b/lib/Lufi/Controller/Misc.pm @@ -2,22 +2,18 @@ package Lufi::Controller::Misc; use Mojo::Base 'Mojolicious::Controller'; use Mojo::File; -use LufiDB; -use Lufi::File; -use Lufi::Slice; +use Lufi::DB::File; sub fullstats { my $c = shift; - my $files = LufiDB::Files->count('WHERE created_at IS NOT null AND deleted = 0'); - my $deleted = LufiDB::Files->count('WHERE created_at IS NOT null AND deleted = 1'); - my $empty = LufiDB::Files->count('WHERE created_at IS null'); + my $stats = Lufi::DB::File->new(app => $c->app)->get_stats; return $c->render( json => { - files => $files, - deleted => $deleted, - empty => $empty, + files => $stats->{files}, + deleted => $stats->{deleted}, + empty => $stats->{empty}, timestamp => time, } ); diff --git a/lib/Lufi/DB/File.pm b/lib/Lufi/DB/File.pm new file mode 100644 index 0000000..09d6589 --- /dev/null +++ b/lib/Lufi/DB/File.pm @@ -0,0 +1,291 @@ +# vim:set sw=4 ts=4 sts=4 ft=perl expandtab: +package Lufi::DB::File; +use Mojo::Base -base; +use Mojo::Collection; + +has 'short'; +has 'deleted' => 0; +has 'mediatype'; +has 'filename'; +has 'filesize'; +has 'counter' => 0; +has 'delete_at_first_view' => 0; +has 'delete_at_day'; +has 'created_at' => sub { + return time; +}; +has 'created_by'; +has 'last_access_at'; +has 'mod_token'; +has 'nbslices'; +has 'complete' => 0; +has 'slices' => sub { + return Mojo::Collection->new(); +}; +has 'passwd'; +has 'app'; + +=head1 NAME + +Lufi::DB::File - DB abstraction layer for Lufi file + +=head1 Contributing + +When creating a new database accessor, make sure that it provides the following subroutines. +After that, modify this file and modify the C subroutine to allow to use your accessor. + +Have a look at Lufi::DB::File::SQLite's code: it's simple and may be more understandable that this doc. + +=head1 Attributes + +=over 1 + +=item B : string + +=item B : boolean + +=item B : string + +=item B : string + +=item B : integer + +=item B : integer + +=item B : boolean + +=item B : integer + +=item B : unix timestamp + +=item B : string + +=item B : unix timestamp + +=item B : string + +=item B : integer + +=item B : boolean + +=item B : Mojo::Collection of Lufi::DB::Slice + +=item B : string + +=item B : a Mojolicious object + +=back + +=head1 Sub routines + +=head2 new + +=over 1 + +=item B : C<$c = Lufi::DB::File-Enew(app =E $self);> + +=item B : any of the attribute above + +=item B : construct a new db accessor object. If the C attribute is provided, it have to load the informations from the database. + +=item B : the db accessor object + +=item B : the app argument is used by Lufi::DB::File to choose which db accessor will be used, you don't need to use it in new(), but you can use it to access helpers or configuration settings in the other subroutines + +=back + +=cut + +sub new { + my $c = shift; + + $c = $c->SUPER::new(@_); + + if (ref($c) eq 'Lufi::DB::File') { + my $dbtype = $c->app->config('dbtype'); + if ($dbtype eq 'sqlite') { + use Lufi::DB::File::SQLite; + $c = Lufi::DB::File::SQLite->new(@_); + #} elsif ($dbtype eq 'postgresql') { + #use Lufi::DB::File::Pg; + #$c = Lufi::DB::File::Pg->new(@_); + } + } + + return $c; +} + +=head2 delete + +=over 1 + +=item B : C<$c-Edelet> + +=item B : none + +=item B : delete the files of the slices and the directory containing those files, then update the object by setting the deleted attribute to 1 (true) + +=item B : the db accessor object + +=back + +=cut + +sub delete { + my $c = shift; + + $c->slices->each(sub { + my ($e, $num) = @_; + unlink $e->path; + }); + rmdir Mojo::File->new($c->app->config('upload_dir'), $c->short); + $c->deleted(1); + + $c->write; + + return $c; +} + +=head2 write + +=over 1 + +=item B : C<$c-Ewrite> + +=item B : none + +=item B : create or update a record in the database, with the values of the object's attributes + +=item B : the db accessor object + +=back + +=head2 count_empty + +=over 1 + +=item B : C<$c-Ecount_empty> + +=item B : none + +=item B : count how many records have a null created_at column + +=item B : integer + +=back + +=head2 already_exists + +=over 1 + +=item B : C<$c-Ealready_exists($short)> + +=item B : a string + +=item B : check if the given string is already used as short attribute for a file + +=item B : 1 or 0 + +=back + +=head2 get_empty + +=over 1 + +=item B : C<$c-Eget_empty> + +=item B : none + +=item B : select an empty ready-to-use record from the database + +=item B : a db accessor object + +=back + +=head2 get_stats + +=over 1 + +=item B : C<$c-Eget_stats> + +=item B : none + +=item B : get stats about how many empty files, deleted files and non-deleted files there is in the database + +=item B : a hash table reference containing three keys: files, deleted and empty + +=back + +=head2 from_short + +=over 1 + +=item B : C<$c-Efrom_short($short)> + +=item B : string + +=item B : find a file in the database from its short attribute + +=item B : a db accessor object + +=back + +=head2 get_oldest_undeleted_files + +=over 1 + +=item B : C<$c-Eget_oldest_undeleted_files($num)> + +=item B : integer + +=item B : get the X oldest non-deleted files + +=item B : a Mojo::Collection of Lufi::DB::File objects + +=back + +=head2 get_expired + +=over 1 + +=item B : C<$c-Eget_expired($time)> + +=item B : unix timestamp + +=item B : get the non-deleted files that are expired at the given timestamp minus 2 days + +=item B : a Mojo::Collection of Lufi::DB::File objects + +=back + +=head2 get_no_longer_viewed + +=over 1 + +=item B : C<$c-Eget_no_longer_viewed($time)> + +=item B : unix timestamp + +=item B : get the files that have not been viewed after the given timestamp + +=item B : a Mojo::Collection of Lufi::DB::File objects + +=back + +=head2 delete_creator_before + +=over 1 + +=item B : C<$c-Edelete_creator_before($time)> + +=item B : unix timestamp + +=item B : empty the created_by column for files created before the given timestamp + +=item B : nothing + +=back + +=cut + +1; diff --git a/lib/Lufi/DB/File/SQLite.pm b/lib/Lufi/DB/File/SQLite.pm new file mode 100644 index 0000000..e0e37a9 --- /dev/null +++ b/lib/Lufi/DB/File/SQLite.pm @@ -0,0 +1,192 @@ +# vim:set sw=4 ts=4 sts=4 ft=perl expandtab: +package Lufi::DB::File::SQLite; +use Mojo::Base 'Lufi::DB::File'; +use Mojo::File; +use Mojo::Collection 'c'; +use Lufi::DB::SQLite; +use Lufi::DB::Slice; + +has 'record'; + +sub new { + my $c = shift; + + $c = $c->SUPER::new(@_); + $c = $c->_slurp if defined $c->record; + + return $c; +} + +sub write { + my $c = shift; + + if (defined $c->record) { + $c->record->update( + short => $c->short, + deleted => $c->deleted, + mediatype => $c->mediatype, + filename => $c->filename, + filesize => $c->filesize, + counter => $c->counter, + delete_at_first_view => $c->delete_at_first_view, + delete_at_day => $c->delete_at_day, + created_at => $c->created_at, + created_by => $c->created_by, + last_access_at => $c->last_access_at, + mod_token => $c->mod_token, + nbslices => $c->nbslices, + complete => $c->complete, + passwd => $c->passwd, + ); + } else { + my $record = Lufi::DB::SQLite::Files->create( + short => $c->short, + deleted => $c->deleted, + mediatype => $c->mediatype, + filename => $c->filename, + filesize => $c->filesize, + counter => $c->counter, + delete_at_first_view => $c->delete_at_first_view, + delete_at_day => $c->delete_at_day, + created_at => $c->created_at, + created_by => $c->created_by, + last_access_at => $c->last_access_at, + mod_token => $c->mod_token, + nbslices => $c->nbslices, + complete => $c->complete, + passwd => $c->passwd, + ); + $c->record($record); + } + + return $c; +} + +sub count_empty { + my $c = shift; + + return Lufi::DB::SQLite::Files->count('WHERE created_at IS NULL'); +} + +sub already_exists { + my $c = shift; + my $short = shift; + + return Lufi::DB::SQLite::Files->count('WHERE short = ?', $short); +} + +sub get_empty { + my $c = shift; + + my @records = Lufi::DB::SQLite::Files->select('WHERE created_at IS NULL LIMIT 1'); + $c->record($records[0]); + $c->record->update(created_at => time); + $c->write; + $c->_slurp; + + return $c; +} + +sub get_stats { + my $c = shift; + + my $files = Lufi::DB::SQLite::Files->count('WHERE created_at IS NOT null AND deleted = 0'); + my $deleted = Lufi::DB::SQLite::Files->count('WHERE created_at IS NOT null AND deleted = 1'); + my $empty = Lufi::DB::SQLite::Files->count('WHERE created_at IS null'); + + return {files => $files, deleted => $deleted, empty => $empty}; +} + +sub from_short { + my $c = shift; + my $short = shift; + + my @records = Lufi::DB::SQLite::Files->select('WHERE short = ?', $short); + + if (scalar @records) { + $c->record($records[0]); + $c->_slurp; + + return $c; + } else { + return undef; + } +} + +sub get_oldest_undeleted_files { + my $c = shift; + my $num = shift; + + my @files = Lufi::DB::SQLite::Files->select('WHERE deleted = 0 ORDER BY created_at ASC LIMIT ?', $num); + + return c(map { Lufi::DB::File->new(app => $c->app, record => $_) } @files); +} + +sub get_expired { + my $c = shift; + my $time = shift; + + ## Select only files expired since two days, to be sure that nobody is still downloading it + my @files = LufiDB::Files->select('WHERE deleted = 0 AND ((delete_at_day + 2) * 86400) < (? - created_at) AND delete_at_day != 0', $time); + + return c(map { Lufi::DB::File->new(app => $c->app, record => $_) } @files); +} + +sub get_no_longer_viewed { + my $c = shift; + my $time = shift; + + my @files = LufiDB::Files->select('WHERE deleted = 0 AND last_access_at < ?', $time); + + return c(map { Lufi::DB::File->new(app => $c->app, record => $_) } @files); +} + +sub delete_creator_before { + my $c = shift; + my $separation = shift; + + Lufi::DB::SQLite->do( + 'UPDATE files SET created_by = NULL WHERE created_by IS NOT NULL AND created_at < ?', + {}, + $separation + ); +} + +sub _slurp { + my $c = shift; + + my @files; + if ($c->record) { + @files = ($c->record); + } elsif ($c->short) { + @files = Lufi::DB::SQLite::Files->select('WHERE short = ?', $c->short); + } + + if (scalar @files) { + my $file = $files[0]; + + $c->short($file->short); + $c->deleted($file->deleted) if defined $file->deleted; + $c->mediatype($file->mediatype) if defined $file->mediatype; + $c->filename($file->filename) if defined $file->filename; + $c->filesize($file->filesize) if defined $file->filesize; + $c->counter($file->counter) if defined $file->counter; + $c->delete_at_first_view($file->delete_at_first_view) if defined $file->delete_at_first_view; + $c->delete_at_day($file->delete_at_day) if defined $file->delete_at_day; + $c->created_at($file->created_at) if defined $file->created_at; + $c->created_by($file->created_by) if defined $file->created_by; + $c->last_access_at($file->last_access_at) if defined $file->last_access_at; + $c->mod_token($file->mod_token) if defined $file->mod_token; + $c->nbslices($file->nbslices) if defined $file->nbslices; + $c->complete($file->complete) if defined $file->complete; + $c->passwd($file->passwd) if defined $file->passwd; + + $c->record($file) unless $c->record; + } + + $c->slices(Lufi::DB::Slice->new(app => $c->app)->get_slices_of_file($c->short)); + + return $c; +} + +1; diff --git a/lib/Lufi/DB/SQLite.pm b/lib/Lufi/DB/SQLite.pm new file mode 100644 index 0000000..4553f56 --- /dev/null +++ b/lib/Lufi/DB/SQLite.pm @@ -0,0 +1,64 @@ +# vim:set sw=4 ts=4 sts=4 ft=perl expandtab: +package Lufi::DB::SQLite; +use Mojolicious; +use Mojo::File; +use FindBin qw($Bin); + +BEGIN { + my $m = Mojolicious->new; + my $cfile = Mojo::File->new($Bin, '..' , 'lufi.conf'); + if (defined $ENV{MOJO_CONFIG}) { + $cfile = Mojo::File->new($ENV{MOJO_CONFIG}); + unless (-e $cfile->to_abs) { + $cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG}); + } + } + our $config = $m->plugin('Config' => + { + file => $cfile->to_abs->to_string, + default => { + db_path => 'lufi.db' + } + } + ); +} + +# Create database +use ORLite { + file => $config->{db_path}, + unicode => 1, + create => sub { + my $dbh = shift; + $dbh->do( + 'CREATE TABLE files ( + short TEXT PRIMARY KEY, + deleted INTEGER, + mediatype TEXT, + filename TEXT, + filesize INTEGER, + counter INTEGER, + delete_at_first_view INTEGER, + delete_at_day INTEGER, + created_at INTEGER, + created_by TEXT, + last_access_at INTEGER, + mod_token TEXT, + nbslices INTEGER, + complete INTEGER, + passwd TEXT)' + ); + $dbh->do( + 'CREATE TABLE slices ( + short TEXT, + j INTEGER, + path TEXT, + FOREIGN KEY (short) REFERENCES files(short))' + ); + $dbh->do( + 'CREATE INDEX slices_idx ON slices(short)' + ); + return 1; + } +}; + +1; diff --git a/lib/Lufi/DB/Slice.pm b/lib/Lufi/DB/Slice.pm new file mode 100644 index 0000000..5d77b4b --- /dev/null +++ b/lib/Lufi/DB/Slice.pm @@ -0,0 +1,104 @@ +# vim:set sw=4 ts=4 sts=4 ft=perl expandtab: +package Lufi::DB::Slice; +use Mojo::Base -base; + +has 'short'; +has 'j'; +has 'path'; +has 'app'; + +=head1 NAME + +Lufi::DB::Slice - DB abstraction layer for Lufi file + +=head1 Contributing + +When creating a new database accessor, make sure that it provides the following subroutines. +After that, modify this file and modify the C subroutine to allow to use your accessor. + +Have a look at Lufi::DB::Slice::SQLite's code: it's simple and may be more understandable that this doc. + +=head1 Attributes + +=over 1 + +=item B : string + +=item B : integer + +=item B : string + +=item B : A mojolicious object + +=back + +=head1 Sub routines + +=head2 new + +=over 1 + +=item B : C<$c = Lufi::DB::Slice-Enew(app =E $self);> + +=item B : any of the attribute above + +=item B : construct a new db accessor object. If the C attribute is provided, it have to load the informations from the database. + +=item B : the db accessor object + +=item B : the app argument is used by Lufi::DB::Slice to choose which db accessor will be used, you don't need to use it in new(), but you can use it to access helpers or configuration settings in the other subroutines + +=back + +=cut + +sub new { + my $c = shift; + + $c = $c->SUPER::new(@_); + + if (ref($c) eq 'Lufi::DB::Slice') { + my $dbtype = $c->app->config('dbtype'); + if ($dbtype eq 'sqlite') { + use Lufi::DB::Slice::SQLite; + $c = Lufi::DB::Slice::SQLite->new(@_); + #} elsif ($dbtype eq 'postgresql') { + # use Lufi::DB::Slice::Pg; + # $c = Lufi::DB::Slice::Pg->new(@_); + } + } + + return $c; +} + +=head2 write + +=over 1 + +=item B : C<$c-Ewrite> + +=item B : none + +=item B : create or update a record in the database, with the values of the object's attributes + +=item B : the db accessor object + +=back + +=head2 get_slices_of_file + +=over 1 + +=item B : C<$c-Eget_slices_of_file($short)> + +=item B : string + +=item B : get all Lufi::DB::Slice objects related to a file + +=item B : a Mojo::Collection of Lufi::DB::Slice objects + +=back + +=cut + +1; diff --git a/lib/Lufi/DB/Slice/SQLite.pm b/lib/Lufi/DB/Slice/SQLite.pm new file mode 100644 index 0000000..5927f9b --- /dev/null +++ b/lib/Lufi/DB/Slice/SQLite.pm @@ -0,0 +1,59 @@ +# vim:set sw=4 ts=4 sts=4 ft=perl expandtab: +package Lufi::DB::Slice::SQLite; +use Mojo::Base 'Lufi::DB::Slice'; +use Lufi::DB::SQLite; +use Mojo::Collection 'c'; + +has 'record'; + +sub new { + my $c = shift; + + $c = $c->SUPER::new(@_); + + $c = $c->_slurp if defined $c->record; + + return $c; +} + +sub write { + my $c = shift; + + if (defined $c->record) { + $c->record->update( + short => $c->short, + j => $c->j, + path => $c->path + ); + } else { + my $record = Lufi::DB::SQLite::Slices->create( + short => $c->short, + j => $c->j, + path => $c->path + ); + $c->record($record); + } + + return $c; +} + +sub get_slices_of_file { + my $c = shift; + my $short = shift; + + my @slices = Lufi::DB::SQLite::Slices->select('WHERE short = ? ORDER BY j ASC', $short); + + return c(map { Lufi::DB::Slice->new(app => $c->app, record => $_) } @slices); +} + +sub _slurp { + my $c = shift; + + $c->short($c->record->short) if defined $c->record->short; + $c->j($c->record->j) if defined $c->record->j; + $c->path($c->record->path) if defined $c->record->path; + + return $c; +} + +1; diff --git a/lib/Lufi/File.pm b/lib/Lufi/File.pm deleted file mode 100644 index ddc3613..0000000 --- a/lib/Lufi/File.pm +++ /dev/null @@ -1,103 +0,0 @@ -# vim:set sw=4 ts=4 sts=4 ft=perl expandtab: -package Lufi::File; -use Mojo::Base -base; -use Mojo::Collection; -use LufiDB; -use Lufi::Slice; - -has 'record'; -has 'short'; -has 'deleted' => 0; -has 'mediatype'; -has 'filename'; -has 'filesize'; -has 'counter' => 0; -has 'delete_at_first_view' => 0; -has 'delete_at_day'; -has 'created_at' => sub { - return time; -}; -has 'created_by'; -has 'last_access_at'; -has 'mod_token'; -has 'nbslices'; -has 'complete' => 0; -has 'slices' => sub { - return Mojo::Collection->new(); -}; -has 'passwd'; - -sub new { - my $c = shift; - - $c = $c->SUPER::new(@_); - - $c = $c->_slurp if defined $c->record; - - return $c; -} - -sub write { - my $c = shift; - - $c->record->update( - deleted => $c->deleted, - mediatype => $c->mediatype, - filename => $c->filename, - filesize => $c->filesize, - counter => $c->counter, - delete_at_first_view => $c->delete_at_first_view, - delete_at_day => $c->delete_at_day, - created_at => $c->created_at, - created_by => $c->created_by, - last_access_at => $c->last_access_at, - mod_token => $c->mod_token, - nbslices => $c->nbslices, - complete => $c->complete, - passwd => $c->passwd, - ); - - return $c; -} - -sub delete { - my $c = shift; - - $c->slices->each(sub { - my ($e, $num) = @_; - unlink $e->path; - }); - $c->deleted(1); - - $c->write; - - return $c; -} - -sub _slurp { - my $c = shift; - - $c->short($c->record->short); - $c->deleted($c->record->deleted) if defined $c->record->deleted; - $c->mediatype($c->record->mediatype) if defined $c->record->mediatype; - $c->filename($c->record->filename) if defined $c->record->filename; - $c->filesize($c->record->filesize) if defined $c->record->filesize; - $c->counter($c->record->counter) if defined $c->record->counter; - $c->delete_at_first_view($c->record->delete_at_first_view) if defined $c->record->delete_at_first_view; - $c->delete_at_day($c->record->delete_at_day) if defined $c->record->delete_at_day; - $c->created_at($c->record->created_at) if defined $c->record->created_at; - $c->created_by($c->record->created_by) if defined $c->record->created_by; - $c->last_access_at($c->record->last_access_at) if defined $c->record->last_access_at; - $c->mod_token($c->record->mod_token) if defined $c->record->mod_token; - $c->nbslices($c->record->nbslices) if defined $c->record->nbslices; - $c->complete($c->record->complete) if defined $c->record->complete; - $c->passwd($c->record->passwd) if defined $c->record->passwd; - - my @slices = LufiDB::Slices->select('WHERE short = ? ORDER BY j ASC', $c->short); - - $c->slices(Mojo::Collection->new(map { Lufi::Slice->new(record => $_) } @slices)); - - return $c; -} - -1; diff --git a/lib/Lufi/Plugin/Helpers.pm b/lib/Lufi/Plugin/Helpers.pm index cda1381..1d5539f 100644 --- a/lib/Lufi/Plugin/Helpers.pm +++ b/lib/Lufi/Plugin/Helpers.pm @@ -1,20 +1,37 @@ # vim:set sw=4 ts=4 sts=4 ft=perl expandtab: package Lufi::Plugin::Helpers; use Mojo::Base 'Mojolicious::Plugin'; +use Lufi::DB::File; use Data::Entropy qw(entropy_source); -use LufiDB; sub register { my ($self, $app) = @_; - # SQLite database migration if needed - my $columns = LufiDB::Files->table_info; - my $pwd_col = 0; - foreach my $col (@{$columns}) { - $pwd_col = 1 if $col->{name} eq 'passwd'; - } - unless ($pwd_col) { - LufiDB->do('ALTER TABLE files ADD COLUMN passwd TEXT;'); + $app->plugin('PgURLHelper'); + # + # if ($app->config('dbtype') eq 'postgresql') { + # use Mojo::Pg; + # $app->helper(pg => \&_pg); + # + # # Database migration + # my $migrations = Mojo::Pg::Migrations->new(pg => $app->pg); + # if ($app->mode eq 'development' && $ENV{LUFI_DEV} == 1) { + # $migrations->from_file('utilities/migrations.sql')->migrate(0)->migrate(1); + # } else { + # $migrations->from_file('utilities/migrations.sql')->migrate(1); + # } + # } elsif ($app->config('dbtype') eq 'sqlite') { + if ($app->config('dbtype') eq 'sqlite') { + # SQLite database migration if needed + use Lufi::DB::SQLite; + my $columns = Lufi::DB::SQLite::Files->table_info; + my $pwd_col = 0; + foreach my $col (@{$columns}) { + $pwd_col = 1 if $col->{name} eq 'passwd'; + } + unless ($pwd_col) { + Lufi::DB::SQLite->do('ALTER TABLE files ADD COLUMN passwd TEXT;'); + } } $app->helper(provisioning => \&_provisioning); @@ -27,23 +44,26 @@ sub register { $app->helper(stop_upload => \&_stop_upload); } +sub _pg { + my $c = shift; + + state $pg = Mojo::Pg->new($c->app->pg_url($c->app->config('pgdb'))); + return $pg; +} + sub _provisioning { my $c = shift; # Create some short patterns for provisioning - if (LufiDB::Files->count('WHERE created_at IS NULL') < $c->config('provisioning')) { - for (my $i = 0; $i < $c->config('provis_step'); $i++) { - if (LufiDB->begin) { - my $short; - do { - $short= $c->shortener($c->config('length')); - } while (LufiDB::Files->count('WHERE short = ?', $short)); - - LufiDB::Files->create( - short => $short - ); - LufiDB->commit; - } + my $ldfile = Lufi::DB::File->new(app => $c->app); + if ($ldfile->count_empty < $c->app->config('provisioning')) { + for (my $i = 0; $i < $c->app->config('provis_step'); $i++) { + my $short; + do { + $short = $c->shortener($c->app->config('length')); + } while ($ldfile->already_exists($short)); + + $ldfile->created_at(undef)->short($short)->write; } } } @@ -51,8 +71,9 @@ sub _provisioning { sub _get_empty { my $c = shift; - my @records = LufiDB::Files->select('WHERE created_at IS NULL LIMIT 1'); - return $records[0]; + my $ldfile = Lufi::DB::File->new(app => $c->app)->get_empty; + + return $ldfile; } sub _shortener { @@ -79,7 +100,7 @@ sub _ip { sub _default_delay { my $c = shift; - return $c->config('default_delay') if ($c->config('default_delay') >= 0); + return $c->app->config('default_delay') if ($c->app->config('default_delay') >= 0); warn "default_delay set to a negative value. Default to 0."; return 0; @@ -88,7 +109,7 @@ sub _default_delay { sub _max_delay { my $c = shift; - return $c->config('max_delay') if ($c->config('max_delay') >= 0); + return $c->app->config('max_delay') if ($c->app->config('max_delay') >= 0); warn "max_delay set to a negative value. Default to 0."; return 0; diff --git a/lib/Lufi/Slice.pm b/lib/Lufi/Slice.pm deleted file mode 100644 index 2821032..0000000 --- a/lib/Lufi/Slice.pm +++ /dev/null @@ -1,52 +0,0 @@ -# vim:set sw=4 ts=4 sts=4 ft=perl expandtab: -package Lufi::Slice; -use Mojo::Base -base; -use LufiDB; - -has 'record'; -has 'short'; -has 'j'; -has 'path'; - -sub new { - my $c = shift; - - $c = $c->SUPER::new(@_); - - $c = $c->_slurp if defined $c->record; - - return $c; -} - -sub write { - my $c = shift; - - if (defined $c->record) { - $c->record->update( - short => $c->short, - j => $c->j, - path => $c->path - ); - } else { - my $record = LufiDB::Slices->create( - short => $c->short, - j => $c->j, - path => $c->path - ); - $c->record($record); - } - - return $c; -} - -sub _slurp { - my $c = shift; - - $c->short($c->record->short) if defined $c->record->short; - $c->j($c->record->j) if defined $c->record->j; - $c->path($c->record->path) if defined $c->record->path; - - return $c; -} - -1; diff --git a/lib/LufiDB.pm b/lib/LufiDB.pm deleted file mode 100644 index 1bb66f4..0000000 --- a/lib/LufiDB.pm +++ /dev/null @@ -1,57 +0,0 @@ -# vim:set sw=4 ts=4 sts=4 ft=perl expandtab: -package LufiDB; -use Mojolicious; -use FindBin qw($Bin); -use File::Spec::Functions; - -BEGIN { - my $m = Mojolicious->new; - our $config = $m->plugin('Config' => - { - file => catfile($Bin, '..' ,'lufi.conf'), - default => { - db_path => 'lufi.db' - } - } - ); -} - -# Create database -use ORLite { - file => $config->{db_path}, - unicode => 1, - create => sub { - my $dbh = shift; - $dbh->do( - 'CREATE TABLE files ( - short TEXT PRIMARY KEY, - deleted INTEGER, - mediatype TEXT, - filename TEXT, - filesize INTEGER, - counter INTEGER, - delete_at_first_view INTEGER, - delete_at_day INTEGER, - created_at INTEGER, - created_by TEXT, - last_access_at INTEGER, - mod_token TEXT, - nbslices INTEGER, - complete INTEGER, - passwd TEXT)' - ); - $dbh->do( - 'CREATE TABLE slices ( - short TEXT, - j INTEGER, - path TEXT, - FOREIGN KEY (short) REFERENCES files(short))' - ); - $dbh->do( - 'CREATE INDEX slices_idx ON slices(short)' - ); - return 1; - } -}; - -1; diff --git a/lufi.conf.template b/lufi.conf.template index 56bda8f..218f23b 100755 --- a/lufi.conf.template +++ b/lufi.conf.template @@ -107,12 +107,28 @@ # Optional, default to no-reply@lufi.io #mail_sender => 'no-reply@lufi.io', + # choose what database you want to use + # valid choices are sqlite and postgresql (all lowercase) + # optional, default is sqlite + #dbtype => 'sqlite', + + # SQLite ONLY - only used if dbtype is set to sqlite # define a path to the SQLite database # you can define it relative to lufi directory or set an absolute path - # remember that it has to be in a directory writable by Lufi user + # remember that it has to be in a directory writable by Lutim user # optional, default is lufi.db #db_path => 'lufi.db', + # PostgreSQL ONLY - only used if dbtype is set to postgresql + # these are the credentials to access the PostgreSQL database + # mandatory if you choosed postgresql as dbtype + #pgdb => { + # database => 'lufi', + # host => 'localhost', + # #user => 'DBUSER', + # #pwd => 'DBPASSWORD' + #}, + # define a path to the upload directory, where the uploaded files will be stored # you can define it relative to lufi directory or set an absolute path # remember that it has to be in a directory writable by Lufi user diff --git a/themes/default/lib/Lufi/I18N/ca.po b/themes/default/lib/Lufi/I18N/ca.po index 86bd4a9..80a9ba1 100644 --- a/themes/default/lib/Lufi/I18N/ca.po +++ b/themes/default/lib/Lufi/I18N/ca.po @@ -93,15 +93,15 @@ msgstr "Copia tots els enllaços al porta-retalls" msgid "Copy to clipboard" msgstr "Copia al porta-retalls" -#: lib/Lufi/Controller/Files.pm:423 +#: lib/Lufi/Controller/Files.pm:429 msgid "Could not delete the file. You are not authenticated." msgstr "No es pot esborrar el fitxer. No esteu autenticat." -#: lib/Lufi/Controller/Files.pm:407 +#: lib/Lufi/Controller/Files.pm:411 msgid "Could not find the file. Are you sure of the URL and the token?" msgstr "No es troba el fitxer. Esteu segur de la URL i el testimoni?" -#: lib/Lufi/Controller/Files.pm:323 +#: lib/Lufi/Controller/Files.pm:322 msgid "Could not find the file. Are you sure of the URL?" msgstr "No trobo el fitxer. Esteu segurs de la URL?" @@ -157,15 +157,15 @@ msgstr "correus electrònics" msgid "Encrypting part XX1 of XX2" msgstr "S'està xifrant la part XX1 de XX2" -#: lib/Lufi/Controller/Files.pm:230 +#: lib/Lufi/Controller/Files.pm:225 msgid "Error: the file existed but was deleted." msgstr "Error: el fitxer existia però va ser eliminat." -#: lib/Lufi/Controller/Files.pm:292 +#: lib/Lufi/Controller/Files.pm:291 msgid "Error: the file has not been sent entirely." msgstr "Error: el fitxer no s'ha enviat del tot." -#: lib/Lufi/Controller/Files.pm:302 +#: lib/Lufi/Controller/Files.pm:301 msgid "Error: unable to find the file. Are you sure of your URL?" msgstr "Error: no trobo el fitxer. Esteu segur de la URL ?" @@ -181,7 +181,7 @@ msgstr "Expira el" msgid "Export localStorage data" msgstr "Exporta dades a l'emmagatzematge local" -#: lib/Lufi/Controller/Files.pm:391 +#: lib/Lufi/Controller/Files.pm:393 msgid "File deleted" msgstr "Fitxer eliminat" @@ -275,7 +275,7 @@ msgid "My files" msgstr "Els meus fitxers" #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:70 +#: lib/Lufi/Controller/Files.pm:69 msgid "No enough space available on the server for this file (size: %1)." msgstr "No hi ha prou espai al servidor per a aquest fitxer (mida: %1)" @@ -300,7 +300,7 @@ msgstr "Si us plau contacteu amb l'administrador: %1" msgid "Please wait while we are getting your file. We first need to download and decrypt all parts before you can get it." msgstr "Si us plau, espereu mentre obtenim el fitxer. Abans que el tingueu disponible primer cal descarregar i desxifrar tots els trossos." -#: lib/Lufi.pm:300 +#: lib/Lufi.pm:191 msgid "Please, check your credentials: unable to authenticate." msgstr "" @@ -341,7 +341,7 @@ msgstr "Compartiu fitxers amb total privacitat a %1" msgid "Signin" msgstr "Autenticació" -#: lib/Lufi.pm:303 +#: lib/Lufi.pm:194 msgid "Sorry mate, you are not authorised to use that service. Contact your sysadmin if you think there's a glitch in the matrix." msgstr "" @@ -349,7 +349,7 @@ msgstr "" msgid "Sorry, the uploading is currently disabled. Please try again later." msgstr "Disculpeu, les pujades estan actualment desactivades. Si us plau proveu-ho més tard." -#: lib/Lufi/Controller/Files.pm:44 +#: lib/Lufi/Controller/Files.pm:43 msgid "Sorry, uploading is disabled." msgstr "Disculpeu, les pujades estan deshabilitades" @@ -371,7 +371,7 @@ msgstr "El cos del correu no pot estar buit." msgid "The email subject can't be empty." msgstr "L'assumpte dle correu no pot estar buit." -#: lib/Lufi/Controller/Files.pm:388 +#: lib/Lufi/Controller/Files.pm:390 msgid "The file has already been deleted" msgstr "El fitxer ja ha estat esborrat" @@ -396,7 +396,7 @@ msgstr "El correu ja està enviat." msgid "The original (and only for now) author is Luc Didry. If you want to support him, you can do it via Tipeee or via Liberapay." msgstr "L'autor original (i per ara l'únic) és Luc Didry. Si voleu fer una contribució podeu fer-ho via Tipeee o via Liberapay." -#: lib/Lufi/Controller/Files.pm:182 +#: lib/Lufi/Controller/Files.pm:179 msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator." msgstr "El servidor no ha pogut trobar el registre del fitxer per afegir-hi el tros del fitxer. Si us plau, contacteu l'administrador." @@ -476,11 +476,11 @@ msgid "You must give email addresses." msgstr "Heu de donar l'adreça de correu electrònic." #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:57 +#: lib/Lufi/Controller/Files.pm:56 msgid "Your file is too big: %1 (maximum size allowed: %2)" msgstr "El fitxer és massa gran: %1 (mida màxima admesa: %2)" -#: lib/Lufi/Controller/Files.pm:276 +#: lib/Lufi/Controller/Files.pm:273 msgid "Your password is not valid. Please refresh the page to retry." msgstr "" diff --git a/themes/default/lib/Lufi/I18N/en.po b/themes/default/lib/Lufi/I18N/en.po index 876e2f9..b37f64c 100644 --- a/themes/default/lib/Lufi/I18N/en.po +++ b/themes/default/lib/Lufi/I18N/en.po @@ -90,15 +90,15 @@ msgstr "" msgid "Copy to clipboard" msgstr "" -#: lib/Lufi/Controller/Files.pm:423 +#: lib/Lufi/Controller/Files.pm:429 msgid "Could not delete the file. You are not authenticated." msgstr "" -#: lib/Lufi/Controller/Files.pm:407 +#: lib/Lufi/Controller/Files.pm:411 msgid "Could not find the file. Are you sure of the URL and the token?" msgstr "" -#: lib/Lufi/Controller/Files.pm:323 +#: lib/Lufi/Controller/Files.pm:322 msgid "Could not find the file. Are you sure of the URL?" msgstr "" @@ -154,15 +154,15 @@ msgstr "" msgid "Encrypting part XX1 of XX2" msgstr "" -#: lib/Lufi/Controller/Files.pm:230 +#: lib/Lufi/Controller/Files.pm:225 msgid "Error: the file existed but was deleted." msgstr "" -#: lib/Lufi/Controller/Files.pm:292 +#: lib/Lufi/Controller/Files.pm:291 msgid "Error: the file has not been sent entirely." msgstr "" -#: lib/Lufi/Controller/Files.pm:302 +#: lib/Lufi/Controller/Files.pm:301 msgid "Error: unable to find the file. Are you sure of your URL?" msgstr "" @@ -178,7 +178,7 @@ msgstr "" msgid "Export localStorage data" msgstr "" -#: lib/Lufi/Controller/Files.pm:391 +#: lib/Lufi/Controller/Files.pm:393 msgid "File deleted" msgstr "" @@ -271,7 +271,7 @@ msgid "My files" msgstr "" #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:70 +#: lib/Lufi/Controller/Files.pm:69 msgid "No enough space available on the server for this file (size: %1)." msgstr "" @@ -296,7 +296,7 @@ msgstr "" msgid "Please wait while we are getting your file. We first need to download and decrypt all parts before you can get it." msgstr "" -#: lib/Lufi.pm:300 +#: lib/Lufi.pm:191 msgid "Please, check your credentials: unable to authenticate." msgstr "" @@ -337,7 +337,7 @@ msgstr "" msgid "Signin" msgstr "" -#: lib/Lufi.pm:303 +#: lib/Lufi.pm:194 msgid "Sorry mate, you are not authorised to use that service. Contact your sysadmin if you think there's a glitch in the matrix." msgstr "" @@ -345,7 +345,7 @@ msgstr "" msgid "Sorry, the uploading is currently disabled. Please try again later." msgstr "" -#: lib/Lufi/Controller/Files.pm:44 +#: lib/Lufi/Controller/Files.pm:43 msgid "Sorry, uploading is disabled." msgstr "" @@ -365,7 +365,7 @@ msgstr "" msgid "The email subject can't be empty." msgstr "" -#: lib/Lufi/Controller/Files.pm:388 +#: lib/Lufi/Controller/Files.pm:390 msgid "The file has already been deleted" msgstr "" @@ -390,7 +390,7 @@ msgstr "" msgid "The original (and only for now) author is Luc Didry. If you want to support him, you can do it via Tipeee or via Liberapay." msgstr "" -#: lib/Lufi/Controller/Files.pm:182 +#: lib/Lufi/Controller/Files.pm:179 msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator." msgstr "" @@ -470,11 +470,11 @@ msgid "You must give email addresses." msgstr "" #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:57 +#: lib/Lufi/Controller/Files.pm:56 msgid "Your file is too big: %1 (maximum size allowed: %2)" msgstr "" -#: lib/Lufi/Controller/Files.pm:276 +#: lib/Lufi/Controller/Files.pm:273 msgid "Your password is not valid. Please refresh the page to retry." msgstr "" diff --git a/themes/default/lib/Lufi/I18N/fr.po b/themes/default/lib/Lufi/I18N/fr.po index 08c7e3a..74f0993 100644 --- a/themes/default/lib/Lufi/I18N/fr.po +++ b/themes/default/lib/Lufi/I18N/fr.po @@ -92,15 +92,15 @@ msgstr "Copier tous les liens dans le presse-papier" msgid "Copy to clipboard" msgstr "Copier dans le presse-papier" -#: lib/Lufi/Controller/Files.pm:423 +#: lib/Lufi/Controller/Files.pm:429 msgid "Could not delete the file. You are not authenticated." msgstr "Impossible de supprimer le fichier. Vous n’êtes pas connecté·e." -#: lib/Lufi/Controller/Files.pm:407 +#: lib/Lufi/Controller/Files.pm:411 msgid "Could not find the file. Are you sure of the URL and the token?" msgstr "Impossible de retrouver le fichier. Êtes-vous sûr(e) que l’URL et le jeton sont les bons ?" -#: lib/Lufi/Controller/Files.pm:323 +#: lib/Lufi/Controller/Files.pm:322 msgid "Could not find the file. Are you sure of the URL?" msgstr "Impossible de retrouver le fichier. Êtes-vous sûr(e) que l’URL est la bonne ?" @@ -156,15 +156,15 @@ msgstr "Mails" msgid "Encrypting part XX1 of XX2" msgstr "Chiffrement du fragment XX1 sur XX2" -#: lib/Lufi/Controller/Files.pm:230 +#: lib/Lufi/Controller/Files.pm:225 msgid "Error: the file existed but was deleted." msgstr "Erreur : le fichier existait mais a été supprimé" -#: lib/Lufi/Controller/Files.pm:292 +#: lib/Lufi/Controller/Files.pm:291 msgid "Error: the file has not been sent entirely." msgstr "Erreur : le fichier n’a pas été envoyé dans son intégralité" -#: lib/Lufi/Controller/Files.pm:302 +#: lib/Lufi/Controller/Files.pm:301 msgid "Error: unable to find the file. Are you sure of your URL?" msgstr "Erreur : impossible de retrouver le fichier. Êtes-vous sûr(e) de l’URL ?" @@ -180,7 +180,7 @@ msgstr "Expire le" msgid "Export localStorage data" msgstr "Exporter les données localStorage" -#: lib/Lufi/Controller/Files.pm:391 +#: lib/Lufi/Controller/Files.pm:393 msgid "File deleted" msgstr "Fichier supprimé" @@ -273,7 +273,7 @@ msgid "My files" msgstr "Mes fichiers" #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:70 +#: lib/Lufi/Controller/Files.pm:69 msgid "No enough space available on the server for this file (size: %1)." msgstr "Espace disque insuffisant sur le serveur pour ce fichier (taille du fichier : %1)." @@ -298,7 +298,7 @@ msgstr "Veuillez contacter l’administrateur : %1" msgid "Please wait while we are getting your file. We first need to download and decrypt all parts before you can get it." msgstr "Veuillez patientez pendant la récupération de votre fichier. Nous devons d’abord récupérer et déchiffrer tous les fragments avant que vous puissiez le télécharger." -#: lib/Lufi.pm:300 +#: lib/Lufi.pm:191 msgid "Please, check your credentials: unable to authenticate." msgstr "Veuillez vérifier vos identifiants : impossible de vous authentifier." @@ -339,7 +339,7 @@ msgstr "Partagez vos fichiers en toute confidentialité sur %1" msgid "Signin" msgstr "Connexion" -#: lib/Lufi.pm:303 +#: lib/Lufi.pm:194 msgid "Sorry mate, you are not authorised to use that service. Contact your sysadmin if you think there's a glitch in the matrix." msgstr "Désolé, vous n’êtes pas autorisé à utiliser ce service. Contactez votre administrateur si vous pensez qu’il s’agit d’une erreur." @@ -347,7 +347,7 @@ msgstr "Désolé, vous n’êtes pas autorisé à utiliser ce service. Contactez msgid "Sorry, the uploading is currently disabled. Please try again later." msgstr "Désolé, l’envoi de fichier est actuellement désactivé. Veuillez réessayer plus tard." -#: lib/Lufi/Controller/Files.pm:44 +#: lib/Lufi/Controller/Files.pm:43 msgid "Sorry, uploading is disabled." msgstr "Désolé, l’envoi de fichier est désactivé." @@ -367,7 +367,7 @@ msgstr "Le corps du mail ne peut être vide." msgid "The email subject can't be empty." msgstr "Le sujet du mail ne peut être vide." -#: lib/Lufi/Controller/Files.pm:388 +#: lib/Lufi/Controller/Files.pm:390 msgid "The file has already been deleted" msgstr "Le fichier a déjà été supprimé" @@ -392,7 +392,7 @@ msgstr "Le mail a été envoyé." msgid "The original (and only for now) author is Luc Didry. If you want to support him, you can do it via Tipeee or via Liberapay." msgstr "L’auteur originel (et pour l’instant, le seul) est Luc Didry. Si vous avez envie de le supporter, vous pouvez le faire via Tipeee ou via Liberapay." -#: lib/Lufi/Controller/Files.pm:182 +#: lib/Lufi/Controller/Files.pm:179 msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator." msgstr "Le serveur a été incapable de retrouver l’enregistrement du fichier auquel ajouter votre fragment de fichier. Veuillez contacter l’administrateur." @@ -472,11 +472,11 @@ msgid "You must give email addresses." msgstr "Vous devez envoyer des adresses mail." #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:57 +#: lib/Lufi/Controller/Files.pm:56 msgid "Your file is too big: %1 (maximum size allowed: %2)" msgstr "Votre fichier est trop volumineux : %1 (la taille maximum autorisée est %2)" -#: lib/Lufi/Controller/Files.pm:276 +#: lib/Lufi/Controller/Files.pm:273 msgid "Your password is not valid. Please refresh the page to retry." msgstr "Votre mot de passe est invalide. Veuillez rafraîchir la page pour réessayer." diff --git a/themes/default/lib/Lufi/I18N/it.po b/themes/default/lib/Lufi/I18N/it.po index cfa410a..d9938b9 100644 --- a/themes/default/lib/Lufi/I18N/it.po +++ b/themes/default/lib/Lufi/I18N/it.po @@ -92,15 +92,15 @@ msgstr "Copiare tutti i link negli appunti" msgid "Copy to clipboard" msgstr "Copiare negli appunti" -#: lib/Lufi/Controller/Files.pm:423 +#: lib/Lufi/Controller/Files.pm:429 msgid "Could not delete the file. You are not authenticated." msgstr "Impossibile cancellare il file. Non siete autenticati." -#: lib/Lufi/Controller/Files.pm:407 +#: lib/Lufi/Controller/Files.pm:411 msgid "Could not find the file. Are you sure of the URL and the token?" msgstr "Impossibile trovare il file. Sei sicuro che URL e token siano corretti ?" -#: lib/Lufi/Controller/Files.pm:323 +#: lib/Lufi/Controller/Files.pm:322 msgid "Could not find the file. Are you sure of the URL?" msgstr "Impossibile trovare il file. Sei sicuro che l'URL sia corretto?" @@ -156,15 +156,15 @@ msgstr "Email" msgid "Encrypting part XX1 of XX2" msgstr "Cifratura della parte XX1 di XX2" -#: lib/Lufi/Controller/Files.pm:230 +#: lib/Lufi/Controller/Files.pm:225 msgid "Error: the file existed but was deleted." msgstr "Errore: il file esisteva ma è stato eliminato" -#: lib/Lufi/Controller/Files.pm:292 +#: lib/Lufi/Controller/Files.pm:291 msgid "Error: the file has not been sent entirely." msgstr "Errore: il file non è stato inviato completamente" -#: lib/Lufi/Controller/Files.pm:302 +#: lib/Lufi/Controller/Files.pm:301 msgid "Error: unable to find the file. Are you sure of your URL?" msgstr "Errore: impossibile trovare il file. Sei certo dell'URL ?" @@ -180,7 +180,7 @@ msgstr "Scade il" msgid "Export localStorage data" msgstr "Esportare i dati del localStorage" -#: lib/Lufi/Controller/Files.pm:391 +#: lib/Lufi/Controller/Files.pm:393 msgid "File deleted" msgstr "File cancellato" @@ -273,7 +273,7 @@ msgid "My files" msgstr "I miei file" #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:70 +#: lib/Lufi/Controller/Files.pm:69 msgid "No enough space available on the server for this file (size: %1)." msgstr "Spazio disco insufficiente sul server per questo file (dimensione: %1)." @@ -298,7 +298,7 @@ msgstr "Contattare l'amministratore : %1" msgid "Please wait while we are getting your file. We first need to download and decrypt all parts before you can get it." msgstr "Attendere mentre otteniamo il vostro file. Dobbiamo prima scaricare e decifrare tutte le parti prima che possiate averlo." -#: lib/Lufi.pm:300 +#: lib/Lufi.pm:191 msgid "Please, check your credentials: unable to authenticate." msgstr "" @@ -339,7 +339,7 @@ msgstr "Condividi tutti i file in totale riservatezza su %1" msgid "Signin" msgstr "Autenticazione" -#: lib/Lufi.pm:303 +#: lib/Lufi.pm:194 msgid "Sorry mate, you are not authorised to use that service. Contact your sysadmin if you think there's a glitch in the matrix." msgstr "" @@ -347,7 +347,7 @@ msgstr "" msgid "Sorry, the uploading is currently disabled. Please try again later." msgstr "L'invio del file è attualemente disattivato. Riprovare più tardi." -#: lib/Lufi/Controller/Files.pm:44 +#: lib/Lufi/Controller/Files.pm:43 msgid "Sorry, uploading is disabled." msgstr "L'invio del file è attualemente disattivato." @@ -367,7 +367,7 @@ msgstr "Il corpo dell'email non può essere vuoto." msgid "The email subject can't be empty." msgstr "Il soggetto dell'email non può essere vuoto." -#: lib/Lufi/Controller/Files.pm:388 +#: lib/Lufi/Controller/Files.pm:390 msgid "The file has already been deleted" msgstr "Il file è già stato cancellato" @@ -392,7 +392,7 @@ msgstr "Email inviata." msgid "The original (and only for now) author is Luc Didry. If you want to support him, you can do it via Tipeee or via Liberapay." msgstr "L'autore ( e per ora l'unico) è Luc Didry. Se aveste voglia di aiutarlo, potreste farlo tramite Tipeee ou via Liberapay." -#: lib/Lufi/Controller/Files.pm:182 +#: lib/Lufi/Controller/Files.pm:179 msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator." msgstr "Il server non è stato in grado di trovare il file record a cui aggiungere la vostra porzione di file. Prego contattare l'amministratore." @@ -472,11 +472,11 @@ msgid "You must give email addresses." msgstr "Devi fornire gli indirizzi email." #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:57 +#: lib/Lufi/Controller/Files.pm:56 msgid "Your file is too big: %1 (maximum size allowed: %2)" msgstr "Il vostro file è troppo grande : %1 (la dimensione massima permessa è %2)" -#: lib/Lufi/Controller/Files.pm:276 +#: lib/Lufi/Controller/Files.pm:273 msgid "Your password is not valid. Please refresh the page to retry." msgstr "" diff --git a/themes/default/lib/Lufi/I18N/nl.po b/themes/default/lib/Lufi/I18N/nl.po index 93189a3..aafa7c1 100644 --- a/themes/default/lib/Lufi/I18N/nl.po +++ b/themes/default/lib/Lufi/I18N/nl.po @@ -79,15 +79,15 @@ msgstr "Kopieer alle links naar klembord" msgid "Copy to clipboard" msgstr "Kopieer naar klembord" -#: lib/Lufi/Controller/Files.pm:423 +#: lib/Lufi/Controller/Files.pm:429 msgid "Could not delete the file. You are not authenticated." msgstr "Kan het bestand niet verwijderen. Je bent niet geautoriseerd." -#: lib/Lufi/Controller/Files.pm:407 +#: lib/Lufi/Controller/Files.pm:411 msgid "Could not find the file. Are you sure of the URL and the token?" msgstr "Kan het bestand niet vinden. Klopt de URL en token wel?" -#: lib/Lufi/Controller/Files.pm:323 +#: lib/Lufi/Controller/Files.pm:322 msgid "Could not find the file. Are you sure of the URL?" msgstr "Kan het bestand niet vinden. Klopt de URL?" @@ -143,15 +143,15 @@ msgstr "Emails" msgid "Encrypting part XX1 of XX2" msgstr "Encrypten deel XX1 van XX2 " -#: lib/Lufi/Controller/Files.pm:230 +#: lib/Lufi/Controller/Files.pm:225 msgid "Error: the file existed but was deleted." msgstr "Fout: het bestand bestond wel maar is verwijderd." -#: lib/Lufi/Controller/Files.pm:292 +#: lib/Lufi/Controller/Files.pm:291 msgid "Error: the file has not been sent entirely." msgstr "Fout: het bestand is niet volledig opgestuurd." -#: lib/Lufi/Controller/Files.pm:302 +#: lib/Lufi/Controller/Files.pm:301 msgid "Error: unable to find the file. Are you sure of your URL?" msgstr "Fout: kan het bestand niet vinden. Is de URL juist?" @@ -167,7 +167,7 @@ msgstr "Vervalt op" msgid "Export localStorage data" msgstr "Exporteer opgeslagen data" -#: lib/Lufi/Controller/Files.pm:391 +#: lib/Lufi/Controller/Files.pm:393 msgid "File deleted" msgstr "Bestand verwijderd" @@ -260,7 +260,7 @@ msgid "My files" msgstr "Mijn bestanden" #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:70 +#: lib/Lufi/Controller/Files.pm:69 msgid "No enough space available on the server for this file (size: %1)." msgstr "Geen genoeg ruimte op de server voor deze bestand (grootte: %1)." @@ -285,7 +285,7 @@ msgstr "Neem contact op met administrator: %1" msgid "Please wait while we are getting your file. We first need to download and decrypt all parts before you can get it." msgstr "Een ogenblik geduld, we pakken je bestand er bij. We moeten alle delen downloaden en decrypten voordat je het kan downloaden." -#: lib/Lufi.pm:300 +#: lib/Lufi.pm:191 msgid "Please, check your credentials: unable to authenticate." msgstr "" @@ -330,7 +330,7 @@ msgstr "Deel je bestanden met volledige privacy op %1" msgid "Signin" msgstr "Inloggen" -#: lib/Lufi.pm:303 +#: lib/Lufi.pm:194 msgid "Sorry mate, you are not authorised to use that service. Contact your sysadmin if you think there's a glitch in the matrix." msgstr "" @@ -338,7 +338,7 @@ msgstr "" msgid "Sorry, the uploading is currently disabled. Please try again later." msgstr "Sorry, uploaden is momenteel uitgeschakeld. Probeer het later nogmaals." -#: lib/Lufi/Controller/Files.pm:44 +#: lib/Lufi/Controller/Files.pm:43 msgid "Sorry, uploading is disabled." msgstr "SOrry, uploaden is uitgeschakeld." @@ -358,7 +358,7 @@ msgstr "Mail inhoud kan niet leeg zijn." msgid "The email subject can't be empty." msgstr "Onderwerp kan niet leeg zijn." -#: lib/Lufi/Controller/Files.pm:388 +#: lib/Lufi/Controller/Files.pm:390 msgid "The file has already been deleted" msgstr "Bestand is reeds verwijderd" @@ -383,7 +383,7 @@ msgstr "Email is verzonden." msgid "The original (and only for now) author is Luc Didry. If you want to support him, you can do it via Tipeee or via Liberapay." msgstr "De oorspronkelijke auteur is Luc Didry. Als je hem wilt ondersteunen, dan kan dat via Tipeee of via Liberapay." -#: lib/Lufi/Controller/Files.pm:182 +#: lib/Lufi/Controller/Files.pm:179 msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator." msgstr "Server kon een deel van het bestand niet vinden. Neem contact op met beheerder." @@ -463,11 +463,11 @@ msgid "You must give email addresses." msgstr "Je moet een mail adres opgeven." #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:57 +#: lib/Lufi/Controller/Files.pm:56 msgid "Your file is too big: %1 (maximum size allowed: %2)" msgstr "Je bestand is te groot: %1 (max: %2)" -#: lib/Lufi/Controller/Files.pm:276 +#: lib/Lufi/Controller/Files.pm:273 msgid "Your password is not valid. Please refresh the page to retry." msgstr "" diff --git a/themes/default/lib/Lufi/I18N/oc.po b/themes/default/lib/Lufi/I18N/oc.po index f787473..259db3e 100644 --- a/themes/default/lib/Lufi/I18N/oc.po +++ b/themes/default/lib/Lufi/I18N/oc.po @@ -92,15 +92,15 @@ msgstr "Copiar totes los ligams dins lo quichapapièrs" msgid "Copy to clipboard" msgstr "Copiar dins lo quichapapièrs" -#: lib/Lufi/Controller/Files.pm:423 +#: lib/Lufi/Controller/Files.pm:429 msgid "Could not delete the file. You are not authenticated." msgstr "Impossible de suprimir lo fichièr. Sètz pas connectat-ada." -#: lib/Lufi/Controller/Files.pm:407 +#: lib/Lufi/Controller/Files.pm:411 msgid "Could not find the file. Are you sure of the URL and the token?" msgstr "Impossible de trobar lo fichièr. Sètz segur-a que l’URL e lo geton son bons ?" -#: lib/Lufi/Controller/Files.pm:323 +#: lib/Lufi/Controller/Files.pm:322 msgid "Could not find the file. Are you sure of the URL?" msgstr "Impossible de trobar lo fichièr. Sètz segur-a que l’URL es bona ?" @@ -156,15 +156,15 @@ msgstr "Corrièl" msgid "Encrypting part XX1 of XX2" msgstr "Chiframent del tròç XX1 sus XX2" -#: lib/Lufi/Controller/Files.pm:230 +#: lib/Lufi/Controller/Files.pm:225 msgid "Error: the file existed but was deleted." msgstr "Error : lo fichièr existissiá mas es estat suprimit" -#: lib/Lufi/Controller/Files.pm:292 +#: lib/Lufi/Controller/Files.pm:291 msgid "Error: the file has not been sent entirely." msgstr "Error : lo fichièr es pas estat mandat completament" -#: lib/Lufi/Controller/Files.pm:302 +#: lib/Lufi/Controller/Files.pm:301 msgid "Error: unable to find the file. Are you sure of your URL?" msgstr "Error : impossible de trobar lo fichièr. Sètz segur-a de l’URL ?" @@ -180,7 +180,7 @@ msgstr "Expira lo" msgid "Export localStorage data" msgstr "Exportar las donadas localStorage" -#: lib/Lufi/Controller/Files.pm:391 +#: lib/Lufi/Controller/Files.pm:393 msgid "File deleted" msgstr "Fichièr suprimit" @@ -273,7 +273,7 @@ msgid "My files" msgstr "Mos fichièrs" #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:70 +#: lib/Lufi/Controller/Files.pm:69 msgid "No enough space available on the server for this file (size: %1)." msgstr "Espaci disc insufisent sul servidor per aqueste fichièr (talha del fichièr : \"%1)." @@ -298,7 +298,7 @@ msgstr "Mercés de contactar l’administrator : %1" msgid "Please wait while we are getting your file. We first need to download and decrypt all parts before you can get it." msgstr "Mercés d’esperar pendent la recuperacion de vòstre fichièr. Nos cal d’en primièr recuperar e deschifrar totes los fragaments abans que poscatz o telecargar." -#: lib/Lufi.pm:300 +#: lib/Lufi.pm:191 msgid "Please, check your credentials: unable to authenticate." msgstr "" @@ -339,7 +339,7 @@ msgstr "Partejatz vòstres fichièrs en tota confidencialitat sus %1" msgid "Signin" msgstr "Connexion" -#: lib/Lufi.pm:303 +#: lib/Lufi.pm:194 msgid "Sorry mate, you are not authorised to use that service. Contact your sysadmin if you think there's a glitch in the matrix." msgstr "" @@ -347,7 +347,7 @@ msgstr "" msgid "Sorry, the uploading is currently disabled. Please try again later." msgstr "O planhèm, la foncion per mandar de fichièr es desactivada pel moment. Mercés de tornar ensajar mai tard." -#: lib/Lufi/Controller/Files.pm:44 +#: lib/Lufi/Controller/Files.pm:43 msgid "Sorry, uploading is disabled." msgstr "O planhèm, la foncion per mandar de fichièr es desactivada." @@ -367,7 +367,7 @@ msgstr "Lo contengut del corrièl pòt pas èsser void." msgid "The email subject can't be empty." msgstr "Lo sujècte del corrièl pòt pas èsser void." -#: lib/Lufi/Controller/Files.pm:388 +#: lib/Lufi/Controller/Files.pm:390 msgid "The file has already been deleted" msgstr "Lo fichièr es ja estat suprimit" @@ -392,7 +392,7 @@ msgstr "Lo corrièl es estat mandat." msgid "The original (and only for now) author is Luc Didry. If you want to support him, you can do it via Tipeee or via Liberapay." msgstr "L’autor original (e pel moment, lo sol) es Luc Didry. S’avètz enveja de lo sostenir, podètz o far via Tipeee o via Liberapay." -#: lib/Lufi/Controller/Files.pm:182 +#: lib/Lufi/Controller/Files.pm:179 msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator." msgstr "Lo servidor es pas estat capable de retrobar l’enregistrament del fichièr que li cal ajustar vòstre tròç de fichièr. Mercés de contactar l’administrator." @@ -472,11 +472,11 @@ msgid "You must give email addresses." msgstr "Vos cal donar d’adreças." #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:57 +#: lib/Lufi/Controller/Files.pm:56 msgid "Your file is too big: %1 (maximum size allowed: %2)" msgstr "Vòstre fichièr es tròp voluminós : %1 (la talha maximum autorizada es %2)" -#: lib/Lufi/Controller/Files.pm:276 +#: lib/Lufi/Controller/Files.pm:273 msgid "Your password is not valid. Please refresh the page to retry." msgstr "" diff --git a/themes/default/lib/Lufi/I18N/pt.po b/themes/default/lib/Lufi/I18N/pt.po index 35d0d0d..f38cc4d 100644 --- a/themes/default/lib/Lufi/I18N/pt.po +++ b/themes/default/lib/Lufi/I18N/pt.po @@ -93,15 +93,15 @@ msgstr "Copiar todos os links para a área de transferência" msgid "Copy to clipboard" msgstr "Copiar para a área de transferência" -#: lib/Lufi/Controller/Files.pm:423 +#: lib/Lufi/Controller/Files.pm:429 msgid "Could not delete the file. You are not authenticated." msgstr "Impossível apagar o ficheiro. Não está conectado." -#: lib/Lufi/Controller/Files.pm:407 +#: lib/Lufi/Controller/Files.pm:411 msgid "Could not find the file. Are you sure of the URL and the token?" msgstr "Impossível encontrar o ficheiro.Tem a certeza que o URL e os símbolos estão corretos?" -#: lib/Lufi/Controller/Files.pm:323 +#: lib/Lufi/Controller/Files.pm:322 msgid "Could not find the file. Are you sure of the URL?" msgstr "Impossível encontar o ficheiro. Tem a certeza de que o URL está correto?" @@ -161,15 +161,15 @@ msgstr "E-mails" msgid "Encrypting part XX1 of XX2" msgstr "Codificação do fragmento XX1 de XX2" -#: lib/Lufi/Controller/Files.pm:230 +#: lib/Lufi/Controller/Files.pm:225 msgid "Error: the file existed but was deleted." msgstr "Erro: o ficheiro existia mas foi apagado." -#: lib/Lufi/Controller/Files.pm:292 +#: lib/Lufi/Controller/Files.pm:291 msgid "Error: the file has not been sent entirely." msgstr "Erro: o ficheiro não foi enviado na totalidade." -#: lib/Lufi/Controller/Files.pm:302 +#: lib/Lufi/Controller/Files.pm:301 msgid "Error: unable to find the file. Are you sure of your URL?" msgstr "Erro: impossível encontrar o ficheiro. Tem a certeza do URL?" @@ -185,7 +185,7 @@ msgstr "Expira no" msgid "Export localStorage data" msgstr "Exportar os dados localStorage" -#: lib/Lufi/Controller/Files.pm:391 +#: lib/Lufi/Controller/Files.pm:393 msgid "File deleted" msgstr "Ficheiro apagado" @@ -282,7 +282,7 @@ msgid "My files" msgstr "Meus ficheiros" #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:70 +#: lib/Lufi/Controller/Files.pm:69 msgid "No enough space available on the server for this file (size: %1)." msgstr "O servidor não tem espaço suficiente para este ficheiro (tamanho: %1)." @@ -307,7 +307,7 @@ msgstr "Contacte o administrador: %1" msgid "Please wait while we are getting your file. We first need to download and decrypt all parts before you can get it." msgstr "Por favor aguarde durante a recuperação do seu ficheiro. Primeiro devemos recuperar e descodificar todos os fragmentos e depois poderá descarregar o ficheiro." -#: lib/Lufi.pm:300 +#: lib/Lufi.pm:191 msgid "Please, check your credentials: unable to authenticate." msgstr "" @@ -348,7 +348,7 @@ msgstr "Partilhe os seus ficheiros com toda a privacidade em %1" msgid "Signin" msgstr "Conexão" -#: lib/Lufi.pm:303 +#: lib/Lufi.pm:194 msgid "Sorry mate, you are not authorised to use that service. Contact your sysadmin if you think there's a glitch in the matrix." msgstr "" @@ -356,7 +356,7 @@ msgstr "" msgid "Sorry, the uploading is currently disabled. Please try again later." msgstr "Desculpe, o envio do ficheiro está atualmente desativado. Tente mais tarde." -#: lib/Lufi/Controller/Files.pm:44 +#: lib/Lufi/Controller/Files.pm:43 msgid "Sorry, uploading is disabled." msgstr "Desculpe, o envio do ficheiro está desativado." @@ -376,7 +376,7 @@ msgstr "A mensagem do e-mail não pode estar vazia." msgid "The email subject can't be empty." msgstr "O assunto do e-mail não pode estar vazio." -#: lib/Lufi/Controller/Files.pm:388 +#: lib/Lufi/Controller/Files.pm:390 msgid "The file has already been deleted" msgstr "O ficheiro já foi apagado" @@ -401,7 +401,7 @@ msgstr "O e-mail foi enviado." msgid "The original (and only for now) author is Luc Didry. If you want to support him, you can do it via Tipeee or via Liberapay." msgstr "O autor original (e por agora, o único) é Luc Didry. Se o desejar apoiar pode fazer-lo via Tipeee ou via Liberapay." -#: lib/Lufi/Controller/Files.pm:182 +#: lib/Lufi/Controller/Files.pm:179 msgid "The server was unable to find the file record to add your file part to. Please, contact the administrator." msgstr "O servidor foi incapaz de encontrar o registo do ficheiro no qual devia-se juntar o fragmento do seu ficheiro. Contacte o administrador." @@ -485,11 +485,11 @@ msgid "You must give email addresses." msgstr "Deve escrever os e-mails." #. (format_bytes($json->{size}) -#: lib/Lufi/Controller/Files.pm:57 +#: lib/Lufi/Controller/Files.pm:56 msgid "Your file is too big: %1 (maximum size allowed: %2)" msgstr "O seu ficheiro é grande de mais: %1 (o tamanho máximo autorizado é de %2)" -#: lib/Lufi/Controller/Files.pm:276 +#: lib/Lufi/Controller/Files.pm:273 msgid "Your password is not valid. Please refresh the page to retry." msgstr "" diff --git a/themes/default/public/js/lufi-down.js b/themes/default/public/js/lufi-down.js index 1af603d..3285fdf 100644 --- a/themes/default/public/js/lufi-down.js +++ b/themes/default/public/js/lufi-down.js @@ -106,6 +106,10 @@ function spawnWebsocket(pa) { innerHTML.push(''); + } else if (data.type.match(/^audio\//) !== null) { + innerHTML.push(''); } pbd.html(innerHTML.join('')); diff --git a/utilities/migrations_pg.sql b/utilities/migrations_pg.sql new file mode 100644 index 0000000..e2917b2 --- /dev/null +++ b/utilities/migrations_pg.sql @@ -0,0 +1,27 @@ +-- 1 up +CREATE TABLE IF NOT EXISTS files ( + short text PRIMARY KEY, + deleted boolean default false, + mediatype text, + filename text, + filesize integer, + counter integer default 0, + delete_at_first_view boolean, + delete_at_day integer, + created_at integer, + created_by text, + last_access_at integer, + mod_token text, + nbslices integer, + complete boolean default false, + passwd text +); + +CREATE TABLE IF NOT EXISTS slices ( + short text REFERENCES files(short) ON DELETE CASCADE, + j integer NOT NULL, + path text unique NOT NULL, +); +-- 1 down +DROP TABLE slices; +DROP TABLE files;