PROJET AUTOBLOG


Planet-Libre

source: Planet-Libre

⇐ retour index

Tuxicoman : Raccourcis clavier Gnome Shell

dimanche 7 mai 2017 à 07:03

Avez-vous jeté un oeil à la liste des raccourcis claviers pour le bureau Gnome?

J’y ai découvert des trucs bien sympas comme :

 

Related Posts:

Gravatar de Tuxicoman
Original post of Tuxicoman.Votez pour ce billet sur Planet Libre.

Articles similaires

Thuban : zeniTK - un zenity sans GTK

samedi 6 mai 2017 à 17:58

Alors que je bricole 2-3 trucs sur mes sessions, je râle à chaque fois qu'un script doit utiliser zenity. C'est censé être de petits outils rapides, mais la moindre petite fenêtre met 3 plombes à s'ouvrir le temps que toutes les libs GTK soient chargées.

J'ai donc eu envie de refaire un zenity à ma façon à partir de la librairie tkinter, et ça donne ZeniTK.

L'outil ne propose pas encore autant d'options que zenity, et je ne suis pas certain d'en rajouter sauf si j'en ai besoin ou si des contributions sont proposées.

On peut déjà profiter des éléments suivants :


Ce dernier permet de faire un éditeur de texte tout bête pour prendre des notes par exemple :

#!/bin/sh

DIR=~/Documents/notes
mkdir -p $DIR

N=$(zeniTK --title="Nouvelle note" --text="Nom de la nouvelle note : " --entry)

if [ -n "$N" ]; then
        RES=$(cat "$DIR/$N" | zeniTK --text-info)
        if [ -n "$RES" ]; then
                echo $RES > "$DIR/$N"
        fi
fi
exit

Ne vous fiez pas aux couleurs dans les captures d'écran, j'ai modifié des fichiers système par erreur mais ne parviens plus à les retrouver pour remettre à la normale. Oui, je suis un boulet :)

Gravatar de Thuban
Original post of Thuban.Votez pour ce billet sur Planet Libre.

mozillaZine-fr : Quoi de neuf dans Firefox Nightly ? 15ᵉ éd.

vendredi 5 mai 2017 à 21:51

logo-nightlyLe blog de Firefox Nightly publie les articles de Mike Conley (aidé cette semaine par Johann Hofmann) intitulés These Weeks in Firefox. Sa 15ᵉ édition rapporte des nouvelles du développement de Firefox. Nous en avons sélectionnées quelques-unes :

Firefox 55 (actuellement en Nightly) inclut la fonctionnalité lazy-tabs-browsers qui ne restaure que les onglets lors de la demande. Cela signifie que la restauration de n’importe quelle session (même avec beaucoup d’onglets) devient presque instantanée.

(Re)lire : Aurora s’éteindra à l’aube, sur Mozilla francophone

La refonte de Places (la bibliothèque de Firefox : marque-pages, historique…) pour prendre en charge des favicons en haute résolution a embarqué et apporte un gain en performances de près de 30 % pour certaines mesures d’entrées-sorties (I/O) de fichiers. Du travail de suivi est toujours en cours.

Dans le cadre de Photon Animation, Mozilla a inclus une préférence pour consolider et activer/désactiver toutes les animations cosmétiques dans l’interface du navigateur et a une variable qui arrive pour activer/désactiver spécifiquement les changements de l’animation de Photon (dans Nightly jusqu’à la version 57).

Pour aider à mesurer l’impact sur les performances que les efforts en matière de Quantum Flow ont, Mozilla a désactivé les modules qui exigent des aménagements temporaires pour la compatibilité pour les versions Nightly. Cela signifie que seules les WebExtensions et les extensions étiquetées comme compatibles avec le multiprocessus resteront actives.

Firefox Nightly : barre de notification de la désactivation d'extensions

Ce changement est réversible en passant la préférence extensions.allow-non-mpc-extensions à true. Cependant, l’équipe aimerait que vous ne reveniez pas sur ce basculement pour permettre à l’équipe performances d’avoir une idée plus claire sur l’amélioration de Firefox dans ce domaine et si ces efforts ont rendu Firefox plus rapide ou pas.

