1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/lutim_ynh.git synced 2024-09-03 19:36:24 +02:00

mise à jour

This commit is contained in:
Maniack Crudelis 2015-03-10 12:47:07 +01:00
parent d1c6879d4c
commit f49b7a58a6
45 changed files with 1742 additions and 1300 deletions

View file

@ -1,11 +1,12 @@
# Génération des statistiques. Tous les jours, à 5h. # Génération des statistiques. Tous les jours, à 5h.
0 5 * * * www-data carton exec script/lutim cron stats && carton exec hypnotoad script/lutim # 0 5 * * * www-data carton exec script/lutim cron stats && carton exec hypnotoad __FINALPATH__/script/lutim
0 5 * * * www-data cd "__FINALPATH__" && /usr/local/bin/carton exec script/lutim cron stats
# Suppression des adresses IP obsolètes. Tous les jours, à 6h. # Suppression des adresses IP obsolètes. Tous les jours, à 6h.
0 6 * * * www-data carton exec script/lutim cron cleanbdd 0 6 * * * www-data cd "__FINALPATH__" && /usr/local/bin/carton exec script/lutim cron cleanbdd
# Suppression des images dont le délai a expiré. Tous les jours, à 6h. # Suppression des images dont le délai a expiré. Tous les jours, à 6h.
0 6 * * * www-data carton exec script/lutim cron cleanfiles 0 6 * * * www-data cd "__FINALPATH__" && /usr/local/bin/carton exec script/lutim cron cleanfiles
# Vérification de l'occupation du dossier des images. Tous les jours, à 7h. # Vérification de l'occupation du dossier des images. Tous les jours, à 7h.
0 7 * * * www-data carton exec script/lutim cron watch 0 7 * * * www-data cd "__FINALPATH__" && /usr/local/bin/carton exec script/lutim cron watch

View file

@ -6,6 +6,7 @@
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings # see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
hypnotoad => { hypnotoad => {
# array of IP addresses and ports you want to listen to # array of IP addresses and ports you want to listen to
#listen => ['http://127.0.0.1:8080'],
listen => ['http://127.0.0.1:8095'], listen => ['http://127.0.0.1:8095'],
# user and group you want for Lutim to run with # user and group you want for Lutim to run with
# be sure that this user/group have rights on the lutim directory # be sure that this user/group have rights on the lutim directory
@ -36,9 +37,6 @@
#provis_step => 5, #provis_step => 5,
# max number of URLs to be provisioned # max number of URLs to be provisioned
# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
# in the first version, this option was provisionning with two 'n'. While the option with the typo is still valid, it is deprecated.
# in the next version (0.4), only provisioning with ine 'n' will be accepted
# optional, default is 100 # optional, default is 100
#provisioning => 100, #provisioning => 100,
@ -66,6 +64,7 @@
# here's an exemple to put the logo of your hoster # here's an exemple to put the logo of your hoster
# optional, no default # optional, no default
#hosted_by => 'My super hoster <img src="http://hoster.example.com" alt="Hoster logo">', #hosted_by => 'My super hoster <img src="http://hoster.example.com" alt="Hoster logo">',
hosted_by => '<a href="__DOMAIN__/__PATH__/stats">Stats'</a>,
# DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED # DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
# Lutim now checks if the X-Forwarded-Proto header is present and equal to https. # Lutim now checks if the X-Forwarded-Proto header is present and equal to https.
@ -85,7 +84,7 @@
# default time limit for files # default time limit for files
# valid values are 0, 1, 7, 30 and 365 # valid values are 0, 1, 7, 30 and 365
# optional, default is 0 (no limit) # optional, default is 0 (no limit)
#default_delay => 0, default_delay => 365,
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay) # number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
# a warning message will be displayed on homepage # a warning message will be displayed on homepage
@ -100,6 +99,13 @@
# optional, default is 24 # optional, default is 24
#token_length => 24, #token_length => 24,
# URL sub-directory in which you want Lutim to be accessible
# example: you want to have Lutim under https://example.org/lutim/
# => set url_sub_dir to '/lutim' or to '/lutim/', it doesn't matter
# optional, defaut is /
#url_sub_dir => '/',
url_sub_dir => '__PATH__',
########################## ##########################
# Lutim cron jobs settings # Lutim cron jobs settings
########################## ##########################
@ -116,16 +122,17 @@
# max size of the files directory, in octets # max size of the files directory, in octets
# used by script/lutim cron watch to trigger an action # used by script/lutim cron watch to trigger an action
# optional, no default # optional, no default
#max_total_size => 10*1024*1024*1024, #max_total_size => 10*1024*1024*1024, # (=10 Go)
max_total_size => 1024*1024*1024, # (=1 Go)
# default action when files directory is over max_total_size (used with script/lutim cron watch) # default action when files directory is over max_total_size (used with script/lutim cron watch)
# valid values are 'warn', 'stop-upload' and 'delete' # valid values are 'warn', 'stop-upload' and 'delete'
# please, see readme # please, see readme
# optional, default is 'warn' # optional, default is 'warn'
#policy_when_full => 'warn', policy_when_full => 'stop-upload',
# images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task # images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task
# if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted # if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted
# optional, no default # optional, no default
delete_no_longer_viewed_files => 180 #delete_no_longer_viewed_files => 90
}; };

View file

@ -1,72 +1,36 @@
#location __PATH__ { location __PATH__ {
# alias __FINALPATH__; if ($scheme = http) {
# if ($scheme = http) { rewrite ^ https://$server_name$request_uri? permanent;
# rewrite ^ https://$server_name$request_uri? permanent; }
# } location ~ [^/]\.php(/|$) {
# index index.php index.html index.htm; fastcgi_split_path_info ^(.+?\.php)(/.*)$;
# default_type text/html; fastcgi_pass unix:/var/run/php5-fpm.sock;
# location ~ [^/]\.php(/|$) { fastcgi_index index.php;
# fastcgi_split_path_info ^(.+?\.php)(/.*)$; include fastcgi_params;
# fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_param REMOTE_USER $remote_user;
# fastcgi_index index.php; fastcgi_param PATH_INFO $fastcgi_path_info;
# include fastcgi_params; }
# fastcgi_param REMOTE_USER $remote_user;
# fastcgi_param PATH_INFO $fastcgi_path_info;
# }
#
# Include SSOWAT user panel.
# include conf.d/yunohost_panel.conf.inc;
#}
# Include SSOWAT user panel.
include conf.d/yunohost_panel.conf.inc;
#server {
# listen 80;
# root /path/to/lutim/public;
# This is important for user's privacy ! # This is important for user's privacy !
# access_log off; access_log off;
# error_log /var/log/nginx/lutim.error.log; error_log /var/log/nginx/lutim.error.log;
# This is important ! Make it OK with your Lutim configuration # This is important ! Make it OK with your Lutim configuration
client_max_body_size 40M; client_max_body_size 40M;
location ~* ^/(img|css|font|js)/ { proxy_pass http://127.0.0.1:8095;
try_files $uri @lutim;
add_header Expires "Thu, 31 Dec 2037 23:55:55 GMT";
add_header Cache-Control "public, max-age=315360000";
# HTTPS only header, improves security proxy_set_header Host $host;
#add_header Strict-Transport-Security "max-age=15768000"; proxy_set_header X-Real-IP $remote_addr;
} proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# location / { # Lutim reads this header and understands that the current session is actually HTTPS.
location __PATH__ { # Enable it if you run a HTTPS server (in this case, don't forgot to change the listen port $
#alias __FINALPATH__; proxy_set_header X-Forwarded-Proto https;
try_files $uri @lutim;
# HTTPS only header, improves security # We expect the downsteam servers to redirect to the right hostname, so don't do any rewrite$
#add_header Strict-Transport-Security "max-age=15768000"; proxy_redirect off;
} }
location @lutim {
# Adapt this to your configuration
# My advice: put a varnish between nginx and Lutim, it's really useful when images are widel$
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# If you want to log the remote port of the image senders, you'll need that
proxy_set_header X-Remote-Port $remote_port;
# Lutim reads this header and understands that the current session is actually HTTPS.
# Enable it if you run a HTTPS server (in this case, don't forgot to change the listen port $
#proxy_set_header X-Forwarded-Proto https;
# We expect the downsteam servers to redirect to the right hostname, so don't do any rewrite$
proxy_redirect off;
}
#}

BIN
lutim-proxy.zip Normal file

Binary file not shown.

View file

@ -3,8 +3,7 @@
"id": "lutim", "id": "lutim",
"description": { "description": {
"en": "Leed is a minimalistic RSS feed aggregator which allows quick and non-intrusive reading of feeds.", "en": "Leed is a minimalistic RSS feed aggregator which allows quick and non-intrusive reading of feeds.",
"fr": "Leed est un agrégateur RSS minimaliste qui permet la consultation de flux RSS de manière rapide et non intrusive." "fr": "Lutim est un logiciel dhébergement dimages. Il sagit aussi du nom du logiciel (libre) qui fournit ce service."
Lutim est un logiciel dhébergement dimages. Il sagit aussi du nom du logiciel (libre) qui fournit ce service.
}, },
"version": "0.6", "version": "0.6",
"url": "https://lut.im", "url": "https://lut.im",
@ -19,36 +18,38 @@ Lutim est un logiciel dhébergement dimages. Il sagit aussi du nom du l
"name": "domain", "name": "domain",
"ask": { "ask": {
"en": "Choose a domain for Lutim", "en": "Choose a domain for Lutim",
"fr": "Choisissez un domaine pour Lutim" "fr": "Choisissez un domaine pour Lutim"
}, },
"example": "domain.org" "example": "domain.org",
"default": "crudelis-test.fr"
}, },
{ {
"name": "path", "name": "path",
"ask": { "ask": {
"en": "Choose a path for Lutim", "en": "Choose a path for Lutim",
"fr": "Choisissez un chemin pour Lutim" "fr": "Choisissez un chemin pour Lutim"
}, },
"example": "/lutim", "example": "/lutim",
"default": "/lutim" "default": "/lutim"
}, },
{ {
"name": "admin", "name": "admin",
"ask": { "ask": {
"en": "Choose the Lutim administrator (must be an existing YunoHost user)", "en": "Choose the Lutim administrator (must be an existing YunoHost user)",
"fr": "Choisissez un administrateur Lutim (doit être un utilisateur YunoHost)" "fr": "Choisissez un administrateur Lutim (doit être un utilisateur YunoHost)"
}, },
"example": "john" "example": "john",
}, "default": "mcrudelis"
{ },
"name": "is_public", {
"ask": { "name": "is_public",
"en": "Uploading images is it public?", "ask": {
"fr": "L'upload des images est-il public ?" "en": "Uploading images is it public?",
}, "fr": "L'upload des images est-il public ?"
"choices": ["Yes", "No"], },
"default": "No" "choices": ["Yes", "No"],
} "default": "No"
}
] ]
} }
} }

View file

