8 Commits

Author SHA1 Message Date
Luc Didry
1633a0b0ed WIP - Swift storage 2020-08-23 10:40:42 +02:00
Luc Didry
95745c83d1 🔥 — Remove tap.xml from git 2020-08-23 10:40:13 +02:00
Luc Didry
32dff45a52 Merge branch 'improve-tests' into 'development'
Improve tests

See merge request fiat-tux/hat-softwares/lutim!76
2020-08-23 10:32:03 +02:00
Luc Didry
1a83ebc0d0 👷 — Improve CI
- Refactor .gitlab-ci.yml
- Update Makefile
- Introduce junit test output
- Improve minion test
2020-08-23 10:26:49 +02:00
Luc Didry
721ad30058 Merge branch 'weblate-lutim-default-theme' into 'development'
Translations update from Weblate

See merge request fiat-tux/hat-softwares/lutim!75
2020-06-17 08:37:18 +02:00
Konstantin Timashov
8ec459bdde Translated using Weblate (Russian)
Currently translated at 94.2% (131 of 139 strings)

Translation: Lutim/Default theme
Translate-URL: https://weblate.framasoft.org/projects/lutim/default-theme/ru/
2020-06-16 22:24:42 +02:00
Luc Didry
688293481a Merge branch 'weblate-lutim-default-theme' into 'development'
Translations update from Weblate

See merge request fiat-tux/hat-softwares/lutim!74
2020-06-10 06:52:40 +02:00
roberto marcolin
ad2f4bb724 Translated using Weblate (Italian)
Currently translated at 100.0% (139 of 139 strings)

Translation: Lutim/Default theme
Translate-URL: https://weblate.framasoft.org/projects/lutim/default-theme/it/
2020-06-09 21:24:40 +02:00
18 changed files with 581 additions and 188 deletions

3
.gitignore vendored
View File