Le nombre de compartiments mémoire que les processus de contenu utilisent a été réduit. Cela devrait réduire leur impact de quelques mégas chacun !

eslint-plugin-mozilla peut désormais être utilisé via npm pour des projets externes. Il comprend une configuration « recommandée » qui est celle initialement présente dans toolkit/.

Les permissions « optionnelles » pour les WebExtensions ont été activées par défaut.

Permissions optionnelles pour les WebExtensions

La fonctionnalité de remplissage automatique de formulaire a été activée cette semaine (pour @autocmplete sur ).

Firefox Screenshots est en bêta 2 cachée derrière une préférence par défaut. Il sera activé très bientôt. Vous pouvez voler le départ en basculant la préférence extensions.screenshots.system-disabled.

Firefox Screenshots (Beta) – Coming soon

Firefox Screenshots est l’outil de partage de captures d’écran testé originellement dans Test Pilot (wiki) sous le nom de Page Shot.

Modules complémentaires

Vous voulez découvrir les WebExtensions exécutées dans leur propre processus ? Alors réglez la préférence cachée extensions.webextensions.remote true. Remplissez des rapports de bogues !

La nouvelle API pour appliquer un thème visuel a été activé par défaut. Ainsi, les auteurs d’extension peuvent changer l’apparence dynamiquement dans les WebExtensions.

Mobile

Un effort de Photon sur mobile (Android+iOS) a été lancé, avec comme objectif Firefox 57.

Quelques super nouvelles fonctionnalités arrive dans Firefox pour Android :

Vie privée / Sécurité

jkt a rédigé un billet de blog sur la nouvelle fonctionnalité « Toujours ouvrir dans ce conteneur ».

Test Pilot

Min Vid célèbre sa plus grosse version avec l’ajout une file de lecture et d’historique. Ajoutez les médias que vous voulez regarder à votre file de vidéos en cours ou revoyez quelque chose que vous avez manqué en cliquant sur l’onglet historique. Min VId fonctionne actuellement sur YouTube, SoundCloud, Vimeo et les liens directs pour l’audio et la vidéo.

⁨Pulse⁩ a ajouté des invites occasionnelles (moins d’une fois par jour) pour des retours afin d’aider à éviter les données biaisées. Si vous voulez aider Firefox à améliorer les performances sur vos sites préférés, c’est votre chance ! Les données provenant de cette expérimentation vont directement à l’équipe produit de Firefox pour aider à prioritiser les améliorations.

Snooze Tabs est proposé dans le monde entier en 23 langues. En plus de pouvoir utiliser Snooze Tabs dans votre langue préférée, vous trouverez aussi un bouton Annuler lorsque vous supprimez un onglet différé.

Pour des détails du développement d’Activity Stream, de l’ingénirie du cœur de Firefox, du remplissage automatique des formulaires, de Photon, du projet Mortar (PDFium), de la recherche et des sujets abordés ici, lisez l’article original de Mike Conley sur le blog de Firefox Nightly (version de Firefox que nous vous conseillons d’utiliser au quotidien).

Gravatar de mozillaZine-fr
Original post of mozillaZine-fr.Votez pour ce billet sur Planet Libre.

Articles similaires

Max Koder : cURL : Dialogue avec une API en PHP

vendredi 5 mai 2017 à 17:15
curl-php

Il y a quelques temps, j’ai été confronté à l’API de Mastodon, et me suis rendu compte que j’utilisais en fait 2 méthodes pour dialoguer avec une API en PHP. J’étais initialement parti pour vous présenter les 2, mais je ne détaillerai que la plus efficace : cURL.
La seconde, plus aisée et rapide fera l’objet d’un second article à venir.

Euh, Jamie, c’est quoi une API ?

Vous avez raison, avant tout cela, posons les bases.

API

Je suis sûr que vous avez déjà entendu parler d’API, même sans savoir ce que c’est. API signifie Application Programming Interface, ou Interface de Programmation Applicative. Ouais, moi non plus ça m’aide pas beaucoup. Ce qui est important là dedans, c’est le mot Interface.

En programmation comme dans la vie quotidienne, une interface désigne un moyen accessible (dans le sens facile) d’interagir avec un programme, une classe, une chaîne HiFi ou votre lave-vaisselle.
Pour imager, prenons l’exemple classique d’une télévision et sa télécommande. Cette dernière est l’interface entre vous et la TV.