@ -14,7 +14,7 @@ if [[ ! $? -eq 0 ]]; then
fi fi
# Check domain/path availability # Check domain/path availability
sudo yunohost app checkurl $domain$path -a leed sudo yunohost app checkurl $domain$path -a lutim
if [[ ! $? -eq 0 ]]; then if [[ ! $? -eq 0 ]]; then
exit 1 exit 1
fi fi
@ -30,25 +30,32 @@ sudo cp -a ../sources/lutim-master/* $final_path
sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/lutim.conf sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/lutim.conf
# Installation du module perl carton # Installation du module perl carton
yes | sudo cpan Carton echo "Installation du module perl carton. Attention, étape très longue..."
# yes | sudo cpan Carton | sudo tee $final_path/cpan_setup.log 2>&1 > /dev/null 2>&1 # Debug
yes | sudo cpan Carton > /dev/null 2>&1
# Installation de perlmagick, interface perl pour imagemagick # Installation de perlmagick, interface perl pour imagemagick
sudo apt-get install perlmagick -qy sudo apt-get install perlmagick -qy
# Installation de lutim via carton
cd $final_path
echo pwd
sudo carton install
## Copie et configuration du fichier de conf. ## Copie et configuration du fichier de conf.
sudo cp ../conf/lutim.conf.template $final_path/lutim.conf sudo cp ../conf/lutim.conf.template $final_path/lutim.conf
sudo sed -i "s@__DOMAIN__@$domain@g" $final_path/lutim.conf sudo sed -i "s@__DOMAIN__@$domain@g" $final_path/lutim.conf
sudo sed -i "s@__PATH__@$path@g" $final_path/lutim.conf
# Mise en place des scripts init # Mise en place des scripts init
sudo cp ../sources/lutim-master/utilities/lutim.init /etc/init.d/lutim sudo cp ../sources/lutim-master/utilities/lutim.init /etc/init.d/lutim
sudo cp ../conf/lutim.default /etc/default/lutim sudo cp ../conf/lutim.default /etc/default/lutim
sudo chmod +x /etc/init.d/lutim sudo chmod +x /etc/init.d/lutim
chown root:root /etc/init.d/lutim /etc/default/lutim sudo chown root:root /etc/init.d/lutim /etc/default/lutim
sudo sed -i "s@__FINALPATH__@$final_path@g" /etc/default/lutim sudo sed -i "s@__FINALPATH__@$final_path/@g" /etc/default/lutim
## Mise en place des crons
sudo cp ../conf/cron_lutim /etc/cron.d/lutim
sudo sed -i "s@__FINALPATH__@$final_path/@g" /etc/cron.d/lutim
# Installation de lutim via carton
cd $final_path
sudo carton install
## Démarrage auto des scripts init ## Démarrage auto des scripts init
sudo update-rc.d lutim defaults sudo update-rc.d lutim defaults
@ -56,17 +63,8 @@ sudo update-rc.d lutim defaults
# Change variables in nginx configuration # Change variables in nginx configuration
sudo sed -i "s@__PATH__@$path@g" /etc/nginx/conf.d/$domain.d/lutim.conf sudo sed -i "s@__PATH__@$path@g" /etc/nginx/conf.d/$domain.d/lutim.conf
sudo sed -i "s@__FINALPATH__@$final_path/@g" /etc/nginx/conf.d/$domain.d/lutim.conf
## Voir les crons et les mettre en place.
# Files owned by root, www-data can just read
# sudo find $final_path -type f | xargs sudo chmod 644
# sudo find $final_path -type d | xargs sudo chmod 755
# sudo chown -R root: $final_path
# www-data can write on plugins and cache
# sudo chown -R www-data $final_path/cache $final_path/plugins
# Set right permissions # Set right permissions
sudo chown -R www-data: $final_path sudo chown -R www-data: $final_path
@ -76,8 +74,8 @@ if [ "$is_public" = "Yes" ];
then then
sudo yunohost app setting lutim skipped_uris -v "/" sudo yunohost app setting lutim skipped_uris -v "/"
else # Si l'app est privée, seul le visionnage des images est public else # Si l'app est privée, seul le visionnage des images est public
sudo yunohost app setting lutim skipped_regex -v "/(stats|manifest.webapp|(d|m)/.+)?$" # sudo yunohost app setting lutim skipped_regex -v "/(stats|manifest.webapp|(d|m)/.+)?$"
fi # REGEX À INVERSER ! Je pense... fi
# Reload Nginx, start lutim and regenerate SSOwat conf # Reload Nginx, start lutim and regenerate SSOwat conf
sudo service nginx reload sudo service nginx reload

15
sources/cpanfile Normal file
View file

@ -0,0 +1,15 @@
requires 'Mojolicious';
requires 'EV';
requires 'Data::Validate::URI';
requires 'Mojolicious::Plugin::I18N';
requires 'Mojolicious::Plugin::AssetPack';
requires 'ORLite';
requires 'File::Type';
requires 'Text::Unidecode';
requires 'DateTime';
requires 'Filesys::DiskUsage';
requires 'Switch';
requires 'Data::Validate::URI';
requires 'Crypt::CBC';
requires 'Crypt::Blowfish';
requires "IO::Socket::SSL";

View file

@ -1,5 +1,19 @@
Revision history for Lutim Revision history for Lutim
0.7 2015-?
- Allow Lutim to be on a sub-directory (like http://example.org/lutim/) (#46)
- Remove deprecated (due to typo) option "provisionning".
0.6 2014-10-03
- Add OpenGraph tags in social page (ex-twitter page)
- Update README.md
- Update info page
0.5 2014-09-24
- Add support for animated gif in Twitter cards (#45)
- Update README.md with Twitter integration informations
- bugfixes
0.4 2014-07-12 0.4 2014-07-12
- Webapp ! Downloadable directly from the Lutim instance - Webapp ! Downloadable directly from the Lutim instance
- Configure expiration delay after uploading (#12) - Configure expiration delay after uploading (#12)

View file

@ -4,7 +4,8 @@
It means Let's Upload That Image. It means Let's Upload That Image.
## What does it do? ## What does it do?
It stores images and allows you to see them, download them or use them in Twitter. It stores images and allows you to see them, download them or share them on social networks. From version 0.5, the gif images can be displayed as animated gifs in Twitter, but you need a HTTPS server (Twitter requires that. Lutim detects if you have a HTTPS server and displays an static image twitter card if you don't);
Images are indefinitly stored unless you request that they will be deleted at first view or after 24 hours / one week / one month / one year. Images are indefinitly stored unless you request that they will be deleted at first view or after 24 hours / one week / one month / one year.
## License ## License
@ -34,21 +35,27 @@ sudo apt-get install carton
* But, on another hand, some modules that Carton will install need to be compiled. So you will need some tools: * But, on another hand, some modules that Carton will install need to be compiled. So you will need some tools:
```shell ```shell
sudo apt-get install build-essential libssl-dev sudo apt-get install build-essential
``` ```
### Thumbnails dependancy ### Thumbnails and animated gifs in Twitter dependancy
If you want to provide thumbnails of uploaded images, you have to install the *ImageMagick* image manipulation software (<http://www.imagemagick.org/>) and the Image::Magick CPAN module. If you want to provide thumbnails of uploaded images or have animated gifs in Twitter, you have to install the *ImageMagick* image manipulation software (<http://www.imagemagick.org/>) and the Image::Magick CPAN module.
On Debian, you can do: On Debian, you can do:
```shell ```shell
sudo apt-get install perlmagick sudo apt-get install perlmagick
``` ```
## Twitter integration
If you want to share images of your Lutim instance on Twitter, you have to register your site at <https://cards-dev.twitter.com/validator>.
## Other social networks integration
It seems that you only need to put the Lutim' social page link (the one with `?t`) in your post and it will be automatically embedded.
## Installation ## Installation
After installing Carton : After installing Carton :
```shell ```shell
git clone https://github.com/ldidry/lutim.git git clone https://git.framasoft.org/luc/lutim.git
cd lutim cd lutim
carton install carton install
cp lutim.conf.template lutim.conf cp lutim.conf.template lutim.conf
@ -119,6 +126,17 @@ UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE lutim ( short TEXT PRIMARY KEY, pat
PRAGMA writable_schema = 0; PRAGMA writable_schema = 0;
``` ```
***Warning!!!***
If you want to update to Lutim **0.5**, from a previous version, you'll have to modify the database.
```
sqlite3 lutim.db
PRAGMA writable_schema = 1;
UPDATE SQLITE_MASTER SET SQL = 'CREATE TABLE lutim ( short TEXT PRIMARY KEY, path TEXT, footprint TEXT, enabled INTEGER, mediatype TEXT, filename TEXT, counter INTEGER, delete_at_first_view INTEGER, delete_at_day INTEGER, created_at INTEGER, created_by TEXT, last_access_at INTEGER, mod_token TEXT, width INTEGER, height INTEGER)' WHERE NAME = 'lutim';
PRAGMA writable_schema = 0;
```
## Reverse proxy ## Reverse proxy
You can use a reverse proxy like Nginx or Varnish (or Apache with the mod_proxy module). The web is full of tutos. You can use a reverse proxy like Nginx or Varnish (or Apache with the mod_proxy module). The web is full of tutos.
@ -272,10 +290,12 @@ vim de.pm
There's just a few sentences, so it will be quick to translate. Please consider to send me you language file in order to help the other users :smile:. There's just a few sentences, so it will be quick to translate. Please consider to send me you language file in order to help the other users :smile:.
## Others projects dependancies ## Others projects dependancies
Lutim is written in Perl with the [Mojolicious](http://mojolicio.us) framework, uses the [Twitter bootstrap](http://getbootstrap.com) framework to look not too ugly, [JQuery](http://jquery.com) and [JQuery File Uploader](https://github.com/danielm/uploader/) (slightly modified) to add some modernity, [Raphaël](http://raphaeljs.com/) and [morris.js](http://www.oesmith.co.uk/morris.js/) for stats graphs. Lutim is written in Perl with the [Mojolicious](http://mojolicio.us) framework, uses the [Twitter bootstrap](http://getbootstrap.com) framework to look not too ugly, [JQuery](http://jquery.com) and [JQuery File Uploader](https://github.com/danielm/uploader/) (slightly modified) to add some modernity, [Raphaël](http://raphaeljs.com/) and [morris.js](http://www.oesmith.co.uk/morris.js/) for stats graphs and [freezeframe.js](http://freezeframe.chrisantonellis.com/) (slightly modified) to be able to freeze animated gifs in twitter card.
Licenses for the icons fonts are in `public/font/LICENSE.txt`.
## Main developers ## Main developers
* Luc Didry, aka Sky (<http://www.fiat-tux.fr>), core developer, [@framasky](https://twitter.com/framasky) * Luc Didry, aka Sky (<http://www.fiat-tux.fr>), core developer, @framasky on [Twitter](https://twitter.com/framasky) and on [Diaspora*](https://framasphere.org/public/framasky)
* Dattaz (<http://dattaz.fr>), webapp developer, [@dat_taz](https://twitter.com/dat_taz) * Dattaz (<http://dattaz.fr>), webapp developer, [@dat_taz](https://twitter.com/dat_taz)
## Contributors ## Contributors

View file

@ -2,7 +2,6 @@ requires 'Mojolicious';
requires 'EV'; requires 'EV';
requires 'Data::Validate::URI'; requires 'Data::Validate::URI';
requires 'Mojolicious::Plugin::I18N'; requires 'Mojolicious::Plugin::I18N';
requires 'Mojolicious::Plugin::ConfigHashMerge';
requires 'Mojolicious::Plugin::AssetPack'; requires 'Mojolicious::Plugin::AssetPack';
requires 'ORLite'; requires 'ORLite';
requires 'File::Type'; requires 'File::Type';
@ -13,3 +12,4 @@ requires 'Switch';
requires 'Data::Validate::URI'; requires 'Data::Validate::URI';
requires 'Crypt::CBC'; requires 'Crypt::CBC';
requires 'Crypt::Blowfish'; requires 'Crypt::Blowfish';
requires "IO::Socket::SSL";

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
{ {
"name": "", "name": "fontello",
"css_prefix_text": "icon-", "css_prefix_text": "icon-",
"css_use_suffix": false, "css_use_suffix": false,
"hinting": true, "hinting": true,
@ -18,6 +18,12 @@
"code": 59397, "code": 59397,
"src": "fontawesome" "src": "fontawesome"
}, },
{
"uid": "4aad6bb50b02c18508aae9cbe14e784e",
"css": "share",
"code": 59400,
"src": "fontawesome"
},
{ {
"uid": "f48ae54adfb27d8ada53d0fd9e34ee10", "uid": "f48ae54adfb27d8ada53d0fd9e34ee10",
"css": "trash", "css": "trash",

View file

@ -10,14 +10,12 @@ mkdir($ENV{MOJO_TMPDIR}, 0700) unless (-d $ENV{MOJO_TMPDIR});
sub startup { sub startup {
my $self = shift; my $self = shift;
push @{$self->commands->namespaces}, 'Lutim::Command';
$self->{wait_for_it} = {}; $self->{wait_for_it} = {};
$self->plugin('I18N'); $self->plugin('I18N');
$self->plugin('AssetPack'); $self->plugin('AssetPack');
my $config = $self->plugin('ConfigHashMerge', { my $config = $self->plugin('Config', {
default => { default => {
provisioning => 100, provisioning => 100,
provis_step => 5, provis_step => 5,
@ -33,9 +31,6 @@ sub startup {
} }
}); });
# Default values
$config->{provisioning} = $config->{provisionning} if (defined($config->{provisionning}));
die "You need to provide a contact information in lutim.conf !" unless (defined($config->{contact})); die "You need to provide a contact information in lutim.conf !" unless (defined($config->{contact}));
$ENV{MOJO_MAX_MESSAGE_SIZE} = $config->{max_file_size}; $ENV{MOJO_MAX_MESSAGE_SIZE} = $config->{max_file_size};
@ -83,6 +78,19 @@ sub startup {
} }
); );
$self->helper(
index_url => sub {
my $c = shift;
my $to_abs = shift;
my $url = $c->url_for('index');
$url = $url->to_abs() if (defined($to_abs) && $to_abs);
$url =~ s#([^/])$#$1/#;
return $url;
}
);
$self->helper( $self->helper(
ip => sub { ip => sub {
my $c = shift; my $c = shift;
@ -293,8 +301,9 @@ sub startup {
$self->asset('stats.css' => 'css/bootstrap.min.css', 'css/fontello-embedded.css', 'css/morris-0.4.3.min.css', 'css/hennypenny.css', 'css/lutim.css'); $self->asset('stats.css' => 'css/bootstrap.min.css', 'css/fontello-embedded.css', 'css/morris-0.4.3.min.css', 'css/hennypenny.css', 'css/lutim.css');
$self->asset('about.css' => 'css/bootstrap.min.css', 'css/fontello-embedded.css', 'css/hennypenny.css', 'css/lutim.css'); $self->asset('about.css' => 'css/bootstrap.min.css', 'css/fontello-embedded.css', 'css/hennypenny.css', 'css/lutim.css');
$self->asset('index.js' => 'js/jquery-2.1.0.min.js', 'js/bootstrap.min.js', 'js/lutim.js', 'js/dmuploader.min.js'); $self->asset('index.js' => 'js/jquery-2.1.0.min.js', 'js/bootstrap.min.js', 'js/lutim.js', 'js/dmuploader.min.js');
$self->asset('stats.js' => 'js/jquery-2.1.0.min.js', 'js/bootstrap.min.js', 'js/lutim.js', 'js/raphael-min.js', 'js/morris-0.4.3.min.js', 'js/stats.js'); $self->asset('stats.js' => 'js/jquery-2.1.0.min.js', 'js/bootstrap.min.js', 'js/lutim.js', 'js/raphael-min.js', 'js/morris-0.4.3.min.js', 'js/stats.js');
$self->asset('freeze.js' => 'js/jquery-2.1.0.min.js', 'js/freezeframe.min.js');
$self->defaults(layout => 'default'); $self->defaults(layout => 'default');

View file

@ -2,6 +2,8 @@ package Lutim::Command::cron::cleanbdd;
use Mojo::Base 'Mojolicious::Command'; use Mojo::Base 'Mojolicious::Command';
use LutimModel; use LutimModel;
use Mojo::Util qw(slurp decode); use Mojo::Util qw(slurp decode);
use FindBin qw($Bin);
use File::Spec qw(catfile);
has description => 'Delete IP addresses from database after configured delay.'; has description => 'Delete IP addresses from database after configured delay.';
has usage => sub { shift->extract_usage }; has usage => sub { shift->extract_usage };
@ -9,7 +11,8 @@ has usage => sub { shift->extract_usage };
sub run { sub run {
my $c = shift; my $c = shift;
my $config = $c->app->plugin('ConfigHashMerge', { my $config = $c->app->plugin('Config', {
file => File::Spec->catfile($Bin, '..' ,'lutim.conf'),
default => { default => {
keep_ip_during => 365, keep_ip_during => 365,
} }

View file

@ -1,29 +1,35 @@
package Lutim::Command::cron::cleanfiles; package Lutim::Command::cron::cleanfiles;
use Mojo::Base 'Mojolicious::Command'; use Mojo::Base 'Mojolicious::Command';
use LutimModel; use LutimModel;
use Lutim;
use Mojo::Util qw(slurp decode); use Mojo::Util qw(slurp decode);
use FindBin qw($Bin);
use File::Spec qw(catfile);
has description => 'Delete expired files.'; has description => 'Delete expired files.';
has usage => sub { shift->extract_usage }; has usage => sub { shift->extract_usage };
sub run { sub run {
my $c = shift; my $c = shift;
my $l = Lutim->new;
my $time = time(); my $time = time();
my @images = LutimModel::Lutim->select('WHERE enabled = 1 AND (delete_at_day * 86400) < (? - created_at) AND delete_at_day != 0', $time); my @images = LutimModel::Lutim->select('WHERE enabled = 1 AND (delete_at_day * 86400) < (? - created_at) AND delete_at_day != 0', $time);
for my $image (@images) { for my $image (@images) {
$c->app->delete_image($image); $l->app->delete_image($image);
} }
my $config = $c->app->plugin('Config'); my $config = $c->app->plugin('Config', {
file => File::Spec->catfile($Bin, '..' ,'lutim.conf'),
});
if (defined($config->{delete_no_longer_viewed_files}) && $config->{delete_no_longer_viewed_files} > 0) { if (defined($config->{delete_no_longer_viewed_files}) && $config->{delete_no_longer_viewed_files} > 0) {
$time = time() - $config->{delete_no_longer_viewed_files} * 86400; $time = time() - $config->{delete_no_longer_viewed_files} * 86400;
@images = LutimModel::Lutim->select('WHERE enabled = 1 AND last_access_at < ?', $time); @images = LutimModel::Lutim->select('WHERE enabled = 1 AND last_access_at < ?', $time);
for my $image (@images) { for my $image (@images) {
$c->app->delete_image($image); $l->app->delete_image($image);
} }
} }
} }

View file

@ -4,6 +4,8 @@ use LutimModel;
use Mojo::DOM; use Mojo::DOM;
use Mojo::Util qw(slurp spurt decode); use Mojo::Util qw(slurp spurt decode);
use DateTime; use DateTime;
use FindBin qw($Bin);
use File::Spec qw(catfile);
has description => 'Generate statistics about Lutim.'; has description => 'Generate statistics about Lutim.';
has usage => sub { shift->extract_usage }; has usage => sub { shift->extract_usage };
@ -11,7 +13,8 @@ has usage => sub { shift->extract_usage };
sub run { sub run {
my $c = shift; my $c = shift;
my $config = $c->app->plugin('ConfigHashMerge', { my $config = $c->app->plugin('Config', {
file => File::Spec->catfile($Bin, '..' ,'lutim.conf'),
default => { default => {
stats_day_num => 365 stats_day_num => 365
} }

View file

@ -4,6 +4,8 @@ use Mojo::Util qw(slurp decode);
use Filesys::DiskUsage qw/du/; use Filesys::DiskUsage qw/du/;
use LutimModel; use LutimModel;
use Switch; use Switch;
use FindBin qw($Bin);
use File::Spec qw(catfile);
has description => 'Watch the files directory and take action when over quota'; has description => 'Watch the files directory and take action when over quota';
has usage => sub { shift->extract_usage }; has usage => sub { shift->extract_usage };
@ -11,7 +13,8 @@ has usage => sub { shift->extract_usage };
sub run { sub run {
my $c = shift; my $c = shift;
my $config = $c->app->plugin('ConfigHashMerge', { my $config = $c->app->plugin('Config', {
file => File::Spec->catfile($Bin, '..' ,'lutim.conf'),
default => { default => {
policy_when_full => 'warn' policy_when_full => 'warn'
} }

View file

@ -279,9 +279,13 @@ sub add {
my $filename = unidecode($upload->filename); my $filename = unidecode($upload->filename);
my $ext = ($filename =~ m/([^.]+)$/)[0]; my $ext = ($filename =~ m/([^.]+)$/)[0];
my $path = 'files/'.$records[0]->short.'.'.$ext; my $path = 'files/'.$records[0]->short.'.'.$ext;
my ($width, $height);
if ($im_loaded) { if ($im_loaded) {
my $im = Image::Magick->new; my $im = Image::Magick->new;
$im->BlobToImage($upload->slurp); $im->BlobToImage($upload->slurp);
$width = $im->Get('width');
$height = $im->Get('height');
$im->Resize(geometry=>'x85'); $im->Resize(geometry=>'x85');
$thumb = 'data:'.$mediatype.';base64,'; $thumb = 'data:'.$mediatype.';base64,';
@ -301,7 +305,9 @@ sub add {
delete_at_day => ($c->param('delete-day') && $c->param('delete-day') <= $c->max_delay) ? $c->param('delete-day') : $c->max_delay, delete_at_day => ($c->param('delete-day') && $c->param('delete-day') <= $c->max_delay) ? $c->param('delete-day') : $c->max_delay,
delete_at_first_view => ($c->param('first-view')) ? 1 : 0, delete_at_first_view => ($c->param('first-view')) ? 1 : 0,
created_at => time(), created_at => time(),
created_by => $ip created_by => $ip,
width => $width,
height => $height
); );
# Log image creation # Log image creation
@ -413,11 +419,31 @@ sub short {
$test = 1; $test = 1;
my $short = $images[0]->short; my $short = $images[0]->short;
$short .= '/'.$key if (defined($key)); $short .= '/'.$key if (defined($key));
my ($width, $height) = (340,340);
if ($images[0]->mediatype eq 'image/gif') {
if (defined($images[0]->width) && defined($images[0]->height)) {
($width, $height) = ($images[0]->width, $images[0]->height);
} elsif ($im_loaded) {
my $upload = $c->decrypt($key, $images[0]->path);
my $im = Image::Magick->new;
$im->BlobToImage($upload->slurp);
$width = $im->Get('width');
$height = $im->Get('height');
$images[0]->update(
width => $width,
height => $height
);
}
}
return $c->render( return $c->render(
template => 'twitter', template => 'twitter',
layout => undef, layout => undef,
short => $short, short => $short,
filename => $images[0]->filename filename => $images[0]->filename,
mimetype => ($c->req->url->to_abs()->scheme eq 'https') ? $images[0]->mediatype : '',
width => $width,
height => $height
); );
} else { } else {
# Delete image if needed # Delete image if needed

View file

@ -6,7 +6,7 @@ my $inf_body = <<EOF;
<p>Lutim is a free (as in free beer) and anonymous image hosting service. It's also the name of the free (as in free speech) software which provides this service.</p> <p>Lutim is a free (as in free beer) and anonymous image hosting service. It's also the name of the free (as in free speech) software which provides this service.</p>
<p>The images you post on Lutim can be stored indefinitely or be deleted at first view or after a delay selected from those proposed.</p> <p>The images you post on Lutim can be stored indefinitely or be deleted at first view or after a delay selected from those proposed.</p>
<h4>How does it work?</h4> <h4>How does it work?</h4>
<p>Drag and drop an image in the appropriate area or use the traditional way to send files and Lutim will provide you three URLs. One to view the image, an other to directly download it an a last which you can use in Twitter.</p> <p>Drag and drop an image in the appropriate area or use the traditional way to send files and Lutim will provide you three URLs. One to view the image, an other to directly download it, one you can use on social networks and a last to delete the image when you want.</p>
<p>You can, optionally, request that the image(s) posted on Lutim to be deleted at first view (or download) or after the delay selected from those proposed.</p> <p>You can, optionally, request that the image(s) posted on Lutim to be deleted at first view (or download) or after the delay selected from those proposed.</p>
<h4>Is it really free (as in free beer)?</h4> <h4>Is it really free (as in free beer)?</h4>
<p>Yes, it is! On the other side, if you want to support the developer, you can do it via <a href="https://flattr.com/submit/auto?user_id=_SKy_&amp;url=[_1]&amp;title=Lutim&amp;category=software">Flattr</a> or with <a href="bitcoin:1K3n4MXNRSMHk28oTfXEvDunWFthePvd8v?label=lutim">BitCoin</a>.</p> <p>Yes, it is! On the other side, if you want to support the developer, you can do it via <a href="https://flattr.com/submit/auto?user_id=_SKy_&amp;url=[_1]&amp;title=Lutim&amp;category=software">Flattr</a> or with <a href="bitcoin:1K3n4MXNRSMHk28oTfXEvDunWFthePvd8v?label=lutim">BitCoin</a>.</p>
@ -14,6 +14,9 @@ my $inf_body = <<EOF;
<p>Yes, it is! On the other side, for legal reasons, your IP address will be stored when you send an image. Don't panic, it is normally the case of all sites on which you send files!</p> <p>Yes, it is! On the other side, for legal reasons, your IP address will be stored when you send an image. Don't panic, it is normally the case of all sites on which you send files!</p>
<p>The IP address of the image's sender is retained for a delay which depends of the administrator's choice (for the official instance, which is located in France, it's one year).</p> <p>The IP address of the image's sender is retained for a delay which depends of the administrator's choice (for the official instance, which is located in France, it's one year).</p>
<p>If the files are deleted if you ask it while posting it, their SHA512 footprint are retained.</p> <p>If the files are deleted if you ask it while posting it, their SHA512 footprint are retained.</p>
<h4>Who owns rights on images uploaded on Lutim?</h4>
<p>Only the uploader! (well, only if he's the only owner of the images' rights before the upload)</p>
<p>Unlike many image sharing services, you don't give rights on uploaded images.</p>
<h4>How to report an image?</h4> <h4>How to report an image?</h4>
<p>Please contact the administrator: [_2]</p> <p>Please contact the administrator: [_2]</p>
<h4>How do you pronounce Lutim?</h4> <h4>How do you pronounce Lutim?</h4>
@ -23,7 +26,7 @@ my $inf_body = <<EOF;
<p>For more details, see the <a href="https://github.com/ldidry/lutim">Github</a> page of the project.</p> <p>For more details, see the <a href="https://github.com/ldidry/lutim">Github</a> page of the project.</p>
<h4>Main developers</h4> <h4>Main developers</h4>
<ul> <ul>
<li>Luc Didry, aka Sky (<a href="http://www.fiat-tux.fr">http://www.fiat-tux.fr</a>), core developer, <a href="https://twitter.com/framasky">\@framasky</a></li> <li>Luc Didry, aka Sky (<a href="http://www.fiat-tux.fr">http://www.fiat-tux.fr</a>), core developer, \@framasky on <a href="https://twitter.com/framasky">Twitter</a>, or on <a href="https://framasphere.org/public/framasky">Diaspora*</a></li>
<li>Dattaz (<a href="http://dattaz.fr">http://dattaz.fr</a>), webapp developer, <a href="https://twitter.com/dat_taz">\@dat_taz</a></li> <li>Dattaz (<a href="http://dattaz.fr">http://dattaz.fr</a>), webapp developer, <a href="https://twitter.com/dat_taz">\@dat_taz</a></li>
</ul> </ul>
<h4>Contributors</h4> <h4>Contributors</h4>
@ -44,51 +47,53 @@ our %Lexicon = (
'informations-body' => $inf_body, 'informations-body' => $inf_body,
'view-link' => 'View link', 'view-link' => 'View link',
'download-link' => 'Download link', 'download-link' => 'Download link',
'twitter-link' => 'Link for put in a tweet', 'share-link' => 'Link for share on social networks',
'tweet_it' => 'Tweet it!', 'tweet_it' => 'Tweet it!',
'share_it' => 'Share it!', 'share_it' => 'Share it!',
'delete-link' => 'Deletion link', 'delete-link' => 'Deletion link',
'some-bad' => 'Something bad happened', 'some-bad' => 'Something bad happened',
'delete-first' => 'Delete at first view?', 'delete-first' => 'Delete at first view?',
'delete-day' => 'Delete after 24 hours?', 'delete-day' => 'Delete after 24 hours?',
'upload_image' => 'Send an image', 'upload_image' => 'Send an image',
'image-only' => 'Only images are allowed', 'image-only' => 'Only images are allowed',
'go' => 'Let\'s go!', 'go' => 'Let\'s go!',
'drag-n-drop' => 'Drag & drop images here', 'drag-n-drop' => 'Drag & drop images here',
'or' => '-or-', 'or' => '-or-',
'file-browser' => 'Click to open the file browser', 'file-browser' => 'Click to open the file browser',
'image_not_found' => 'Unable to find the image: it has been deleted.', 'image_not_found' => 'Unable to find the image: it has been deleted.',
'no_more_short' => 'There is no more available URL. Retry or contact the administrator. [_1]', 'no_more_short' => 'There is no more available URL. Retry or contact the administrator. [_1]',
'no_valid_file' => 'The file [_1] is not an image.', 'no_valid_file' => 'The file [_1] is not an image.',
'file_too_big' => 'The file exceed the size limit ([_1])', 'file_too_big' => 'The file exceed the size limit ([_1])',
'no_time_limit' => 'No time limit', 'no_time_limit' => 'No time limit',
'24_hours' => '24 hours', '24_hours' => '24 hours',
'7_days' => '7 days', '7_days' => '7 days',
'30_days' => '30 days', '30_days' => '30 days',
'1_year' => 'One year', '1_year' => 'One year',
'pushed-images' => ' sent images on this instance from beginning.', 'pushed-images' => ' sent images on this instance from beginning.',
'graph-data-once-a-day' => 'The graph\'s datas are not updated in real-time.', 'graph-data-once-a-day' => 'The graph\'s datas are not updated in real-time.',
'lutim-stats' => 'Lutim\'s statistics', 'lutim-stats' => 'Lutim\'s statistics',
'back-to-index' => 'Back to homepage', 'back-to-index' => 'Back to homepage',
'stop_upload' => 'Uploading is currently disabled, please try later or contact the administrator ([_1]).', 'stop_upload' => 'Uploading is currently disabled, please try later or contact the administrator ([_1]).',
'download_error' => 'An error occured while downloading the image.', 'download_error' => 'An error occured while downloading the image.',
'no_valid_url' => 'The URL is not valid.', 'no_valid_url' => 'The URL is not valid.',
'image_url' => 'Image URL', 'image_url' => 'Image URL',
'upload_image_url' => 'Upload an image with its URL', 'upload_image_url' => 'Upload an image with its URL',
'delay_0' => 'no time limit', 'delay_0' => 'no time limit',
'delay_1' => '24 hours', 'delay_1' => '24 hours',
'delay_days' => '[_1] days', 'delay_days' => '[_1] days',
'delay_365' => '1 year', 'delay_365' => '1 year',
'max_delay' => 'Warning! The maximum time limit for an image is [_1] day(s), even if you choose "no time limit".', 'max_delay' => 'Warning! The maximum time limit for an image is [_1] day(s), even if you choose "no time limit".',
'crypt_image' => 'Encrypt the image (Lutim does not keep the key).', 'crypt_image' => 'Encrypt the image (Lutim does not keep the key).',
'always_encrypt' => 'The images are encrypted on the server (Lutim does not keep the key).', 'always_encrypt' => 'The images are encrypted on the server (Lutim does not keep the key).',
'image_deleted' => 'The image [_1] has been successfully deleted', 'image_deleted' => 'The image [_1] has been successfully deleted',
'invalid_token' => 'The delete token is invalid.', 'invalid_token' => 'The delete token is invalid.',
'already_deleted' => 'The image [_1] has already been deleted.', 'already_deleted' => 'The image [_1] has already been deleted.',
'install_as_webapp' => 'Install webapp', 'install_as_webapp' => 'Install webapp',
'image_delay_modified' => 'The image\'s delay has been successfully modified', 'image_delay_modified' => 'The image\'s delay has been successfully modified',
'image_mod_not_found' => 'Unable to find the image [_1].', 'image_mod_not_found' => 'Unable to find the image [_1].',
'modify_image_error' => 'Error while trying to modify the image.', 'modify_image_error' => 'Error while trying to modify the image.',
'uploaded_files_by_days' => 'Number of uploaded files, per day',
'evolution_total_files' => 'Evolution of total number of uploaded files',
); );
1; 1;

View file

@ -6,7 +6,7 @@ my $inf_body = <<EOF;
<p>Lutim est un service gratuit et anonyme dhébergement dimages. Il sagit aussi du nom du logiciel (libre) qui fournit ce service.</p> <p>Lutim est un service gratuit et anonyme dhébergement dimages. Il sagit aussi du nom du logiciel (libre) qui fournit ce service.</p>
<p>Les images déposées sur Lutim peuvent être stockées indéfiniment, ou seffacer dès le premier affichage ou au bout du délai choisi parmi ceux proposés.</p> <p>Les images déposées sur Lutim peuvent être stockées indéfiniment, ou seffacer dès le premier affichage ou au bout du délai choisi parmi ceux proposés.</p>
<h4>Comment ça marche ?</h4> <h4>Comment ça marche ?</h4>
<p>Faites glisser des images dans la zone prévue à cet effet ou sélectionnez un fichier de façon classique et Lutim vous fournira troie URLs en retour. Une pour afficher limage, une autre pour la télécharger directement et une dernière utilisable sur Twitter.</p> <p>Faites glisser des images dans la zone prévue à cet effet ou sélectionnez un fichier de façon classique et Lutim vous fournira troie URLs en retour. Une pour afficher limage, une autre pour la télécharger directement, une pour l'utiliser sur les réseaux sociaux et une dernière pour supprimer votre image quand vous le souhaitez.</p>
<p>Vous pouvez, de façon facultative, demander à ce que la ou les images déposées sur Lutim soient supprimées après leur premier affichage (ou téléchargement) ou au bout d'un délai choisi parmi ceux proposés.</p> <p>Vous pouvez, de façon facultative, demander à ce que la ou les images déposées sur Lutim soient supprimées après leur premier affichage (ou téléchargement) ou au bout d'un délai choisi parmi ceux proposés.</p>
<h4>Cest vraiment gratuit ?</h4> <h4>Cest vraiment gratuit ?</h4>
<p>Oui, ça lest ! Par contre, si vous avez envie de soutenir le développeur, vous pouvez faire un microdon avec <a href="https://flattr.com/submit/auto?user_id=_SKy_&amp;url=[_1]&amp;title=Lutim&amp;category=software">Flattr</a> ou en <a href="bitcoin:1K3n4MXNRSMHk28oTfXEvDunWFthePvd8v?label=lutim">BitCoin</a>.</p> <p>Oui, ça lest ! Par contre, si vous avez envie de soutenir le développeur, vous pouvez faire un microdon avec <a href="https://flattr.com/submit/auto?user_id=_SKy_&amp;url=[_1]&amp;title=Lutim&amp;category=software">Flattr</a> ou en <a href="bitcoin:1K3n4MXNRSMHk28oTfXEvDunWFthePvd8v?label=lutim">BitCoin</a>.</p>
@ -14,6 +14,9 @@ my $inf_body = <<EOF;
<p>Oui, ça lest ! Par contre, pour des raisons légales, votre adresse IP sera enregistrée lorsque vous enverrez une image. Ne vous affolez pas, cest de toute façon normalement le cas de tous les sites sur lesquels vous envoyez des fichiers !</p> <p>Oui, ça lest ! Par contre, pour des raisons légales, votre adresse IP sera enregistrée lorsque vous enverrez une image. Ne vous affolez pas, cest de toute façon normalement le cas de tous les sites sur lesquels vous envoyez des fichiers !</p>
<p>LIP de la personne ayant déposé limage est stockée pendant un délai dépendant de l'administrateur de l'instance (pour l'instance officielle, dont le serveur est en France, c'est un délai d'un an).</p> <p>LIP de la personne ayant déposé limage est stockée pendant un délai dépendant de l'administrateur de l'instance (pour l'instance officielle, dont le serveur est en France, c'est un délai d'un an).</p>
<p>Si les fichiers sont bien supprimés si vous en avez exprimé le choix, leur empreinte SHA512 est toutefois conservée.</p> <p>Si les fichiers sont bien supprimés si vous en avez exprimé le choix, leur empreinte SHA512 est toutefois conservée.</p>
<h4>Qui possède des droits sur les images envoyées sur Lutim ?</h4>
<p>Seulement l'envoyeur ! (enfin, seulement s'il possède des droits exclusifs sur les images avant de les envoyer)</p>
<p>Au contraire de la majorité des services de partages d'image, vous ne cédez aucun droit sur les images envoyées.</p>
<h4>Comment peut-on faire pour signaler une image ?</h4> <h4>Comment peut-on faire pour signaler une image ?</h4>
<p>Veuillez contacter ladministrateur : [_2]</p> <p>Veuillez contacter ladministrateur : [_2]</p>
<h4>Comment doit-on prononcer Lutim ?</h4> <h4>Comment doit-on prononcer Lutim ?</h4>
@ -23,7 +26,7 @@ my $inf_body = <<EOF;
<p>Pour plus de détails, consultez la page <a href="https://github.com/ldidry/lutim">Github</a> du projet.</p> <p>Pour plus de détails, consultez la page <a href="https://github.com/ldidry/lutim">Github</a> du projet.</p>
<h4>Développeurs de l'application</h4> <h4>Développeurs de l'application</h4>
<ul> <ul>
<li>Luc Didry, aka Sky (<a href="http://www.fiat-tux.fr">http://www.fiat-tux.fr</a>), développeur principal, <a href="https://twitter.com/framasky">\@framasky</a></li> <li>Luc Didry, aka Sky (<a href="http://www.fiat-tux.fr">http://www.fiat-tux.fr</a>), développeur principal, \@framasky sur <a href="https://twitter.com/framasky">Twitter</a> ou sur <a href="https://framasphere.org/public/framasky">Diaspora*</a></li>
<li>Dattaz (<a href="http://dattaz.fr">http://dattaz.fr</a>), développeur de la webapp, <a href="https://twitter.com/dat_taz">\@dat_taz</a></li> <li>Dattaz (<a href="http://dattaz.fr">http://dattaz.fr</a>), développeur de la webapp, <a href="https://twitter.com/dat_taz">\@dat_taz</a></li>
</ul> </ul>
<h4>Contributeurs</h4> <h4>Contributeurs</h4>
@ -44,51 +47,53 @@ our %Lexicon = (
'informations-body' => $inf_body, 'informations-body' => $inf_body,
'view-link' => 'Lien d\'affichage', 'view-link' => 'Lien d\'affichage',
'download-link' => 'Lien de téléchargement', 'download-link' => 'Lien de téléchargement',
'twitter-link' => 'Lien pour mettre dans un tweet', 'share-link' => 'Lien pour partager sur les réseaux sociaux',
'tweet_it' => 'Tweetez !', 'tweet_it' => 'Tweetez !',
'share_it' => 'Partagez !', 'share_it' => 'Partagez !',
'delete-link' => 'Lien de suppression', 'delete-link' => 'Lien de suppression',
'some-bad' => 'Un problème est survenu', 'some-bad' => 'Un problème est survenu',
'delete-first' => 'Supprimer au premier accès ?', 'delete-first' => 'Supprimer au premier accès ?',
'delete-day' => 'Supprimer après 24 heures ?', 'delete-day' => 'Supprimer après 24 heures ?',
'upload_image' => 'Envoyez une image', 'upload_image' => 'Envoyez une image',
'image-only' => 'Seules les images sont acceptées', 'image-only' => 'Seules les images sont acceptées',
'go' => 'Allons-y !', 'go' => 'Allons-y !',
'drag-n-drop' => 'Déposez vos images ici', 'drag-n-drop' => 'Déposez vos images ici',
'or' => '-ou-', 'or' => '-ou-',
'file-browser' => 'Cliquez pour utiliser le navigateur de fichier', 'file-browser' => 'Cliquez pour utiliser le navigateur de fichier',
'image_not_found' => 'Impossible de trouver l\'image : elle a été supprimée.', 'image_not_found' => 'Impossible de trouver l\'image : elle a été supprimée.',
'no_more_short' => 'Il n\'y a plus d\'URL disponible. Veuillez réessayer ou contactez l\'administrateur. [_1].', 'no_more_short' => 'Il n\'y a plus d\'URL disponible. Veuillez réessayer ou contactez l\'administrateur. [_1].',
'no_valid_file' => 'Le fichier [_1] n\'est pas une image.', 'no_valid_file' => 'Le fichier [_1] n\'est pas une image.',
'file_too_big' => 'Le fichier dépasse la limite de taille ([_1])', 'file_too_big' => 'Le fichier dépasse la limite de taille ([_1])',
'no_time_limit' => 'Pas de limitation de durée', 'no_time_limit' => 'Pas de limitation de durée',
'24_hours' => '24 heures', '24_hours' => '24 heures',
'7_days' => '7 jours', '7_days' => '7 jours',
'30_days' => '30 jours', '30_days' => '30 jours',
'1_year' => 'Un an', '1_year' => 'Un an',
'pushed-images' => ' images envoyées sur cette instance depuis le début.', 'pushed-images' => ' images envoyées sur cette instance depuis le début.',
'graph-data-once-a-day' => 'Les données du graphique ne sont pas mises à jour en temps réél.', 'graph-data-once-a-day' => 'Les données du graphique ne sont pas mises à jour en temps réél.',
'lutim-stats' => 'Statistiques de Lutim', 'lutim-stats' => 'Statistiques de Lutim',
'back-to-index' => 'Retour à la page d\'accueil', 'back-to-index' => 'Retour à la page d\'accueil',
'stop_upload' => 'L\'envoi d\'images est actuellement désactivé, veuillez réessayer plus tard ou contacter l\'administrateur ([_1]).', 'stop_upload' => 'L\'envoi d\'images est actuellement désactivé, veuillez réessayer plus tard ou contacter l\'administrateur ([_1]).',
'download_error' => 'Une erreur est survenue lors du téléchargement de l\'image.', 'download_error' => 'Une erreur est survenue lors du téléchargement de l\'image.',
'no_valid_url' => 'l\'URL n\'est pas valide.', 'no_valid_url' => 'l\'URL n\'est pas valide.',
'image_url' => 'URL de l\'image', 'image_url' => 'URL de l\'image',
'upload_image_url' => 'Déposer une image par son URL', 'upload_image_url' => 'Déposer une image par son URL',
'delay_0' => 'pas de limitation de durée', 'delay_0' => 'pas de limitation de durée',
'delay_1' => '24 heures', 'delay_1' => '24 heures',
'delay_days' => '[_1] jours', 'delay_days' => '[_1] jours',
'delay_365' => '1 an', 'delay_365' => '1 an',
'max_delay' => 'Attention ! Le délai maximal de rétention d\'une image est de [_1] jour(s), même si vous choisissez « pas de limitation de durée ».', 'max_delay' => 'Attention ! Le délai maximal de rétention d\'une image est de [_1] jour(s), même si vous choisissez « pas de limitation de durée ».',
'crypt_image' => 'Chiffrer l\'image (Lutim ne stocke pas la clé).', 'crypt_image' => 'Chiffrer l\'image (Lutim ne stocke pas la clé).',
'always_encrypt' => 'Les images sont chiffrées sur le serveur (Lutim ne stocke pas la clé).', 'always_encrypt' => 'Les images sont chiffrées sur le serveur (Lutim ne stocke pas la clé).',
'image_deleted' => 'L\'image [_1] a été supprimée avec succès.', 'image_deleted' => 'L\'image [_1] a été supprimée avec succès.',
'invalid_token' => 'Le jeton de suppression est invalide.', 'invalid_token' => 'Le jeton de suppression est invalide.',
'already_deleted' => 'L\'image [_1] a déjà été supprimée.', 'already_deleted' => 'L\'image [_1] a déjà été supprimée.',
'install_as_webapp' => 'Installer la webapp', 'install_as_webapp' => 'Installer la webapp',
'image_delay_modified' => 'Le délai de l\'image a été modifié avec succès.', 'image_delay_modified' => 'Le délai de l\'image a été modifié avec succès.',
'image_mod_not_found' => 'Impossible de trouver l\'image [_1].', 'image_mod_not_found' => 'Impossible de trouver l\'image [_1].',
'modify_image_error' => 'Une erreur est survenue lors de la tentative de modification de l\'image.', 'modify_image_error' => 'Une erreur est survenue lors de la tentative de modification de l\'image.',
'uploaded_files_by_days' => 'Nombre de fichiers envoyés, par jour',
'evolution_total_files' => 'Évolution du nombre total de fichiers envoyés',
); );
1; 1;

View file

@ -20,7 +20,9 @@ use ORLite {
created_at INTEGER, created_at INTEGER,
created_by TEXT, created_by TEXT,
last_access_at INTEGER, last_access_at INTEGER,
mod_token TEXT)' mod_token TEXT,
width INTEGER,
height INTEGER)'
); );
return 1; return 1;
} }

View file

@ -0,0 +1,24 @@
package Mounter;
use Mojo::Base 'Mojolicious';
use FindBin qw($Bin);
use File::Spec qw(catfile);
# This method will run once at server start
sub startup {
my $self = shift;
push @{$self->commands->namespaces}, 'Lutim::Command';
my $config = $self->plugin('Config' =>
{
file => File::Spec->catfile($Bin, '..' ,'lutim.conf'),
default => {
url_sub_dir => '/'
}
}
);
$self->plugin('Mount' => {$config->{url_sub_dir} => File::Spec->catfile($Bin, '..', 'script', 'application')});
}
1;

View file

@ -36,9 +36,6 @@
#provis_step => 5, #provis_step => 5,
# max number of URLs to be provisioned # max number of URLs to be provisioned
# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
# in the first version, this option was provisionning with two 'n'. While the option with the typo is still valid, it is deprecated.
# in the next version (0.4), only provisioning with ine 'n' will be accepted
# optional, default is 100 # optional, default is 100
#provisioning => 100, #provisioning => 100,
@ -100,6 +97,12 @@
# optional, default is 24 # optional, default is 24
#token_length => 24, #token_length => 24,
# URL sub-directory in which you want Lutim to be accessible
# example: you want to have Lutim under https://example.org/lutim/
# => set url_sub_dir to '/lutim' or to '/lutim/', it doesn't matter
# optional, defaut is /
#url_sub_dir => '/',
########################## ##########################
# Lutim cron jobs settings # Lutim cron jobs settings
########################## ##########################

View file

@ -7,3 +7,4 @@
.icon-download:before { content: '\e805'; } /* '' */ .icon-download:before { content: '\e805'; } /* '' */
.icon-spinner:before { content: '\e806'; } /* '' */ .icon-spinner:before { content: '\e806'; } /* '' */
.icon-eye:before { content: '\e807'; } /* '' */ .icon-eye:before { content: '\e807'; } /* '' */
.icon-share:before { content: '\e808'; } /* '' */

