Verified Commit 1bf33e5d authored by Luc Didry's avatar Luc Didry
Browse files

Merge branch 'development'

parents 442c2c35 72a5e2a5
......@@ -174,3 +174,5 @@ cover:
script:
- make cover
coverage: '/Total .*\d+\.\d+$/'
except:
- tags
[weblate]
url = https://weblate.framasoft.org/api/
translation = lutim/development
Revision history for Lutim
0.1?.? ????-??-??
0.12.0 ????-??-??
- Add watermarking feature (#112)
0.11.6 2019-11-16
- Remove the "Support the author" dropdown
......
EXTRACTDIR=-D lib -D themes/default/templates
POT=themes/default/lib/Lutim/I18N/lutim.pot
ENPO=themes/default/lib/Lutim/I18N/en.po
XGETTEXT=carton exec local/bin/xgettext.pl -u
CARTON=carton exec
LUTIM=script/lutim
......@@ -15,21 +16,10 @@ minify:
locales:
$(XGETTEXT) $(EXTRACTDIR) -o $(POT) 2>/dev/null
push-locales:
ifeq ($(HEAD),$(filter $(HEAD),master development))
sed -e 's@<project-version>.*</project-version>@<project-version>$(HEAD)</project-version>@' -i zanata.xml && \
zanata-cli -q -B push
endif
pull-locales:
ifeq ($(HEAD),$(filter $(HEAD),master development))
sed -e 's@<project-version>.*</project-version>@<project-version>$(HEAD)</project-version>@' -i zanata.xml && \
zanata-cli -q -B pull
endif
$(XGETTEXT) $(EXTRACTDIR) -o $(ENPO) 2>/dev/null
stats-locales:
zanata-cli -q stats
wlc stats
podcheck:
podchecker lib/Lutim/DB/Image.pm
......
......@@ -3,6 +3,7 @@ package Lutim;
use Mojo::Base 'Mojolicious';
use Mojo::IOLoop;
use Lutim::DB::Image;
use Lutim::DefaultConfig qw($default_config);
use vars qw($im_loaded);
BEGIN {
......@@ -28,41 +29,32 @@ sub startup {
$self->plugin('DebugDumperHelper');
my $config = $self->plugin('Config', {
default => {
provisioning => 100,
provis_step => 5,
length => 8,
always_encrypt => 0,
anti_flood_delay => 5,
max_file_size => 10*1024*1024,
https => 0,
proposed_delays => '0,1,7,30,365',
default_delay => 0,
max_delay => 0,
token_length => 24,
crypto_key_length => 8,
thumbnail_size => 100,
theme => 'default',
dbtype => 'sqlite',
db_path => 'lutim.db',
max_files_in_zip => 15,
prefix => '/',
minion => {
enabled => 0,
dbtype => 'sqlite',
db_path => 'minion.db'
},
session_duration => 3600,
cache_max_size => 0,
memcached_servers => [],
quiet_logs => 0,
disable_img_stats => 0,
x_frame_options => 'DENY',
x_content_type_options => 'nosniff',
x_xss_protection => '1; mode=block',
}
default => $default_config
});
if ($config->{watermark_path}) {
die sprintf('%s does not exist or is not readable.', $config->{watermark_path}) unless -r $config->{watermark_path};
my $valid = {
center => 1,
north => 1,
northeast => 1,
east => 1,
southeast => 1,
south => 1,
southwest => 1,
west => 1,
northwest => 1
};
die sprintf('%s is not a valid value for watermark_placement.', $config->{watermark_placement}) unless $valid->{lc($config->{watermark_placement})};
$valid = {
'tiling' => 1,
'single' => 1,
'none' => 1
};
die sprintf('%s is not a valid value for watermark_default.', $config->{watermark_default}) unless $valid->{lc($config->{watermark_default})};
die sprintf('%s is not a valid value for watermark_enforce.', $config->{watermark_enforce}) unless $valid->{lc($config->{watermark_enforce})};
}
if (scalar(@{$config->{memcached_servers}})) {
$self->plugin(CHI => {
lutim_images_cache => {
......@@ -121,7 +113,7 @@ sub startup {
if ($config->{minion}->{enabled}) {
$self->config->{minion}->{dbtype} = 'sqlite' unless defined $config->{minion}->{dbtype};
if ($config->{minion}->{dbtype} eq 'sqlite') {
$self->config('minion')->{db_path} = 'minion.db' unless defined $config->{minion}->{db_path};
$config->{minion}->{db_path} = 'minion.db' unless defined $config->{minion}->{db_path};
$self->plugin('Minion' => { SQLite => 'sqlite:'.$config->{minion}->{db_path} });
} elsif ($config->{minion}->{dbtype} eq 'postgresql') {
$self->plugin('PgURLHelper');
......@@ -178,14 +170,14 @@ sub startup {
});
# Authentication (if configured)
if (defined($self->config('ldap')) || defined($self->config('htpasswd'))) {
if (defined($self->config('ldap'))) {
if (defined($config->{ldap}) || defined($config->{htpasswd})) {
if (defined($config->{ldap})) {
require Net::LDAP;
}
if (defined($self->config('htpasswd'))) {
if (defined($config->{htpasswd})) {
require Apache::Htpasswd;
}
die 'Unable to read '.$self->config('htpasswd') if (defined($self->config('htpasswd')) && !-r $self->config('htpasswd'));
die sprintf('Unable to read %s', $config->{htpasswd}) if (defined($config->{htpasswd}) && !-r $config->{htpasswd});
$self->plugin('Authentication' =>
{
autoload_user => 1,
......@@ -274,7 +266,7 @@ sub startup {
}
}
);
$self->app->sessions->default_expiration($self->config('session_duration'));
$self->app->sessions->default_expiration($config->{session_duration});
}
$self->defaults(layout => 'default');
......@@ -287,7 +279,7 @@ sub startup {
$r->add_condition(authorized => sub {
my ($r, $c, $captures) = @_;
return 1 unless (defined($self->config('ldap')) || defined($self->config('htpasswd')));
return 1 unless (defined($config->{ldap}) || defined($config->{htpasswd}));
return $c->is_user_authenticated;
});
......@@ -306,7 +298,7 @@ sub startup {
to('Authent#index');
if (defined $self->config('ldap') || defined $self->config('htpasswd')) {
if (defined $config->{ldap} || defined $config->{htpasswd}) {
# Login page
$r->get('/login')
->to('Authent#index')
......
......@@ -3,6 +3,7 @@ package Lutim::Command::cron::cleanbdd;
use Mojo::Base 'Mojolicious::Command';
use Mojo::File;
use Lutim::DB::Image;
use Lutim::DefaultConfig qw($default_config);
use FindBin qw($Bin);
use File::Spec qw(catfile);
......@@ -21,10 +22,7 @@ sub run {
}
my $config = $c->app->plugin('Config', {
file => $cfile,
default => {
keep_ip_during => 365,
dbtype => 'sqlite',
}
default => $default_config
});
my $separation = time() - $config->{keep_ip_during} * 86400;
......
......@@ -3,6 +3,7 @@ package Lutim::Command::cron::cleanfiles;
use Mojo::Base 'Mojolicious::Command';
use Mojo::File;
use Lutim::DB::Image;
use Lutim::DefaultConfig qw($default_config);
use Lutim;
use FindBin qw($Bin);
use File::Spec qw(catfile);
......@@ -22,9 +23,7 @@ sub run {
}
my $config = $c->app->plugin('Config', {
file => $cfile,
default => {
dbtype => 'sqlite',
}
default => $default_config
});
my $l = Lutim->new;
......
......@@ -6,6 +6,7 @@ use Mojo::Util qw(encode);
use Mojo::File;
use Mojo::JSON qw(encode_json);
use Lutim::DB::Image;
use Lutim::DefaultConfig qw($default_config);
use DateTime;
use FindBin qw($Bin);
use File::Spec qw(catfile);
......@@ -26,11 +27,7 @@ sub run {
}
my $config = $c->app->plugin('Config', {
file => $cfile,
default => {
theme => 'default',
stats_day_num => 365,
dbtype => 'sqlite'
}
default => $default_config
});
my $template = 'themes/'.$config->{theme}.'/templates/data.html.ep.template';
......
......@@ -3,6 +3,7 @@ package Lutim::Command::cron::watch;
use Mojo::Base 'Mojolicious::Command';
use Filesys::DiskUsage qw/du/;
use Lutim::DB::Image;
use Lutim::DefaultConfig qw($default_config);
use Lutim;
use Mojo::File;
use Switch;
......@@ -24,10 +25,7 @@ sub run {
}
my $config = $c->app->plugin('Config', {
file => $cfile,
default => {
policy_when_full => 'warn',
dbtype => 'sqlite',
}
default => $default_config
});
if (defined($config->{max_total_size})) {
......
......@@ -4,6 +4,7 @@ use Mojo::Base 'Mojolicious::Command';
use Mojo::Util qw(getopt);
use Mojo::Collection 'c';
use Lutim::DB::Image;
use Lutim::DefaultConfig qw($default_config);
use FindBin qw($Bin);
use File::Spec qw(catfile);
......@@ -25,38 +26,7 @@ sub run {
}
my $config = $c->app->plugin('Config', {
file => $cfile,
default => {
provisioning => 100,
provis_step => 5,
length => 8,
always_encrypt => 0,
anti_flood_delay => 5,
max_file_size => 10*1024*1024,
https => 0,
proposed_delays => '0,1,7,30,365',
default_delay => 0,
max_delay => 0,
token_length => 24,
crypto_key_length => 8,
thumbnail_size => 100,
theme => 'default',
dbtype => 'sqlite',
db_path => 'lutim.db',
max_files_in_zip => 15,
prefix => '/',
minion => {
enabled => 0,
dbtype => 'sqlite',
db_path => 'minion.db'
},
cache_max_size => 0,
memcached_servers => [],
quiet_logs => 0,
disable_img_stats => 0,
x_frame_options => 'DENY',
x_content_type_options => 'nosniff',
x_xss_protection => '1; mode=block',
}
default => $default_config
});
if (scalar(@{$config->{memcached_servers}})) {
......
......@@ -285,6 +285,7 @@ sub add {
my $upload = $c->param('file');
my $file_url = $c->param('lutim-file-url');
my $keep_exif = $c->param('keep-exif');
my $wm = $c->param('watermark');
if(!defined($c->stash('stop_upload'))) {
if (defined($file_url) && $file_url) {
......@@ -406,14 +407,56 @@ sub add {
# Automatic rotation from EXIF tag
$im->AutoOrient();
# Update the uploaded file with it's auto-rotated clone
# Get dimensions
$width = $im->Get('width');
$height = $im->Get('height');
# Optionally add watermark
if ($c->config('watermark_path') && (
($wm && $wm ne 'none') ||
$c->config('watermark_enforce') ne 'none'
)) {
my $watermarkim = Image::Magick->new;
$watermarkim->ReadImage($c->config('watermark_path'));
$watermarkim->Evaluate(
operator => 'Multiply',
value => 0.25,
channel => 'Alpha'
);
if ($height <= 80) {
$watermarkim->Resize(geometry => 'x10');
} else {
$watermarkim->Resize(geometry => 'x80');
}
# Add one watermark or repeat it all over the image?
my $tilingw = 1 if ($c->config('watermark_enforce') eq 'tiling' || $wm eq 'tiling');
my $singlew = 1 if ($c->config('watermark_enforce') eq 'single' || $wm eq 'single');
if ($tilingw) {
$im->Composite(
image => $watermarkim,
compose => 'Dissolve',
tile => 'True',
gravity => 'Center'
);
} elsif ($singlew) {
$im->Composite(
image => $watermarkim,
compose => 'Dissolve',
tile => 'False',
x => '20',
y => '20',
gravity => $c->config('watermark_placement')
);
}
}
# Update the uploaded file with it's auto-rotated/watermarked clone
my $asset = Mojo::Asset::Memory->new->add_chunk($im->ImageToBlob());
$upload->asset($asset);
# Create the thumbnail
$width = $im->Get('width');
$height = $im->Get('height');
$im->Resize(geometry=>'x85');
$im->Resize(geometry => 'x85');
$thumb = 'data:'.$mediatype.';base64,';
if ($mediatype eq 'image/gif') {
......
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
package Lutim::DefaultConfig;
require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw($default_config);
our $default_config = {
provisioning => 100,
provis_step => 5,
length => 8,
always_encrypt => 0,
anti_flood_delay => 5,
max_file_size => 10*1024*1024,
https => 0,
proposed_delays => '0,1,7,30,365',
default_delay => 0,
max_delay => 0,
token_length => 24,
crypto_key_length => 8,
thumbnail_size => 100,
watermark_path => '',
watermark_placement => 'SouthEast',
watermark_default => 'none',
watermark_enforce => 'none',
theme => 'default',
dbtype => 'sqlite',
db_path => 'lutim.db',
max_files_in_zip => 15,
prefix => '/',
minion => {
enabled => 0,
dbtype => 'sqlite',
db_path => 'minion.db'
},
session_duration => 3600,
cache_max_size => 0,
memcached_servers => [],
quiet_logs => 0,
disable_img_stats => 0,
x_frame_options => 'DENY',
x_content_type_options => 'nosniff',
x_xss_protection => '1; mode=block',
stats_day_num => 365,
keep_ip_during => 365,
policy_when_full => 'warn',
};
1;
......@@ -47,6 +47,7 @@ sub register {
$app->helper(max_delay => \&_max_delay);
$app->helper(default_delay => \&_default_delay);
$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);
......@@ -250,6 +251,13 @@ sub _is_selected {
return ($num == $c->default_delay) ? 'selected="selected"' : '';
}
sub _is_wm_selected {
my $c = shift;
my $wm = shift;
return ($wm eq $c->config('watermark_default')) ? 'selected="selected"' : '';
}
sub _crypt {
my $c = shift;
my $upload = shift;
......
......@@ -4,6 +4,7 @@ use Mojo::Base 'Mojolicious';
use Mojo::File;
use FindBin qw($Bin);
use File::Spec qw(catfile);
use Lutim::DefaultConfig qw($default_config);
# This method will run once at server start
sub startup {
......@@ -18,43 +19,10 @@ sub startup {
$cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG});
}
}
my $config = $self->plugin('Config' =>
{
file => $cfile,
default => {
provisioning => 100,
provis_step => 5,
length => 8,
always_encrypt => 0,
anti_flood_delay => 5,
max_file_size => 10*1024*1024,
https => 0,
proposed_delays => '0,1,7,30,365',
default_delay => 0,
max_delay => 0,
token_length => 24,
crypto_key_length => 8,
thumbnail_size => 100,
theme => 'default',
dbtype => 'sqlite',
db_path => 'lutim.db',
max_files_in_zip => 15,
prefix => '/',
minion => {
enabled => 0,
dbtype => 'sqlite',
db_path => 'minion.db'
},
cache_max_size => 0,
memcached_servers => [],
quiet_logs => 0,
disable_img_stats => 0,
x_frame_options => 'DENY',
x_content_type_options => 'nosniff',
x_xss_protection => '1; mode=block',
}
}
);
my $config = $self->plugin('Config', {
file => $cfile,
default => $default_config
});
$config->{prefix} = $config->{url_sub_dir} if (defined($config->{url_sub_dir}) && $config->{prefix} eq '/');
......
......@@ -102,6 +102,29 @@
# optional, default is 0
#always_encrypt => 0,
# you can allow to use a watermark on the uploaded images (or enforce its use)
# define a path to the watermark image (provide an image with alpha channel)
# you can define the path relative to lutim directory or set an absolute path
# to disable the usage of a watermark, leave it blank or commented
# optional, no default
#watermark_path => '',
# the watermark can be a tiling one or a single one
# when using a small one, you can choose where to place it
# valid values are 'Center', 'North', 'NorthEast', 'East', 'SouthEast', 'South', 'SouthWest', 'West' and 'NorthWest' (case insensitive)
# optional, default is 'SouthEast'
#watermark_placement => 'SouthEast',
# choose which watermark (tiling, single or none) should be used by default
# valid values are 'tiling', 'single' or 'none' (case insensitive)
# optional, default is 'none'
#watermark_default => 'none',
# choose which watermark (tiling, single or none) should be enforced (users will always have a watermark and won’t be able to disable it)
# valid values are 'tiling', 'single' or 'none' (case insensitive)
# optional, default is 'none'
#watermark_enforce => 'none',
# length of the image's delete token
# optional, default is 24
#token_length => 24,
......
......@@ -10,17 +10,17 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2019-11-16 09:11+0000\n"
"Last-Translator: ButterflyOfFire <butterflyoffire@protonmail.com>\n"
"PO-Revision-Date: 2020-03-09 16:23+0000\n"
"Last-Translator: Luc Didry <luc@framasoft.org>\n"
"Language-Team: Arabic <https://weblate.framasoft.org/projects/lutim/"
"development/ar/>\n"
"default-theme/ar/>\n"
"Language: ar\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
"X-Generator: Weblate 3.9.1\n"
"X-Generator: Weblate 3.11.2\n"
"n%100<=10 ? 3: n%100>=11 ? 4 : 5);\n"
#. (7)
......@@ -110,7 +110,7 @@ msgstr ""
#: themes/default/templates/stats.html.ep:15
msgid "Delay repartition chart for enabled images"
msgstr ""
msgstr "المنحنى البياني للتوزيع الزمني للصور النشطة"
#: themes/default/templates/index.html.ep:133 themes/default/templates/index.html.ep:165 themes/default/templates/index.html.ep:196 themes/default/templates/myfiles.html.ep:124 themes/default/templates/myfiles.html.ep:45 themes/default/templates/partial/lutim.js.ep:161
msgid "Delete at first view?"
......@@ -152,8 +152,8 @@ msgid ""
"to delete the image when you want."
msgstr ""
"إسحب ثم القي صورة ما على المساحة المخصصة لذلك أو قم باستخدام الأسلوب المعتاد "
"لإرسال الملفات و سيقوم لوتان بعدها بتوفير أربع روابط. رابط لعرض الصورة و "
"آخر لتنزيل الصورة مباشرة و آخر يمكنكم إستخدامه على شبكات التواصل الإجتماعي و "
"لإرسال الملفات و سيقوم لوتان بعدها بتوفير أربع روابط. رابط لعرض الصورة و آخر "
"لتنزيل الصورة مباشرة و آخر يمكنكم إستخدامه على شبكات التواصل الإجتماعي و "
"أخيرا رابط آخر يمكّنكم من حذف الصورة إن شئتم."
#: themes/default/templates/index.html.ep:168 themes/default/templates/index.html.ep:199
......@@ -174,7 +174,7 @@ msgstr "تنتهي مدة صلاحيتها في"
#: themes/default/templates/myfiles.html.ep:112
msgid "Export localStorage data"
msgstr ""
msgstr "تصدير بيانات localStorage"
#: themes/default/templates/myfiles.html.ep:121
msgid "File name"
......@@ -242,7 +242,7 @@ msgstr "الصورة غير موجودة."
#: themes/default/templates/myfiles.html.ep:113
msgid "Import localStorage data"
msgstr ""
msgstr "استيراد بيانات localStorage"
#: themes/default/templates/partial/navbar.html.ep:69
msgid "Informations"
......@@ -314,6 +314,8 @@ msgid ""
"also the name of the free (as in free speech) software which provides this "
"service."
msgstr ""
"لوتيم أو Lutim خدمة مجانية ومجهولة لاستضافة الصور. ويعني كذلك اسم البرنامج "
"الحر الموفّر لهذه الخدمة."
#: themes/default/templates/about.html.ep:25
msgid "Main developers"
......@@ -321,7 +323,7 @@ msgstr "المطورون الرئيسيون"
#: themes/default/templates/index.html.ep:91 themes/default/templates/index.html.ep:93 themes/default/templates/partial/lutim.js.ep:86 themes/default/templates/partial/lutim.js.ep:89
msgid "Markdown syntax"
msgstr ""
msgstr "صيغة ماركداون"
#: themes/default/templates/partial/myfiles.js.ep:149
msgid "Modify expiration delay"
......@@ -333,7 +335,7 @@ msgstr "صوري"
#: themes/default/templates/gallery.html.ep:45
msgid "Next (arrow right)"
msgstr ""