Pour changer une chaîne, il suffit d’appuyer sur le bouton du canal désiré, et la télécommande va envoyer un signal au récepteur de la TV afin qu’elle change de fréquence. Personnellement, j’ai encore en mémoire la vieille TV de mes grands-parents où il fallait changer la fréquence avec un potar en façade. Ça change la vie
Et donc, comme dans chaque interface, une API impose une procédure qu’il faut respecter si l’on souhaite que ça fonctionne. Vous n’imaginez pas allumer votre voiture en appuyant sur le bouton des phares ? Ici c’est pareil

Comment ça marche ?

Je l’attendais celle-là. Et bien, ça marche plutôt bien.

Plus sérieusement, voilà comment ça fonctionne en très gros :
Un site web propose d’héberger des photos. Il est alors possible de s’inscrire sur ce site, et d’y envoyer des photos. Le site vous donne en retour une URL que vous pouvez donner à vos amis pour montrer vos prouesses.
Et bien généralement, ces services web proposent une API pour utiliser leurs services sans passer par leur site. C’est le cas de Twitter (récupérer des tweets), PayPal pour les solutions de paiement, Facebook, … où l’on peut récupérer des informations où en poster via PHP, ou une console, …

Pour notre exemple d’hébergement de photos, on peut imaginer qu’on effectuera une première requête vers l’API pour s’authentifier sur le site, puis une seconde en envoyant la photo, et le serveur nous renverra alors l’URL de l’image en ligne si la transaction a été effectuée.

REST, SOAP, RESTful, …

Je ne détaillerai pas ici les différents types d’API, mais sachez, même si l’on entend parler que de lui, qu’il n’existe pas que REST.
SOAP est à ma connaissance le plus vieux (90), mais aussi moins utilisé, et repose sur des échanges basés sur du XML. Certains prétendent qu’il connaîtra un essor dans quelques années, à voir.

Enfin RESTful désigne simplement une application REST, plus récent (2000) mais également voulu moins lourd et plus simple. Dans la suite de ce billet, je ne parlerai que de ce type d’API.

cURL

La bibliothèque cURL de PHP est certainement la plus efficace et la plus utilisée des méthodes pour se connecter à une API. Il est possible de faire des tas de choses avec, comme l’utilisation de web services, de proxy, de faire du téléchargement, un crawler, gérer un FTP, …
Si cURL est bien connu des utilisateurs de Linux, c’est un outil multi-plateforme rapide, pas très compliqué à utiliser et qui gère l’authentification sécurisée.

Pour pouvoir l’utiliser avec PHP, il suffit d’activer la bibliothèque libcurl. Un petit

phpinfo()
  pour vérifier si elle est bien activée :

et c’est parti.

Initialiser cURL

Pour créer une nouvelle ressource cURL, la syntaxe est simple:

$curl = curl_init();

A cela, on peut ajouter un argument : L’URL de destination. Ou l’on peut l’ajouter plus tard, c’est la méthode que je préfère.

Mise en place des paramètres

Il existe 2 façons pour ajouter des options à une ressource cURL :

Par l’array

J’aime bien le jeu de mots
Il est possible de fournir à notre ressource un tableau préalablement créé afin de lui spécifier des paramètres avec la fonction

curl_setopt_array()
:
$opts = [
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_HTTPHEADER     => $headers,
    CURLOPT_URL            => $this->domainURL . $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
    CURLOPT_CONNECTTIMEOUT => 30
];

curl_setopt_array($curl, $opts);

Le premier argument à fournir est la ressource à paramétrer. La seconde contient notre tableau associatif, avec les options.

A l’ancienne

Quand je dis à l’ancienne, ne pas comprendre que cette fonction est plus vieille que l’autre. C’est juste la forme redondante que prend cette méthode à écrire. Bref, il est possible de passer les arguments un à un avec la fonction

curl_setopt()
:
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

Cette fonction attend en argument :

  1. La ressource cURL à paramétrer
  2. Le paramètre
  3. La valeur

Quelques options intéressantes

Je vous livre ici quelques options de cURL, les plus utiles et basiques selon moi :

Exécution de la session