@@ -7,6 +7,7 @@ script/hypnotoad.pid
local/*
files/*
stop-upload
tap.xml
themes/*
!themes/default
!themes/default/*
@@ -21,4 +22,4 @@ cover_db/*
.ash_history
.vscode/
.DS_Store
.cpanm/
.cpanm/

View File

@@ -21,6 +21,7 @@ variables:
retry: 2
except:
- tags
.carton_bdd_template: &carton_bdd_definition
<<: *retry
stage: carton_bdd
@@ -29,20 +30,29 @@ variables:
- local/
needs:
- carton
.sqlite_template: &sqlite_definition
.test_template: &test_definition
<<: *retry
stage: tests
script:
- MOJO_CONFIG=t/$CI_JOB_NAME.conf make test
- MOJO_CONFIG=t/$CI_JOB_NAME.conf make watch
- MOJO_CONFIG=t/$CI_JOB_NAME.conf make cleanbdd
- MOJO_CONFIG=t/$CI_JOB_NAME.conf make cleanfiles
- MOJO_CONFIG=t/$CI_JOB_NAME.conf make stats
- MOJO_CONFIG=t/$CI_JOB_NAME.conf make test-junit-output
artifacts:
paths:
- tap.xml
- cover_db/
.sqlite_template: &sqlite_definition
<<: *test_definition
needs:
- carton_sqlite
.pg_template: &pg_definition
<<: *retry
stage: tests
artifacts:
paths:
- cover_db/
<<: *test_definition
needs:
- carton_postgresql
services:
@@ -96,75 +106,37 @@ carton_postgresql:
#
sqlite1:
<<: *sqlite_definition
script:
before_script:
- carton install --deployment --without=postgresql --without=minion --without=cache --without=memcached
- MOJO_CONFIG=t/sqlite1.conf make test-sqlite
- MOJO_CONFIG=t/sqlite1.conf make watch
- MOJO_CONFIG=t/sqlite1.conf make cleanbdd
- MOJO_CONFIG=t/sqlite1.conf make cleanfiles
- MOJO_CONFIG=t/sqlite1.conf make stats
sqlite2:
<<: *sqlite_definition
script:
before_script:
- carton install --deployment --without=postgresql --without=cache --without=memcached
- MOJO_CONFIG=t/sqlite2.conf make minion &
- sleep 3
- MOJO_CONFIG=t/sqlite2.conf make test-sqlite
- MOJO_CONFIG=t/sqlite2.conf make watch
- MOJO_CONFIG=t/sqlite2.conf make cleanbdd
- MOJO_CONFIG=t/sqlite2.conf make cleanfiles
- MOJO_CONFIG=t/sqlite2.conf make stats
sqlite3:
<<: *sqlite_definition
services:
- name: postgres:9.6
alias: postgres
script:
before_script:
- carton install --deployment --without=cache --without=memcached
- export PGPASSWORD=lutim_pwd; echo 'CREATE DATABASE lutim_minion WITH OWNER lutim;' | psql -h postgres -U lutim lutim_db
- MOJO_CONFIG=t/sqlite3.conf make minion &
- sleep 3
- MOJO_CONFIG=t/sqlite3.conf make test-sqlite
- MOJO_CONFIG=t/sqlite3.conf make watch
- MOJO_CONFIG=t/sqlite3.conf make cleanbdd
- MOJO_CONFIG=t/sqlite3.conf make cleanfiles
- MOJO_CONFIG=t/sqlite3.conf make stats
### PostgreSQL tests
##
#
postgresql1:
<<: *pg_definition
script:
before_script:
- carton install --deployment --without=sqlite --without=minion --without=cache --without=memcached
- MOJO_CONFIG=t/postgresql1.conf make test-pg
- MOJO_CONFIG=t/postgresql1.conf make watch
- MOJO_CONFIG=t/postgresql1.conf make cleanbdd
- MOJO_CONFIG=t/postgresql1.conf make cleanfiles
- MOJO_CONFIG=t/postgresql1.conf make stats
postgresql2:
<<: *pg_definition
script:
before_script:
- carton install --deployment --without=cache --without=memcached
- MOJO_CONFIG=t/postgresql2.conf make minion &
- sleep 3
- MOJO_CONFIG=t/postgresql2.conf make test-pg
- MOJO_CONFIG=t/postgresql2.conf make watch
- MOJO_CONFIG=t/postgresql2.conf make cleanbdd
- MOJO_CONFIG=t/postgresql2.conf make cleanfiles
- MOJO_CONFIG=t/postgresql2.conf make stats
postgresql3:
<<: *pg_definition
script:
before_script:
- carton install --deployment --without=sqlite --without=cache --without=memcached
- export PGPASSWORD=lutim_pwd; echo 'CREATE DATABASE lutim_minion WITH OWNER lutim;' | psql -h postgres -U lutim lutim_db
- MOJO_CONFIG=t/postgresql3.conf make minion &
- sleep 3
- MOJO_CONFIG=t/postgresql3.conf make test-pg
- MOJO_CONFIG=t/postgresql3.conf make watch
- MOJO_CONFIG=t/postgresql3.conf make cleanbdd
- MOJO_CONFIG=t/postgresql3.conf make cleanfiles
- MOJO_CONFIG=t/postgresql3.conf make stats
### Code coverage
##
@@ -173,6 +145,9 @@ cover:
stage: cover
script:
- make cover
coverage: '/Total .*\d+\.\d+$/'
coverage: '/Total.* (\d+\.\d+)$/'
artifacts:
reports:
junit: tap.xml
except:
- tags

View File

@@ -5,6 +5,7 @@ XGETTEXT=carton exec local/bin/xgettext.pl -u
CARTON=carton exec
LUTIM=script/lutim
REAL_LUTIM=script/application
HARNESS_PERL_SWITCHES=-MDevel::Cover=+ignore,local
HEAD := $(shell git rev-parse --abbrev-ref HEAD)
minify:
@@ -24,16 +25,20 @@ stats-locales:
podcheck:
podchecker lib/Lutim/DB/Image.pm
check-syntax:
find lib/ themes/ -name \*.pm -exec $(CARTON) perl -Ilib -c {} \;
find t/ -name \*.t -exec $(CARTON) perl -Ilib -c {} \;
cover:
PERL5OPT='-Ilib/' HARNESS_PERL_SWITCHES='-MDevel::Cover' $(CARTON) cover --ignore_re '^local'
PERL5OPT='-Ilib' $(CARTON) cover --ignore_re '^local'
test-sqlite:
@PERL5OPT='-Ilib/' HARNESS_PERL_SWITCHES='-MDevel::Cover' $(CARTON) $(REAL_LUTIM) test
test:
@PERL5OPT='-Ilib/' HARNESS_PERL_SWITCHES='$(HARNESS_PERL_SWITCHES)' $(CARTON) -- prove -l --failures
test-pg:
@PERL5OPT='-Ilib/' HARNESS_PERL_SWITCHES='-MDevel::Cover' $(CARTON) $(REAL_LUTIM) test
test-junit-output:
@PERL5OPT='-Ilib/' HARNESS_PERL_SWITCHES='$(HARNESS_PERL_SWITCHES)' $(CARTON) -- prove -l --failures --formatter TAP::Formatter::JUnit > tap.xml
test: podcheck test-sqlite test-pg
full-test: podcheck just-test
clean:
rm -rf lutim.db files/

View File

@@ -53,6 +53,9 @@ feature 'htpasswd', 'Htpasswd authentication support' => sub {
requires 'Apache::Htpasswd';
requires 'Mojolicious::Plugin::Authentication';
};
feature 'swift-storage', 'Openstack Swift object storage support' => sub {
requires 'Net::OpenStack::Swift';
};
feature 'test' => sub {
requires 'Devel::Cover';
};

View File

@@ -9,6 +9,23 @@ DISTRIBUTIONS
Digest::SHA 2
ExtUtils::MakeMaker 0
MIME::Base64 0
App-Rad-1.05
pathname: G/GA/GARU/App-Rad-1.05.tar.gz
provides:
App::Rad 1.05
App::Rad::Config undef
App::Rad::Exclude 0.01
App::Rad::Help 0.03
App::Rad::Include 0.01
requirements:
Attribute::Handlers 0
B::Deparse 0
Carp 0
ExtUtils::MakeMaker 0
File::Temp 0
FindBin 0
Getopt::Long 2.36
Test::More 0
Archive-Zip-1.60
pathname: P/PH/PHRED/Archive-Zip-1.60.tar.gz
provides:
@@ -173,6 +190,12 @@ DISTRIBUTIONS
strict 0
vars 0
warnings 0
Class-Accessor-Lite-0.08
pathname: K/KA/KAZUHO/Class-Accessor-Lite-0.08.tar.gz
provides:
Class::Accessor::Lite 0.08
requirements:
ExtUtils::MakeMaker 6.36
Class-Data-Inheritable-0.08
pathname: T/TM/TMTM/Class-Data-Inheritable-0.08.tar.gz
provides:
@@ -537,6 +560,23 @@ DISTRIBUTIONS
Data::Validate::Domain 0
Data::Validate::IP 0
ExtUtils::MakeMaker 0
Data-Validator-1.07
pathname: G/GF/GFUJI/Data-Validator-1.07.tar.gz
provides:
Data::Validator 1.07
Data::Validator::Role::AllowExtra undef
Data::Validator::Role::Croak undef
Data::Validator::Role::Method undef
Data::Validator::Role::NoRestricted undef
Data::Validator::Role::NoThrow undef
Data::Validator::Role::Sequenced undef
Data::Validator::Role::SmartSequenced undef
Data::Validator::Role::StrictSequenced undef
requirements:
ExtUtils::MakeMaker 6.59
Module::Build 0.38
Mouse 0.93
perl 5.008001
DateTime-1.48
pathname: D/DR/DROLSKY/DateTime-1.48.tar.gz
provides:
@@ -995,6 +1035,19 @@ DISTRIBUTIONS
perl 5.008004
strict 0
warnings 0
Devel-CheckCompiler-0.07
pathname: S/SY/SYOHEX/Devel-CheckCompiler-0.07.tar.gz
provides:
Devel::AssertC99 undef
Devel::CheckCompiler 0.07
requirements:
Exporter 0
ExtUtils::CBuilder 0
File::Temp 0
Module::Build::Tiny 0.035
Test::More 0.98
parent 0
perl 5.008001
Devel-Cover-1.29
pathname: P/PJ/PJCJ/Devel-Cover-1.29.tar.gz
provides:
@@ -1077,6 +1130,13 @@ DISTRIBUTIONS
perl 5.006
strict 0
warnings 0
Devel-PPPort-3.57
pathname: A/AT/ATOOMIC/Devel-PPPort-3.57.tar.gz
provides:
Devel::PPPort 3.57
requirements:
ExtUtils::MakeMaker 0
FindBin 0
Devel-StackTrace-2.03
pathname: D/DR/DROLSKY/Devel-StackTrace-2.03.tar.gz
provides:
@@ -1329,6 +1389,27 @@ DISTRIBUTIONS
Test::More 0
Test::Warn 0
perl 5.006
Furl-3.13
pathname: T/TO/TOKUHIROM/Furl-3.13.tar.gz
provides:
Furl 3.13
Furl::ConnectionCache undef
Furl::HTTP 3.13
Furl::Headers undef
Furl::Request undef
Furl::Response undef
Furl::ZlibStream undef
requirements:
Class::Accessor::Lite 0
Encode 0
HTTP::Parser::XS 0.11
MIME::Base64 0
Module::Build::Tiny 0.035
Mozilla::CA 0
Scalar::Util 0
Socket 0
Time::HiRes 0
perl 5.008001
HTML-Parser-3.72
pathname: G/GA/GAAS/HTML-Parser-3.72.tar.gz
provides:
@@ -1447,6 +1528,14 @@ DISTRIBUTIONS
ExtUtils::MakeMaker 0
HTTP::Headers 6
perl 5.008001
HTTP-Parser-XS-0.17
pathname: K/KA/KAZUHO/HTTP-Parser-XS-0.17.tar.gz
provides:
HTTP::Parser::XS 0.17
HTTP::Parser::XS::PP undef
requirements:
ExtUtils::MakeMaker 6.36
Test::More 0.96
Hash-Merge-0.300
pathname: R/RE/REHSACK/Hash-Merge-0.300.tar.gz
provides:
@@ -1802,6 +1891,18 @@ DISTRIBUTIONS
constant 0
strict 0
warnings 0
Log-Minimal-0.19
pathname: K/KA/KAZEBURO/Log-Minimal-0.19.tar.gz
provides:
Log::Minimal 0.19
requirements:
CPAN::Meta 0
CPAN::Meta::Prereqs 0
Data::Dumper 0
ExtUtils::CBuilder 0
Module::Build 0.38
Scalar::Util 0
Term::ANSIColor 0
MRO-Compat-0.13
pathname: H/HA/HAARG/MRO-Compat-0.13.tar.gz
provides:
@@ -1918,6 +2019,21 @@ DISTRIBUTIONS
perl 5.006
strict 0
warnings 0
Module-Build-XSUtil-0.19
pathname: H/HI/HIDEAKIO/Module-Build-XSUtil-0.19.tar.gz
provides:
Module::Build::XSUtil 0.19
requirements:
Devel::CheckCompiler 0
Devel::PPPort 0
Exporter 0
ExtUtils::CBuilder 0
File::Basename 0
File::Path 0
Module::Build 0.4005
XSLoader 0
parent 0
perl 5.008001
Module-Implementation-0.09
pathname: D/DR/DROLSKY/Module-Implementation-0.09.tar.gz
provides:
@@ -2082,7 +2198,6 @@ DISTRIBUTIONS
Mojolicious::Lite undef
Mojolicious::Plugin undef
Mojolicious::Plugin::Config undef
Mojolicious::Plugin::Config::Sandbox undef
Mojolicious::Plugin::DefaultHelpers undef
Mojolicious::Plugin::EPLRenderer undef
Mojolicious::Plugin::EPRenderer undef
@@ -2605,6 +2720,44 @@ DISTRIBUTIONS
parent 0.223
strict 1.03
warnings 1.03
Mouse-v2.5.9
pathname: S/SK/SKAJI/Mouse-v2.5.9.tar.gz
provides:
Mouse v2.5.9
Mouse::Exporter undef
Mouse::Meta::Attribute undef
Mouse::Meta::Class undef
Mouse::Meta::Method undef
Mouse::Meta::Method::Accessor undef
Mouse::Meta::Method::Constructor undef
Mouse::Meta::Method::Delegation undef
Mouse::Meta::Method::Destructor undef
Mouse::Meta::Module undef
Mouse::Meta::Role undef
Mouse::Meta::Role::Application undef
Mouse::Meta::Role::Application::RoleSummation undef
Mouse::Meta::Role::Composite undef
Mouse::Meta::Role::Method undef
Mouse::Meta::TypeConstraint undef
Mouse::Object undef
Mouse::PurePerl undef
Mouse::Role v2.5.9
Mouse::Spec v2.5.9
Mouse::TypeRegistry undef
Mouse::Util v2.5.9
Mouse::Util::MetaRole undef
Mouse::Util::TypeConstraints undef
Squirrel undef
Squirrel::Role undef
Test::Mouse undef
ouse undef
requirements:
ExtUtils::CBuilder 0
Module::Build 0.4005
Module::Build::XSUtil 0.19
Scalar::Util 1.14
XSLoader 0.02
perl 5.008005
Mozilla-CA-20180117
pathname: A/AB/ABH/Mozilla-CA-20180117.tar.gz
provides:
@@ -2640,6 +2793,31 @@ DISTRIBUTIONS
strict 0
vars 0
warnings 0
Net-OpenStack-Swift-0.15
pathname: M/MA/MASAKYST/Net-OpenStack-Swift-0.15.tar.gz
provides:
Net::OpenStack::Swift 0.15
Net::OpenStack::Swift::InnerKeystone::Base undef
Net::OpenStack::Swift::InnerKeystone::V1_0 undef
Net::OpenStack::Swift::InnerKeystone::V2_0 undef
Net::OpenStack::Swift::InnerKeystone::V3_0 undef
Net::OpenStack::Swift::Util undef
requirements:
App::Rad 0
Data::Validator 0
Furl 0
IO::Socket::SSL 0
JSON 0
Log::Minimal 0
Module::Build::Tiny 0.035
Mouse 0
Parallel::Fork::BossWorkerAsync 0
Path::Tiny 0
Sys::CPU 0
Text::ASCIITable 0
URI::Escape 0
namespace::clean 0
perl 5.010_001
Net-SSLeay-1.85
pathname: M/MI/MIKEM/Net-SSLeay-1.85.tar.gz
provides:
@@ -2707,6 +2885,12 @@ DISTRIBUTIONS
XSLoader 0
strict 0
warnings 0
Parallel-Fork-BossWorkerAsync-0.09
pathname: J/JV/JVANNUCCI/Parallel-Fork-BossWorkerAsync-0.09.tar.gz
provides:
Parallel::Fork::BossWorkerAsync 0.09
requirements:
ExtUtils::MakeMaker 0
Params-Classify-0.015
pathname: Z/ZE/ZEFRAM/Params-Classify-0.015.tar.gz
provides:
@@ -2749,6 +2933,32 @@ DISTRIBUTIONS
overload 0
strict 0
warnings 0
Path-Tiny-0.112
pathname: D/DA/DAGOLDEN/Path-Tiny-0.112.tar.gz
provides:
Path::Tiny 0.112
Path::Tiny::Error 0.112
requirements:
Carp 0
Cwd 0
Digest 1.03
Digest::SHA 5.45
Encode 0
Exporter 5.57
ExtUtils::MakeMaker 6.17
Fcntl 0
File::Copy 0
File::Glob 0
File::Path 2.07
File::Spec 0.86
File::Temp 0.19
File::stat 0
constant 0
overload 0
perl 5.008001
strict 0
warnings 0
warnings::register 0
Role-Tiny-2.000006
pathname: H/HA/HAARG/Role-Tiny-2.000006.tar.gz
provides:
@@ -2774,17 +2984,6 @@ DISTRIBUTIONS
Sub::Quote 2.000001
Text::Balanced 2.00
perl 5.006
Scalar-List-Utils-1.50
pathname: P/PE/PEVANS/Scalar-List-Utils-1.50.tar.gz
provides:
List::Util 1.50
List::Util::XS 1.50
Scalar::Util 1.50
Sub::Util 1.50
requirements:
ExtUtils::MakeMaker 0
Test::More 0
perl 5.006
Specio-0.42
pathname: D/DR/DROLSKY/Specio-0.42.tar.gz
provides:
@@ -2948,6 +3147,12 @@ DISTRIBUTIONS
Text::Balanced 2
if 0
perl 5.005
Sys-CPU-0.52
pathname: M/MK/MKODERER/Sys-CPU-0.52.tar.gz
provides:
Sys::CPU 0.52
requirements:
ExtUtils::MakeMaker 0
Task-Weaken-1.06
pathname: E/ET/ETHER/Task-Weaken-1.06.tar.gz
provides:
@@ -2993,6 +3198,16 @@ DISTRIBUTIONS
Test::Builder 0.13
Test::Builder::Tester 1.02
perl 5.006
Text-ASCIITable-0.22
pathname: L/LU/LUNATIC/Text-ASCIITable-0.22.tar.gz
provides:
Text::ASCIITable 0.22
Text::ASCIITable::Wrap 0.2
requirements:
Carp 0
Encode 0
List::Util 0
perl v5.6.0
Text-Soundex-3.05
pathname: R/RJ/RJBS/Text-Soundex-3.05.tar.gz
provides:

View File

@@ -109,6 +109,11 @@ sub startup {
$self->plugin('Lutim::Plugin::Helpers');
$self->plugin('Lutim::Plugin::Lang');
# Now helpers has been loaded, time to check Swift container
if ($config->{swift}) {
$self->check_swift_container();
}
# Minion
if ($config->{minion}->{enabled}) {
$self->config->{minion}->{dbtype} = 'sqlite' unless defined $config->{minion}->{dbtype};

View File

@@ -33,7 +33,7 @@ sub run {
$dbi->get_images_to_clean()->each(
sub {
my ($img, $num) = @_;
$l->app->delete_image($img);
$img->delete();
}
);
@@ -42,7 +42,7 @@ sub run {
$dbi->get_no_longer_viewed_files($time)->each(
sub {
my ($img, $num) = @_;
$l->app->delete_image($img);
$img->delete();
}
);
}

View File

@@ -50,7 +50,7 @@ sub run {
$dbi->get_50_oldest()->each(
sub {
my ($img, $num) = @_;
$l->app->delete_image($img);
$img->delete();
}
);
} while (du(qw/files/) > $config->{max_total_size});

View File

@@ -173,7 +173,7 @@ sub delete_short {
chomp $confirm;
}
if ($confirm =~ m/^y(es)?$/i) {
$c->app->delete_image($i);
$i->delete();
} else {
say 'Answer was not "y" or "yes". Aborting deletion.';
}

View File

@@ -231,7 +231,7 @@ sub delete {
} else {
$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);
$image->delete();
return $c->respond_to(
json => {
json => {
@@ -397,7 +397,8 @@ sub add {
# Save file and create record
my $filename = unidecode($upload->filename);
my $ext = ($filename =~ m/([^.]+)$/)[0];
my $path = 'files/'.$record->short.'.'.$ext;
my $path = $record->short.'.'.$ext;
$path = Mojo::File->new('files', $path)->to_string unless ($c->app->config('swift'));
my ($width, $height);
if ($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?)
@@ -493,12 +494,11 @@ sub add {
if ($c->param('crypt') || $c->config('always_encrypt')) {
($upload, $key, $iv) = $c->crypt($upload, $filename);
}
$upload->move_to($path);
$record->path($path)
->filename($filename)
->mediatype($mediatype)
->footprint(digest_file_hex($path, 'SHA-512'))
->footprint(digest_file_hex($upload->asset->to_file->path, 'SHA-512'))
->enabled(1)
->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)
->delete_at_first_view(($c->param('first-view'))? 1 : 0)
@@ -507,7 +507,8 @@ sub add {
->width($width)
->height($height)
->iv($iv)
->write;
->write
->store($upload);
# Log image creation
$c->app->log->info('[CREATION] '.$ip.' pushed '.$filename.' (path: '.$path.')') unless $c->config('quiet_logs');
@@ -605,12 +606,13 @@ sub short {
my $image = Lutim::DB::Image->new(app => $c->app, short => $short);
if ($image->enabled && $image->path) {
# Image deleted
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.')') unless $c->config('quiet_logs');
# Delete image
$c->delete_image($image);
$image->delete();
# Warn user
$c->flash(
@@ -620,6 +622,7 @@ sub short {
}
my $test;
# Twitter page
if (defined($touit) && $image->mediatype !~ m/svg/) {
$test = 1;
my $short = $image->short;
@@ -629,11 +632,11 @@ sub short {
if (defined($image->width) && defined($image->height)) {
($width, $height) = ($image->width, $image->height);
} elsif ($im_loaded) {
my $upload = $c->decrypt($key, $image->path, $image->iv);
my $im = Image::Magick->new;
$im->BlobToImage($upload->slurp);
$width = $im->Get('width');
$height = $im->Get('height');
my $tmp = $image->decrypt($key);
my $im = Image::Magick->new;
$im->BlobToImage($tmp->slurp);
$width = $im->Get('width');
$height = $im->Get('height');
$image->width($width)
->height($height)
@@ -656,7 +659,7 @@ sub short {
$c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')') unless $c->config('quiet_logs');
# Delete image
$c->delete_image($image);
$image->delete();
$c->flash(
msg => $c->l('Unable to find the image: it has been deleted.')
@@ -688,7 +691,7 @@ sub short {
$c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')') unless $c->config('quiet_logs');
# Delete image
$c->delete_image($image);
$image->delete();
}
});
} else {
@@ -740,7 +743,7 @@ sub zip {
$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);
$image->delete();
# Warn user
$zip->addString(encode('UTF-8', $c->l('Unable to find the image: it has been deleted.')), 'images/'.$filename.'.txt');
@@ -753,7 +756,7 @@ sub zip {
$c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')') unless $c->config('quiet_logs');
# Delete image
$c->delete_image($image);
$image->delete();
$zip->addString(encode('UTF-8', $c->l('Unable to find the image: it has been deleted.')), 'images/'.$filename.'.txt');
next;
@@ -764,16 +767,18 @@ sub zip {
$expires = $dt->strftime("%a, %d %b %Y %H:%M:%S GMT");
my $path = $image->path;
unless ( -f $path && -r $path ) {
$c->app->log->error("Cannot read file [$path]. error [$!]");
$zip->addString(encode('UTF-8', $c->l('Unable to find the image: it has been deleted.')), 'images/'.$filename.'.txt');
next;
unless ($c->app->config('swift')) {
unless ( -f $path && -r $path ) {
$c->app->log->error("Cannot read file [$path]. error [$!]");
$zip->addString(encode('UTF-8', $c->l('Unable to find the image: it has been deleted.')), 'images/'.$filename.'.txt');
next;
}
}
if ($key) {
$zip->addString($c->decrypt($key, $path, $image->iv), "images/$filename");
$zip->addString($image->decrypt($key), "images/$filename");
} else {
$zip->addFile($path, "images/$filename");
$zip->addString($image->retrieve, "images/$filename");
}
# Log access

View File

@@ -1,6 +1,10 @@
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
package Lutim::DB::Image;
use bytes;
use Mojo::Base -base;
use Mojo::File;
use Crypt::CBC;
use File::Temp qw(tempfile);
has 'short';
has 'path';
@@ -20,6 +24,8 @@ has 'height';
has 'iv';
has 'app';
=encoding utf8
=head1 NAME
Lutim::DB::Image - DB abstraction layer for Lutim images
@@ -151,13 +157,11 @@ sub to_hash {
=over 1
=item B<Usage> : C<$c-E<gt>count_delete_at_day_endis($delete_at_day, $enabled[, $time])>
=item B<Usage> : C<$c-E<gt>count_delete_at_day_endis($delete_at_day, $enabled, [$time])>
=item B<Arguments> : two mandatory parameters: one integer, the delete_at_day attribute, a boolean (0 or 1), the enabled attribute
an optional parameter: an unix timestamp
=item B<Arguments> : two mandatory parameters: one integer, the delete_at_day attribute, a boolean (0 or 1), the enabled attribute and an optional parameter: an unix timestamp.
=item B<Purpose> : count how many images there are with the given delete_at_day attribute, and enabled or disabled, depending on the given enabled attribute
if the optional parameter is given, count only images according to the given mandatory parameters that were created before the timestamp
=item B<Purpose> : count how many images there are with the given delete_at_day attribute, and enabled or disabled, depending on the given enabled attribute. If the optional parameter is given, count only images according to the given mandatory parameters that were created before the timestamp
=item B<Returns> : integer
@@ -345,6 +349,158 @@ sub to_hash {
=back
=head2 store
=over 1
=item B<Usage> : C<$c-E<gt>store($upload)>
=item B<Arguments> : a Mojo::Upload object
=item B<Purpose> : will store the content to the objects path, either on filesystem or on Swift object storage
=item B<Returns> : the db accessor object
=back
=cut
sub store {
my $c = shift;
my $upload = shift;
if ($c->app->config('swift')) {
$c->app->swift->put_object(
container_name => $c->app->config('swift')->{container},
object_name => $c->path,
content_length => $upload->size,
content => $upload->slurp
);
} else {
$upload->move_to($c->path);
}
return $c;
}
=head2 retrieve
=over 1
=item B<Usage> : C<$c-E<gt>retrieve>
=item B<Arguments> : none
=item B<Purpose> : get file from storage, either filesystem or Swift object storage
=item B<Returns> : the data from the file
=back
=cut
sub retrieve {
my $c = shift;
my $upload = shift;
if ($c->app->config('swift')) {
my $file;
$c->app->swift->get_object(
container_name => $c->app->config('swift')->{container},
object_name => $c->path,
write_code => sub {
my ($status, $message, $headers, $chunk) = @_;
$file .= $chunk;
}
);
return $file;
} else {
return Mojo::File->new($c->path)->slurp;
}
}
=head2 decrypt
=over 1
=item B<Usage> : C<$c-E<gt>decrypt($key)>
=item B<Arguments> : the decryption key
=item B<Purpose> : decrypt the image
=item B<Returns> : a Mojo::Asset::File object
=back
=cut
sub decrypt {
my $c = shift;
my $key = shift;
$c->iv = 'dupajasi' unless $c->iv;
my $cipher = Crypt::CBC->new(
-key => $key,
-cipher => 'Blowfish',
-header => 'none',
-iv => $c->iv
);
$cipher->start('decrypting');
my $decrypt_asset = Mojo::Asset::File->new;
if ($c->app->config('swift')) {
$c->app->swift->get_object(
container_name => $c->app->config('swift')->{container},
object_name => $c->path,
write_code => sub {
my ($status, $message, $headers, $chunk) = @_;
$decrypt_asset->add_chunk($cipher->crypt($chunk));
}
);
} else {
open(my $f, "<", $c->path) or die "Unable to read encrypted file: $!";
binmode $f;
while (read($f, my $buffer, 1024)) {
$decrypt_asset->add_chunk($cipher->crypt($buffer));
}
$decrypt_asset->add_chunk($cipher->finish);
}
return $decrypt_asset->slurp;
}
=head2 delete
=over 1
=item B<Usage> : C<$c-E<gt>delete>
=item B<Arguments> : none
=item B<Purpose> : delete the file on filesystem or Swift object storage and disable the image in database
=item B<Returns> : the db accessor object
=back
=cut
sub delete {
my $c = shift;
if ($c->app->config('cache_max_size') != 0 || scalar(@{$c->app->config('memcached_servers')})) {
$c->app->chi('lutim_images_cache')->remove($c->short);
}
if ($c->app->config('swift')) {
$c->app->swift->delete_object({
container_name => $c->app->config('swift')->{container},
object_name => $c->path
});
} else {
unlink $c->path or warn "Could not unlink ".$c->path.": $!";
}
return $c->disable();
}
1;

View File

@@ -49,26 +49,61 @@ sub register {
$app->helper(is_selected => \&_is_selected);
$app->helper(is_wm_selected => \&_is_wm_selected);
$app->helper(crypt => \&_crypt);
$app->helper(decrypt => \&_decrypt);
$app->helper(delete_image => \&_delete_image);
$app->helper(iso639_native_name => \&_iso639_native_name);
$app->helper(prefix => \&_prefix);
if ($app->config('swift')) {
use Net::OpenStack::Swift;
$app->helper(swift => \&_swift);
$app->helper(check_swift_container => \&_check_swift_container);
$app->helper(find_swift_container => \&_find_swift_container);
}
}
sub _pg {
my $c = shift;
my $c = shift;
state $pg = Mojo::Pg->new($c->app->pg_url($c->app->config('pgdb')));
return $pg;
}
sub _sqlite {
my $c = shift;
my $c = shift;
state $sqlite = Mojo::SQLite->new('sqlite:'.$c->app->config('db_path'));
return $sqlite;
}
sub _swift {
my $c = shift;
state $swift = Net::OpenStack::Swift->new($c->app->config('swift'));
return $swift;
}
sub _check_swift_container {
my $c = shift;
my ($storage_url, $token) = $c->swift->get_auth();
my ($headers, $containers) = $c->swift->get_account(url => $storage_url, token => $token);
unless ($c->find_swift_container($containers)) {
$c->swift->put_container(container_name => $c->app->config('swift')->{container});
my ($headers, $containers) = $c->swift->get_account(url => $storage_url, token => $token);
die sprintf("Swift container %s not found, and unable to create it.", $c->app->config('swift')->{container}) unless $c->find_swift_container($containers);
}
}
sub _find_swift_container {
my $c = shift;
my $containers = shift;
my $found_container = 0;
foreach my $container (@{$containers}) {
$found_container = 1 if $container->{name} eq $c->app->config('swift')->{container};
}
return $found_container;
}
sub _render_file {
my $c = shift;
my ($im_loaded, $img, $dl, $key, $thumb) = @_;
@@ -83,12 +118,15 @@ sub _render_file {
$dl = 'attachment' if ($mediatype =~ m/svg/);
$filename = quote($filename);
unless (-f $path && -r $path) {
$c->app->log->error("Cannot read file [$path]. error [$!]");
$c->flash(
msg => $c->l('Unable to find the image: it has been deleted.')
);
return 500;
unless ($c->app->config('swift')) {
# Do we have the file on disk?
unless (-f $path && -r $path) {
$c->app->log->error("Cannot read file [$path]. error [$!]");
$c->flash(
msg => $c->l('Unable to find the image: it has been deleted.')
);
return 500;
}
}
$mediatype =~ s/x-//;
@@ -104,21 +142,22 @@ sub _render_file {
$c->res->content->headers($headers);
my $cache;
# Do we have the file in cache?
if ($c->config('cache_max_size') != 0 || scalar(@{$c->config('memcached_servers')})) {
$cache = $c->chi('lutim_images_cache')->compute($img->short, undef, sub {
if ($key) {
return {
asset => $c->decrypt($key, $path, $iv),
asset => $img->decrypt($key),
key => $key
};
} else {
return {
asset => Mojo::File->new($path)->slurp,
asset => $img->retrieve
};
}
});
if ($key && $key ne $cache->{key}) {
my $tmp = $c->decrypt($key, $path, $iv);
my $tmp = $img->decrypt($key);
$cache->{asset} = $tmp;
$c->chi('lutim_images_cache')->replace(
$img->short,
@@ -131,18 +170,18 @@ sub _render_file {
} else {
if ($key) {
$cache = {
asset => $c->decrypt($key, $path, $iv),
asset => $img->decrypt($key),
};
} else {
$cache = {
asset => Mojo::File->new($path)->slurp,
asset => $img->retrieve,
};
}
}
# Extend expiration time
my $asset = Mojo::Asset::Memory->new;
$asset->add_chunk($cache->{asset});
# Do we need to create a thumbnail?
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;
$im->BlobToImage($asset->slurp);
@@ -287,44 +326,6 @@ sub _crypt {
return ($crypt_upload, $key, $iv);
}
sub _decrypt {
my $c = shift;
my $key = shift;
my $file = shift;
my $iv = shift;
$iv = 'dupajasi' unless $iv;
my $cipher = Crypt::CBC->new(
-key => $key,
-cipher => 'Blowfish',
-header => 'none',
-iv => $iv
);
$cipher->start('decrypting');
my $decrypt_asset = Mojo::Asset::File->new;
open(my $f, "<",$file) or die "Unable to read encrypted file: $!";
binmode $f;
while (read($f, my $buffer, 1024)) {
$decrypt_asset->add_chunk($cipher->crypt($buffer));
}
$decrypt_asset->add_chunk($cipher->finish) ;
return $decrypt_asset->slurp;
}
sub _delete_image {
my $c = shift;
my $img = shift;
if ($c->config('cache_max_size') != 0 || scalar(@{$c->config('memcached_servers')})) {
$c->chi('lutim_images_cache')->remove($img->short);
}
unlink $img->path or warn "Could not unlink ".$img->path.": $!";
$img->disable();
}
sub _iso639_native_name {
my $c = shift;
return ucfirst(decode 'UTF-8', get_iso639_1(shift)->{nativeName});

View File

@@ -205,6 +205,18 @@
# optional, default is 3600
#session_duration => 3600,
# you can store images on Swift object storage (https://en.wikipedia.org/wiki/OpenStack#Swift) instead of filesystem
# please read https://metacpan.org/pod/Net::OpenStack::Swift#SYNOPSIS to know how to configure this setting
# IMPORTANT: add a `container` key in it, to let Lutim know which container to use. This is not a regular Net::OpenStack::Swift setting, but Lutim need it.
# optional, no default
#swift => {
# auth_url => 'https://auth-endpoint-url/v2.0',
# user => 'userid',
# password => 'password',
# tenant_name => 'project_id',
# container => 'lutim'
#},
# disable counters of images
# set to 1 to disable counters
# optional, counters are enabled by default

View File

@@ -150,8 +150,7 @@ $t->get_ok('/d/'.$rshort.'/'.$token, form => { format => 'json' })
$t->get_ok('/'.$rshort)
->status_is(302);
# Needed if we use Minion with sqlite for increasing counters
sleep 8;
$t->app->minion->perform_jobs if $t->app->config('minion')->{enabled};
# Get image counter
$t->post_ok('/c', form => { short => $rshort, token => $token })

View File

@@ -31,11 +31,11 @@ msgstr "%1 sent images on this instance from beginning."
msgid "-or-"
msgstr "-or-"
#: lib/Lutim.pm:342 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:172 lib/Lutim/Command/cron/stats.pm:189 themes/default/templates/index.html.ep:5 themes/default/templates/myfiles.html.ep:5 themes/default/templates/partial/raw.js.ep:25 themes/default/templates/partial/raw.js.ep:8 themes/default/templates/raw.html.ep:10
#: lib/Lutim.pm:347 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:172 lib/Lutim/Command/cron/stats.pm:189 themes/default/templates/index.html.ep:5 themes/default/templates/myfiles.html.ep:5 themes/default/templates/partial/raw.js.ep:25 themes/default/templates/partial/raw.js.ep:8 themes/default/templates/raw.html.ep:10
msgid "1 year"
msgstr "1 year"
#: lib/Lutim.pm:341 lib/Lutim/Command/cron/stats.pm:155 lib/Lutim/Command/cron/stats.pm:169 lib/Lutim/Command/cron/stats.pm:186 themes/default/templates/index.html.ep:4 themes/default/templates/myfiles.html.ep:33 themes/default/templates/myfiles.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/lutim.js.ep:149 themes/default/templates/partial/raw.js.ep:22 themes/default/templates/partial/raw.js.ep:5 themes/default/templates/raw.html.ep:7
#: lib/Lutim.pm:346 lib/Lutim/Command/cron/stats.pm:155 lib/Lutim/Command/cron/stats.pm:169 lib/Lutim/Command/cron/stats.pm:186 themes/default/templates/index.html.ep:4 themes/default/templates/myfiles.html.ep:33 themes/default/templates/myfiles.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/lutim.js.ep:149 themes/default/templates/partial/raw.js.ep:22 themes/default/templates/partial/raw.js.ep:5 themes/default/templates/raw.html.ep:7
msgid "24 hours"
msgstr "24 hours"
@@ -211,7 +211,7 @@ msgstr "Image delay"
msgid "Image deleted"
msgstr "Image deleted"
#: lib/Lutim/Controller/Image.pm:799
#: lib/Lutim/Controller/Image.pm:804
msgid "Image not found."
msgstr "Image not found."
@@ -369,7 +369,7 @@ msgid "Something bad happened"
msgstr "Something bad happened"
#. ($c->config('contact')
#: lib/Lutim/Controller/Image.pm:806
#: lib/Lutim/Controller/Image.pm:811
msgid "Something went wrong when creating the zip file. Try again later or contact the administrator (%1)."
msgstr "Something went wrong when creating the zip file. Try again later or contact the administrator (%1)."
@@ -398,7 +398,7 @@ msgid "The delete token is invalid."
msgstr "The delete token is invalid."
#. ($upload->filename)
#: lib/Lutim/Controller/Image.pm:531
#: lib/Lutim/Controller/Image.pm:532
msgid "The file %1 is not an image."
msgstr "The file %1 is not an image."
@@ -440,7 +440,7 @@ msgid "There is XXXX image(s) in the gallery"
msgstr "There is XXXX image(s) in the gallery"
#. ($c->config->{contact})
#: lib/Lutim/Controller/Image.pm:528
#: lib/Lutim/Controller/Image.pm:529
msgid "There is no more available URL. Retry or contact the administrator. %1"
msgstr "There is no more available URL. Retry or contact the administrator. %1"
@@ -473,7 +473,7 @@ msgstr "Unable to copy to clipboard"
msgid "Unable to find the image %1."
msgstr "Unable to find the image %1."
#: lib/Lutim/Controller/Image.pm:617 lib/Lutim/Controller/Image.pm:662 lib/Lutim/Controller/Image.pm:703 lib/Lutim/Controller/Image.pm:746 lib/Lutim/Controller/Image.pm:758 lib/Lutim/Controller/Image.pm:769 lib/Lutim/Controller/Image.pm:796 lib/Lutim/Plugin/Helpers.pm:89
#: lib/Lutim/Controller/Image.pm:619 lib/Lutim/Controller/Image.pm:665 lib/Lutim/Controller/Image.pm:706 lib/Lutim/Controller/Image.pm:749 lib/Lutim/Controller/Image.pm:761 lib/Lutim/Controller/Image.pm:773 lib/Lutim/Controller/Image.pm:801 lib/Lutim/Plugin/Helpers.pm:126
msgid "Unable to find the image: it has been deleted."
msgstr "Unable to find the image: it has been deleted."
@@ -498,7 +498,7 @@ msgid "Uploaded files by days"
msgstr "Uploaded files by days"
#. ($c->app->config('contact')
#: lib/Lutim/Plugin/Helpers.pm:222
#: lib/Lutim/Plugin/Helpers.pm:261
msgid "Uploading is currently disabled, please try later or contact the administrator (%1)."
msgstr "Uploading is currently disabled, please try later or contact the administrator (%1)."
@@ -558,7 +558,7 @@ msgstr "arabic translation"
msgid "core developer"
msgstr "core developer"
#: lib/Lutim.pm:340 lib/Lutim/Command/cron/stats.pm:154 lib/Lutim/Command/cron/stats.pm:168 lib/Lutim/Command/cron/stats.pm:185 themes/default/templates/index.html.ep:3 themes/default/templates/myfiles.html.ep:3 themes/default/templates/partial/raw.js.ep:21 themes/default/templates/partial/raw.js.ep:4 themes/default/templates/raw.html.ep:6
#: lib/Lutim.pm:345 lib/Lutim/Command/cron/stats.pm:154 lib/Lutim/Command/cron/stats.pm:168 lib/Lutim/Command/cron/stats.pm:185 themes/default/templates/index.html.ep:3 themes/default/templates/myfiles.html.ep:3 themes/default/templates/partial/raw.js.ep:21 themes/default/templates/partial/raw.js.ep:4 themes/default/templates/raw.html.ep:6
msgid "no time limit"
msgstr "no time limit"

View File

@@ -4,8 +4,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2020-03-09 16:23+0000\n"
"Last-Translator: Luc Didry <luc@framasoft.org>\n"
"PO-Revision-Date: 2020-06-09 19:24+0000\n"
"Last-Translator: roberto marcolin <nilogadda@gmail.com>\n"
"Language-Team: Italian <https://weblate.framasoft.org/projects/lutim/"
"default-theme/it/>\n"
"Language: it\n"
@@ -691,3 +691,15 @@ msgid "For more details, see the <a href=\"https://framagit.org/fiat-tux/hat-sof
msgstr ""
"Per altre informazioni, vedi la <a href=\"https://framagit.org/fiat-tux/"
"hat-softwares/lutim\">homepage del progetto</a>."
#: themes/default/templates/index.html.ep:171 themes/default/templates/index.html.ep:215
msgid "Tiling watermark"
msgstr "Filigrana ripetuta"
#: themes/default/templates/index.html.ep:174 themes/default/templates/index.html.ep:218
msgid "Single watermark"
msgstr "Filigrana semplice"
#: themes/default/templates/index.html.ep:177 themes/default/templates/index.html.ep:221
msgid "No watermark"
msgstr "Nessuna filigrana"

View File

@@ -32,11 +32,11 @@ msgstr ""
msgid "-or-"
msgstr ""
#: lib/Lutim.pm:342 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:172 lib/Lutim/Command/cron/stats.pm:189 themes/default/templates/index.html.ep:5 themes/default/templates/myfiles.html.ep:5 themes/default/templates/partial/raw.js.ep:25 themes/default/templates/partial/raw.js.ep:8 themes/default/templates/raw.html.ep:10
#: lib/Lutim.pm:347 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:172 lib/Lutim/Command/cron/stats.pm:189 themes/default/templates/index.html.ep:5 themes/default/templates/myfiles.html.ep:5 themes/default/templates/partial/raw.js.ep:25 themes/default/templates/partial/raw.js.ep:8 themes/default/templates/raw.html.ep:10
msgid "1 year"
msgstr ""
#: lib/Lutim.pm:341 lib/Lutim/Command/cron/stats.pm:155 lib/Lutim/Command/cron/stats.pm:169 lib/Lutim/Command/cron/stats.pm:186 themes/default/templates/index.html.ep:4 themes/default/templates/myfiles.html.ep:33 themes/default/templates/myfiles.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/lutim.js.ep:149 themes/default/templates/partial/raw.js.ep:22 themes/default/templates/partial/raw.js.ep:5 themes/default/templates/raw.html.ep:7
#: lib/Lutim.pm:346 lib/Lutim/Command/cron/stats.pm:155 lib/Lutim/Command/cron/stats.pm:169 lib/Lutim/Command/cron/stats.pm:186 themes/default/templates/index.html.ep:4 themes/default/templates/myfiles.html.ep:33 themes/default/templates/myfiles.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/lutim.js.ep:149 themes/default/templates/partial/raw.js.ep:22 themes/default/templates/partial/raw.js.ep:5 themes/default/templates/raw.html.ep:7
msgid "24 hours"
msgstr ""
@@ -212,7 +212,7 @@ msgstr ""
msgid "Image deleted"
msgstr ""
#: lib/Lutim/Controller/Image.pm:799
#: lib/Lutim/Controller/Image.pm:804
msgid "Image not found."
msgstr ""
@@ -370,7 +370,7 @@ msgid "Something bad happened"
msgstr ""
#. ($c->config('contact')
#: lib/Lutim/Controller/Image.pm:806
#: lib/Lutim/Controller/Image.pm:811
msgid "Something went wrong when creating the zip file. Try again later or contact the administrator (%1)."
msgstr ""
@@ -399,7 +399,7 @@ msgid "The delete token is invalid."
msgstr ""
#. ($upload->filename)
#: lib/Lutim/Controller/Image.pm:531
#: lib/Lutim/Controller/Image.pm:532
msgid "The file %1 is not an image."
msgstr ""
@@ -441,7 +441,7 @@ msgid "There is XXXX image(s) in the gallery"
msgstr ""
#. ($c->config->{contact})
#: lib/Lutim/Controller/Image.pm:528
#: lib/Lutim/Controller/Image.pm:529
msgid "There is no more available URL. Retry or contact the administrator. %1"
msgstr ""
@@ -474,7 +474,7 @@ msgstr ""
msgid "Unable to find the image %1."
msgstr ""
#: lib/Lutim/Controller/Image.pm:617 lib/Lutim/Controller/Image.pm:662 lib/Lutim/Controller/Image.pm:703 lib/Lutim/Controller/Image.pm:746 lib/Lutim/Controller/Image.pm:758 lib/Lutim/Controller/Image.pm:769 lib/Lutim/Controller/Image.pm:796 lib/Lutim/Plugin/Helpers.pm:89
#: lib/Lutim/Controller/Image.pm:619 lib/Lutim/Controller/Image.pm:665 lib/Lutim/Controller/Image.pm:706 lib/Lutim/Controller/Image.pm:749 lib/Lutim/Controller/Image.pm:761 lib/Lutim/Controller/Image.pm:773 lib/Lutim/Controller/Image.pm:801 lib/Lutim/Plugin/Helpers.pm:126
msgid "Unable to find the image: it has been deleted."
msgstr ""
@@ -499,7 +499,7 @@ msgid "Uploaded files by days"
msgstr ""
#. ($c->app->config('contact')
#: lib/Lutim/Plugin/Helpers.pm:222
#: lib/Lutim/Plugin/Helpers.pm:261
msgid "Uploading is currently disabled, please try later or contact the administrator (%1)."
msgstr ""
@@ -559,7 +559,7 @@ msgstr ""
msgid "core developer"
msgstr ""
#: lib/Lutim.pm:340 lib/Lutim/Command/cron/stats.pm:154 lib/Lutim/Command/cron/stats.pm:168 lib/Lutim/Command/cron/stats.pm:185 themes/default/templates/index.html.ep:3 themes/default/templates/myfiles.html.ep:3 themes/default/templates/partial/raw.js.ep:21 themes/default/templates/partial/raw.js.ep:4 themes/default/templates/raw.html.ep:6
#: lib/Lutim.pm:345 lib/Lutim/Command/cron/stats.pm:154 lib/Lutim/Command/cron/stats.pm:168 lib/Lutim/Command/cron/stats.pm:185 themes/default/templates/index.html.ep:3 themes/default/templates/myfiles.html.ep:3 themes/default/templates/partial/raw.js.ep:21 themes/default/templates/partial/raw.js.ep:4 themes/default/templates/raw.html.ep:6
msgid "no time limit"
msgstr ""

View File

@@ -4,8 +4,8 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2020-03-09 16:23+0000\n"
"Last-Translator: Luc Didry <luc@framasoft.org>\n"
"PO-Revision-Date: 2020-06-16 20:24+0000\n"
"Last-Translator: Konstantin Timashov <ktimashov@hse.ru>\n"
"Language-Team: Russian <https://weblate.framasoft.org/projects/lutim/"
"default-theme/ru/>\n"
"Language: ru\n"
@@ -83,7 +83,7 @@ msgstr "Участники"
#: themes/default/templates/partial/common.js.ep:113 themes/default/templates/partial/common.js.ep:93
msgid "Copied to clipboard"
msgstr ""
msgstr "Скопировано в буфер обмена"
#: themes/default/templates/partial/lutim.js.ep:215 themes/default/templates/partial/lutim.js.ep:278 themes/default/templates/partial/lutim.js.ep:364
msgid "Copy all view links to clipboard"
@@ -227,7 +227,7 @@ msgstr "Срок хранения"
#: themes/default/templates/partial/common.js.ep:157
msgid "Image deleted"
msgstr ""
msgstr "Изображение удалено"
#: lib/Lutim/Controller/Image.pm:756
msgid "Image not found."
@@ -287,11 +287,11 @@ msgstr "Ссылка для того, чтоб поделиться в соци
#: themes/default/templates/login.html.ep:8
msgid "Login"
msgstr ""
msgstr "Имя пользователя"
#: themes/default/templates/partial/navbar.html.ep:33
msgid "Logout"
msgstr ""
msgstr "Выйти"
#: themes/default/templates/zip.html.ep:7
msgid ""
@@ -389,7 +389,7 @@ msgstr "Сырые статистические данные"
#: themes/default/templates/myfiles.html.ep:52
msgid "Save changes"
msgstr ""
msgstr "Сохранить изменения"
#: themes/default/templates/index.html.ep:176
msgid "Send an image"
@@ -460,7 +460,7 @@ msgstr ""
#: themes/default/templates/partial/myfiles.js.ep:32
msgid "The data has been successfully imported."
msgstr ""
msgstr "Данные были успешно импортированы."
#: lib/Lutim/Controller/Image.pm:160 lib/Lutim/Controller/Image.pm:228
msgid "The delete token is invalid."
@@ -511,7 +511,7 @@ msgstr "Срок хранения изображения успешно изме
#: themes/default/templates/partial/gallery.js.ep:277
msgid "There is XXXX image(s) in the gallery"
msgstr ""
msgstr "В галерее есть изображения для взрослых"
#. ($c->config->{contact})
#: lib/Lutim/Controller/Image.pm:485
@@ -538,7 +538,7 @@ msgstr "Твитнуть!"
#: themes/default/templates/partial/common.js.ep:110 themes/default/templates/partial/common.js.ep:90
msgid "Unable to copy to clipboard"
msgstr ""
msgstr "Не удается скопировать в буфер обмена"
#. ($short)
#: lib/Lutim/Controller/Image.pm:108 lib/Lutim/Controller/Image.pm:202 lib/Lutim/Controller/Image.pm:273
@@ -633,11 +633,11 @@ msgstr ""
#: lib/Lutim/Controller/Authent.pm:27
msgid "You have been successfully logged in."
msgstr ""
msgstr "Вы успешно вошли в учетную запись."
#: lib/Lutim/Controller/Authent.pm:66 themes/default/templates/logout.html.ep:3
msgid "You have been successfully logged out."
msgstr ""
msgstr "Вы успешно вышли из учетной записи."
#: themes/default/templates/gallery.html.ep:31
msgid "Zoom in/out"
@@ -688,3 +688,7 @@ msgid "For more details, see the <a href=\"https://framagit.org/fiat-tux/hat-sof
msgstr ""
"Чтоб узнать больше, посетите <a href=\"https://framagit.org/fiat-tux/"
"hat-softwares/lutim\">главную страницу проекта</a>."
#: themes/default/templates/index.html.ep:177 themes/default/templates/index.html.ep:221
msgid "No watermark"
msgstr "Без водного знака"