Lutim

Le partage d'images libre, anonyme et en Perl !

Luc Didry

13 juin 2014

Qu'est-ce que Lutim ?

Lutim est une solution de partage d'images :

  • libre (license AGPLv3) ;
  • sécurisée (les images sont chiffrées) ;
  • anonyme (la rétention de l'IP de l'envoyeur est configurable) ;
  • simple ;
  • rapide.

Lutim est écrit avec le framework Mojolicious.

D'où est partie l'idée de Lutim ?

D'un raccourcisseur d'URL.

Si si !

J'avais codé un soir par désœuvrement un raccourcisseur d'URL : Lstu

Un autre soir, j'ai voulu envoyer un screenshot à un ami.

  • le mail… ça prend de la place 😛
  • Owncloud, ça fait des URLs impossibles, et il y a trop de manipulations 😕
  • imgur et consorts, c'est des Terms of service longs et imbitables 😓
  • et puis je voulais un truc qui efface le screenshot tout seul.
Terms of service d'imgur
Terms of service d'imgur

Du coup, j'ai réutilisé une majorité du code de Lstu pour coder Lutim.

Parce que les URLs des images de Lutim sont comme les URLs raccourcies : une suite aléatoire de chiffres et de lettres.

Interface de Lutim
Interface de Lutim

Comment Lutim fonctionne-t'il ?

  • on sélectionne la durée de rétention voulue ;
  • on fait un glisser-déposer de(s) l'image(s), on choisit le fichier de façon classique ou on donne une URL ;
  • on note les URLs fournies :
    • affichage ;
    • téléchargement ;
    • page pour inclusion dans twitter ;
    • suppression ;

Lutim fournit quatre commandes à exécuter en cron si on le souhaite :

  • cleanbdd, pour vider les IPs de la base de données après un certain délai ;
  • cleanfiles, pour supprimer les fichiers expirés ;
  • stats, pour générer une page de statistiques ;
  • watch, pour surveiller le répertoire des images ;

Ces commandes sont codées de la même façon que les commandes mojo vues dans la conférence Mojolicious.

Les possibilités d'extension sont infinies !

Et pourquoi pas créer des applis non web avec Mojolicious.

Revenons à Mojolicious

script/lutim get /

Dans lib/Lutim.pm (dans la sous-routine startup) :

$r->get('/')->
    to('Controller#home')->
    name('index');

Dans lib/Lutim/Controller.pm :

sub home {
    my $c = shift;

    $c->render(
        template      => 'index',
        max_file_size => $c->req->max_message_size
    );

    $c->on(finish => sub {
            my $c = shift;
            $c->app->log->info('[HIT] someone visited site index');
        }
    );
}

Dans template/layouts/default.html.ep :

% if (defined(config('hosted_by'))) {
    <div class="pull-right">
        <%== config('hosted_by') %>
    </div>
% }
    <img src="<%= url_for('/') %>img/Lutim_small.png" alt="Lutim logo">
    <%= link_to url_for('about') => begin %><%=l 'informations' %><% end %>

    <%= content %>

Ceci est un petit pot-pourri de ce qu'on peut retrouver dans un template.

Le layout est un template qui va contenir ce qu'il y a dans le template 'index' appelé dans lib/Lutim/Controller.pm.

La partie <%= content %>

On y place généralement les menus, les appels css, javascript, etc. Tout ce qui est commun à plusieurs pages.

On peut créer plusieurs layouts et en définir un par défaut.

Il est possible d'inclure aussi dans des templates — même si ce ne sont pas des layouts —, d'autres templates.

%= include 'header'

(au passage : le moteur de template par défaut est Embedded Perl)

Format de sortie

Par défaut, Mojolicious renvoie de l'html, mais il peut nativement renvoyer d'autres formats.

Dans lib/Lutim/Controller.pm :

if (defined($c->param('format')) && $c->param('format') eq 'json') {
    return $c->render(
        json => {
            success => Mojo::JSON->false,
            msg     => {
                filename => $file_url,
                msg      => $msg
            }
        }
    );
} else {
    $c->flash(msg      => $msg);
    $c->flash(filename => $upload->filename);
    return $c->redirect_to('/');
}

Des données pour plus tard

Le $c->flash(msg => $msg) du code précédent est une donnée stockée dans un cookie pour être utilisée à la prochaine page affichée.

Cela me permet ici de rediriger vers la page d'accueil plutôt que de rendre le template index.

$c->render(
    template      => 'index',
    max_file_size => $c->req->max_message_size
);

Des helpers custom

Les helpers sont des fonctions accessibles de partout dans le code de l'application, et c'est bien pratique !

Dans lib/Lutim.pm :

$self->helper(
    delete_image => sub {
        my $c = shift;
        my $image = shift;
        unlink $image->path();
        $image->update(enabled => 0);
    }
);
$c->delete_image($images[0]);

Utilisation des hooks

Les hooks interviennent à certains moments du processus de routage, sans discrimination par rapport à la route.

Lutim et Lstu provisionnent les suites aléatoires de chiffres et de lettres pour en avoir un stock prêt à être utilisé.

Cette provision est constituée petit à petit après chaque visite de page.

Dans lib/Lutim.pm :

$self->hook(
    after_dispatch => sub {
        my $c = shift;
        $c->provisioning();
    }
);

Manipulation des transactions HTTP

Manipulation d'en-tête :

my $headers = Mojo::Headers->new();
$headers->add('Content-Type' => $mediatype.';name='.$filename);
$c->res->content->headers($headers);

Accès à des éléments des transactions :

$c->tx->remote_address
$c->req->max_message_size

Mojolicious permet un accès et une manipulation aisés des transactions.

Utilisation du plugin Mojolicious::Plugin::AssetPack

Le but :

  • concaténer les différents fichiers css et javascript ;
  • les minifier.

Le résultat (pour Lutim) :

  • une requête HTTP pour le js, une pour le css (au lieu de 4 et 6) ;
  • un gain appréciable de taille ;
  • temps de chargement divisé au minimum par 2 !

Dans lib/Lutim.pm :

$self->plugin('AssetPack');
$self->asset('index.css' => 'css/bootstrap.min.css', \
'css/fontello-embedded.css', 'css/animation.css', \
'css/uploader.css', 'css/hennypenny.css', 'css/lutim.css');

Dans templates/layouts/default.html.ep

%= asset 'index.css'

Je dois pas être loin de mes 20 minutes 😚

Questions ?

http://lstu.fr

https://github.com/ldidry/lstu

https://lut.im

https://github.com/ldidry/lutim

https://github.com/ldidry

https://twitter.com/framasky

http://slides.fiat-tux.fr