Pour exécuter la requête, rien de plus simple. Il suffit d’utiliser la fonction :

curl_exec()
  :
$response = curl_exec($curl);

Vous l’aurez compris, l’argument à passer à cette fonction est notre ressource cURL. Cette fonction retourne simplement la réponse de l’hôte distant.

Fermer la ressource

Pour libérer de la mémoire, il est vivement conseillé, une fois la transmission terminée, de fermer la ressource :

curl_close($curl);

Testons cela alors.

Récupérer le contenu d’une page web

Ici, nous allons tenter de récupérer le contenu d’une page web. Vous allez voir que le code est très simple :

 'www.google.fr',
    CURLOPT_RETURNTRANSFER => true,
];

curl_setopt_array($curl, $opts);

$response = curl_exec($curl);
curl_close($curl);

Ici on définit peu de paramètres :

La variable

$response
  contient en sortie la réponse de la requête. Ici, c’est une chaîne de caractères comprenant le code HTML de la page de google.
Vous pouvez donc exploiter comme n’importe quelle string ce résultat.

Petit rappel : Pour parser un document HTML, vous pouvez vous aider de la classe DOMDocument ou de l’extension SimpleXML.
Sinon, il suffit d’un

echo
  pour l’afficher sur la page :

L’utilité du User-Agent

Brève petite astuce : Je vous ai mis l’option CURLOPT_USERAGENT dans la liste des paramètres tout à l’heure. Celle-ci peut nous permettre par exemple de simuler une connexion à Google comme si nous nous connections avec un smartphone.

Dans le code précèdent, ajoutons simplement un user-agent de navigateur mobile dans les paramètres de la transmission :

 'www.google.fr',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERAGENT => 'Mozilla/5.0 (Linux; U; Android 2.1-update1; fr-fr; GTI9000 Build/ECLAIR) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17',
];

curl_setopt_array($curl, $opts);

$response = curl_exec($curl);
curl_close($curl);

echo $response;

On voit ainsi que Google a pris en compte notre requête, et a adressé la réponse en fonction du user-agent spécifié :

Transmission avec une API

Maintenant que nous avons vu sommairement l’utilisation de cURL, nous allons nous attaquer à ce qui nous intéresse : Dialoguer avec une API.

Requête GET

Selon l’API, comme avec le protocole HTTP que vous connaissez, il faut parfois effectuer une transaction GET ou POST.
GET est généralement utilisée lorsque votre application ne doit que récupérer des données de l’hôte, mais il est possible d’y passer des arguments.

Pour tester cela, nous allons nous servir de l’API Random User Generator, que j’ai découvert il y a peu, grâce au blog de ShevAbam. Il s’agit uniquement de pouvoir récupérer des informations d’utilisateurs aléatoires (factices), utiles pour vos éventuels tests.

La documentation, portée sur jQuery, permet tout de même d’en comprendre le fonctionnement.

On y apprend que l’URL d’entrée pour cette API, celle qui représente la ressource à récupérer, appelée endpoint, est , et que la ressource récupérée est un objet JSON.

Passons au code :

 '
    CURLOPT_RETURNTRANSFER => true,
];

curl_setopt_array($curl, $opts);

$response = json_decode(curl_exec($curl), true);

print_r($response);

Si vous avez bien suivi, il ne devrait rien y avoir de compliqué.
J’ai renseigné le endpoint dans le paramètre CURLOPT_URL, et décode ensuite l’objet JSON que l’API me renvoie.

Voilà le résultat produit :

Array
(
    [results] => Array
        (
            [0] => Array
                (
                    [gender] => male
                    [name] => Array
                        (
                            [title] => mr
                            [first] => leon
                            [last] => hübner
                        )

                    [location] => Array
                        (
                            [street] => 9377 parkstraße
                            [city] => bayreuth
                            [state] => hamburg
                            [postcode] => 29972
                        )

                    [email] => leon.hübner@example.com
                    [login] => Array
                        (
                            [username] => heavyladybug706
                            [password] => dogwood
                            [salt] => iSK8r2hd
                            [md5] => ce2261b02d713de1b6f25710f40a38e0
                            [sha1] => e640a316dca46761476458eb17fbf8f8018949f7
                            [sha256] => 9c919250c04e2c3b925434c56a0aae210cd96b70e6b5a65cc1ddf764067f8260
                        )

                    [dob] => 1982-10-19 09:48:01
                    [registered] => 2004-04-06 02:49:59
                    [phone] => 0658-4413331
                    [cell] => 0174-7427152
                    [id] => Array
                        (
                            [name] => 
                            [value] => 
                        )

                    [picture] => Array
                        (
                            [large] => 
                            [medium] => 
                            [thumbnail] => 
                        )

                    [nat] => DE
                )

        )

    [info] => Array
        (
            [seed] => 04b9f8b8ed62a4a6
            [results] => 1
            [page] => 1
            [version] => 1.1
        )

)

