<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Corentin Desfarges]]></title><description><![CDATA[Dev passionné, technophile confirmé, et prof de temps en temps 👨‍🏫]]></description><link>https://blog.corentindesfarges.fr/</link><image><url>https://blog.corentindesfarges.fr/favicon.png</url><title>Corentin Desfarges</title><link>https://blog.corentindesfarges.fr/</link></image><generator>Ghost 5.2</generator><lastBuildDate>Sat, 02 May 2026 16:53:05 GMT</lastBuildDate><atom:link href="https://blog.corentindesfarges.fr/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Un regard sur le passé 👶🏼]]></title><description><![CDATA[<p>Cette magnifique photo prise par ma ch&#xE8;re et tendre est, je trouve, une belle m&#xE9;taphore de cette soir&#xE9;e de septembre, o&#xF9;, au d&#xE9;tour d&apos;un tas de vieux fichiers &#xE9;parpill&#xE9;s sur un (encore plus) vieux disque dur,</p>]]></description><link>https://blog.corentindesfarges.fr/un-regard-sur-le-passe/</link><guid isPermaLink="false">62caf2052107b58c0d83f50b</guid><category><![CDATA[legacy]]></category><category><![CDATA[java]]></category><dc:creator><![CDATA[Corentin Desfarges]]></dc:creator><pubDate>Sat, 10 Oct 2020 22:12:00 GMT</pubDate><media:content url="https://blog.corentindesfarges.fr/content/images/2020/10/P1620445-1.JPG" medium="image"/><content:encoded><![CDATA[<img src="https://blog.corentindesfarges.fr/content/images/2020/10/P1620445-1.JPG" alt="Un regard sur le pass&#xE9; &#x1F476;&#x1F3FC;"><p>Cette magnifique photo prise par ma ch&#xE8;re et tendre est, je trouve, une belle m&#xE9;taphore de cette soir&#xE9;e de septembre, o&#xF9;, au d&#xE9;tour d&apos;un tas de vieux fichiers &#xE9;parpill&#xE9;s sur un (encore plus) vieux disque dur, j&apos;ai retrouv&#xE9; le projet <strong>Hygi</strong>.</p><h2 id="hygi-qu-est-ce-que-c-est">Hygi, qu&apos;est-ce que c&apos;est ?</h2><p>Hygi est ma premi&#xE8;re application personnelle. Enfin, la plus ancienne dont j&apos;ai retrouv&#xE9; trace &#xE0; ce jour. C&apos;est un peu comme pour les dinosaures : on sait dire qu&apos;un fossile est plus &#xE2;g&#xE9; qu&apos;un autre, mais on n&apos;est jamais s&#xFB;r de ne pas en trouver un plus ancien.</p><blockquote>L&apos;objectif ? Suivre et am&#xE9;liorer mon hygi&#xE8;ne de vie !</blockquote><p>C&apos;est donc un petit projet JAVA, d&#xE9;velopp&#xE9; probablement entre 2010 et 2011. Une petite interface reposant sur Swing / AWT, un gros paquet de JButton et JLabel, ainsi qu&apos;une base MySQL embarqu&#xE9;e... wait what ? Oui vous avez bien lu. Alors &quot;embarqu&#xE9;e&quot;, pas tout &#xE0; fait. Dans le projet se trouve l&apos;ex&#xE9;cutable de WampServer, qui est install&#xE9; et lanc&#xE9; par un somptueux <strong>Runtime.getRuntime().exec(...) ... </strong>&#x1F92A; Pourquoi Wamp ? Pour installer MySQL, il faut suivre :D. Et oui, mes lacunes &#xE9;taient grandes. Mais j&apos;&#xE9;tais jeune ! (Mais admettez que &#xE7;a a un peu c&#xF4;t&#xE9; malin)</p><p>C&#xF4;t&#xE9; fonctionnel, un &#xE9;cran d&apos;inscription, un de connexion (et oui ! je g&#xE9;rais des sessions !), et une succession de formulaire pour saisir mes bons et mauvais points quotidiennement : alimentation, sommeil, sociabilisation... tout y est ! Enfin, un &#xE9;cran de r&#xE9;sultat donnant une vue synth&#xE9;tique des donn&#xE9;es saisies. Je suis assez surpris de la qualit&#xE9; du code de l&apos;&#xE9;poque (non je rigole). Mais en tous cas, &#xE7;a tourne encore.</p><p>Il m&apos;aura juste fallu retrouver comment builder et lancer, un projet en Java. &#x1F575;&#x1F3FC;&#x200D;&#x2642;&#xFE0F; C&apos;est loin tout &#xE7;a. Un petit coup de javac, de java, le classpath et hop, voici le r&#xE9;sultat :</p><figure class="kg-card kg-image-card"><img src="https://blog.corentindesfarges.fr/content/images/2020/10/demo_hygi.gif" class="kg-image" alt="Un regard sur le pass&#xE9; &#x1F476;&#x1F3FC;" loading="lazy" width="375" height="483"></figure><p>Allez, bonne nuit les enfants, si vous voulez le .jar, on peut s&apos;arranger &#x1F605;</p><p>Tchao</p>]]></content:encoded></item><item><title><![CDATA[Verbes irréguliers, premiers pas avec Android]]></title><description><![CDATA[<p>C&apos;&#xE9;tait il y a 5 ans. 5 ans ! En 2015, apr&#xE8;s avoir f&#xEA;t&#xE9; mes 4 ans en tant qu&apos;apprenant d&#xE9;veloppeur, j&apos;ai eu l&apos;envie de cr&#xE9;er enfin quelque chose de <u>concret</u>. Fini les</p>]]></description><link>https://blog.corentindesfarges.fr/verbes-irreguliers/</link><guid isPermaLink="false">62caf2052107b58c0d83f510</guid><category><![CDATA[android]]></category><dc:creator><![CDATA[Corentin Desfarges]]></dc:creator><pubDate>Sat, 10 Oct 2020 11:00:00 GMT</pubDate><media:content url="https://blog.corentindesfarges.fr/content/images/2020/10/vieng-3.svg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.corentindesfarges.fr/content/images/2020/10/vieng-3.svg" alt="Verbes irr&#xE9;guliers, premiers pas avec Android"><p>C&apos;&#xE9;tait il y a 5 ans. 5 ans ! En 2015, apr&#xE8;s avoir f&#xEA;t&#xE9; mes 4 ans en tant qu&apos;apprenant d&#xE9;veloppeur, j&apos;ai eu l&apos;envie de cr&#xE9;er enfin quelque chose de <u>concret</u>. Fini les animaleries, byebye les calculatrices. Je voulais pouvoir montrer le fruit de mon travail &#xE0; mes proches, et recevoir autre chose que des regards dubitatifs.</p><p>Ayant &#xE0; l&apos;&#xE9;poque besoin de progresser en anglais, car je devais passer le TOEIC afin de pouvoir valider mon futur dipl&#xF4;me d&apos;ing&#xE9;nieur, je me suis dit que passer des heures &#xE0; travailler avec un fonctionnel dans la langue de Shakespeare serait un exercice b&#xE9;n&#xE9;fique.</p><p>Je me mis alors &#xE0; la r&#xE9;alisation d&apos;une app permettant d&apos;apprendre les verbes irr&#xE9;guliers anglais, &#xE9;ternel &#xE9;pouvantail des coll&#xE9;giens et lyc&#xE9;ens fran&#xE7;ais. Je choisis Android comme terrain de jeu, pour &#xEA;tre mesure de toucher le plus grand nombre.</p><figure class="kg-card kg-image-card"><img src="https://blog.corentindesfarges.fr/content/images/2020/10/vieng-1.png" class="kg-image" alt="Verbes irr&#xE9;guliers, premiers pas avec Android" loading="lazy" width="1924" height="1011" srcset="https://blog.corentindesfarges.fr/content/images/size/w600/2020/10/vieng-1.png 600w, https://blog.corentindesfarges.fr/content/images/size/w1000/2020/10/vieng-1.png 1000w, https://blog.corentindesfarges.fr/content/images/size/w1600/2020/10/vieng-1.png 1600w, https://blog.corentindesfarges.fr/content/images/2020/10/vieng-1.png 1924w" sizes="(min-width: 720px) 720px"></figure><p>Liste de verbes, personnalisation, quiz, entrainement, etc... Nombreuses furent les fonctionnalit&#xE9;s qui, au fil de mon d&#xE9;veloppement, vinrent s&apos;ajouter &#xE0; ce nouveau projet.</p><p>Vint alors le temps du partage. Comment montrer mon application ? &#xC0; qui ? R&#xE9;ponse : &#xC0; qui veut ! &#xC0; tout le monde ! Destination le Play Store. Quelques ajustements plus tard, &quot;<strong>Verbes Irr&#xE9;guliers Anglais</strong>&quot; d&#xE9;barquait sur le store. En quelques mois, <strong>plus de 8.000 personnes</strong> l&apos;install&#xE8;rent et les quelques retours re&#xE7;us furent pour le moins constructifs et permirent d&apos;am&#xE9;liorer encore l&apos;application.</p><p>L&apos;un des retours cependant, me lan&#xE7;a sur la piste d&apos;un r&#xE9;ussite plus grande encore.</p><blockquote>&quot;C&apos;est top, j&apos;aime beaucoup! Mais pourriez-vous faire la m&#xEA;me chose pour les verbes allemands ?</blockquote><p>Ah l&apos;allemand. Petit d&#xE9;fi graphique pour faire rentrer les mots &#xE0; rallonge du langage de nos voisins. Ma r&#xE9;ponse fut positive, et quelques semaines plus tard, une nouvelle application parut sur le Play Store.</p><p>Simple clone du projet, j&apos;ai longuement regrett&#xE9; de ne pas avoir tout fait sur la m&#xEA;me base de code, chaque &#xE9;volution ou correction devant &#xEA;tre copi&#xE9;e coll&#xE9;e d&apos;un projet &#xE0; l&apos;autre. Quelle m&#xE9;connaissance de Git ! (que je n&apos;utilisais pas, posez pas la question).</p><p>Sobrement appel&#xE9;e &quot;<strong>Verbes Irr&#xE9;guliers Allemands</strong>&quot;, celle-ci rencontra un succ&#xE8;s plus fort encore, avec au dernier d&#xE9;compte un total d&#xE9;passant les <strong>29.000 t&#xE9;l&#xE9;chargements</strong> ! Je vous avoue que je ne m&apos;attendais pas &#xE0; cela. Mais la concurrence &#xE9;tait moins forte, et l&apos;appli b&#xE9;n&#xE9;ficiait des am&#xE9;liorations de sa grande s&#x153;ur anglaise.</p><figure class="kg-card kg-image-card"><img src="https://blog.corentindesfarges.fr/content/images/2020/10/demo_viall2.gif" class="kg-image" alt="Verbes irr&#xE9;guliers, premiers pas avec Android" loading="lazy" width="391" height="736"></figure><p>&#xC9;tudiant &#xE0; l&apos;&#xE9;poque, j&apos;avais fait le choix de mettre un peu de publicit&#xE9; dans l&apos;application, et de faire une version pro &#xE0; 1&#x20AC;20 (demandez pas pourquoi .20, je ne sais pas). Un choix qu&apos;aujourd&apos;hui je ne referais probablement pas, mais qui me permis &#xE0; l&apos;&#xE9;poque de me payer le Coca n&#xE9;cessaire &#xE0; ma productivit&#xE9; sur ces projets.</p><p>&#xC0; ce jour, ces deux applications ne sont plus disponibles sur le Store, du fait des mises &#xE0; jour exig&#xE9;es par Google que je n&apos;ai pas eu le temps de faire. Mais elles reviendront, j&apos;y travaille ! :)</p><p>En attendant, vous pouvez t&#xE9;l&#xE9;charger les APK (promis, la pub ne s&apos;affiche plus) :<br>- <a href="https://drive.google.com/file/d/1KD-Sfq9On-fcrxDuAZr0WWaCfNUhg-jX/view?usp=sharing">Verbes Irr&#xE9;guliers Anglais</a><br>- <a href="https://drive.google.com/file/d/16q-9or8NDT91rAgC4aLvR_G0korQ042j/view?usp=sharing">Verbes Irr&#xE9;guliers Allemands</a></p><p>Allez, au boulot, interro surprise dans 1 heure :)</p><p>Corentin</p>]]></content:encoded></item><item><title><![CDATA[GoalLister : Encore une TODO list ?]]></title><description><![CDATA[<p>Cas pratique que l&apos;on retrouve un peu (trop) partout, la &quot;TODO list&quot; n&apos;en est pas moins un parfait sujet pour &#xE9;tayer ses comp&#xE9;tences front-end et back-end, &#xE0; condition d&apos;aller un peu plus loin qu&apos;une simple liste statiques</p>]]></description><link>https://blog.corentindesfarges.fr/goalister-encore-une-todo-list/</link><guid isPermaLink="false">62caf2052107b58c0d83f507</guid><category><![CDATA[nodejs]]></category><category><![CDATA[mongo]]></category><category><![CDATA[mysql]]></category><category><![CDATA[oauth]]></category><category><![CDATA[react]]></category><dc:creator><![CDATA[Corentin Desfarges]]></dc:creator><pubDate>Thu, 08 Oct 2020 15:36:00 GMT</pubDate><media:content url="https://blog.corentindesfarges.fr/content/images/2020/10/goalister-9.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.corentindesfarges.fr/content/images/2020/10/goalister-9.png" alt="GoalLister : Encore une TODO list ?"><p>Cas pratique que l&apos;on retrouve un peu (trop) partout, la &quot;TODO list&quot; n&apos;en est pas moins un parfait sujet pour &#xE9;tayer ses comp&#xE9;tences front-end et back-end, &#xE0; condition d&apos;aller un peu plus loin qu&apos;une simple liste statiques interrogeant une base de donn&#xE9;es mono-table-mono-colonne, on est d&apos;accord.</p><h2 id="back">Back</h2><p>Cette fois, je n&apos;ai pas opt&#xE9; pour la facilit&#xE9; : pas de Sails.js, pas de gros framework tout fait qui fait tout. Je me lance sur une stack Node.js bas&#xE9;e sur express, une petite architecture maison 3-tiers (data / logic / api), et pour bien lier tous les ingr&#xE9;dients, j&apos;utilise la m&#xE9;connue librairie d&apos;injection de d&#xE9;pendances Piquouze (article &#xE0; venir).</p><h3 id="couche-data">Couche &quot;Data&quot;</h3><p>C&#xF4;t&#xE9; base de donn&#xE9;es, j&apos;ai opt&#xE9; pour un duo MySQL / MongoDB, coupl&#xE9;s respectivement avec Sequelize et Mongoose. Le choix d&apos;avoir les deux technologies n&apos;&#xE9;tait clairement pas indispensable, et s&apos;apparente plus &#xE0; une exp&#xE9;rimentation technique qu&apos;&#xE0; un choix strat&#xE9;gique. :)</p><h3 id="couche-logic">Couche &quot;Logic&quot;</h3><p>Toutes les r&#xE8;gles m&#xE9;tiers sont impl&#xE9;ment&#xE9;es dans cette couche applicative, et celle-ci ne communique qu&apos;avec la couche data. Techniquement, rien de tr&#xE8;s sp&#xE9;cial ici : j&apos;utilise quelques librairies qui sont pour moi des classiques : ramda, request-promise, bluebird, etc.</p><h3 id="api">API</h3><p>Comme bien souvent dans mes projets personnels, j&apos;utilise une surcouche maison d&apos;express.js, facilitant son utilisation avec mon syst&#xE8;me d&apos;injection de d&#xE9;pendances. Cette surcouche simplifie grandement la gestion de l&apos;authentification des appels entrants. Elle est encore &#xE0; l&apos;&#xE9;tat exp&#xE9;rimental, mais j&apos;aimerais, &#xE0; terme, la rendre open source.</p><p>Je n&apos;ai pour le moment impl&#xE9;ment&#xE9; que l&apos;authentification oauth basique (login/password/access token) et la connexion depuis un service tiers, ici Google.</p><h2 id="front">Front</h2><p>Parfois, une d&#xE9;mo est plus parlante qu&apos;un grand discours :</p><figure class="kg-card kg-image-card"><img src="https://blog.corentindesfarges.fr/content/images/2020/10/demo_bfront.gif" class="kg-image" alt="GoalLister : Encore une TODO list ?" loading="lazy" width="964" height="437" srcset="https://blog.corentindesfarges.fr/content/images/size/w600/2020/10/demo_bfront.gif 600w, https://blog.corentindesfarges.fr/content/images/2020/10/demo_bfront.gif 964w" sizes="(min-width: 720px) 720px"></figure><p>C&#xF4;t&#xE9; front-end, je me suis bas&#xE9; sur la derni&#xE8;re version en date de React.js, pour profiter de toutes les nouveaut&#xE9;s de la libraire, notamment les hooks.</p><p>J&apos;ai utilis&#xE9; react-beautiful-dnd pour le drag and drop des &#xE9;l&#xE9;ments, et si la mise en place a pris un peu de temps, le r&#xE9;sultat est vraiment bluffant, aussi bien sur PC que sur mobile.</p><h2 id="d-mo">D&#xE9;mo</h2><p>Assez parl&#xE9;, voici le lien pour d&#xE9;couvrir et vous faire une id&#xE9;e par vous-m&#xEA;me : <a href="https://bfront.lab.corentindesfarges.fr/">https://bfront.lab.corentindesfarges.fr/</a></p><h2 id="-volutions">&#xC9;volutions</h2><p>Si pour le moment je n&apos;ai pas une grande bande passante pour travailler sur ce projet, j&apos;ai toutefois identifi&#xE9; les prochaines &#xE9;volutions &#xE0; venir :</p><ul><li>Gestion de listes (bah oui c&apos;est une TODO list), un peu &#xE0; la mani&#xE8;re d&apos;un tableau Kanban</li><li>Ajout des deadlines et rappels automatiques</li><li>Refonte de l&apos;&#xE9;cran &quot;Rapport quotidien&quot;</li></ul><p>Allez, c&apos;est tout pour aujourd&apos;hui !</p><p>&#xC0; tr&#xE8;s bient&#xF4;t</p><p>Corentin</p>]]></content:encoded></item><item><title><![CDATA[Installer mon propre GitLab ✔️]]></title><description><![CDATA[Installer GitLab sur son propre serveur est une idée alléchante, mais qui s'avère être un parcours du combattant pour peu que vous ne soyez pas un habitué et que vous vouliez personnaliser un peu votre installation : mailing, HTTPS, et sous-domaine...]]></description><link>https://blog.corentindesfarges.fr/mon-gitlab/</link><guid isPermaLink="false">62caf2052107b58c0d83f508</guid><category><![CDATA[docker]]></category><category><![CDATA[gitlab]]></category><category><![CDATA[nginx]]></category><dc:creator><![CDATA[Corentin Desfarges]]></dc:creator><pubDate>Wed, 07 Oct 2020 21:35:12 GMT</pubDate><media:content url="https://blog.corentindesfarges.fr/content/images/2020/10/gitlab-logo-white-rgb-1.svg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.corentindesfarges.fr/content/images/2020/10/gitlab-logo-white-rgb-1.svg" alt="Installer mon propre GitLab &#x2714;&#xFE0F;"><p>Installer GitLab sur son propre serveur est une id&#xE9;e all&#xE9;chante, mais qui s&apos;av&#xE8;re &#xEA;tre un parcours du combattant pour peu que vous ne soyez pas un habitu&#xE9; et que vous vouliez personnaliser un peu votre installation : mailing, HTTPS, et sous-domaine...</p><p>Pour ma part, apr&#xE8;s avoir pas mal t&#xE2;tonner sur mon ancien VPS, j&apos;ai fini par tout reprendre de z&#xE9;ro, et ai profit&#xE9; d&apos;un serveur bien mieux dimensionner pour faire tourner convenablement mon instance GitLab, qui, il faut le dire, n&apos;est pas si l&#xE9;g&#xE8;re que &#xE7;a.</p><p>Ici, je vous propose d&apos;installer GitLab via l&apos;image Docker officielle, et de l&apos;exposer sur un de vos sous-domaines, le tout accessible en HTTPS, gr&#xE2;ce &#xE0; nginx et certbot (Let&apos;s Encrypt).</p><h2 id="docker">Docker</h2><p>Commen&#xE7;ons par le fichier docker-compose.yml</p><figure class="kg-card kg-code-card"><pre><code class="language-yaml">version: &apos;3&apos;