File diff suppressed because one or more lines are too long

View file

@ -7,3 +7,4 @@
.icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe805;&nbsp;'); } .icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe805;&nbsp;'); }
.icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe806;&nbsp;'); } .icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe806;&nbsp;'); }
.icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe807;&nbsp;'); } .icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe807;&nbsp;'); }
.icon-share { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe808;&nbsp;'); }

View file

@ -18,3 +18,4 @@
.icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe805;&nbsp;'); } .icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe805;&nbsp;'); }
.icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe806;&nbsp;'); } .icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe806;&nbsp;'); }
.icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe807;&nbsp;'); } .icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe807;&nbsp;'); }
.icon-share { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe808;&nbsp;'); }

View file

@ -1,10 +1,10 @@
@font-face { @font-face {
font-family: 'fontello'; font-family: 'fontello';
src: url('../font/fontello.eot?47445522'); src: url('../font/fontello.eot?96982888');
src: url('../font/fontello.eot?47445522#iefix') format('embedded-opentype'), src: url('../font/fontello.eot?96982888#iefix') format('embedded-opentype'),
url('../font/fontello.woff?47445522') format('woff'), url('../font/fontello.woff?96982888') format('woff'),
url('../font/fontello.ttf?47445522') format('truetype'), url('../font/fontello.ttf?96982888') format('truetype'),
url('../font/fontello.svg?47445522#fontello') format('svg'); url('../font/fontello.svg?96982888#fontello') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@ -14,7 +14,7 @@
@media screen and (-webkit-min-device-pixel-ratio:0) { @media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face { @font-face {
font-family: 'fontello'; font-family: 'fontello';
src: url('../font/fontello.svg?47445522#fontello') format('svg'); src: url('../font/fontello.svg?96982888#fontello') format('svg');
} }
} }
*/ */
@ -58,3 +58,4 @@
.icon-download:before { content: '\e805'; } /* '' */ .icon-download:before { content: '\e805'; } /* '' */
.icon-spinner:before { content: '\e806'; } /* '' */ .icon-spinner:before { content: '\e806'; } /* '' */
.icon-eye:before { content: '\e807'; } /* '' */ .icon-eye:before { content: '\e807'; } /* '' */
.icon-share:before { content: '\e808'; } /* '' */

View file

@ -0,0 +1,30 @@
Font license info
## Font Awesome
Copyright (C) 2012 by Dave Gandy
Author: Dave Gandy
License: SIL ()
Homepage: http://fortawesome.github.com/Font-Awesome/
## Zocial
Copyright (C) 2012 by Sam Collins
Author: Sam Collins
License: MIT (http://opensource.org/licenses/mit-license.php)
Homepage: http://zocial.smcllns.com/
## MFG Labs
Copyright (C) 2012 by Daniel Bruce
Author: MFG Labs
License: SIL (http://scripts.sil.org/OFL)
Homepage: http://www.mfglabs.com/

View file

@ -6,14 +6,15 @@
<font id="fontello" horiz-adv-x="1000" > <font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" /> <font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" /> <missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="twitter" unicode="&#xe800;" d="m904 622q-37-54-90-93 0-8 0-23 0-73-21-145t-64-139-103-117-144-82-181-30q-151 0-276 81 19-3 43-3 126 0 224 77-59 2-105 36t-64 89q19-2 34-2 24 0 48 6-63 13-104 62t-41 115v2q38-21 82-23-37 25-59 64t-22 86q0 49 25 91 68-83 164-133t208-55q-5 21-5 41 0 75 53 127t127 53q79 0 132-57 61 12 114 44-20-64-79-100 52 6 104 28z" horiz-adv-x="928.6" /> <glyph glyph-name="twitter" unicode="&#xe800;" d="m25 74q19-2 43-2 126 0 224 77-59 1-105 36t-64 89q19-3 34-3 24 0 48 6-63 13-104 62t-41 115v2q38-21 82-23-37 25-59 64t-22 86q0 49 25 91 67-83 164-133t208-55q-5 21-5 41 0 75 53 127t127 53q78 0 132-57 61 12 114 44-20-64-79-100 52 6 104 28-37-54-90-93 0-8 0-23 0-73-21-145t-64-139-103-117-144-82-181-30q-151 0-276 81z" horiz-adv-x="928.6" />
<glyph glyph-name="github-circled" unicode="&#xe801;" d="m857 350q0-140-82-252t-211-155q-15-3-22 4t-7 17v118q0 54-29 79 32 3 57 10t53 22 45 37 30 58 11 84q0 68-44 115 21 51-5 114-15 5-45-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22-48 7q-24-63-4-114-44-47-44-115 0-47 12-83t29-59 45-37 52-22 57-10q-22-20-27-58-12-5-25-8t-32-3-36 12-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7 5-8 7-6l4-3q12-6 24-21t18-29l5-13q8-21 25-34t37-17 39-4 31 2l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252q0 117 58 215t155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" /> <glyph glyph-name="github-circled" unicode="&#xe801;" d="m0 350q0 117 58 215t155 156 216 58 215-58 156-156 57-215q0-140-82-252t-211-155q-15-3-22 4t-7 17v118q0 54-29 79 32 3 57 10t53 22 45 37 30 58 11 84q0 68-44 115 21 51-5 114-15 5-45-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22-48 7q-24-63-4-114-44-47-44-115 0-47 12-83t29-59 45-37 52-22 57-10q-22-20-27-58-12-5-25-8t-32-3-36 12-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7 5-8 7-6l4-3q12-6 24-21t18-29l5-13q8-21 25-34t37-17 39-4 31 2l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252z" horiz-adv-x="857.1" />
<glyph glyph-name="flattr" unicode="&#xe802;" d="m0-37l0 514q0 179 85 278t259 99l548 0q-5-5-52-53t-100-101-109-109-95-93-42-37q-15 0-15 16l0 156-48 0q-59 0-94-6t-63-26-39-57-12-96l0-262z m67-117q5 5 53 53t100 101 109 110 95 93 41 36q15 0 15-16l0-156 48 0q116 0 162 36t45 149l0 262 224 223 0-514q0-179-84-278t-260-99l-548 0z" horiz-adv-x="959" /> <glyph glyph-name="flattr" unicode="&#xe802;" d="m0-37l0 514q0 179 85 278t259 99l548 0q-5-5-52-53t-100-101-109-109-95-93-42-37q-15 0-15 16l0 156-48 0q-59 0-94-6t-63-26-39-57-12-96l0-262z m67-117q5 5 53 53t100 101 109 110 95 93 41 36q15 0 15-16l0-156 48 0q116 0 162 36t45 149l0 262 224 223 0-514q0-179-84-278t-260-99l-548 0z" horiz-adv-x="959" />
<glyph glyph-name="bitcoin" unicode="&#xe803;" d="m651 493q10-102-73-144 65-16 98-58t25-119q-4-40-18-70t-36-49-54-33-68-19-81-9v-142h-86v140q-45 0-68 1v-141h-86v142q-10 0-30 1t-31 0h-112l18 102h62q27 0 32 28v225h9q-4 0-9 0v160q-7 38-50 38h-62v92l119-1q35 0 54 1v141h86v-138q45 1 68 1v137h86v-141q44-4 78-13t63-25 46-43 20-64z m-120-304q0 20-8 35t-21 26-32 17-36 10-42 5-38 2-36 0-27-1v-189q5 0 21 0t27 0 29 1 33 2 32 5 31 8 26 11 22 17 14 22 5 29z m-39 265q0 19-7 33t-17 23-27 16-31 9-34 5-33 1-30 0-22-1v-171q3 0 20 0t26 0 27 1 31 3 29 6 27 10 21 15 15 22 5 28z" horiz-adv-x="714.3" /> <glyph glyph-name="bitcoin" unicode="&#xe803;" d="m31-7l18 102h62q27 0 32 28v225h9q-4 0-9 0v160q-7 38-50 38h-62v92l119-1q35 0 54 1v141h86v-138q45 1 68 1v137h86v-141q44-4 78-13t63-25 46-43 20-64q10-102-73-144 65-16 98-58t25-119q-4-40-18-70t-36-49-54-33-68-19-81-9v-142h-86v140q-45 0-68 1v-141h-86v142q-10 0-30 1t-31 0h-112z m260 101q5 0 21 0t27 0 29 1 33 2 32 5 31 8 26 11 22 17 14 22 5 29q0 20-8 35t-21 26-32 17-36 10-42 6-38 1-36 0-27-1v-189z m0 275q3 0 20 0t26 0 27 1 31 3 29 6 27 10 21 15 15 22 5 28q0 19-7 33t-17 23-27 16-31 9-34 5-33 1-30 0-22-1v-171z" horiz-adv-x="714.3" />
<glyph glyph-name="trash" unicode="&#xe804;" d="m286 439v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m143 0v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m142 0v-321q0-8-5-13t-12-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q7 0 12-5t5-13z m72-404v529h-500v-529q0-12 4-22t8-15 6-5h464q2 0 6 5t8 15 4 22z m-375 601h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q22 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" /> <glyph glyph-name="trash" unicode="&#xe804;" d="m0 582v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q22 0 44-15t30-35l39-93h173q8 0 13-5t5-13v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13z m143-547q0-12 4-22t8-15 6-5h464q2 0 6 5t8 15 4 22v529h-500v-529z m71 83v321q0 8 5 13t13 5h36q8 0 13-5t5-13v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13z m54 518h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m89-518v321q0 8 5 13t13 5h36q8 0 13-5t5-13v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13z m143 0v321q0 8 5 13t13 5h36q7 0 12-5t5-13v-321q0-8-5-13t-12-5h-36q-8 0-13 5t-5 13z" horiz-adv-x="785.7" />
<glyph glyph-name="download" unicode="&#xe805;" d="m714 100q0 15-10 25t-25 11-26-11-10-25 10-25 26-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-40l-250-250q-10-10-25-10t-25 10l-250 250q-17 17-8 40 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" /> <glyph glyph-name="download" unicode="&#xe805;" d="m0 46v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37z m181 497q10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21 10-23-8-40l-250-250q-10-10-25-10t-25 10l-250 250q-17 17-8 40z m462-443q0-14 10-25t26-11 25 11 10 25-10 25-25 11-26-11-10-25z m143 0q0-14 10-25t25-11 26 11 10 25-10 25-26 11-25-11-10-25z" horiz-adv-x="928.6" />
<glyph glyph-name="spinner" unicode="&#xe806;" d="m469 614v204q129 0 237-61t169-170 62-237h-204q0 72-36 133t-95 96-133 35z" horiz-adv-x="937.5" /> <glyph glyph-name="spinner" unicode="&#xe806;" d="m469 614v204q129 0 237-61t169-170 62-237h-204q0 72-36 133t-95 96-133 35z" horiz-adv-x="937.5" />
<glyph glyph-name="eye" unicode="&#xe807;" d="m929 314q-85 132-213 197 34-58 34-125 0-104-73-177t-177-73-177 73-73 177q0 67 34 125-128-65-213-197 75-114 187-182t242-68 242 68 187 182z m-402 215q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-12 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m473-215q0-19-11-38-78-129-210-206t-279-77-279 77-210 206q-11 19-11 38t11 39q78 128 210 205t279 78 279-78 210-205q11-20 11-39z" horiz-adv-x="1000" /> <glyph glyph-name="eye" unicode="&#xe807;" d="m0 314q0 19 11 39 78 128 210 205t279 78 279-78 210-205q11-20 11-39t-11-38q-78-129-210-206t-279-77-279 77-210 206q-11 19-11 38z m71 0q75-114 187-182t242-68 242 68 187 182q-85 132-213 197 34-58 34-125 0-104-73-177t-177-73-177 73-73 177q0 67 34 125-128-65-213-197z m259 72q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19-8 19-19 7q-70 0-120-50t-50-119z" horiz-adv-x="1000" />
<glyph glyph-name="share" unicode="&#xe808;" d="m0 350q0 74 52 126t127 53q70 0 121-48l201 100q-1 12-1 19 0 74 52 126t127 53 126-53 52-126-52-126-126-53q-71 0-122 48l-201-100q1-12 1-19t-1-19l201-100q51 48 122 48 74 0 126-53t52-126-52-126-126-53-127 53-52 126q0 7 1 19l-201 100q-51-48-121-48-75 0-127 53t-52 126z" horiz-adv-x="857.1" />
</font> </font>
</defs> </defs>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View file

@ -0,0 +1,390 @@
/* -----------------------------------------------------------------------------
* Freezeframe
* freezeframe.js v2.0.2
* 2014 Chris Antonellis
*
* Freezeframe.js is a script that automatically pauses animated GIFs and
* enables them to start animating on mouse hover.
*
* Website: http://freezeframe.chrisantonellis.com/
* Documentation: http://freezeframe.chrisantonellis.com/documentation/
*
* Licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License
* http://creativecommons.org/licenses/by-sa/3.0/deed.en_US
* -------------------------------------------------------------------------- */
FreezeFrame = (function($) {
var _ff;
var canvas;
var context;
var class_name;
var trigger_event;
var support_touch_devices;
var animation_play_duration;
var loading_background_color;
var loading_background_image;
var loading_background_position;
var loading_fade_in_speed;
var animation_icon_image;
var animation_icon_position;
var animation_fade_out_speed;
var is_touch_device;
var freezeframe_count;
function FreezeFrame( _options ) {
_ff = this;
_options.class_name == null ?
this.class_name = "freezeframe" :
this.class_name = _options.class_name;
_options.trigger_event == null ?
this.trigger_event = "hover" :
this.trigger_event = _options.trigger_event.toLowerCase();
_options.support_touch_devices == null ?
this.support_touch_devices = true :
this.support_touch_devuces = _options.support_touch_devices.toLowerCase();
_options.animation_play_duration == null ?
this.animation_play_duration = 10000 :
this.animation_play_duration = parseInt(_options.animation_play_duration);
_options.loading_background_color == null ?
this.loading_background_color = "#666" :
this.loading_background_color = _options.loading_background_color.toLowerCase();
_options.loading_background_image == null ?
this.loading_background_image = "data:image/gif;base64,R0lGODlhEAAQAPIAAGZmZv///4mJidbW1v///8PDw7CwsKampiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" :
this.loading_background_image = _options.loading_background_image;
_options.loading_background_position == null ?
this.loading_background_position = "center center" :
this.loading_background_position = _options.loading_background_position.toLowerCase();
_options.animation_icon_image == null ?
this.animation_icon_image = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAl9JREFUeNrs2s2K2lAUAGATb3TE2Cr+oaJQNFOh1MVsxK0OuJbSdX2V9gG67GqW3RbaB7B9gy7qgKJF8G/EarHVWGMyJj230EXLLITm6q05F44/IVw5X3JPjiGCZVkuJw/R5fCBAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAiAAAjwjyMej79MpVKP/hcAwe6boul0+p3P5/vmdruv4evbVqvVdRRALpd7HQqFpn6/XxUEwdI07UZV1ffNZvMzjwDE7gk9Hs8mGAwuYCl8hTNB32630nw+f1IqlRY8QtgOQAjRZVleJxKJ77AcVLptOBwup9PpPR4hbAcQRdGUJOk2HA5riqKokUjEgKK4GY/HKo8QhMGcv4oKIJg0+Xw+r8H7bSaT0XiEICwnhyLoCgQCptfrNSgCjxDkED8ChdGiwSMEOaQ2jxDkGOtuH4jJZHJ/Nps9LRaLi+Vy2WDVUB0FYB+IXq+36ff7P0ajURj2eQbF9EO73W6cFMBdENA8mXQbNFDier0mhULhQaVSeZzNZj+d3Bnwe+i6LkDCAqx9QmMwGJwlk8nzarV6Cf3EDHZ5DvHx5ADuSjwWiz0sl8uX8H9izjLxowLskfgL1okfBYCnxA8KwGPiBwGg9xpWq5XIY+IsAQT6stvt6BGX4Nrt4jFxZgCmaYqGYRDo4nzdbncny3KGx8SZAcCRl6CH9yuKcl6r1S6i0egXHhP/Y53aGfV6/U2n02nA5yuIC7vntzsEBo/KXkG84vaI/12w8Flhhw8EQAAEQAAEQAAEQAAEQAAEQAAEQAAEQAAEcNr4KcAABsB8S2vxAV8AAAAASUVORK5CYII=" :
this.animation_icon_image = _options.animation_icon_image;
_options.animation_icon_position == null ?
this.animation_icon_position = "top left" :
this.animation_icon_position = _options.animation_icon_position.toLowerCase();
_options.loading_fade_in_speed == null ?
this.loading_fade_in_speed = 500 :
this.loading_fade_in_speed = parseInt(_options.loading_fade_in_speed);
_options.animation_fade_out_speed == null ?
this.animation_fade_out_speed = 250 :
this.animation_fade_out_speed = parseInt(_options.animation_fade_out_speed);
this.is_touch_device = isMouseEventSupported("ontouchstart");
this.freezeframe_count = 0;
};
/** --------------------------------------------------------------------------
* @function .setup()
* Sets up the freezeframe instance by adding a canvas element to the
* document and capturing references to the canvas and its 2D context
* ------------------------------------------------------------------------ */
FreezeFrame.prototype.setup = function() {
$("<canvas>",{id:"freezeframe-canvas"})
.css("display", "none")
.prependTo($("body"));
this.canvas = $("canvas#freezeframe-canvas");
this.context = this.canvas[0].getContext('2d');
};
/** --------------------------------------------------------------------------
* .run()
* Starts freezeframe processing for each image. Copies the image to
* the freezeframe canvas and converts it to a data url
* ------------------------------------------------------------------------ */
FreezeFrame.prototype.run = function() {
var images = [];
var ext;
var figure_background = _ff.loading_background_color;
if( _ff.loading_background_image !== false ) {
figure_background += " url('" + _ff.loading_background_image + "') " +
_ff.loading_background_position + " no-repeat";
}
// Select all images with a class matching the option class_name
images = $('img[class*="' + _ff.class_name + '"]')
.not('[class*="' + _ff.class_name + '_done"]');
// Process each image by resetting the animation sequence, copying to the
// canvas, converting to a data url, and attaching that data url to the
// image itself as an attribute
$(images).each(function(index) {
// Change image class so it won't be reprocessed if .run() is run again
$(this).removeClass(_ff.class_name).addClass(_ff.class_name + "_done");
// Set cross-origin to anon to load images from remote services that send
// the correct header. Not working correctly, needs more testing
$(this).crossOrigin = "anonymous";
// Determine file extension
ext = $(this)[0].src.split(".");
ext = ext[ext.length - 1].toLowerCase();
// Remove non GIF files
if(ext !== "gif") {
images.splice(index, 1);
} else {
var freezeframe_figure = $("<figure />")
.attr("class", "freezeframe-container " + _ff.freezeframe_count)
.css({"display": "inline-block",
"overflow": "hidden",
"margin": 0,
"background-size": "100% auto",
"width": "100%",
"max-height": "100%",
"background": figure_background});
$(this).css({"opacity": 0,
"display": "block"})
.wrap(freezeframe_figure);
freezeframe_figure = $(this).parent();
// If an animation icon image is available, attach it
if(_ff.animation_icon_image !== false) {
var animation_icon = $("<div />")
.attr("class", "freezeframe-animation-icon")
.css({"display": "block",
"position": "absolute",
"background": "transparent " + "url('" + _ff.animation_icon_image + "') " +
_ff.animation_icon_position + " no-repeat",
"pointer-events": "none",
"z-index": 100,
"opacity": 0});
$(freezeframe_figure).prepend(animation_icon);
animation_icon = $(this).siblings($(".freezeframe-animation-icon"));
}
// Increment counter so each image gets a unique number
_ff.freezeframe_count++;
// Create a temporary refernce to the image as non-object to pass to .drawImage
var _self = this;
// Using imagesLoaded by Desandro because .load doesn't work on cached images
$(this).imagesLoaded(function() {
$(this).off("imagesLoaded");
_ff.canvas[0].width = $(this)[0].clientWidth;
_ff.canvas[0].height = $(this)[0].clientHeight;
$(this).attr("animated", $(this).attr("src"))
.attr("src", $(this).attr("src"));
_ff.context.drawImage(_self, 0, 0, $(this)[0].clientWidth, $(this)[0].clientHeight);
$(this).attr("src", _ff.canvas[0].toDataURL());
// If an animation icon image is available, show it
if(_ff.animation_icon_image !== false) {
$(animation_icon).css({
"width": parseInt($(this)[0].width),
"height": parseInt($(this)[0].height)})
.animate({"opacity": 1}, _ff.loading_fade_in_speed);
}
// When fade in sequence is complete, enable interaction
$(this).animate({"opacity": 1}, _ff.loading_fade_in_speed, function() {
$(freezeframe_figure).css("background", "url('" + $(this).attr("src") + "')");
$(this).css("opacity", 0)
.attr("src", $(this).attr("animated"));
// Touch Device or Click Event
if((_ff.support_touch_devices && _ff.is_touch_device) || _ff.trigger_event.toLowerCase() == "click") {
var stop_animation;
var animating = false;
$(this).click(function() {
// If not currently animating, start animating
if(!animating) {
$(this).attr("src", $(this).attr("src"))
.css("opacity", 1);
if(_ff.animation_icon_image !== false) {
$(animation_icon).css("opacity", 0);
}
stop_animation = setInterval(function() {
clearInterval(stop_animation);
this.animate({"opacity": 0}, _ff.animation_fade_out_speed);
if(_ff.animation_icon_image !== false) {
$(animation_icon).animate({"opacity": 1}, _ff.animation_fade_out_speed);
}
animating = false;
}, _ff.animation_play_duration);
animating = true;
// If currently animating, stop animating
} else {
clearInterval(stop_animation);
$(this).animate({"opacity": 0}, _ff.animation_fade_out_speed);
if(_ff.animation_icon_image !== false) {
$(animation_icon).animate({"opacity": 1}, _ff.animation_fade_out_speed);
}
animating = false;
}
});
} else {
// Hover Event
$(this).mouseenter(function() {
$(this).attr("src", $(this).attr("src"))
.css("opacity", 1);
if(_ff.animation_icon_image !== false) {
$(animation_icon).css("opacity", 0);
}
});
$(this).mouseleave(function() {
$(this).animate({"opacity": 0}, _ff.animation_fade_out_speed);
if(_ff.animation_icon_image !== false) {
$(animation_icon).animate({"opacity": 1}, _ff.animation_fade_out_speed);
}
});
}
});
});
}
});
};
return FreezeFrame;
})(jQuery);
/** ----------------------------------------------------------------------------
* Setup & Run Freezeframe
* -------------------------------------------------------------------------- */
jQuery(document).ready(function($) {
typeof(freezeframe_options) == 'undefined' ? freezeframe_options = {} : null;
freezeframe = new FreezeFrame(freezeframe_options);
freezeframe.setup();
freezeframe.run();
});
/** ----------------------------------------------------------------------------
* jQuery imagesLoaded plugin v2.1.1
* http://github.com/desandro/imagesloaded
*
* MIT License. by Paul Irish et al.
* -------------------------------------------------------------------------- */
;(function($, undefined) {
'use strict';
var BLANK = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';
$.fn.imagesLoaded = function( callback ) {
var $this = this,
deferred = $.isFunction($.Deferred) ? $.Deferred() : 0,
hasNotify = $.isFunction(deferred.notify),
$images = $this.find('img').add( $this.filter('img') ),
loaded = [],
proper = [],
broken = [];
if ($.isPlainObject(callback)) {
$.each(callback, function (key, value) {
if (key === 'callback') {
callback = value;
} else if (deferred) {
deferred[key](value);
}
});
}
function doneLoading() {
var $proper = $(proper),
$broken = $(broken);
if ( deferred ) {
if ( broken.length ) {
deferred.reject( $images, $proper, $broken );
} else {
deferred.resolve( $images );
}
}
if ( $.isFunction( callback ) ) {
callback.call( $this, $images, $proper, $broken );
}
}
function imgLoadedHandler( event ) {
imgLoaded( event.target, event.type === 'error' );
}
function imgLoaded( img, isBroken ) {
if ( img.src === BLANK || $.inArray( img, loaded ) !== -1 ) {
return;
}
loaded.push( img );
if ( isBroken ) {
broken.push( img );
} else {
proper.push( img );
}
$.data( img, 'imagesLoaded', { isBroken: isBroken, src: img.src } );
if ( hasNotify ) {
deferred.notifyWith( $(img), [ isBroken, $images, $(proper), $(broken) ] );
}
if ( $images.length === loaded.length ) {
setTimeout( doneLoading );
$images.unbind( '.imagesLoaded', imgLoadedHandler );
}
}
if ( !$images.length ) {
doneLoading();
} else {
$images.bind( 'load.imagesLoaded error.imagesLoaded', imgLoadedHandler )
.each( function( i, el ) {
var src = el.src;
var cached = $.data( el, 'imagesLoaded' );
if ( cached && cached.src === src ) {
imgLoaded( el, cached.isBroken );
return;
}
if ( el.complete && el.naturalWidth !== undefined ) {
imgLoaded( el, el.naturalWidth === 0 || el.naturalHeight === 0 );
return;
}
if ( el.readyState || el.complete ) {
el.src = BLANK;
el.src = src;
}
});
}
return deferred ? deferred.promise( $this ) : $this;
};
})(jQuery);
/** ----------------------------------------------------------------------------
* isMouseEventSupported by kangax
* http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
* -------------------------------------------------------------------------- */
function isMouseEventSupported(eventName) {
var el = document.createElement('div');
eventName = 'on' + eventName;
var isSupported = (eventName in el);
if (!isSupported) {
el.setAttribute(eventName, 'return;');
isSupported = typeof el[eventName] == 'function';
}
el = null;
return isSupported;
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,11 @@
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
BEGIN { unshift @INC, "$FindBin::Bin/../lib" }
# Start command line interface for application
require Mojolicious::Commands;
Mojolicious::Commands->start_app('Lutim');

View file

@ -8,4 +8,4 @@ BEGIN { unshift @INC, "$FindBin::Bin/../lib" }
# Start command line interface for application # Start command line interface for application
require Mojolicious::Commands; require Mojolicious::Commands;
Mojolicious::Commands->start_app('Lutim'); Mojolicious::Commands->start_app('Mounter');

View file

@ -1,5 +1,5 @@
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab: % # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
<div> <div>
<%==l 'informations-body', url_for('/')->to_abs(), config('contact') %> <%==l 'informations-body', index_url(1), config('contact') %>
<%= link_to url_for('index') => ( class => "btn btn-primary btn-lg" ) => begin %><%=l 'back-to-index' %><% end%> <%= link_to index_url => ( class => "btn btn-primary btn-lg" ) => begin %><%=l 'back-to-index' %><% end%>
</div> </div>

View file

@ -10,14 +10,14 @@
% } % }
<div> <div>
% # Display image informations % # Display image informations
% my $url = url_for('/')->to_abs().stash('short'); % my $url = index_url(1).stash('short');
<strong><%= stash('filename') %></strong> <strong><%= stash('filename') %></strong>
&nbsp;&nbsp;&nbsp;<a target="_blank" class="btn btn-default btn-primary btn-xs" href="https://twitter.com/share?url=<%= $url %>?t"><%=l 'tweet_it' %></a> &nbsp;&nbsp;&nbsp;<a target="_blank" class="btn btn-default btn-primary btn-xs" href="https://twitter.com/share?url=<%= $url %>?t"><%=l 'tweet_it' %></a>
<ul class="list-unstyled"> <ul class="list-unstyled">
% my $delete_url = url_for('delete', {short => stash('real_short'), token => stash('token')})->to_abs(); % my $delete_url = url_for('delete', {short => stash('real_short'), token => stash('token')})->to_abs();
<li><i class="icon icon-eye" title =" <%= l 'view-link' %>"></i> <%= link_to $url => begin %> <%= $url %> <%= end %></li> <li><i class="icon icon-eye" title =" <%= l 'view-link' %>"></i> <%= link_to $url => begin %> <%= $url %> <%= end %></li>
<li><i class="icon icon-download" title =" <%= l 'download-link' %>"></i> <%= link_to $url.'?dl' => begin %> <%= $url.'?dl' %> <%= end %></li> <li><i class="icon icon-download" title =" <%= l 'download-link' %>"></i> <%= link_to $url.'?dl' => begin %> <%= $url.'?dl' %> <%= end %></li>
<li><i class="icon icon-twitter" title =" <%= l 'twitter-link' %>"></i> <%= link_to $url.'?t' => begin %> <%= $url.'?t' %> <%= end %></li> <li><i class="icon icon-share" title =" <%= l 'share-link' %>"></i> <%= link_to $url.'?t' => begin %> <%= $url.'?t' %> <%= end %></li>
<li><i class="icon icon-trash" title =" <%= l 'delete-link' %>"></i> <%= link_to $delete_url => begin %> <%= $delete_url %> <%= end %></li> <li><i class="icon icon-trash" title =" <%= l 'delete-link' %>"></i> <%= link_to $delete_url => begin %> <%= $delete_url %> <%= end %></li>
</ul> </ul>
</div> </div>
@ -76,7 +76,7 @@
</div> </div>
<noscript> <noscript>
<form class="form" role="form" method="POST" action="<%== url_for('add') %>" enctype="multipart/form-data"> <form class="form" role="form" method="POST" action="<%== index_url %>" enctype="multipart/form-data">
<div class="form-group form-inline"> <div class="form-group form-inline">
<select name="delete-day" class="form-control"> <select name="delete-day" class="form-control">
% for my $delay (qw/0 1 7 30 365/) { % for my $delay (qw/0 1 7 30 365/) {
@ -165,7 +165,7 @@
</div> </div>
</div> </div>
<p class="help-block"><%=l 'image-only' %></p> <p class="help-block"><%=l 'image-only' %></p>
<form class="form-horizontal" role="form" method="POST" action="<%== url_for('add') %>"> <form class="form-horizontal" role="form" method="POST" action="<%== index_url %>">
<div class="form-group"> <div class="form-group">
<span class="col-sm-3 col-xs-12"><span class="hidden-spin" style="font-size:200%; display:none;" > <i class="icon-spinner animate-spin pull-right"></i></span><label for="lutim-file-url" class="control-label pull-right"><%=l 'upload_image_url' %></label></span> <span class="col-sm-3 col-xs-12"><span class="hidden-spin" style="font-size:200%; display:none;" > <i class="icon-spinner animate-spin pull-right"></i></span><label for="lutim-file-url" class="control-label pull-right"><%=l 'upload_image_url' %></label></span>
<div class="col-sm-9 col-xs-12"> <div class="col-sm-9 col-xs-12">
@ -181,14 +181,14 @@
function link(url, dl, token, modify) { function link(url, dl, token, modify) {
if (token !== undefined) { if (token !== undefined) {
if (modify !== undefined && modify === true) { if (modify !== undefined && modify === true) {
return '<%== url_for('index')->to_abs() %>m/'+url+'/'+token; return '<%== index_url(1) %>m/'+url+'/'+token;
} else { } else {
url = 'd/'+url+'/'+token; url = 'd/'+url+'/'+token;
} }
} else if (dl !== '') { } else if (dl !== '') {
url = url+'?'+dl; url = url+'?'+dl;
} }
return '<a href="<%== url_for('index')->to_abs() %>'+url+'"><%== url_for('index')->to_abs() %>'+url+'</a>'; return '<a href="<%== index_url(1) %>'+url+'"><%== index_url(1) %>'+url+'</a>';
} }
function share(url) { function share(url) {
console.log(url); console.log(url);
@ -202,9 +202,9 @@
}); });
} }
function tw_url(url) { function tw_url(url) {
var btn = '&nbsp;&nbsp;&nbsp;<a target="_blank" class="btn btn-default btn-primary btn-xs" href="https://twitter.com/share?url=<%== url_for('index')->to_abs() %>'+url+'?t"><%=l 'tweet_it' %></a>'; var btn = '&nbsp;&nbsp;&nbsp;<a target="_blank" class="btn btn-default btn-primary btn-xs" href="https://twitter.com/share?url=<%== index_url(1) %>'+url+'?t"><%=l 'tweet_it' %></a>';
if (navigator.mozSetMessageHandler !== undefined) { if (navigator.mozSetMessageHandler !== undefined) {
btn = btn+'&nbsp;&nbsp;&nbsp;<a target="_blank" class="btn btn-default btn-primary btn-xs" href="" onclick="share(\'<%== url_for('index')->to_abs() %>'+url+'?t\');return false;"><%=l 'share_it' %></a>'; btn = btn+'&nbsp;&nbsp;&nbsp;<a target="_blank" class="btn btn-default btn-primary btn-xs" href="" onclick="share(\'<%== index_url(1) %>'+url+'?t\');return false;"><%=l 'share_it' %></a>';
} }
return btn return btn
} }
@ -213,7 +213,7 @@
url : url, url : url,
type : "POST", type : "POST",
data : { data : {
'image_url' : '<%== url_for('index')->to_abs() %>'+short, 'image_url' : '<%== index_url(1) %>'+short,
'format' : 'json', 'format' : 'json',
'first-view' : ($("#first-view-"+short).prop('checked')) ? 1 : 0, 'first-view' : ($("#first-view-"+short).prop('checked')) ? 1 : 0,
'delete-day' : $("#day-"+short).val() 'delete-day' : $("#day-"+short).val()
@ -239,7 +239,7 @@
+link(msg.short, '') +link(msg.short, '')
+'</li><li><i class="icon icon-download" title="<%=l 'download-link' %>"></i>&nbsp;' +'</li><li><i class="icon icon-download" title="<%=l 'download-link' %>"></i>&nbsp;'
+link(msg.short, 'dl') +link(msg.short, 'dl')
+'</li><li><i class="icon icon-twitter" title="<%=l 'twitter-link' %>"></i>&nbsp;' +'</li><li><i class="icon icon-share" title="<%=l 'share-link' %>"></i>&nbsp;'
+link(msg.short, 't') +link(msg.short, 't')
+'</li><li><i class="icon icon-trash" title="<%=l 'delete-link' %>"></i>&nbsp;' +'</li><li><i class="icon icon-trash" title="<%=l 'delete-link' %>"></i>&nbsp;'
+link(msg.real_short, '', msg.token) +link(msg.real_short, '', msg.token)
@ -279,7 +279,7 @@
} }
function bindddz(firstview, deleteday) { function bindddz(firstview, deleteday) {
$('#drag-and-drop-zone').dmUploader({ $('#drag-and-drop-zone').dmUploader({
url: '<%== url_for('add') %>', url: '<%== index_url %>',
dataType: 'json', dataType: 'json',
allowedTypes: 'image/*', allowedTypes: 'image/*',
maxFileSize: <%= $max_file_size %>, maxFileSize: <%= $max_file_size %>,
@ -312,7 +312,7 @@
$(".hidden-spin").css('display', 'block'); $(".hidden-spin").css('display', 'block');
console.log(val); console.log(val);
$.ajax({ $.ajax({
url : '<%== url_for('add') %>', url : '<%== index_url %>',
type : "POST", type : "POST",
data : { data : {
'lutim-file-url' : val, 'lutim-file-url' : val,
@ -352,7 +352,7 @@
$(".messages").append('<div id="1-div">'+file.name+'<br><div class="progress"><div id="1"class="progress-bar progress-striped active" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"><span id="1-text" class="pull-left" style="padding-left: 10px;"> 0%</span></div></div></div>'); $(".messages").append('<div id="1-div">'+file.name+'<br><div class="progress"><div id="1"class="progress-bar progress-striped active" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"><span id="1-text" class="pull-left" style="padding-left: 10px;"> 0%</span></div></div></div>');
// Ajax Submit // Ajax Submit
$.ajax({ $.ajax({
url: '<%== url_for('add') %>', url: '<%== index_url %>',
type: 'POST', type: 'POST',
dataType: 'json', dataType: 'json',
data: fd, data: fd,

View file

@ -1,7 +1,7 @@
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab: % # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
% use Mojo::Util qw(url_escape); % use Mojo::Util qw(url_escape);
% my $twitter_url = 'https://twitter.com/share'; % my $twitter_url = 'https://twitter.com/share';
% my $url = url_for('/')->to_abs(); % my $url = index_url(1);
% $twitter_url .= '?url='.url_escape("$url") % $twitter_url .= '?url='.url_escape("$url")
% .'&via=framasky' % .'&via=framasky'
% .'&text=Check out this %23Lutim instance! '; % .'&text=Check out this %23Lutim instance! ';
@ -14,14 +14,14 @@
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="icon" type="image/png" href="<%= url_for('/') %>img/favicon.png"> <link rel="icon" type="image/png" href="<%= index_url %>img/favicon.png">
<link rel="icon" sizes="128x128" href="<%= url_for('/') %>img/lutim128.png"> <link rel="icon" sizes="128x128" href="<%= index_url %>img/lutim128.png">
<link rel="icon" sizes="196x196" href="<%= url_for('/') %>img/lutim196.png"> <link rel="icon" sizes="196x196" href="<%= index_url %>img/lutim196.png">
<link rel="apple-touch-icon" href="<%= url_for('/') %>img/lutim60.png"> <link rel="apple-touch-icon" href="<%= index_url %>img/lutim60.png">
<link rel="apple-touch-icon" sizes="76x76" href="<%= url_for('/') %>img/lutim76.png"> <link rel="apple-touch-icon" sizes="76x76" href="<%= index_url %>img/lutim76.png">
<link rel="apple-touch-icon" sizes="120x120" href="<%= url_for('/') %>img/lutim120.png"> <link rel="apple-touch-icon" sizes="120x120" href="<%= index_url %>img/lutim120.png">
<link rel="apple-touch-icon" sizes="152x152" href="<%= url_for('/') %>img/lutim152.png"> <link rel="apple-touch-icon" sizes="152x152" href="<%= index_url %>img/lutim152.png">
<link rel="apple-touch-icon-precomposed" sizes="128x128" href="<%= url_for('/') %>img/lutim128.png"> <link rel="apple-touch-icon-precomposed" sizes="128x128" href="<%= index_url %>img/lutim128.png">
% if (current_route 'stats') { % if (current_route 'stats') {
%= asset 'stats.css' %= asset 'stats.css'
% } elsif (current_route 'about') { % } elsif (current_route 'about') {
@ -40,9 +40,9 @@
% } % }
<div> <div>
<div class="pull-left hidden-xs logo"> <div class="pull-left hidden-xs logo">
<img src="<%= url_for('/') %>img/Lutim_small.png" alt="Lutim logo"> <img src="<%= index_url %>img/Lutim_small.png" alt="Lutim logo" width="57" height="75">
</div> </div>
<a class="link_nocol" href="<%= url_for('/') %>" title="<%=l 'homepage' %>"><h1 class="hennypenny">Let's Upload That Image!</h1></a> <a class="link_nocol" href="<%= index_url %>" title="<%=l 'homepage' %>"><h1 class="hennypenny">Let's Upload That Image!</h1></a>
<p> <p>
&copy; 2014 <%= link_to 'http://www.fiat-tux.fr' => begin %>Luc Didry<% end %> —  &copy; 2014 <%= link_to 'http://www.fiat-tux.fr' => begin %>Luc Didry<% end %> — 
<%=l 'license' %> <%= link_to 'https://www.gnu.org/licenses/agpl-3.0.html' => begin %>AGPL<% end %> —  <%=l 'license' %> <%= link_to 'https://www.gnu.org/licenses/agpl-3.0.html' => begin %>AGPL<% end %> — 
@ -51,7 +51,7 @@
<%= link_to $twitter_url => (title => l 'share-twitter') => begin %><i class="lead icon icon-twitter"></i><% end %>  <%= link_to $twitter_url => (title => l 'share-twitter') => begin %><i class="lead icon icon-twitter"></i><% end %> 
<%= link_to 'https://flattr.com/submit/auto?user_id=_SKy_&url='.$url.'&title=Lutim&category=software' => (title => 'Flattr this') => begin %><i class="lead icon icon-flattr"></i><% end %>  <%= link_to 'https://flattr.com/submit/auto?user_id=_SKy_&url='.$url.'&title=Lutim&category=software' => (title => 'Flattr this') => begin %><i class="lead icon icon-flattr"></i><% end %> 
<%= link_to 'bitcoin:1K3n4MXNRSMHk28oTfXEvDunWFthePvd8v?label=lutim' => (title => 'Give Bitcoins') => begin %><i class="lead icon icon-bitcoin"></i><% end %>  <%= link_to 'bitcoin:1K3n4MXNRSMHk28oTfXEvDunWFthePvd8v?label=lutim' => (title => 'Give Bitcoins') => begin %><i class="lead icon icon-bitcoin"></i><% end %> 
<a class="btn btn-default btn-xs" href="#" id="install-app"><img src="<%= url_for('/') %>img/rocket.png" alt="mozilla rocket logo"> <%=l 'install_as_webapp' %></a> <a class="btn btn-default btn-xs" href="#" id="install-app"><img src="<%= index_url %>img/rocket.png" alt="mozilla rocket logo" height="22"> <%=l 'install_as_webapp' %></a>
</p> </p>
</div> </div>
</div> </div>

View file

@ -1,7 +1,7 @@
{ {
"name": "Lutim", "name": "Lutim",
"description": "Lets Upload That Image!\n\nThis is a simple image sharing app which use <%= url_for('/')->to_abs %> for storing the images. Once you have uploaded an image, you'll be provided differents links:\n a view link, which points directly to the image\n a download link, which force the download of the image\n a twitter link, which you can share on twitter : the image will natively appeared in twitter\n a delete link, which allows you to delete the image anytime you want\n\nThe image is stored on <%= url_for('/')->to_abs %> for a delay which you can define.\n\nThe particularity of Lutim is that the image is encrypted and its usage is as most anonymous as possible. See the information page (<%= url_for('about')->to_abs %>) for more details.\nLicense: AGPLv3 (https://www.gnu.org/licenses/agpl-3.0.html)", "description": "Lets Upload That Image!\n\nThis is a simple image sharing app which use <%= index_url(1) %> for storing the images. Once you have uploaded an image, you'll be provided differents links:\n a view link, which points directly to the image\n a download link, which force the download of the image\n a twitter link, which you can share on twitter : the image will natively appeared in twitter\n a delete link, which allows you to delete the image anytime you want\n\nThe image is stored on <%= index_url(1) %> for a delay which you can define.\n\nThe particularity of Lutim is that the image is encrypted and its usage is as most anonymous as possible. See the information page (<%= url_for('about')->to_abs %>) for more details.\nLicense: AGPLv3 (https://www.gnu.org/licenses/agpl-3.0.html)",
"launch_path": "<%= url_for('/') %>", "launch_path": "<%= index_url %>",
"icons": { "icons": {
"32": "<%= url_for('/img/lutim32.png') %>", "32": "<%= url_for('/img/lutim32.png') %>",
"60": "<%= url_for('/img/lutim60.png') %>", "60": "<%= url_for('/img/lutim60.png') %>",
@ -12,12 +12,12 @@
}, },
"developer": { "developer": {
"name": "Lutim team !", "name": "Lutim team !",
"url": "https://github.com/ldidry/lutim" "url": "https://git.framasoft.org/luc/lutim"
}, },
"default_locale": "en", "default_locale": "en",
"locales": { "locales": {
"fr": { "fr": {
"description": "Envoyons cette image !\n\nCeci est une application de partage simple d'images qui utilise <%= url_for('/')->to_abs %> pour enregistrer les images. Une fois que vous avez envoyé une image, vous obtiendrez différents liens :\n un lien de visualisation, qui pointe directement sur l'image\n un lien de téléchargement, qui force le téléchargement de l'image\n un lien twitter, que vous pouvez partager sur twitter : l'image apparaîtra nativement dans twitter\n un lien de suppression, qui vous permet de supprimer l'image quand vous le souhaitez\n\nL'image est conservée sur <%= url_for('/')->to_abs %> pour un délai que vous pouvez définir.\n\nLa particularité de Lutim est que l'image est chiffrée et que son usage est aussi anonyme que possible. Voir la page d'information (<%= url_for('about')->to_abs %>) pour plus de détails.\nLicence : AGPLv3 (https://www.gnu.org/licenses/agpl-3.0.html)" "description": "Envoyons cette image !\n\nCeci est une application de partage simple d'images qui utilise <%= index_url(1) %> pour enregistrer les images. Une fois que vous avez envoyé une image, vous obtiendrez différents liens :\n un lien de visualisation, qui pointe directement sur l'image\n un lien de téléchargement, qui force le téléchargement de l'image\n un lien twitter, que vous pouvez partager sur twitter : l'image apparaîtra nativement dans twitter\n un lien de suppression, qui vous permet de supprimer l'image quand vous le souhaitez\n\nL'image est conservée sur <%= index_url(1) %> pour un délai que vous pouvez définir.\n\nLa particularité de Lutim est que l'image est chiffrée et que son usage est aussi anonyme que possible. Voir la page d'information (<%= url_for('about')->to_abs %>) pour plus de détails.\nLicence : AGPLv3 (https://www.gnu.org/licenses/agpl-3.0.html)"
} }
}, },
"activities": { "activities": {
@ -25,7 +25,7 @@
"filters": { "filters": {
"type": [ "image/*"] "type": [ "image/*"]
}, },
"href": "<%= url_for('/') %>", "href": "<%= index_url %>",
"disposition": "window" "disposition": "window"
} }
}, },

View file

@ -3,11 +3,11 @@
<hr> <hr>
%= include 'data' %= include 'data'
<h4>Uploaded files by days</h4> <h4><%=l 'uploaded_files_by_days' %></h4>
<div id="evol-holder"></div> <div id="evol-holder"></div>
<hr> <hr>
<h4>Evolution of total files</h4> <h4><%=l 'evolution_total_files'%></h4>
<div id="total-holder"></div> <div id="total-holder"></div>
<p><small><%=l 'graph-data-once-a-day' %></small></p> <p><small><%=l 'graph-data-once-a-day' %></small></p>
<%= link_to url_for('index') => ( class => "btn btn-primary btn-lg" ) => begin %><%=l 'back-to-index' %><% end%> <%= link_to index_url => ( class => "btn btn-primary btn-lg" ) => begin %><%=l 'back-to-index' %><% end%>

View file

@ -1,17 +1,40 @@
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab: % # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
% my $g = ($mimetype eq 'image/gif') ? 1 : 0;
<!DOCTYPE html> <!DOCTYPE html>
<html style="height:100%;"> <html style="max-height:100%;">
<head> <head>
<title>Lutim</title> <title>Lutim</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" type="image/png" href="<%= url_for('/')->to_abs() %>img/favicon.png"> <link rel="icon" type="image/png" href="<%= index_url(1) %>img/favicon.png">
<meta name="twitter:card" content="photo"> <meta property="og:title" content="Lutim" />
<meta property="og:type" content="website" />
<meta property="og:url" content="<%= index_url(1).$short %>?t" />
<meta property="og:image" content="<%= index_url(1).$short %>" />
<meta property="og:image:url" content="<%= index_url(1).$short %>" />
<meta property="og:image:type" content="<%= $mimetype %>" />
<meta name="twitter:site" content="<%= config('tweet_card_via') %>"> <meta name="twitter:site" content="<%= config('tweet_card_via') %>">
<meta name="twitter:image:src" content="<%= url_for('/')->to_abs().$short %>"> <meta name="twitter:image:src" content="<%= index_url(1).$short %>">
% if ($g) {
<meta name="twitter:card" content="player">
<meta name="twitter:image" content="<%= index_url(1).$short %>">
<meta name="twitter:player" content="<%= index_url(1).$short.'?t' %>">
<meta name="twitter:title" content="<%= $filename %>">
<meta name="twitter:player:width" content="<%= $width %>">
<meta name="twitter:player:height" content="<%= $height %>">
%= asset 'freeze.js', { inline => 1 }
%= javascript begin
freezeframe_options = {
trigger_event: "click",
animation_play_duration: 60000
}
% end
% } else {
<meta name="twitter:card" content="photo">
% }
</head> </head>
<body style="height: 97%;"> <body<%= ($g) ? '' : ' style="height: 97%;"' %>>
<img style="max-width:100%; max-height:100%;" src="<%= url_for('/').$short %>" alt="<%= $filename %>"> <img<%= ' class="freezeframe"' if ($g) %> style="<%= 'max-' unless ($g) %>width:100%; max-height:100%;" src="<%= index_url(1).$short %><%= '.gif' if ($g) %>" alt="<%= $filename %>">
</body> </body>
</html> </html>

View file

@ -49,7 +49,7 @@ do_start()
# 2 if daemon could not be started # 2 if daemon could not be started
cd $LDIR cd $LDIR
carton exec hypnotoad $DAEMON >/dev/null 2>&1 sudo -u www-data carton exec hypnotoad $DAEMON >/dev/null 2>&1
return "$?" return "$?"
} }

191
sources/lutim.init Executable file
View file

@ -0,0 +1,191 @@
#!/bin/sh
# vim: set ts=4 sw=4 sts=4 tw=0:
# vim: set expandtab:
### BEGIN INIT INFO
# Provides: lutim
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts lutim with hypnotoad
# Description: starts lutim with hypnotoad
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=script/lutim
NAME=lutim
DESC=lutim
if [ -f "/etc/default/lutim" ]
then
. /etc/default/lutim
if [ -z $LDIR ]
then
echo "LDIR variable is empty, please fill it in /etc/default/lutim"
exit 0
fi
else
echo "Missing /etc/default/lutim file"
exit 0
fi
if [ ! -f "$LDIR$DAEMON" ]
then
echo "Missing $LDIR$DAEMON file"
exit 0
fi
set -e
. /lib/lsb/init-functions
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
cd $LDIR
sudo -u www-data carton exec hypnotoad $DAEMON >/dev/null 2>&1
return "$?"
}
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
cd $LDIR
carton exec hypnotoad -s $DAEMON >/dev/null 2>&1
return "$?"
}
do_status()
{
cd $LDIR
if [ -f "script/hypnotoad.pid" ]
then
pgrep -lf $DAEMON >/dev/null 2>&1
if [ "$?" = "0" ]; then
log_progress_msg "$NAME is running"
else
log_progress_msg "$NAME is NOT running"
fi
else
log_progress_msg "$NAME is NOT running"
fi
}
case "$1" in
start)
log_daemon_msg "Starting $NAME"
cd $LDIR
if [ -f "script/hypnotoad.pid" ]
then
pgrep -lf $DAEMON >/dev/null 2>&1
if [ "$?" = "0" ]
then
log_progress_msg "$NAME is already running. Unable to start."
log_end_msg 1;
else
do_start
case "$?" in
0|1)
log_progress_msg "done"
log_end_msg 0
;;
2)
log_progress_msg "failed"
log_end_msg 1
;;
esac
fi
else
do_start
case "$?" in
0|1)
log_progress_msg "done"
log_end_msg 0
;;
2)
log_progress_msg "failed"
log_end_msg 1
;;
esac
fi
;;
stop)
log_daemon_msg "Stopping $NAME"
cd $LDIR
if [ -f "script/hypnotoad.pid" ]
then
pgrep -lf $DAEMON >/dev/null 2>&1
if [ "$?" = "0" ]; then
do_stop
case "$?" in
0|1)
log_progress_msg "done"
log_end_msg 0
;;
*)
log_progress_msg "failed"
log_end_msg 1
;;
esac
else
log_progress_msg "$NAME is NOT running. Unable to stop"
log_end_msg 1
fi
else
log_progress_msg "$NAME is NOT running. Unable to stop"
log_end_msg 1
fi
;;
status)
log_daemon_msg "Checking $NAME status"
do_status
log_end_msg 0
;;
reload)
log_daemon_msg "Reloading $NAME"
do_start
case "$?" in
0|1)
log_progress_msg "done"
log_end_msg 0
;;
2)
log_progress_msg "failed"
log_end_msg 1
;;
esac
;;
restart)
log_daemon_msg "Restarting $NAME"
do_stop
sleep 1
do_start
case "$?" in
0|1)
log_progress_msg "done"
log_end_msg 0
;;
2)
log_progress_msg "failed";
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $0 {start|stop|status|reload|restart}" >&2
exit 3
;;
esac
exit 0