Des paramètres ?

Je vous ai dit tout à l’heure qu’il était possible de spécifier des paramètres dans la requête. Voyons ça.

Comme dans n’importe quelle requête HTTP GET, les paramètres se mettent dans l’URL, tout simplement :

CURLOPT_URL => ' j’ai fourni plusieurs paramètres, récupérés dans la doc. Le résultat :
Array
(
    [results] => Array
        (
            [0] => Array
                (
                    [gender] => male
                    [name] => Array
                        (
                            [title] => mr
                            [first] => adam
                            [last] => addy
                        )

                    [nat] => CA
                )

            [1] => Array
                (
                    [gender] => male
                    [name] => Array
                        (
                            [title] => mr
                            [first] => benjamin
                            [last] => martin
                        )

                    [nat] => NZ
                )

        )

    [info] => Array
        (
            [seed] => 52b8ab0ce31a8031
            [results] => 2
            [page] => 1
            [version] => 1.1
        )

)

Requête POST

Ce type de requête n’est pas plus compliquée. Il suffira généralement de quelques paramètres en plus dans notre ressource cURL.

Pour cet exemple, je me servirais de JSONPlaceholder. Pour ceux qui ne connaissent pas, c’est une fausse API en ligne qui existe uniquement à but de tests et prototypes. C’est parfait pour nous !

Encore une fois, la documentation est écrite pour Javascript, mais l’usage est simple. Vous pouvez si vous le souhaitez vous amuser avec les requêtes GET, mais ce qui nous intéresse ici est la création d’un nouveau post.

Pour faire cela, il va falloir envoyer une requête HTTP POST, avec 3 paramètres :

Je vous donne le code :

 'Welcome Bro !',
    'body' => 'Lorem Ipsum etc etc',
    'userId' => 5
];

$params_string = http_build_query($params);

$opts = [
    CURLOPT_URL => '
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $params_string,
    CURLOPT_RETURNTRANSFER => true,
];

curl_setopt_array($curl, $opts);

$response = json_decode(curl_exec($curl), true);

print_r($response);

J’ai mis en évidence les paramètres à modifier dans la ressource cURL pour exécuter correctement la requête.

Un point cependant, concernant la variable

$params_string
. C’est en fait la génération des paramètres encodés en URL, grâce à la fonction
http_build_query($params) 
.

Encore une fois, on décode la réponse et on observe le résultat :

Array
(
    [title] => Welcome Bro !
    [body] => Lorem Ipsum etc etc
    [userId] => 5
    [id] => 101
)

C’était vraiment compliqué ?

Pour aller plus loin

J’ai testé ici des exemples très scolaires et simples. Lors de l’utilisation d’une API plus complexe, par exemple avec une authentification par OAuth, des procédures et paramètres plus avancées sont requis.

J’essayerai dès que possible de créer un billet sur l’utilisation de Mastodon via l’API, toujours en PHP.

N’hésitez pas d’y aller de vos commentaires si je peux améliorer cet article, merci !

L’article cURL : Dialogue avec une API en PHP est apparu en premier sur Max-Koder.

Gravatar de Max Koder
Original post of Max Koder.Votez pour ce billet sur Planet Libre.

Jehan : ZeMarmot — travail en cours: de l’animatique à l’animation

vendredi 5 mai 2017 à 03:29

Alors que nous sommes en pleine étape d’animation, on s’est dit que vous aimeriez un peu en savoir plus sur cette étape de production. Comment passe-t-on d’images statiques à images animées?

Storyboard, puis Animatique