services:
    gitlab:
      container_name: gitlab
      image: gitlab/gitlab-ce:latest
      restart: always
      hostname: gitlab.corentindesfarges.fr
      environment:
        GITLAB_OMNIBUS_CONFIG: |
          external_url &apos;https://gitlab.corentindesfarges.fr&apos;
          nginx[&apos;listen_https&apos;] = false
      ports:
        - &apos;30443:443&apos;
        - &apos;3080:80&apos;
      volumes:
        - $GITLAB_HOME/config:/etc/gitlab
        - $GITLAB_HOME/logs:/var/log/gitlab
        - $GITLAB_HOME/data:/var/opt/gitlab</code></pre><figcaption>docker-compose.yml</figcaption></figure><p>Il est important ici de d&#xE9;clarer les volumes &#xE0; utiliser, afin de persister vos donn&#xE9;es et configurations.</p><p>J&apos;ai choisi d&apos;exposer GitLab sur les port 30443 (pour le HTTPS - 443) et 3080 (HTTP - 80) afin d&apos;&#xE9;viter tout conflit, mais vous &#xEA;tes libre de choisir vos propres ports. Il faudra toutefois penser &#xE0; les utiliser lorsque vous ferez le param&#xE9;trage du reverse proxy.</p><p>N&apos;oubliez pas de d&#xE9;finir votre hostname, en sp&#xE9;cifiant le sous-domaine. Idem pour la variable d&apos;environnement GITLAB_OMNIBUS_CONFIG, o&#xF9; il faut d&#xE9;finir external_url. N&apos;oubliez pas ici le protocol cible, &#xE0; savoir https://.</p><p>Enfin, notez que nous allons configurer nginx nous-m&#xEA;me afin de forcer l&apos;acc&#xE8;s en HTTPS, d&apos;o&#xF9; le <em>nginx[&apos;listen_https&apos;] = false.</em></p><p>D&#xE9;finissez la variable d&apos;environnement GITLAB_HOME sur votre serveur, comme suit :</p><pre><code class="language-bash">export GITLAB_HOME=/srv/gitlab</code></pre><p>Enfin, lancez la commande suivante pour d&#xE9;marrer votre instance :</p><pre><code class="language-bash">docker-compose up</code></pre><h2 id="nginx">nginx</h2><p>Il faut maintenant configurer votre reverse proxy, afin de rediriger correctement les appels vers votre instance sur votre sous-domaine.</p><p>Si ce n&apos;est d&#xE9;j&#xE0; fait, commencez par installer nginx :</p><pre><code class="language-bash">sudo apt update
sudo apt install nginx</code></pre><p>Cr&#xE9;ez ensuite le fichier /etc/nginx/conf.d/gitlab.conf, en rempla&#xE7;ant server_name par votre adresse (avec sous-domaine), et v&#xE9;rifiez que le port du proxy_pass correspond bien &#xE0; ce que vous avez d&#xE9;fini dans le docker-compose.yml.</p><figure class="kg-card kg-code-card"><pre><code># bloc de rediction http =&gt; https
server {
  listen 80;
  server_name gitlab.corentindesfarges.fr;
  return 301 https://$server_name$request_uri;
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name gitlab.corentindesfarges.fr;

  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header HOST $http_host;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass http://127.0.0.1:30443;
    proxy_redirect off;
  }
}</code></pre><figcaption>/etc/nginx/conf.d/gitlab.conf</figcaption></figure><p>Enregistrez et relancez nginx :</p><pre><code class="language-bash">sudo systemctl restart nginx</code></pre><h2 id="certbot">certbot</h2><p>Comme d&apos;habitude, on l&apos;installe si on ne l&apos;a pas d&#xE9;j&#xE0; :</p><pre><code class="language-bash">sudo apt update
sudo apt install certbot</code></pre><p>Et puis on le lance, rien de plus simple ici :</p><pre><code class="language-bash">sudo certbot --nginx</code></pre><p>L&apos;outil va automatiquement scanner vos configuration nginx, et vous proposera de choisir les domaines pour lesquels vous souhaitez obtenir un certificat SSL. Si vous avez plusieurs sous-domaines, pour &#xE9;viter de g&#xE9;rer trop de certificat, n&apos;h&#xE9;sitez pas &#xE0; les res&#xE9;lectionner &#xE0; chaque fois que vous lancerez la commande et choisissez (E)xpand lorsque ce choix vous sera sugg&#xE9;r&#xE9;.</p><p>Certbot vous proposera par la suite de rediriger vos appels HTTP vers HTTPS. N&apos;acceptez pas, vous l&apos;avez d&#xE9;j&#xE0; fait dans votre gitlab.conf !</p><p>La suite ? Rendez-vous dans votre navigateur !</p>]]></content:encoded></item><item><title><![CDATA[WoloLan : Ma première app depuis longtemps, comme un retour aux sources 🕰️]]></title><description><![CDATA[<p>D&#xE9;veloppeur Android autodidacte &#xE0; mes d&#xE9;buts, j&apos;ai toujours eu une affinit&#xE9; pour la cr&#xE9;ation d&apos;application pour cette plateforme ; pouvoir me balader avec mes r&#xE9;alisations dans ma poche et les montrer &#xE0; qui veut (et parfois qui ne</p>]]></description><link>https://blog.corentindesfarges.fr/wololan/</link><guid isPermaLink="false">62caf2052107b58c0d83f506</guid><category><![CDATA[react-native]]></category><category><![CDATA[kotlin]]></category><category><![CDATA[android]]></category><category><![CDATA[react]]></category><dc:creator><![CDATA[Corentin Desfarges]]></dc:creator><pubDate>Wed, 07 Oct 2020 18:08:00 GMT</pubDate><media:content url="https://blog.corentindesfarges.fr/content/images/2020/10/wologo.svg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.corentindesfarges.fr/content/images/2020/10/wologo.svg" alt="WoloLan : Ma premi&#xE8;re app depuis longtemps, comme un retour aux sources &#x1F570;&#xFE0F;"><p>D&#xE9;veloppeur Android autodidacte &#xE0; mes d&#xE9;buts, j&apos;ai toujours eu une affinit&#xE9; pour la cr&#xE9;ation d&apos;application pour cette plateforme ; pouvoir me balader avec mes r&#xE9;alisations dans ma poche et les montrer &#xE0; qui veut (et parfois qui ne veut pas :p) a un c&#xF4;t&#xE9; tr&#xE8;s satisfaisant, et ma courbe d&apos;apprentissage fut plut&#xF4;t rapide.</p><p>En 2016, j&apos;ai eu la chance de d&#xE9;couvrir React Native dans le cadre de mon travail, et de mener un projet from scratch avec une petite &#xE9;quipe et une expression du besoin particuli&#xE8;rement bien cadr&#xE9;e. Cela m&apos;a permis de faire mes armes sur cette technologie qui aujourd&apos;hui encore, est un de mes terrains de jeu pr&#xE9;f&#xE9;r&#xE9; pour mes POC.</p><p>L&apos;id&#xE9;e de WoloLan est tr&#xE8;s simple : pouvoir allumer (ou au moins sortir de veille) mon PC, qui me sert &#xE9;galement de serveur multim&#xE9;dia, depuis mon canap&#xE9;. Pourquoi ? Parce que bien souvent, ce dernier (le PC, pas le canap&#xE9;) se met en veille entre deux &#xE9;pisodes de s&#xE9;rie, et m&apos;oblige &#xE0; traverser tout l&apos;appartement pour le relancer. Alors oui, c&apos;est vrai, &#xE7;a permet d&apos;&#xE9;viter de m&apos;enfoncer de mani&#xE8;re permanente dans mon canap. Mais ce n&apos;est pas une raison. Je pourrais &#xE9;galement r&#xE9;gl&#xE9; mon PC pour &#xE9;viter ces mise en veille intempestive, mais le challenge est moins int&#xE9;ressant.</p><p>L&apos;interface est extr&#xEA;mement simple, et permet de saisir l&apos;adresse MAC de la machine &#xE0; lancer. On peut &#xE9;galement saisir l&apos;adresse IP, mais cela ne fonctionnera que si le PC est allum&#xE9;. L&apos;int&#xE9;r&#xEA;t ? Dans ce cas de figure, l&apos;adresse MAC sera r&#xE9;cup&#xE9;r&#xE9;e et l&apos;utilisateur pourra la r&#xE9;utiliser ult&#xE9;rieurement. Il est &#xE9;galement possible de sauvegarder une configuration (MAC + IP) afin de gagner un peu de temps.</p><p>WoloLan, est donc une appli Android bas&#xE9;e sur React Native. Le r&#xE9;veil des PC distants se fait via l&apos;envoi de &quot;Magic Packet&quot;. React Native n&apos;&#xE9;tant pas en mesure d&apos;envoyer ses paquets lui-m&#xEA;me, j&apos;ai &#xE9;galement d&#xE9;velopp&#xE9; un module en Kotlin (premi&#xE8;re fois!), appel&#xE9; par React pour faire le travail.</p><p>J&apos;ai ressortie mes notes de cours de r&#xE9;seau de DUT pour utiliser Wireshark - qui soit dit en passant est bien moins compliqu&#xE9; que dans mes souvenirs - et scruter le r&#xE9;seau &#xE0; la recherche de mes Magic Packets.</p><p>Et voil&#xE0; ! C&apos;est tout ! Vous pouvez r&#xE9;cup&#xE9;rer depuis le Store <a href="https://play.google.com/store/apps/details?id=fr.corentindesfarges.wololan">https://play.google.com/store/apps/details?id=fr.corentindesfarges.wololan</a> :)</p><p>Pour que &#xE7;a fonctionne, veillez bien &#xE0; ce que le r&#xE9;veil par ce protocole r&#xE9;seau soit activ&#xE9; dans votre BIOS. ;)</p>]]></content:encoded></item><item><title><![CDATA[ComptAct : Régler mes comptes avec React 🤝]]></title><description><![CDATA[The Ghost editor post settings menu has everything you need to fully optimise and distribute your content effectively.]]></description><link>https://blog.corentindesfarges.fr/comptact-react/</link><guid isPermaLink="false">62caf2052107b58c0d83f503</guid><category><![CDATA[react]]></category><dc:creator><![CDATA[Corentin Desfarges]]></dc:creator><pubDate>Tue, 04 Aug 2020 19:55:28 GMT</pubDate><media:content url="https://blog.corentindesfarges.fr/content/images/2020/10/cco-2.png" medium="image"/><content:encoded><![CDATA[<h2 id="il-tait-temps">Il &#xE9;tait temps</h2><img src="https://blog.corentindesfarges.fr/content/images/2020/10/cco-2.png" alt="ComptAct : R&#xE9;gler mes comptes avec React &#x1F91D;"><p>Des ann&#xE9;es apr&#xE8;s la premi&#xE8;re version de mon application de gestion de la compta destin&#xE9;e &#xE0; ma tr&#xE8;s ch&#xE8;re maman, j&apos;ai d&#xE9;cid&#xE9; de faire quelque chose d&apos;un tout petit peu mieux.</p><p>Un grand coup de refresh dans un projet d&#xE9;but&#xE9; en 2012 en JAVA, r&#xE9;&#xE9;crit en 2013 en C# puis en C++/Qt fin 2014. Je me suis pas mal cherch&#xE9;, au fil de mes d&#xE9;couvertes et de mes amours technologiques. C&#xF4;t&#xE9; stockage des donn&#xE9;es, je suis &#xE9;galement parti de loin, en passant par le tristement c&#xE9;l&#xE8;bre fichier plat (j&apos;&#xE9;tais jeune!), SQLite, MySQL ou encore MongoDB.</p><h2 id="2019-la-react-ion">2019, la React-ion</h2><p>Il est parfois difficile de se dire : allez hop, on refait tout. Certains d&#xE9;veloppeurs adorent &#xE7;a, d&apos;autres fuient ces situations.</p><p>Mais quand votre client (votre maman de surcro&#xEE;t) vous explique qu&apos;elle n&apos;utilise plus votre app parce qu&apos;elle met 6 minutes 30 &#xE0; d&#xE9;marrer (quand elle ne crash pas), difficile de lui expliquer que c&apos;est normal, que c&apos;est parce qu&apos;elle a &#xE9;t&#xE9; compil&#xE9;e en mode debug sous Windows XP, que SQLite 3 n&apos;est pas forc&#xE9;ment hyper opti, et que les images sont en bitmap et p&#xE8;sent 50 Mo. Il n&apos;&#xE9;tait pas non plus temps d&apos;essayer de lui vendre un nouveau PC, au risque de m&apos;entendre dire que ses cahiers de compte faits main ne co&#xFB;taient rien, eux.</p><p>J&apos;ai donc pr&#xE9;f&#xE9;r&#xE9; ne pas faire de diagnostic plus pouss&#xE9;, et en ai profit&#xE9; pour me lancer sur une techno que je connaissais bien, mais avec laquelle je manquais un peu d&apos;occasion de pratiquer : React.js</p><p>Quelques grammes de <a href="https://redux.js.org/">redux</a>, un bon filet de <a href="https://material-ui.com/">material-ui</a>, et une pinc&#xE9;e de <a href="https://react-select.com/">react-select</a> plus tard, et ComptAct version 2019 sortait de terre.</p><p>C&#xF4;t&#xE9; serveur, j&apos;ai opt&#xE9; pour un petit projet bas&#xE9; sur Sails.js, en impl&#xE9;mentant une authentification oauth2 basique.</p><h2 id="d-mo">D&#xE9;mo</h2><p>L&apos;app est utilis&#xE9;e &#xE0; ce jour par ma cliente pr&#xE9;f&#xE9;r&#xE9;e, mais pour plus de simplicit&#xE9;, le back et le front tournent sur un petit Raspberry Pi sur son r&#xE9;seau local.</p><p>J&apos;ai &#xE9;galement publi&#xE9; une version de d&#xE9;mo ici : <a href="https://demo.corentindesfarges.fr/login">https://demo.corentindesfarges.fr</a></p><p>Je pr&#xE9;f&#xE8;re vous pr&#xE9;venir tout de suite : tout n&apos;est pas parfait, et j&apos;ai &#xE9;t&#xE9; contraint de mettre temporairement de c&#xF4;t&#xE9; le d&#xE9;veloppement de ce projet, l&apos;essentiel &#xE9;tant qu&apos;il soit suffisamment fonctionnel et agr&#xE9;able &#xE0; utiliser.</p><p>Pas de responsive design, un code un peu vieillissant par rapport aux derni&#xE8;res features de React, et pour la version de d&#xE9;mo : la base de donn&#xE9;es est r&#xE9;initialis&#xE9;e toutes les 5 minutes, car l&apos;application ne tourne pas sur un tr&#xE8;s gros serveur.</p><p>Voili voilou, j&apos;esp&#xE8;re que vous le trouverez quand m&#xEA;me pas trop mal.</p><p>Corentin</p>]]></content:encoded></item><item><title><![CDATA[nginx : Augmenter la taille max des fichiers à l'upload]]></title><description><![CDATA[<p>En installant ce blog, et en voulant uploader un th&#xE8;me (un zip de 1.5 Mo), je me suis retrouv&#xE9; confront&#xE9; &#xE0; cette erreur :</p><blockquote>The file you uploaded was larger than the maximum file size your server allows.</blockquote><p>Rassurant d&apos;un point de vue s&</p>]]></description><link>https://blog.corentindesfarges.fr/nginx-client_max_body_size/</link><guid isPermaLink="false">62caf2052107b58c0d83f509</guid><category><![CDATA[nginx]]></category><dc:creator><![CDATA[Corentin Desfarges]]></dc:creator><pubDate>Mon, 03 Aug 2020 11:55:00 GMT</pubDate><media:content url="https://blog.corentindesfarges.fr/content/images/2020/10/Nginx_logo.svg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.corentindesfarges.fr/content/images/2020/10/Nginx_logo.svg" alt="nginx : Augmenter la taille max des fichiers &#xE0; l&apos;upload"><p>En installant ce blog, et en voulant uploader un th&#xE8;me (un zip de 1.5 Mo), je me suis retrouv&#xE9; confront&#xE9; &#xE0; cette erreur :</p><blockquote>The file you uploaded was larger than the maximum file size your server allows.</blockquote><p>Rassurant d&apos;un point de vue s&#xE9;curit&#xE9;, mais pas tr&#xE8;s pratique en l&apos;occurrence.</p><p>Pour y rem&#xE9;dier, rien de bien complexe : c&apos;est du c&#xF4;t&#xE9; de nginx que &#xE7;a se passe. J&apos;ai choisi de ne faire la configuration que pour mon blog, on verra &#xE0; l&apos;avenir si d&apos;autres applicatifs en ont besoin.</p><p>Le fix ? Une ligne, &#xE0; rajouter dans le bloc <strong>server</strong> ou <strong>location</strong> du site en question :</p><figure class="kg-card kg-code-card"><pre><code>server {
  ...
  client_max_body_size 2m;
}</code></pre><figcaption>/etc/nginx/conf.d/monblog.conf</figcaption></figure><p>On red&#xE9;marre nginx et c&apos;est parti !</p><figure class="kg-card kg-code-card"><pre><code>sudo systemctl restart nginx</code></pre><figcaption>CLI Debian</figcaption></figure><p>Vous pr&#xE9;f&#xE9;rez tout simplement d&#xE9;sactiver la limite ? Remplacez la valeur de la directive par 0 (z&#xE9;ro, sans unit&#xE9;). C&apos;est tout.</p><p>Le lien vers la doc pour les plus curieux : <a href="https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size">https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size</a></p><h3 id="post-mortem">Post mortem</h3><p>En configurant un nouveau site r&#xE9;cemment, j&apos;ai rencontr&#xE9; le probl&#xE8;me suivant : la directive <em>client_max_body_size</em> n&apos;&#xE9;tait pas prise en compte, alors que je n&apos;avais fait qu&apos;un simple copi&#xE9; / coll&#xE9; de la ligne depuis cet article.</p><p>Apr&#xE8;s de longues minutes d&apos;incompr&#xE9;hension la plus totale, apr&#xE8;s m&apos;&#xEA;tre entendu dire &#xE0; maintes reprises &quot;<em>essaie encore une fois de red&#xE9;marrer nginx, on sait jamais</em>&quot;, j&apos;ai remarqu&#xE9; que la ligne pr&#xE9;c&#xE9;dant ma directive ne finissait pas par un point-virgule... Pas d&apos;erreur lors de red&#xE9;marrage de nginx, tout semblait pourtant bien fonctionner. Mais non. J&apos;ai donc termin&#xE9; cette ligne comme il se doit, et tout est rentr&#xE9; dans l&apos;ordre (apr&#xE8;s un red&#xE9;marrage de nginx, oui!).</p><p>Morale de l&apos;histoire : Bien souvent, l&apos;erreur n&apos;est pas l&#xE0; o&#xF9; vous la cherchez, mais elle n&apos;est g&#xE9;n&#xE9;ralement pas tr&#xE8;s loin.</p>]]></content:encoded></item><item><title><![CDATA[Installer Elasticsearch et Kibana ✔️]]></title><description><![CDATA[Installer Elasticsearch et Kibana en quelques minutes, c'est possible. Merci qui ? Docker ! <3]]></description><link>https://blog.corentindesfarges.fr/installer-elasticsearch-kibana-en-docker/</link><guid isPermaLink="false">62caf2052107b58c0d83f505</guid><category><![CDATA[docker]]></category><category><![CDATA[elastic]]></category><category><![CDATA[kibana]]></category><dc:creator><![CDATA[Corentin Desfarges]]></dc:creator><pubDate>Mon, 20 Jul 2020 23:35:00 GMT</pubDate><media:content url="https://blog.corentindesfarges.fr/content/images/2020/10/logo-elastic-horizontal-color-reverse-4.svg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.corentindesfarges.fr/content/images/2020/10/logo-elastic-horizontal-color-reverse-4.svg" alt="Installer Elasticsearch et Kibana &#x2714;&#xFE0F;"><p>Cela fait maintenant quelques mois que j&apos;avais envie d&apos;essayer d&apos;installer un petit Elastic sur mon serveur, pour jouer avec sans me soucier de casser des donn&#xE9;es.</p><p>Fin 2018 je m&apos;&#xE9;tais pris au jeu de faire une installation &quot;classique&quot; sur mon VPS, et s&apos;il n&apos;a pas pris feu, c&apos;est parce que ce n&apos;est techniquement pas possible. Cette ann&#xE9;e, avec un mod&#xE8;le un peu mieux dimensionn&#xE9;, je me suis lanc&#xE9;, et au lieu de plomber ce nouveau venu &#xE0; grand coup d&apos;apt-get, j&apos;ai choisi de passer par Docker.</p><h2 id="docker-compose">docker-compose</h2><p>Pour d&#xE9;buter, j&apos;ai choisi d&apos;utiliser docker-compose, plus pratique que la cli pour des lignes de 14km de long.</p><figure class="kg-card kg-code-card"><pre><code class="language-yaml">version: &apos;2&apos;
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.8.1
    container_name: elasticsearch
    environment:
      - xpack.security.enabled=true
      - discovery.type=single-node
    volumes:
      - ./elasticsearch/data:/usr/share/elasticsearch/data
    networks:
      - elk-net
    ports:
      - &quot;9200:9200&quot;
      - &quot;9300:9300&quot;
  kibana:
    image: docker.elastic.co/kibana/kibana:7.8.1
    container_name: kibana
    environment:
      - xpack.security.enabled=true
      - ELASTICSEARCH_USERNAME=kibana
      - ELASTICSEARCH_PASSWORD=ahah
    networks:
      - elk-net
    ports:
      - &quot;5601:5601&quot;
    depends_on:
      - elasticsearch