Nous avons déjà parlé en long et en travers de ces étapes, donc nous n’allons pas épiloguer. Nous vous conseillons de lire les blog posts des mois passés pour en savoir plus. Ce sont les étapes des images « purement statiques » type BD (storyboard) puis d’images statiques projetées en vidéo (animatique).

Key Framing

Avec le numérique, le sens terme « keyframe » a changé plusieurs fois. Ainsi dans les vidéos formats, on entend par « keyframe » une image qui est complète dans le flux vidéo, en oppositions d’images partielles qui n’ont de sens qu’associés à une keyframe précédente. Dans l’animation 3D ou vecteur, on va en général nommer keyframe les positions extrêmes dans une transition (mouvement de personnage par exemple), dont les positions intermédiaires sont calculées par un algorithme (interpolation ). C’est plus ou moins la définition donnée par Wikipedia pour une keyframe: « A key frame in animation and filmmaking is a drawing that defines the starting and ending points of any smooth transition. »

Cette définition est cependant un peu trop « mécanique », liée aux méthodes modernes d’animer avec la 3D et le dessin vectoriel (ce n’est pas totalement vrai même avec ces techniques, mais avec un peu de paresse, en découvrant la magie de l’interpolation algorithmique, cela paraît être la définition pour beaucoup). Les keyframes sont en fait simplement des « images importantes », ce qui est déterminé totalement subjectivement. Keyframing est donc une part de l’art de l’animateur, plutôt qu’une science. Bien sûr, très souvent, les keyframes sont des débuts/fins de mouvement, mais ce n’est pas une vérité absolue. On les appelle aussi parfois les « poses clés »; il s’agit donc des poses que l’animateur juge comme importante pour rendre le mouvement juste, de manière totalement partiale comme pour tout œuvre.

Animation Pose à Pose vs Straight Ahead

Il y a 2 principales logiques pour animer. La première méthode consiste à décomposer le mouvement en poses clés (keyframes) dans un premier temps. Dans le second temps, quand vous êtes content du résultat, you pouvez ajouter les images intermédiaires (inbetweens). C’est la méthode pose à pose.

Dans un gros studio, les keyframes sont généralement dessinées par les animateurs expérimentés. Puis les assistants (animateurs juniors)  dessineront les inbetweens après coup. Cela permet un peu plus de partage de travail, d’efficacité et de multi-tâche. Pour ZeMarmot malheureusement, Aryeom fait toutes les étapes elle-même, puisque nous n’avons pas le financement pour engager plus d’artites pour l’instant.

L’autre méthode s’appelle en anglais « Straight Ahead » et consiste à dessiner les images successivement les unes après les autres, sans décomposition préalable. Cela rend le planning de la séquence plus difficile et le timing est bien plus difficile à gérer. Il est également plus probable que vous gâcherez des dessins avec cette méthode. Néanmoins certains animateurs aiment la liberté apportée et aussi le manque de planification peut permettre des mouvements moins parfait, moins mécanique et donc plus réalistes. Il s’agit de reproduire les êtres vivants dans toute leur splendeur de parfaite imperfection!

En observant Aryeom travailler, on peut constater qu’elle utilise régulièrement l’une ou l’autre méthode. Cela dépend des séquences.

Conclusion

Nous espérons que vous aurez apprécié ce petit aperçu dans le monde de l’animation et le travail de l’animateur. Nous espérons également que la petite vidéo attachée vous aura intéressés. Nous l’avons choisie pour vous montrer diverses étapes de la même section de scène, l’une après l’autre, puis côte-à-côte.

Vous remarquerez aussi que nous avons tendance à montrer toujours les mêmes sections du travail car nous souhaitons vous éviter le moins possible de spoiler, ce qui gâcherait le visionnage final. 🙂

Amusez-vous bien!

Équipe de ZeMarmot

Rappel: pour aider notre film d'animation, à voir le jour, lequel est
fait avec des logiciels libres — et pour lequel nous contribuons aussi
beaucoup de code — et qui sera sous licence Creative Commons by-sa 4.0
international, vous pouvez contribuer financièrement en USD sur
Patreon ou en EUR sur Tipeee.

Gravatar de Jehan
Original post of Jehan.Votez pour ce billet sur Planet Libre.