networks:
  elk-net:
    driver: bridge</code></pre><figcaption>docker-compose.yml</figcaption></figure><h3 id="service-elasticsearch">Service elasticsearch</h3><p>Les donn&#xE9;es d&apos;Elastic sont partag&#xE9;es les data avec mon r&#xE9;pertoire ./elasticsearch/data (relatif au chemin depuis lequel je lance ma commande).</p><p>L&apos;authentification est activ&#xE9;e (il faudra donc configurer Kibana en cons&#xE9;quence).</p><p>Le porte 9200 est ouvert, ce qui me permettra d&apos;acc&#xE9;der &#xE0; mon instance (via le port 9200 &#xE9;galement).</p><p>Le service utilise le network <em>elk-net</em>, ce qui lui permettra d&apos;&#xEA;tre appel&#xE9; par Kibana.</p><h3 id="service-kibana">Service kibana</h3><p>Le service est configur&#xE9; de mani&#xE8;re &#xE0; attendre que Elastic soit lanc&#xE9; (propri&#xE9;t&#xE9; <em>depends_on</em>) et partage le m&#xEA;me r&#xE9;seau, <em>elk-net</em>, qui est d&#xE9;fini plus bas.</p><p>Vous l&apos;aurez devin&#xE9;, le pr&#xE9;sent mot de passe ne fonctionnera pas, et vous ne pouvez pas le d&#xE9;finir par vous-m&#xEA;me automagiquement. Pour ce faire, une fois le fichier ci-dessus compl&#xE9;t&#xE9; (vous pouvez laisser le mauvais mot de passe, ou retirer la ligne), lancez la commande suivantes :</p><pre><code class="language-bash">mkdir -p $PWD/elasticsearch/data
chmod 777 -R $PWD/elasticsearch/data

docker-compose up --detach elasticsearch
docker logs -t -f elasticsearch</code></pre><p>Assurez-vous de voir appara&#xEE;tre dans la console la ligne <strong>&quot;Active license is now [BASIC]; Security is enabled&quot;</strong>, puis quittez le log (CTRL+C).</p><pre><code class="language-bash">docker exec elasticsearch bin/elasticsearch-setup-passwords auto -b</code></pre><p>Notez pr&#xE9;cieusement les mots de passe affich&#xE9;s &#xE0; l&apos;&#xE9;cran. Le premier qui va nous &#xEA;tre utile sera <strong>PASSWORD kibana.</strong> Mettez de c&#xF4;t&#xE9; le <strong>PASSWORD elastic</strong> pour la suite. Il vous servira &#xE0; vous connecter &#xE0; l&apos;interface web Kibana.</p><p>Modifiez votre docker-compose comme suit :</p><pre><code class="language-yaml">  kibana:
    ...
    environment:
      ...
      - ELASTICSEARCH_PASSWORD=VOTRE_PASSWORD_KIBANA</code></pre><p>Vous pouvez d&#xE9;sormais lancer le service Kibana :</p><pre><code class="language-bash">docker-compose up --detach kibana</code></pre><p>Au bout de quelques minutes, vous aurez acc&#xE8;s &#xE0; votre interface Kibana (si vous avez configur&#xE9; correctement votre reverse proxy (sinon c&apos;est par l&#xE0; [TODO]).</p><p>Pour vous connecter, utilisez le username <strong>elastic</strong> et le mot de passe <strong>PASSWORD elastic.</strong></p><p>Et voila !</p><h2 id="sources">Sources</h2><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.elastic.co/guide/en/kibana/current/using-kibana-with-security.html#:~:text=Verify%20that%20you%20can%20log,has%20been%20assigned%20Kibana%20privileges."><div class="kg-bookmark-content"><div class="kg-bookmark-title">Configure security in Kibana | Kibana Guide [7.8] | Elastic</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://www.elastic.co/android-chrome-192x192.png" alt="Installer Elasticsearch et Kibana &#x2714;&#xFE0F;"><span class="kg-bookmark-author">Elastic</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://www.elastic.co/static/images/elastic-logo-200.png" alt="Installer Elasticsearch et Kibana &#x2714;&#xFE0F;"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.elastic.co/guide/en/elasticsearch/reference/current/configuring-tls-docker.html"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Encrypting communications in an Elasticsearch Docker Container | Elasticsearch Reference [7.8] | Elastic</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://www.elastic.co/android-chrome-192x192.png" alt="Installer Elasticsearch et Kibana &#x2714;&#xFE0F;"><span class="kg-bookmark-author">Elastic</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://www.elastic.co/static/images/elastic-logo-200.png" alt="Installer Elasticsearch et Kibana &#x2714;&#xFE0F;"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://discuss.elastic.co/t/how-to-set-passwords-for-built-in-users-with-docker-compose-setup/198096"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How to set passwords for built-in users with docker-compose setup</div><div class="kg-bookmark-description">Hey there, I am running an Elasticsearch 7.3.0 cluster with three nodes (on three different machines) via a docker-compose setup. Here is my elasticsearch and kibana service defined in docker-compose.yml: services: es-mdi: container_name: lxelk01-es-mdi image: elasticsearch:7.3.0 por&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://www.elastic.co/android-icon-192x192.png" alt="Installer Elasticsearch et Kibana &#x2714;&#xFE0F;"><span class="kg-bookmark-author">Discuss the Elastic Stack</span><span class="kg-bookmark-publisher">apt-get_install_skil</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://aws1.discourse-cdn.com/elastic/optimized/3X/4/1/41be36a8c4e367bd49458aa714d2d18a5d195735_2_1024x330.png" alt="Installer Elasticsearch et Kibana &#x2714;&#xFE0F;"></div></a></figure>]]></content:encoded></item></channel></rss>