<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Yosko.net</title>
<link>https://dev.yosko.net/blog/</link>
<atom:link href="https://dev.yosko.net/blog/index.xml" rel="self" type="application/rss+xml"/>
<description>Site personnel</description>
<generator>quarto-1.9.37</generator>
<lastBuildDate>Thu, 11 Dec 2025 12:40:00 GMT</lastBuildDate>
<item>
  <title>Pi-hole comme serveur DNS</title>
  <link>https://dev.yosko.net/blog/2025/pi-hole.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/linux-card.png" class="card img-fluid"></p>
<p>J’entend depuis un moment parler de <a href="https://pi-hole.net/">Pi-hole</a> – un petit serveur DNS (voir DHCP) qui a vocation à bloquer la pub au niveau de tout un réseau. Et le mois dernier, <a href="https://sebsauvage.net/links/?CPJSAA">sebsauvage a sauté le pas</a>. Bref, ça éveillait ma curiosité</p>
<p>Hier, j’ai dû resynchroniser de zéro un ordi avec mon Nextcloud (hébergé chez moi). Mais en passant par son nom de domaine, ça tapait sur l’IP <em>publique</em> (donc celle de ma box), et je me retrouvais avec un débit bridé à 580 Ko/s.</p>
<p>Frustré, j’ai débloqué ça en ajoutant une entrée à mon <code>/etc/hosts</code> pour que le domaine du Nextcloud soit lié à son IP <em>privée</em>. Là, je montais à 10 Mo/s. Mieux !</p>
<p>J’ai alors réalisé qu’il était dommage de faire ça pour un seul ordi, et qu’il me faudrait un DNS local permettant entre autre d’éviter l’IP publique quand l’IP privée suffisait. C’était le bon moment pour un Pi-hole.</p>
<section id="config-docker-simple" class="level2">
<h2 class="anchored" data-anchor-id="config-docker-simple">Config Docker simple</h2>
<p>Plutôt que de brancher une nouvelle machine (même petite comme un Raspberry), j’ai préféré intégrer ça à mon serveur hébergeant la plupart de mes services sous Docker.</p>
<p>À ce sujet, la <a href="https://docs.pi-hole.net/docker/">doc de Pi-hole fournit</a> un <code>docker-compose.yml</code> de base déjà bien fonctionnel. Je n’ai eu qu’à commenter les lignes qui ne me concernent pas et à adapter les ports de l’interface web (mais en gardant le port 53 pour le DNS) et le mot de passe de l’interface web.</p>
</section>
<section id="config-via-linterface-dadmin" class="level2">
<h2 class="anchored" data-anchor-id="config-via-linterface-dadmin">Config via l’interface d’admin</h2>
<p>Une fois lancé, l’accès à l’interface d’admin m’a juste servi à configurer : - le serveur DNS <em>upstream</em> (qui sert de source à ce serveur Pi-hole) : j’ai choisis dnsforge.de - ajouter mes sous-domaine de mon serveur local en tant que “<em>Private DNS hostname</em>” - ajouter la <a href="https://sebsauvage.net/wiki/doku.php?id=dns-blocklist">liste de blocage fournie par Seb Sauvage</a> comme liste source pour les blocages effectués par le Pi-hole</p>
</section>
<section id="config-de-la-box" class="level2">
<h2 class="anchored" data-anchor-id="config-de-la-box">Config de la box</h2>
<p>Il ne me restait plus qu’à indiquer à ma box de ne plus fournir via DHCP son propre serveur DNS en premier, mais de pointer sur l’IP locale du serveur hébergeant le Pi-hole.</p>
<p>J’ai tout de même gardé le DNS de la box en DNS secondaire au cas où mon serveur serait indisponible.</p>
<blockquote class="blockquote">
<p>“<em>Keep blocking ads and surf on!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>linux</category>
  <category>réseau</category>
  <guid>https://dev.yosko.net/blog/2025/pi-hole.html</guid>
  <pubDate>Thu, 11 Dec 2025 12:40:00 GMT</pubDate>
</item>
<item>
  <title>PHP : routage avec callable</title>
  <link>https://dev.yosko.net/blog/2025/php-callable-route.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/php-card.png" class="card img-fluid"></p>
<p>Je voulais expérimenter avec le routage de mon <em>framework</em> perso <a href="https://github.com/yosko/watamelo">Watamelo</a> en faisant en sorte que l’action à exécuter de chaque route soit définie sous forme de <em>callable</em> dès le départ.</p>
<p>Jusqu’ici, je transmettais deux arguments (<em>string</em>) : la classe et la méthode à exécuter.</p>
<p>Mais comment rendre cela plus générique pour désigner n’importe quelle fonction/méthode exécutable ?</p>
<section id="callable-rappel" class="level2">
<h2 class="anchored" data-anchor-id="callable-rappel"><em>callable</em> : rappel</h2>
<p>Pour rappel, il existe 4 cas principaux de <em>callable</em></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// fonction classique</span></span>
<span id="cb1-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> action1() {</span>
<span id="cb1-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'résultat 1'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-4">}</span>
<span id="cb1-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// callable définie par chaîne de caractère</span></span>
<span id="cb1-6"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$callback1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action1'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-7"></span>
<span id="cb1-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// méthodes statique et non statique</span></span>
<span id="cb1-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Controller {</span>
<span id="cb1-10">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">public</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">static</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> action2()</span>
<span id="cb1-11">    {</span>
<span id="cb1-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'résultat 2'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-13">    }</span>
<span id="cb1-14"></span>
<span id="cb1-15">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">public</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> action3()</span>
<span id="cb1-16">    {</span>
<span id="cb1-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'résultat 3'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-18">    }</span>
<span id="cb1-19">}</span>
<span id="cb1-20"></span>
<span id="cb1-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// méthode statique : tableau avec nom de classe et nom de méthode</span></span>
<span id="cb1-22"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$callback2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [Controller::<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action2'</span>]<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-23"></span>
<span id="cb1-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// méthode non statique : tableau avec instance de classe et nom de méthode</span></span>
<span id="cb1-25"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$callback3</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> Controller()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action3'</span>]<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-26"></span>
<span id="cb1-27"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// fonction fléchée (anonyme)</span></span>
<span id="cb1-28"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$callback4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">fn</span>() =&gt; <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'résultat 4'</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>Donc un <em>callable</em> peut être une simple chaîne (fonction classique), un tableau (méthode de classe, statique ou non) ou directement une fonction fléchée (fonction anonyme).</p>
</section>
<section id="router-avec-callable-blocage" class="level2">
<h2 class="anchored" data-anchor-id="router-avec-callable-blocage">Router avec <em>callable</em> : blocage</h2>
<p>Mon intention était de transmettre un argument <em>callable</em> au constructeur de la route et que celle-ci se débrouille plus tard pour le faire exécuter sans qu’on ait à se soucier du type de <em>callable</em> dont il s’agit.</p>
<p>Ma première approche naïve a rapidement échoué :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Route {</span>
<span id="cb2-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">public</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">callable</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$action</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-3"></span>
<span id="cb2-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">public</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">__construct</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">callable</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$action</span>)</span>
<span id="cb2-5">    {</span>
<span id="cb2-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$this</span>-&gt;action <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$action</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-7">    }</span>
<span id="cb2-8"></span>
<span id="cb2-9">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">public</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> render()</span>
<span id="cb2-10">    {</span>
<span id="cb2-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$this</span>-&gt;action)()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-12">    }</span>
<span id="cb2-13">}</span></code></pre></div></div>
<p>Mais ça donne l’erreur <code>Property cannot have type callable</code>. Une recherche rapide m’amène rapidement sur un <a href="https://stackoverflow.com/a/57935949/863323">stackoverflow</a> puis <a href="https://wiki.php.net/rfc/typed_properties_v2#callable_type">php.net</a>.</p>
<p>Conclusion : des soucis de portée interdisent la mémorisation de <em>callable</em> dans un attribut de classe. Ils suggèrent à la place d’encapsuler ça dans une <em>Closure</em> pour rendre cela indépendant de toute notion de portée.</p>
</section>
<section id="router-avec-closure-et-ça-marche" class="level2">
<h2 class="anchored" data-anchor-id="router-avec-closure-et-ça-marche">Router avec <em>Closure</em> : et ça marche !</h2>
<p>On remplace le type de l’attribut par <em>Closure</em>, mais on garde toujours un <em>callable</em> en argument du constructeur. Il suffit juste de convertir ce <em>callable</em> en <em>Closure</em> avant de le mémoriser :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Route {</span>
<span id="cb3-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">public</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Closure</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$action</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb3-3"></span>
<span id="cb3-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">public</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">__construct</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">callable</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$action</span>)</span>
<span id="cb3-5">    {</span>
<span id="cb3-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$this</span>-&gt;action <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Closure</span>::fromCallable(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$action</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb3-7">    }</span>
<span id="cb3-8"></span>
<span id="cb3-9">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">public</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> render()</span>
<span id="cb3-10">    {</span>
<span id="cb3-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$this</span>-&gt;action)()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb3-12">    }</span>
<span id="cb3-13">}</span></code></pre></div></div>
<p>J’ai galéré à faire fonctionner ça au départ, puisque les conseils de la doc sont très généraux et ne donnent aucun exemple complet pour gérer ce cas. Au début, à la place de <code>fromCallable</code>, j’écrivais un truc du genre <code>$this-&gt;action = $action(...);</code>, qui semblait marcher, mais je ne suis pas sûr de ce que ça impliquait.</p>
<p>Et puis j’ai tenté l’exécution sous forme de <code>$this-&gt;action-&gt;call($this)</code>, mais la transimssion d’un objet à ce moment-là ne fonctionnait pas (clairement, je ne maîtrise pas encore les <em>Closure</em>).</p>
<p>Et au final, ça marche avec nos 4 différents cas :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb4-1"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$route1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> Route(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action1'</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var_dump</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$route1</span>-&gt;render())<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-3"></span>
<span id="cb4-4"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$route2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> Route([Controller::<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action2'</span>])<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var_dump</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$route2</span>-&gt;render())<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-6"></span>
<span id="cb4-7"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$ctrl</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> Controller()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-8"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$route3</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> Route([<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$ctrl</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action3'</span>])<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var_dump</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$route3</span>-&gt;render())<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-10"></span>
<span id="cb4-11"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$route4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> Route(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">fn</span>() =&gt; <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'action4'</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-12"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">var_dump</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$route4</span>-&gt;render())<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Je suis assez content du résultat, c’est élégant et polyvalent.</p>
<p>Cependant, quid des risques de copies d’éléments contextuels à la création de <em>Closure</em> ? Je soupçonne que même dans le cas de l’instance de classe, c’est juste une référence qui est transmise, donc <em>a priori</em> c’est OK. Seul l’usage de variables globales dans ces fonctions/méthodes seraient un souci (mais comme c’est à proscrire en général…).</p>
<p>Je n’ai finalement pas retenu cette jolie solution malgré tout puisque je tenais à éviter d’instancier tous les contrôleurs lors des définitions de route (puisqu’un seul suffira). Une solution à base de <em>lazy loading</em> serait plus pertinente, mais incompatible avec les <em>callable</em> par nature (puisqu’il faut transmettre le nom de classe plutôt qu’une instance, ce qui correspond à un usage de méthode statique).</p>
<p>Mais je me suis dit que ça serait sympa de partager le résultat de cette petite expérience.</p>
<blockquote class="blockquote">
<p>“<em>Keep routing and call on!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>php</category>
  <guid>https://dev.yosko.net/blog/2025/php-callable-route.html</guid>
  <pubDate>Thu, 03 Apr 2025 20:30:00 GMT</pubDate>
</item>
<item>
  <title>Sauvegarde de session Firefox </title>
  <link>https://dev.yosko.net/blog/2025/firefox-sessionstore-rsnapshot.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/linux-card.png" class="card img-fluid"></p>
<p>Cela fait déjà plusieurs fois que Firefox me fait le coup&nbsp;: un plantage, une mise à jour ou autre. Je le redémarre, mais au lieu de mes centaines (milliers&nbsp;?) d’onglets, je ne trouve qu’un onglet solitaire désespérément vide…</p>
<p>J’ai déjà appris de mes erreurs, je tente en premier lieu de restaurer la session précédente via l’interface, mais rien.</p>
<p>J’ouvre alors mon dossier de profile, me doutant que le fichier <code>sessionstore.jsonlz4</code> que j’y trouverai ne vaudra rien (juste cette nouvelle session vide), mais qu’au moins, le contenu de <code>sessionstore-backups/</code> me permettra de me sortir de ce mauvais pas.</p>
<p>Mais en l’ouvrant&nbsp;: rien, le dossier est vide&nbsp;!</p>
<section id="pourquoi" class="level2">
<h2 class="anchored" data-anchor-id="pourquoi">Pourquoi&nbsp;?</h2>
<p>Ok, vous allez me dire&nbsp;:</p>
<blockquote class="blockquote">
<p>“Mais Yosko, pourquoi tu garde des milliers d’onglets ouverts&nbsp;? C’est complètement con&nbsp;!”</p>
</blockquote>
<p>Et vous aurez sans doute raison&nbsp;!</p>
<p>Mais c’est dans ce bordel organisé que je m’y retrouve. J’aime ouvrir un onglet et le retrouver plus tard (des fois des semaines plus tard) pour m’intéresser à ce contenu quand j’en ai enfin le temps ou la motivation. J’aime aussi garder tous les onglets d’une recherche ouverts pour reprendre ce travail de longue haleine précédemment interrompu par d’autres impératifs.</p>
<p>Bref, la plupart de mes onglets existent mais ne sont pas chargés car ils ont été ouverts il y a un certain temps.</p>
</section>
<section id="objectif-et-approche" class="level2">
<h2 class="anchored" data-anchor-id="objectif-et-approche">Objectif et approche</h2>
<p>J’ai donc décidé de mettre en place mes propres <em>backups</em> du <em>sessionstore</em> de Firefox. Dans l’idée, j’aimerais garder des sauvegardes des derniers jours, semaines et mois, juste au cas où.</p>
<p>Après différentes réflexions autour de <strong>rsync</strong> ou d’un simple script bash à base de <code>cp</code> + <code>find</code> et des recherches me menant sur <strong>borgbackup</strong> (dont sebsauvage ne cesse de nous rebattre les oreilles) ou <strong>restic</strong>, j’ai finalement jeté mon dévolu sur <strong>rsnapshot</strong>.</p>
<p>C’est un <em>wrapper</em> en Perl pour rsync, focalisé sur la gestion de sauvegardes par intervals (jours, semaines, mois) et leur nettoyage.</p>
</section>
<section id="configurer-et-tester-rsnapshot" class="level2">
<h2 class="anchored" data-anchor-id="configurer-et-tester-rsnapshot">Configurer et tester rsnapshot</h2>
<p>J’ai d’abord installé rsnapshot&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> apt install rsnapshot</span></code></pre></div></div>
<p>Puis créé la configuration suivante dans <code>~/.config/rsnapshot/rsnapshot.conf</code> pour définir son comportement lorsqu’il tournera&nbsp;:</p>
<pre><code>config_version  1.2
cmd_rsync       /usr/bin/rsync
snapshot_root   /home/&lt;user&gt;/rsnapshot/
retain  daily   3
retain  weekly  3
retain  monthly 3
rsync_long_args --delete --numeric-ids --relative --delete-excluded
backup  /home/&lt;user&gt;/.mozilla/firefox/./&lt;profile&gt;/sessionstore-backups/ firefox/</code></pre>
<div class="callout callout-style-default callout-warning callout-titled" title="Attention : ce fichier doit contenir de *véritables* tabulations, sous peine d'erreurs !">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Avertissement</span>Attention : ce fichier doit contenir de <em>véritables</em> tabulations, sous peine d’erreurs !
</div>
</div>
<div class="callout-body-container callout-body">
<p>Pensez donc à remplacer les espaces ici par des tabulations.</p>
</div>
</div>
<p>Le principe est simple&nbsp;: à chaque exécution, il vérifiera s’il doit effectuer un backup quotidien, hebdo ou mensuel, et s’il doit supprimer d’anciens backups. Les éléments sauvegarder sont les fichiers du dossier <code>.../sessionstore-backups/</code>, donc les backups de session de Firefox.</p>
<p>Pensez à remplacer les éléments suivants : - les 2 mentions de <code>&lt;user&gt;</code> par votre nom d’utilisateur - la mention à <code>&lt;profile&gt;</code> par le nom du dossier de votre profil Firefox</p>
<p>Pour tester à la main en <em>one shot</em>&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">rsnapshot</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> ~/.config/rsnapshot/rsnapshot.conf daily</span></code></pre></div></div>
</section>
<section id="automatiser-lappel-à-rsnapshot" class="level2">
<h2 class="anchored" data-anchor-id="automatiser-lappel-à-rsnapshot">Automatiser l’appel à rsnapshot</h2>
<p>Reste à automatiser l’appel à rsnapshot.&nbsp;J’ai choisi de le faire avec systemd. J’ai créé le fichier <code>~/.config/systemd/user/rsnapshot-daily.service</code> avec dedans :</p>
<pre><code>[Unit]
Description=User rsnapshot daily backup
[Service]
ExecStart=/usr/bin/rsnapshot -c /home/yjo/.config/rsnapshot/rsnapshot.conf daily</code></pre>
<p>Il ne me restait plus qu’à démarrer le service avec mon utilisateur&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">systemctl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--user</span> start rsnapshot-daily.service</span></code></pre></div></div>
<blockquote class="blockquote">
<p>“<em>Keep calm and backup EVERYTHING!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>linux</category>
  <category>scripting</category>
  <guid>https://dev.yosko.net/blog/2025/firefox-sessionstore-rsnapshot.html</guid>
  <pubDate>Thu, 13 Mar 2025 08:00:00 GMT</pubDate>
</item>
<item>
  <title>Linux : dossier temporaire par utilisateur</title>
  <link>https://dev.yosko.net/blog/2025/téléchargement-tmp.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/linux-card.png" class="card img-fluid"></p>
<p>En voyant les propos de <a href="SebSauvage sur l'usage d'un dossier `tmp` dans notre `home`">https://sebsauvage.net/links/?68lT_w</a>, il m’est venu l’idée de faire quelque chose de similaire.</p>
<p>Le but&nbsp;: prendre l’habitude d’<strong>utiliser un dossier temporaire</strong> (<code>tmp</code>) pour certains travaux nécessitant de conserver des fichiers le temps d’un travail, en sachant que son contenu ne sera pas perduré dans le temps.</p>
<p>Il me servira en premier lieu de dossier de téléchargement, et on verra pour la suite.</p>
<section id="besoin" class="level2">
<h2 class="anchored" data-anchor-id="besoin">Besoin</h2>
<p>Si sebsauvage évoque une <strong>solution en RAM</strong> (dont le contenu est supprimé au redémarrage), je tenais plutôt à un comportement où les fichiers sont <strong>gardés sur le disque pendant quelques jours</strong> — principe proche de <code>/tmp</code> (10 jours) et <code>/var/tmp</code> (30 jours).</p>
<p>J’ai surtout dans l’idée de remplacer le dossier <code>Downloads</code>/<code>Téléchargement</code> de mon <code>home</code> par ce dossier temporaires. J’aurais simplement pu mettre en place un processus de nettoyage sur ces dossiers existants, mais un nom mentionnant <em>explicitement</em> le côté <strong>temporaire</strong> me semblait préférable.</p>
<p>Pourquoi ne pas utiliser directement <code>/tmp</code>&nbsp;? Il me semblait préférable de rester sur des dossiers spécifiques à chaque utilisateur, donc dans leur <code>home</code>&nbsp;: c’est <strong>leurs</strong> téléchargements personnels et <strong>leurs</strong> fichiers de travail.</p>
</section>
<section id="fonctionnalités" class="level2">
<h2 class="anchored" data-anchor-id="fonctionnalités">Fonctionnalités</h2>
<p>Fonctionnalités générales&nbsp;:</p>
<ul>
<li>créé le dossier <code>/home/$USER/tmp</code>&nbsp;;</li>
<li>ajoute une règle à <code>/etc/tmpfiles.d</code> afin de nettoyer dans ce dossier les fichiers de plus de <strong>30 jours</strong>&nbsp;;</li>
<li>définir ce dossier comme “dossier de téléchargement” par défaut de l’utilisateur (<code>XDG_DOWNLOAD_DIR</code>)&nbsp;;</li>
<li>droits d’accès au dossier en 1770 (plutôt que 1777 comme <code>/tmp</code>) pour éviter que d’autres utilisateurs viennent fouiller dedans.</li>
</ul>
<p>Fonctionnalités propres à Linux Mint (LMDE, dans mon cas)&nbsp;:</p>
<ul>
<li>remplacer les raccourcis de Nemo pour supprimer <code>Downloads</code>, <code>Téléchargement</code> et ajouter <code>tmp</code></li>
</ul>
</section>
<section id="script-bash" class="level2">
<h2 class="anchored" data-anchor-id="script-bash">Script bash</h2>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#!/bin/bash</span></span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">user_home</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$HOME</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb1-4"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">tmp_dir</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$user_home</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">/tmp"</span></span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Ajout de la règle tmpfiles.d</span></span>
<span id="cb1-7"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># d pour créer un répertoire qui sera nettoyé régulièrement</span></span>
<span id="cb1-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1770 : droits sur le dossier</span></span>
<span id="cb1-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># $USER $USER : propriétaire et groupe</span></span>
<span id="cb1-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 30d : fichiers virés au bout de ce délai</span></span>
<span id="cb1-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"d </span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$tmp_dir</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> 1770 </span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$USER</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$USER</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> 30d"</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> tee <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/etc/tmpfiles.d/</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">${USER}</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">_tmp.conf"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> /dev/null</span>
<span id="cb1-12"></span>
<span id="cb1-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Appliquer les modifications avec tmpfiles</span></span>
<span id="cb1-14"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> systemd-tmpfiles <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--clean</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--create</span></span>
<span id="cb1-15"></span>
<span id="cb1-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Modifier le fichier user-dirs.dirs pour rediriger "Téléchargements" vers "tmp"</span></span>
<span id="cb1-17"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">user_dirs_file</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$user_home</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">/.config/user-dirs.dirs"</span></span>
<span id="cb1-18"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sed</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"s|^XDG_DOWNLOAD_DIR=.*|XDG_DOWNLOAD_DIR=</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\"\$</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">HOME/tmp</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\"</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">|"</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$user_dirs_file</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb1-19"></span>
<span id="cb1-20"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Appliquer immédiatement le changement dans la session en cours</span></span>
<span id="cb1-21"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">source</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$user_dirs_file</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb1-22"></span>
<span id="cb1-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Chemin du fichier des favoris GTK (utilisé par Nemo)</span></span>
<span id="cb1-24"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">bookmarks_file</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$user_home</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">/.config/gtk-3.0/bookmarks"</span></span>
<span id="cb1-25"></span>
<span id="cb1-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Chemin absolu encodé des dossiers Téléchargements ou Downloads</span></span>
<span id="cb1-27"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">downloads_dir</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"file://</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$user_home</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">/T%C3%A9l%C3%A9chargements Téléchargements"</span></span>
<span id="cb1-28"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">downloads_dir_alt</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"file://</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$user_home</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">/Downloads Downloads"</span></span>
<span id="cb1-29"></span>
<span id="cb1-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Supprimer "Téléchargements" ou "Downloads" des favoris s'ils existent</span></span>
<span id="cb1-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># et "tmp" pour éviter les doublons</span></span>
<span id="cb1-32"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sed</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"\|</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$tmp_dir</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">|d"</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$bookmarks_file</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb1-33"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sed</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"\|</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$downloads_dir</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">|d"</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$bookmarks_file</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb1-34"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sed</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"\|</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$downloads_dir_alt</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">|d"</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$bookmarks_file</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb1-35"></span>
<span id="cb1-36"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Ajouter "tmp" en début de fichier</span></span>
<span id="cb1-37"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sed</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-i</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1i file://</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$tmp_dir</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> tmp (Downloads)"</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$bookmarks_file</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb1-38"></span>
<span id="cb1-39"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Redémarrer Nemo</span></span>
<span id="cb1-40"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">killall</span> nemo</span></code></pre></div></div>
<p>Ça m’a été bien utile. De plus, Je tends à scripter toute configuration pour la reproduire lors de prochaines installations.</p>
<p>Comme c’est prêt à l’emploi, ça pourra peut-être resservir à d’autres, donc je partage.</p>
<blockquote class="blockquote">
<p>“<em>Keep calm and script EVERYTHING!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>linux</category>
  <category>scripting</category>
  <guid>https://dev.yosko.net/blog/2025/téléchargement-tmp.html</guid>
  <pubDate>Tue, 11 Feb 2025 13:45:00 GMT</pubDate>
</item>
<item>
  <title>Algorithmie de collisions de hitboxes</title>
  <link>https://dev.yosko.net/blog/2024/algo-collisions-histboxes.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/shapes.drawio.png" class="card img-fluid"></p>
<p>Je discutais récemment avec un de mes étudiants de la gestion de <em>hitboxes</em> dans un jeu vidéo. Le fruit de cet échange m’intéressant, j’ai voulu formaliser tout cela.</p>
<p>L’idée&nbsp;? Comment aborder les données de <em>hitboxes</em> rectangulaires (AABB) pour simplifier les calculs, ou tout du moins, les rendre plus intuitifs.</p>
<p>Même si j’évoques les différentes approches de <em>hitboxes</em>, ça n’a pas vocation à couvrir pleinement l’état de l’art, ce sont juste les périgrinations d’un informaticien et enseignant curieux.</p>
<hr>
<p>Petit rappel&nbsp;: une <em>hitbox</em> (ou <a href="https://fr.wikipedia.org/wiki/Masque_de_collision">masque de collision</a>) désigne la zone de l’écran autour d’un élément graphique (par exemple un personnage) qui, si elle se chevauche avec la <em>hitbox</em> d’un autre élément, sera considéré comme <strong>en collision</strong>.</p>
<p>L’objectif des algos de collision&nbsp;: comment déterminer par le calcul si un élément est en collision avec un autre.</p>
<section id="types-de-hitboxes" class="level2">
<h2 class="anchored" data-anchor-id="types-de-hitboxes">1. Types de <em>hitboxes</em></h2>
<p>Je m’intéresse ici à un espace en 2 dimensions, mais il est facile d’extrapoler cela pour 3 dimensions (un cube au lieu d’un carré, une sphère au lieu d’un cercle, 3 coordonnées au lieu de 2, etc.).</p>
<ul>
<li>rectangle (<em>axis-aligned bounding boxes</em> ou AABB)&nbsp;: algorithme le plus simple, consistant à substituer à tout objet complexe un rectangle le contenant parfaitement&nbsp;;</li>
<li>cercle (<em>bounding sphere</em>)&nbsp;: même principe, mais avec un cercle&nbsp;;</li>
<li>au pixel près (<em>pixel perfect</em>)&nbsp;: précis, mais très coûteux en ressources.</li>
</ul>
<p>Même si on peut vouloir vérifier la collision entre 2 objects, une grosse partie des collisions peuvent être entre un objet et un simple point, ce qui est notablement plus simple à calculer.</p>
</section>
<section id="cas-complexe-pixel-perfect" class="level2">
<h2 class="anchored" data-anchor-id="cas-complexe-pixel-perfect">2. Cas complexe&nbsp;: <em>pixel perfect</em></h2>
<p>Je ne souhaite pas développer ce cas aujourd’hui. L’idée est de parcourir chacun des pixels d’un objet et de vérifier s’il existe au moins un pixel de l’autre objet à la même coordonnée.</p>
<p>Le coût d’un tel algorithme étant élevé – <math><mrow><mi>O</mi><mo form="prefix" stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo form="postfix" stretchy="false">)</mo></mrow></math> – on préfèrera généralement le précéder d’une première vérification par un test de collision en cercle ou en rectangle. L’idée&nbsp;? Ne pas avoir à vérifier tous les pixels de l’écran pour connaître les collisions, mais ne vérifier les pixels que des objets suffisamment proches.</p>
</section>
<section id="cas-simple-les-cercles" class="level2">
<h2 class="anchored" data-anchor-id="cas-simple-les-cercles">3. Cas simple&nbsp;: les cercles</h2>
<p>Vérifier si 2 cercles se chevauchent est assez direct. Soit 2 cercles&nbsp;:</p>
<ul>
<li>cercle A de centre (x<sub>A</sub>, y<sub>A</sub>) et de rayon r<sub>A</sub></li>
<li>cercle B de centre (x<sub>B</sub>, y<sub>B</sub>) et de rayon r<sub>B</sub></li>
</ul>
<p>Vérifier la collision consiste simplement à contrôler si la distance entre leurs centres respectifs est supérieure ou non à la somme de leurs rayons.</p>
<p>Tout d’abord, le calcul de la distance repose sur le théorème de Pythagore&nbsp;:</p>
<p><math display="block" class="tml-display" style="display:block math;"><mrow><mi>d</mi><mo>=</mo><msqrt><mrow><mo form="prefix" stretchy="false" lspace="0em" rspace="0em">(</mo><msub><mi>x</mi><mi>B</mi></msub><mo>−</mo><msub><mi>x</mi><mi>A</mi></msub><msup><mo form="postfix" stretchy="false">)</mo><mn>2</mn></msup><mo>+</mo><mo form="prefix" stretchy="false">(</mo><msub><mi>y</mi><mi>B</mi></msub><mo>−</mo><msub><mi>y</mi><mi>A</mi></msub><msup><mo form="postfix" stretchy="false">)</mo><mn>2</mn></msup></mrow></msqrt></mrow></math></p>
<p>Puis la comparaison&nbsp;:</p>
<p><math display="block" class="tml-display" style="display:block math;"><mrow><mi>d</mi><mo>≥</mo><msub><mi>r</mi><mi>A</mi></msub><mo>+</mo><msub><mi>r</mi><mi>B</mi></msub></mrow></math></p>
<p>Cette comparaison me semble très élégante, et c’est cette idée qu’on va tenter de reprendre pour le cas des rectangles.</p>
<p><em>N. B.</em>&nbsp;: une adaptation de cet algorithme à une ellipse est possible, mais implique des calculs plus complexes impliquant l’angle que je ne développerai pas ici.</p>
</section>
<section id="cas-simple-mais-lourd-les-rectangles" class="level2">
<h2 class="anchored" data-anchor-id="cas-simple-mais-lourd-les-rectangles">4. Cas simple mais lourd&nbsp;: les rectangles</h2>
<p>Les rectangles peuvent être définis de manières variées, mais les plus courantes&nbsp;:</p>
<ul>
<li>coordonnées du coin haut-gauche (x<sub>1</sub>, y<sub>1</sub>) et du coin bas-droite (x<sub>2</sub>, y<sub>2</sub>)</li>
<li>coordonnées du coin haut-gauche (x<sub>1</sub>, y<sub>1</sub>), largeur w et hauteur h</li>
</ul>
<figure class="figure">
<span style="display: flex; gap: .5em;"> <img src="https://dev.yosko.net/blog/2024/assets/hitboxes-squares-1-distant.drawio.png" class="img-fluid figure-img" alt="Pas de collision"> <img src="https://dev.yosko.net/blog/2024/assets/hitboxes-squares-2-asc.drawio.png" class="img-fluid figure-img" alt="Collision partielle dans un sens"> <img src="https://dev.yosko.net/blog/2024/assets/hitboxes-squares-3-desc.drawio.png" class="img-fluid figure-img" alt="Pas partielle dans l’autre sens"> </span>
<figcaption>
Cas classiques à gérer dans un algorithme de collision
</figcaption>
</figure>
<p>On peut être tentés alors de contrôler si le côté gauche (puis droit) d’un objet se situe bien entre les 2 côtés de l’autre, et de reproduire les mêmes contrôles avec les coordonées verticales.&nbsp;Prenons les objets A et B&nbsp;:</p>
<ul>
<li><math><mrow><msub><mi>x</mi><mrow><mn>1</mn><mi>A</mi></mrow></msub><mo>&lt;</mo><msub><mi>x</mi><mrow><mn>1</mn><mi>B</mi></mrow></msub><mo>&lt;</mo><msub><mi>x</mi><mrow><mn>2</mn><mi>A</mi></mrow></msub></mrow></math></li>
<li><math><mrow><msub><mi>x</mi><mrow><mn>1</mn><mi>A</mi></mrow></msub><mo>&lt;</mo><msub><mi>x</mi><mrow><mn>2</mn><mi>B</mi></mrow></msub><mo>&lt;</mo><msub><mi>x</mi><mrow><mn>2</mn><mi>A</mi></mrow></msub></mrow></math></li>
<li><math><mrow><msub><mi>y</mi><mrow><mn>1</mn><mi>A</mi></mrow></msub><mo>&lt;</mo><msub><mi>y</mi><mrow><mn>1</mn><mi>B</mi></mrow></msub><mo>&lt;</mo><msub><mi>y</mi><mrow><mn>2</mn><mi>A</mi></mrow></msub></mrow></math></li>
<li><math><mrow><msub><mi>y</mi><mrow><mn>1</mn><mi>A</mi></mrow></msub><mo>&lt;</mo><msub><mi>y</mi><mrow><mn>2</mn><mi>B</mi></mrow></msub><mo>&lt;</mo><msub><mi>y</mi><mrow><mn>2</mn><mi>A</mi></mrow></msub></mrow></math></li>
</ul>
<p>Cela fait déjà 8 contrôles à faire – ce qui sera encore plus lourd à écrire avec du code – et qui ne suffiront même pas à couvrir un cas particulier&nbsp;:</p>
<figure class="figure">
<span style="display: flex; gap: .5em;"> <img src="https://dev.yosko.net/blog/2024/assets/hitboxes-squares-4-contains.drawio.png" class="img-fluid figure-img" alt="Collision complète&nbsp;: objet entièrement inclu dans l’autre"> </span>
<figcaption>
Collision complète&nbsp;: objet entièrement inclu dans l’autre.
</figcaption>
</figure>
<p>Alors certes, ça marcherait si A contient B, mais pas si B contient A. On pourrait ajouter les contrôles suivant (seuls 4 peuvent suffir ici)&nbsp;:</p>
<ul>
<li><math><mrow><msub><mi>x</mi><mrow><mn>1</mn><mi>B</mi></mrow></msub><mo>&lt;</mo><msub><mi>x</mi><mrow><mn>1</mn><mi>A</mi></mrow></msub><mo>&lt;</mo><msub><mi>x</mi><mrow><mn>2</mn><mi>B</mi></mrow></msub></mrow></math></li>
<li><math><mrow><msub><mi>y</mi><mrow><mn>1</mn><mi>B</mi></mrow></msub><mo>&lt;</mo><msub><mi>y</mi><mrow><mn>1</mn><mi>A</mi></mrow></msub><mo>&lt;</mo><msub><mi>y</mi><mrow><mn>2</mn><mi>B</mi></mrow></msub></mrow></math></li>
</ul>
<p>Mais ça nous amène à un total de 12 contrôles différents, quoique très similaires. Je ne sais pas vous, mais écrire 12 fois la même chose, ça me donne l’impression de perdre mon temps.</p>
</section>
<section id="simplification-des-rectangles" class="level2">
<h2 class="anchored" data-anchor-id="simplification-des-rectangles">5. Simplification des rectangles</h2>
<p>En réalité, cette impression de faire 12 fois la même chose est fondée&nbsp;: on vérifie bien 12 fois si un point est situé à l’intérieur d’une zone données. Mais on n’a pas 12 zones différentes ni 12 points et on sent bien qu’il serait possible de factoriser un peu.</p>
<p>Si on reprend l’élégance de la méthode du cercle et qu’on l’applique cette fois-ci au rectangle, on peut définir le rectangle par son point central (x, y) plutôt que par une de ses extrémités, et par sa largeur w et sa hauteur h. On va plus exactement s’intéresser aux équivaleurs du rayon d’un cercle, donc à <math><mfrac><mi>w</mi><mn>2</mn></mfrac></math> et <math><mfrac><mi>h</mi><mn>2</mn></mfrac></math>.</p>
<figure class="figure">
<img src="https://dev.yosko.net/blog/2024/assets/hitboxes-squares-5-details-src.drawio.png" class="img-fluid figure-img">
</figure>
<p>Il nous suffit alors uniquement de deux contrôles, un pour chaque axe de notre espace (x et y)&nbsp;:</p>
<ul>
<li>la distance en x entre les centres des objets A et B est-elle inférieure à la somme des «&nbsp;rayons&nbsp;» horizontaux desdits objets (bref, la somme de la moitié de leurs largeurs)&nbsp;;</li>
<li>de même, la distance en y est-elle inférieure à la somme de la moitié de leurs hauteurs</li>
</ul>
<figure class="figure">
<img src="https://dev.yosko.net/blog/2024/assets/hitboxes-squares-6-details-final.drawio.png" class="img-fluid figure-img">
</figure>
<p>Comme ce sont des longueurs et distances, il nous suffit de valeurs absolues&nbsp;:</p>
<p><math display="block"><mrow><msub><mi>x</mi><mi>diff</mi></msub><mo>=</mo></mrow><mrow><mrow><mo fence="true" form="prefix">|</mo><msub><mi>x</mi><mi>B</mi></msub><mo>−</mo><msub><mi>x</mi><mi>A</mi></msub><mo fence="true" form="postfix">|</mo></mrow><mo>≤</mo></mrow><mrow><mrow><mo fence="true" form="prefix">|</mo><mfrac><msub><mi>w</mi><mi>A</mi></msub><mn>2</mn></mfrac><mo>+</mo><mfrac><msub><mi>w</mi><mi>B</mi></msub><mn>2</mn></mfrac><mo fence="true" form="postfix">|</mo></mrow></mrow></math></p>
<p><math display="block"><mrow><msub><mi>y</mi><mi>diff</mi></msub><mo>=</mo></mrow><mrow><mrow><mo fence="true" form="prefix">|</mo><msub><mi>y</mi><mi>B</mi></msub><mo>−</mo><msub><mi>y</mi><mi>A</mi></msub><mo fence="true" form="postfix">|</mo></mrow><mo>≤</mo></mrow><mrow><mrow><mo fence="true" form="prefix">|</mo><mfrac><msub><mi>h</mi><mi>A</mi></msub><mn>2</mn></mfrac><mo>+</mo><mfrac><msub><mi>h</mi><mi>B</mi></msub><mn>2</mn></mfrac><mo fence="true" form="postfix">|</mo></mrow></mrow></math></p>
</section>
<section id="point-dancrage" class="level2">
<h2 class="anchored" data-anchor-id="point-dancrage">6. Point d’ancrage</h2>
<figure style="float: right; margin: 0 0 0 1em;" class="figure">
<img src="https://dev.yosko.net/blog/2024/assets/hitboxes-squares-7-anchor-src.drawio.png" class="img-fluid figure-img">
</figure>
<p>L’unique point servant à définir la position d’un objet est appelé <strong>point d’ancrage</strong>. Pour diverses raisons généralement liées au positionnement, on peut vouloir définir un point d’ancrage qui <strong>n’est pas au centre</strong> de notre rectangle. Par exemple, le point d’ancrage d’un personnage sera généralement au niveau de ses pieds plutôt qu’au centre de son corps.</p>
<p>La conséquence est une recomplexification de notre algorithme, mais dont la logique est déjà adaptée et restera inchangée.</p>
<p>Il suffira de détecter si l’objet B est à droite ou à gauche de A pour savoir si on veut utiliser les largeurs à gauche ou à droite des objets, et de suivre la même logique en vertical.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Si la logique mathématique sous-jacente est la même, on voit bien que les 2 approches de calculs de collisions par rectangles n’amènent pas la complexité de la même manière. Je trouve personnellement l’utilisation d’un point d’ancrage centré (inspirée de la méthode des cercles) très intuitive, ce qui facilite la compréhension des calculs, amenant à une facilité de coder cela.</p>
<blockquote class="blockquote">
<p>“<em>Keep ??? and ??? on!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>divers</category>
  <category>math</category>
  <guid>https://dev.yosko.net/blog/2024/algo-collisions-histboxes.html</guid>
  <pubDate>Fri, 22 Nov 2024 10:00:00 GMT</pubDate>
</item>
<item>
  <title>Bleu-vert</title>
  <link>https://dev.yosko.net/blog/2024/bleu-vert.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/colors-card.png" class="card img-fluid"></p>
<p>Où se trouve la limite entre le vert et le bleu&nbsp;? Je ne parle pas de turquoise ou cyan comme intermédiaire, mais bien de la perception qu’on a du «&nbsp;milieu&nbsp;» entre deux couleurs.</p>
<p>En tombant sur le test <a href="https://ismy.blue/">ismy.blue</a>, je me suis rappelé les fréquents débats que j’ai avec ma compagne sur le sujet. Il est donc temps pour moi de «&nbsp;trancher&nbsp;» la question une bonne fois pour toutes.</p>
<p><em>SPOILER : ça ne sera pas tranché dans cet l’article… C’est plutôt une amorce de réflexion.</em></p>
<section id="le-test" class="level2">
<h2 class="anchored" data-anchor-id="le-test">1. Le test</h2>
<section id="mes-résultats" class="level3">
<h3 class="anchored" data-anchor-id="mes-résultats">1.1 Mes résultats</h3>
<div class="quarto-figure quarto-figure-center" style="width: 220px;">
<figure class="figure">
<p><img src="https://dev.yosko.net/blog/2024/assets/bleu-moi.png" class="img-fluid figure-img" data-align="left"></p>
<figcaption>Mon résultat au test&nbsp;: teinte 189 soit plus bleu que 98% de la population</figcaption>
</figure>
</div>
<p>En faisant le test, je tombe sur une limite à 189, soit plus bleu que 98% de la population, tandis que ma compagne tombe sur 161, soit plus vert que 96% de la population. Rien d’étonnant alors à ce qu’on ne tombe jamais d’accord sur la couleur de quelque-chose&nbsp;!</p>
</section>
<section id="biais-potentiels" class="level3">
<h3 class="anchored" data-anchor-id="biais-potentiels">1.2 Biais potentiels</h3>
<p>Mais évidemment, la couleur calculée par un ordinateur peut être déformée par plusieurs facteurs&nbsp;:</p>
<div style="clear:both;">

</div>
<ol type="1">
<li>la donnée émise
<ol type="1">
<li>le <strong>système</strong> de l’ordinateur (ex.&nbsp;: filtre de lumières bleues type <em>Redshift</em>)&nbsp;;</li>
<li>l’<strong>écran</strong> (ex.&nbsp;: qualité, calibrage)&nbsp;;</li>
</ol></li>
<li>la donnée reçue
<ol type="1">
<li>les spécificités <strong>oculaires</strong> du sujet (ex.&nbsp;: daltonisme, dichromatisme)&nbsp;;</li>
</ol></li>
<li>l’interprétation de la donnée
<ol type="1">
<li>les spécificités <strong>neurologiques</strong> (atypismes, niveau de développement des parties du cerveau s’occupant de l’interprétation des couleurs, etc.)</li>
<li>le <strong>contexte personnel</strong> (l’environnement du test, le context sociologique, ou la neuroplasticité qui fera qu’une exposition visuelle préalable particulière pourrait affecter l’expérience).</li>
</ol></li>
</ol>
<p>J’imagine même que quelqu’un atteint de <a href="https://lamecarlate.net/carnet/ma-synesth%C3%A9sie">synesthésie</a> pourrait aussi potentiellement être influencé par ses éléments déclencheurs s’ils sont percevable avant ou en même temps que l’expérience. Ce serait donc un <strong>contexte personnel</strong> influencé par une <strong>spécificité neurologique</strong>. Mais ça reste une simple supposition.</p>
<p>Je ne vais pas pouvoir théoriser sur tous ces thèmes bien au-delà de mes compétences.</p>
</section>
<section id="biais-expérimentés" class="level3">
<h3 class="anchored" data-anchor-id="biais-expérimentés">1.3 Biais expérimentés</h3>
<p>J’ai refait le test le lendemain, à un autre moment de la journée et avec des conditions de luminosité naturelle différente (soleil et ciel couvert, matin et soir). Je semble toujours tomber sur le même résultat (avec une marge d’erreur de 3).</p>
<p>En revanche, je constate un décalage un peu plus notable dès que je désactive mon filtre de lumière bleue&nbsp;: je passe de 189 à 178. Le décalage réel de la couleur affichée à l’écran est sans doute beaucoup plus important, mais j’imagine que mon cerveau s’adapte en partie au fait que tout l’environnement subit ce gros décalage, et il compense donc partiellement.</p>
</section>
</section>
<section id="analyse-théorique" class="level2">
<h2 class="anchored" data-anchor-id="analyse-théorique">2. Analyse théorique</h2>
Ceci est le fruit de mon exploration. Ça part un peu dans tous les sens et mon manque de connaissance ainsi que la complexité des sujets ne permettra pas d’aller «&nbsp;jusqu’au bout&nbsp;». ### 2.1 Vocabulaire
<figure style="float: right; margin-left: 1em;" class="figure">
<div class="quarto-figure quarto-figure-center" style="width: 250px; background-color: grey;">
<figure class="figure">
<p><img src="https://dev.yosko.net/blog/2024/assets/couleurs-disque-TSV.png" class="img-fluid figure-img"></p>
<figcaption>Disque chromatique TSV/HSL</figcaption>
</figure>
</div>
<figcaption>
source&nbsp;: Wikipedia
</figcaption>
</figure>
<p>Dans cet article, je parle indifféremment de <em>couleur</em> ou de <em>teinte</em>, mais prenez bien en compte que j’ignore ici toutes les informations de saturation et de luminosité (selon l’<a href="https://fr.wikipedia.org/wiki/Teinte_saturation_lumi%C3%A8re">espace colorimétrique TSL</a>) pour uniquement m’intéresser aux valeurs du disque chromatique représentant les valeurs de teinte selon TSL.</p>
<p>Ci-contre, le disque en question, où les lettres désignent les 6 teintes (ou couleurs) primaires correspondant aux espaces colorimétriques des synthèses additives et soustractives&nbsp;:</p>
<ul>
<li><a href="https://fr.wikipedia.org/wiki/Rouge-vert-bleu">espace RVB</a> pour la <a href="https://fr.wikipedia.org/wiki/Synth%C3%A8se_additive">synthèse additive</a>, celle basée sur la lumière et utilisant les couleurs primaires <strong>rouge</strong>, <strong>vert</strong> et <strong>bleu</strong>&nbsp;;</li>
<li><a href="https://fr.wikipedia.org/wiki/Quadrichromie">espace CMJ(N)</a> pour la <a href="https://fr.wikipedia.org/wiki/Synth%C3%A8se_soustractive">synthèse soustractive</a>, celle basée sur l’absorbtion lumineuse par des composants (imprimerie) et utilisant les couleurs primaires <strong>cyan</strong>, <strong>magenta</strong> et <strong>jaune</strong>&nbsp;;</li>
</ul>
<section id="nom-des-couleurs" class="level3">
<h3 class="anchored" data-anchor-id="nom-des-couleurs">2.2 Nom des couleurs</h3>
<p>Beaucoup de couleurs ont un nom. Rien qu’en regardant entre vert et bleu, on en trouve beaucoup. Les 2 principales qui ont une signification particulière&nbsp;:</p>
<ul>
<li>le <a href="https://fr.wikipedia.org/wiki/Turquoise_(couleur)">Turquoise</a> désigne toutes les nuances intermédiaires entre le bleu et le vert. C’est donc un terme général, même si dans certains contextes, il pourra désigner une teinte ou une couleur précise.</li>
<li>le <a href="https://fr.wikipedia.org/wiki/Cyan">Cyan</a> désigne la couleur précise servant de couleur primaire en synthèse soustractive pour l’imprimerie.</li>
</ul>
<p>Mais on a aussi&nbsp;:</p>
<ul>
<li><a href="https://fr.wikipedia.org/wiki/Bleu_p%C3%A9trole_(couleur)">bleu pétrole</a></li>
<li>bleu jean (discutable)</li>
<li>bleu Égée</li>
<li><a href="https://fr.wikipedia.org/wiki/C%C5%93ruleum">bleu cœruleum</a></li>
<li><a href="https://fr.wikipedia.org/wiki/Bleu_de_Prusse">bleu de Prusse</a> (même s’il est discutable de le classer dans les turquoises)</li>
<li><a href="https://fr.wikipedia.org/wiki/Bleu_canard">bleu canard <strong>et</strong> vert canard</a> (qui semblent être 2 nuances différentes)</li>
<li><a href="https://fr.wikipedia.org/wiki/Bleu-vert">vert-bleu et/ou bleu-vert</a></li>
<li>vert russe (dépend des sources)</li>
<li><a href="https://fr.wikipedia.org/wiki/Vert-de-gris">vert-de-gris</a></li>
<li><a href="https://fr.wikipedia.org/wiki/Vert_c%C3%A9ladon">vert céladon</a></li>
<li>etc.</li>
</ul>
</section>
<section id="le-milieu-optique-par-rvb-et-cmjn" class="level3">
<h3 class="anchored" data-anchor-id="le-milieu-optique-par-rvb-et-cmjn">2.3 Le milieu optique par RVB et CMJN</h3>
<p>Vu qu’il existe de nombreux bleus différents, verts différents et turquoises différents, il convient de choisir où commencer et terminer notre échelle. En première intuition, cibler les couleurs primaires de RVB pour choisir notre bleu et notre vert semble pertinent.</p>
<p>Logiquement, le juste milieu entre les deux tombe alors sur le cyan de CMJN. On le voit à leurs valeurs en RVB et CMJN (récupérées sur <a href="https://www.colorhexa.com/">colorhexa</a>)&nbsp;:</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th style="text-align: center;"><strong>Nom</strong></th>
<th style="text-align: center;"><strong>En RGB</strong></th>
<th style="text-align: center;"><strong>En CMJN</strong></th>
<th style="text-align: center;"><strong>Longueur d’onde</strong></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;">Vert</td>
<td style="text-align: center;">(0,1,0)</td>
<td style="text-align: center;">(1,0,1,0)</td>
<td style="text-align: center;">549,2 nm</td>
</tr>
<tr class="even">
<td style="text-align: center;">Cyan</td>
<td style="text-align: center;">(0,1,1)</td>
<td style="text-align: center;">(1,0,0,0)</td>
<td style="text-align: center;"><a href="https://www.colorhexa.com/00ffff">490 nm</a></td>
</tr>
<tr class="odd">
<td style="text-align: center;">Bleu</td>
<td style="text-align: center;">(0,0,1)</td>
<td style="text-align: center;">(1,1,0,0)</td>
<td style="text-align: center;">464,3 nm</td>
</tr>
</tbody>
</table>
<p>Par contre l’intermédiaire <strong>linéaire</strong> des longueurs d’onde ne tombe pas tout à fait juste&nbsp;: <math display="block" class="tml-display" style="display:block math;"><mrow><mfrac><mrow><mo form="prefix" stretchy="false" lspace="0em" rspace="0em">(</mo><mi>V</mi><mi>e</mi><mi>r</mi><mi>t</mi><mo>+</mo><mi>B</mi><mi>l</mi><mi>e</mi><mi>u</mi><mo form="postfix" stretchy="false" lspace="0em" rspace="0em">)</mo></mrow><mn>2</mn></mfrac><mo>=</mo><mfrac><mrow><mo form="prefix" stretchy="false" lspace="0em" rspace="0em">(</mo><mn>549,2</mn><mo>+</mo><mn>464,3</mn><mo form="postfix" stretchy="false" lspace="0em" rspace="0em">)</mo></mrow><mn>2</mn></mfrac><mo>=</mo><mn>506,75</mn><mo>&gt;</mo><mn>490</mn><mo>=</mo><mi>C</mi><mi>y</mi><mi>a</mi><mi>n</mi></mrow></math></p>
<p>Mais ce calcul suppose que l’échelle des longueurs d’onde a un impact linéaire sur notre perception des couleurs, ce qui n’est probablement pas le cas.</p>
<p>Je n’ai hélas par réussi à trouver de source sur le sujet qui réponde clairement à cette question de cette potentielle non-linéarité (en tout cas des sources que j’étais en mesure de comprendre).</p>
</section>
<section id="en-biologie" class="level3">
<h3 class="anchored" data-anchor-id="en-biologie">2.4 En biologie</h3>
<section id="types-de-photorécepteurs" class="level4">
<h4 class="anchored" data-anchor-id="types-de-photorécepteurs">2.4.1 Types de photorécepteurs</h4>
<figure style="float: right; margin: 0 0 0 1em;" class="figure">
<div class="quarto-figure quarto-figure-center" style="width: 250px; background-color: #ccc;">
<figure class="figure">
<p><img src="https://dev.yosko.net/blog/2024/assets/spectre-absorption-cones.png" class="img-fluid figure-img"></p>
<figcaption>Disque chromatique TSV/HSL</figcaption>
</figure>
</div>
<figcaption>
source&nbsp;: Wikipedia
</figcaption>
</figure>
<p>Les photorécepteurs (récepteurs de lumière) de nos yeux, appelés cônes, sont de <a href="https://fr.wikipedia.org/wiki/C%C3%B4ne_(photor%C3%A9cepteur)#Les_deux,_trois_ou_quatre_types_de_c%C3%B4nes_(selon_l'esp%C3%A8ce)">3 types chez l’humain</a>. Si on laisse de côté les atypismes comme le daltonisme, on peut trouver les sensibilités approximatives de chaque type.</p>
<p>Le problème&nbsp;: ces valeurs varient grandement selon les sources. Une fourchette compilée à partir de divers sources&nbsp;:</p>
<ul>
<li>cônes B (basses longueurs d’onde)&nbsp;: entre 430 et 500 nm (bleu)</li>
<li>cônes V (moyennes longueurs d’onde)&nbsp;: entre 460 et 530 nm (vert)</li>
<li>cônes R (grandes longueurs d’onde)&nbsp;: entre 510 et 600 nm (rouge)</li>
</ul>
<p>De plus, les couleurs turquoises excitent 2&nbsp;récepteurs à la fois (V et B), donc&nbsp;:</p>
<ul>
<li>une longueur d’onde de 480 nm excitera ces récepteurs de la même manière que les 2 longueurs d’ondes 430 et 530 nm. Sauf que 530 nm excitera plus le 3ème récepteur (R) que 480, ce qui peut causer un décalage supplémentaire (c’est d’ailleurs ce qui justifie la forme bizarre de gamut).</li>
</ul>
</section>
<section id="non-linéarité-de-perception" class="level4">
<h4 class="anchored" data-anchor-id="non-linéarité-de-perception">2.4.2 Non-linéarité de perception</h4>
<p>Comme dit plus plus haut, je n’ai pas trouvé de source (que je comprenne) sur le sujet, mais je sens bien que lorsqu’on voit un dégradé de teinte (comme celui derrière la courbe plus haut), certaine couleurs semble épouser une plage plus large que d’autres).</p>
<p>Mais percevons-nous tous réellement une même répartition du spectre des couleurs ? Je vois par exemple une plage de jaune très réduite, une verte et une bleue assez grandes et similaires, puis une violet relativement réduite.</p>
<p>J’amerais beaucoup apprendre et comprendre plus de choses sur cette notion, donc si vous avez des notions sur le sujet, n’hésitez pas à me contacter.</p>
</section>
</section>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>En résumé, je sais déjà pourquoi on a du mal à se mettre d’accord avec ma compagne&nbsp;: nos interprétations semble aux deux extrémités du spectre présenté par le test.</p>
<p>Je sais aussi qu’il n’est pas évident de définir ce qu’est le milieu entre 2 couleurs. Il existe diverses manières précises et scientifiques de le faire (moyenne de longueur d’onde, valeur selon un espace colorimétique ou un autre).</p>
<p>Mais c’est sans compter sur la façon bien particulière qu’a notre corps (oeil et cerveau) de fonctionner et d’amener du subjectif. Et ce sans nécessairement parler de biais ou d’atypisme.</p>
<p>Alors, le milieu entre deux couleurs, c’est quoi selon vous&nbsp;?</p>
<blockquote class="blockquote">
<p>“<em>Keep thinking and dig on!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>couleur</category>
  <guid>https://dev.yosko.net/blog/2024/bleu-vert.html</guid>
  <pubDate>Fri, 20 Sep 2024 07:00:00 GMT</pubDate>
</item>
<item>
  <title>Générateur de favicon en JavaScript</title>
  <link>https://dev.yosko.net/blog/2024/favicon-gen.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/js-card.png" class="card img-fluid"></p>
<p>À chaque nouveau petit projet, je ressens le besoin d’ajouter une <em>favicon</em>. Ce n’est même pas pour le <em>design</em> ou une volonté d’identité graphique, mais surtout pour m’y retrouver dans mes nombreux onglets.</p>
<p>J’avais tenté un générateur de <em>favicon</em> en PHP/GD y’a quelques temps, mais j’ai vite abandonné l’idée, frustré du résultat.</p>
<p>Aujourd’hui, j’ai enfin une base qui me plait, ne nécessitant pas de serveur (pur Js).</p>
<section id="aperçu-de-loutil" class="level2">
<h2 class="anchored" data-anchor-id="aperçu-de-loutil">Aperçu de l’outil</h2>
<p>J’ai fait KISS au possible - donc design ultra-basique - préférant me concentrer sur les fonctionnalités.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://dev.yosko.net/blog/2024/assets/favicon-gen.js.png" class="img-fluid figure-img" width="400"></p>
<figcaption>Impression écran de l’outil</figcaption>
</figure>
</div>
<p>J’en ai profité pour découvrir le fonctionnement des <em>Pages</em> de Github et Gitlab. Vous n’aurez donc pas une, mais bien <strong>deux</strong> démos disponibles (c’est pas la classe, ça ?) :</p>
<ul>
<li>démo <a href="https://yosko.frama.io/favicon-gen.js">Gitlab Pages chez Framasoft</a></li>
<li>démo <a href="https://yosko.github.io/favicon-gen.js/">Github Pages</a></li>
<li>sources <a href="https://framagit.org/yosko/favicon-gen.js">chez Framasoft</a> et <a href="https://github.com/yosko/favicon-gen.js">chez Github</a></li>
</ul>
<p>PS : n’hésitez pas à me faire vos retours.</p>
<blockquote class="blockquote">
<p>“<em>Keep It Simple and Stupid on!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>javascript</category>
  <guid>https://dev.yosko.net/blog/2024/favicon-gen.html</guid>
  <pubDate>Thu, 19 Sep 2024 12:55:00 GMT</pubDate>
</item>
<item>
  <title>[Snippet] afficher l’hôte dans les logs d’Apache</title>
  <link>https://dev.yosko.net/blog/2024/snippet-apache-log-host.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/webserver-card.png" class="card img-fluid"></p>
<p>Pour continuer sur ma lancée des petites configs Apache utiles (<em>cf</em> catégorie <a href="../../category/serveur-web/">Serveur web</a>), en voici une concernant les <em>logs</em>.</p>
<section id="besoin" class="level2">
<h2 class="anchored" data-anchor-id="besoin">Besoin</h2>
<p>Lorsqu’on utilise Apache avec plusieurs (sous-)domaines, il est courant d’utiliser des fichiers de <em>logs</em> séparés pour chaque <em>vhost</em> sur le modèle <code>/var/log/apache2/mon_vhost_access.log</code> et <code>/var/log/apache2/mon_vhost_error.log</code>.</p>
<p>Mais dans certains cas, on peut vouloir rassembler les logs des différents <em>vhosts</em> dans un même fichier. Cependant, les formats par défaut des logs ne permettent pas de distinguer quel <em>vhost</em> a déclenché l’écriture d’un log en particulier.</p>
</section>
<section id="explications" class="level2">
<h2 class="anchored" data-anchor-id="explications">Explications</h2>
<p>Pour solutionner cela, il faut <strong>changer le format</strong> des logs d’accès (<code>/var/log/apache2/*access.log</code>). Ceux-ci sont généralement configurés sous une forme semblable à&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource apache number-lines code-with-copy"><code class="sourceCode apache"><span id="cb1-1">ErrorLog<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> ${APACHE_LOG_DIR}/error.log</span></span>
<span id="cb1-2">CustomLog<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> ${APACHE_LOG_DIR}/access.log combined</span></span></code></pre></div></div>
<p>Notez bien le <code>combined</code>&nbsp;: il désigne un des format de log prédéfinis d’Apache&nbsp;:</p>
<p><code>apache title="Extrait de la version par défaut de /etc/apache2/apache2.conf" LogFormat "%v:%p %h %l %u %t \"%r\" %&gt;s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined LogFormat "%h %l %u %t \"%r\" %&gt;s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %&gt;s %O" common LogFormat "%{Referer}i -&gt; %U" referer LogFormat "%{User-agent}i" agent</code></p>
<p><em>Pour plus d’infos sur les éléments possibles d’afficher, <a href="https://httpd.apache.org/docs/2.4/mod/mod_log_config.html#formats">voir dans la doc</a>.</em></p>
</section>
<section id="solution" class="level2">
<h2 class="anchored" data-anchor-id="solution">Solution</h2>
<p>Il suffit alors de définir un nouveau format «&nbsp;maison&nbsp;» affichant en plus le <em>Host</em>. Mais ne modifions pas <code>apache2.conf</code>, afin d’éviter tout conflit lors des mises à jour d’Apache.</p>
<p>Il est préférable de se créer un fichier de configuration additionnel. Par exemple&nbsp;:</p>
<p><code>apache title="/etc/apache2/conf-available/custom-logs.conf" # define a log format like "combined" but with the Host header too # so that "catchall" vhosts help identify which host was called LogFormat "%h %l %u %t %{Host}i \"%r\" %&gt;s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined_with_host</code></p>
<p>Comme il est placé dans <code>conf-available</code>, il convient de l’activer&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">a2enconf</span> custom-logs.conf</span></code></pre></div></div>
<p><em>Cela va juste créer un lien symbolique dans <code>conf-enabled</code> vers ce fichier, sur le même principe que les vhosts.</em></p>
<p>Il suffit ensuite d’utiliser ce nouveau format dans les <em>vhosts</em> concernés &nbsp;:</p>
<p><code>apache title="extrait de vhost" ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined_with_host</code></p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p><em>Profit</em> :moneybag:</p>
<p>Et si vous souhaitez en faire de même sur les formats du log <strong>d’erreur</strong>, il existe la <a href="https://httpd.apache.org/docs/2.4/fr/mod/core.html#errorlogformat">directive équivalente</a> <code>ErrorLogFormat</code> (mais elle ne se règle qu’une fois, à l’échelle du serveur, pas au niveau des <em>vhosts</em>).</p>
<blockquote class="blockquote">
<p>“<em>Keep calm and script EVERYTHING!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>serveur web</category>
  <category>apache</category>
  <guid>https://dev.yosko.net/blog/2024/snippet-apache-log-host.html</guid>
  <pubDate>Sat, 18 May 2024 11:45:00 GMT</pubDate>
</item>
<item>
  <title>[Snippet] changer le port d’écoute d’Apache</title>
  <link>https://dev.yosko.net/blog/2024/snippet-apache-port.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/webserver-card.png" class="card img-fluid"></p>
<p>J’avais déjà partagé un premier conseil de configuration pour Apache, mais j’en ai plein d’autres dans ma hotte. Je vais les rassembler dans la catégorie <a href="../../category/serveur-web/">Serveur web</a>.</p>
<p>Commençons par un snippet pour changer le <strong>port :fontawesome-solid-anchor: d’écoute</strong> d’Apache :fontawesome-solid-feather-pointed:.</p>
<p><em>(oui, je m’amuse avec les icônes, mais c’est mon blog, je fais ce que je veux&nbsp;!)</em></p>
<section id="besoin" class="level2">
<h2 class="anchored" data-anchor-id="besoin">Besoin</h2>
<p>Remplaçons le port par défaut (<code>80</code>) par un autre (ici, j’utiliserai <code>8080</code>). Il faut le changer à plusieurs endroits&nbsp;:</p>
<ul>
<li>sur la directive <code>Listen</code> (fichier <code>/etc/apache2/ports.conf</code>)&nbsp;;</li>
<li>dans les <code>&lt;VirtualHost&gt;</code> de chaque <em>vhost</em>.</li>
</ul>
</section>
<section id="solution" class="level2">
<h2 class="anchored" data-anchor-id="solution">Solution</h2>
<p>Inutile d’aller modifier chaque fichier <em>a la mano</em>, autant scripter tout ça&nbsp;:</p>
<p>```bash title=“change_apache_port.sh” # Replace “Listen 80” by “Listen 8080” in ports.conf sed -i ‘/^Listen 80$/ s/80/8080/’ /etc/apache2/ports.conf</p>
</section>
<section id="replace-virtualhost-80-by-virtualhost-8080-in-all-vhosts" class="level1">
<h1>Replace “&lt;VirtualHost <em>:80&gt;” by ”&lt;VirtualHost </em>:8080&gt;” in all vhosts</h1>
<p>sed -i ‘s/:80&gt;/:8080&gt;/’ /etc/apache2/sites-available/<em>.conf ``<code>*Ces commandes sont __idempotentes__[^1], donc vous ne finirez pas avec</code>80808080` si vous les appelez plusieurs fois.</em></p>
<p>Si certains de vos vhosts actifs ne sont pas des liens symboliques issus de <code>sites-available</code>, vous pouvez toujours cibler <code>sites-enabled</code> ou tout autre dossier à la place.</p>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>J’essaye de <strong>proposer des scripts</strong> plutôt que des manipulations manuelles afin de faciliter l’intégration dans des processus automatisatés.</p>
<p>J’aurai prochainement à vous proposer quelques petits <em>snippets</em> de configurations de <em>vhosts</em> d’Apache, aussi. Et j’expliquerai peut-être l’essentiel à savoir sur les différents dossiers de configuration d’Apache. Bref, que des trucs qu’on ne m’avait jamais dit et que j’ai d’autant plus envie de partager.</p>
<blockquote class="blockquote">
<p>“<em>Keep calm and script EVERYTHING!</em>”</p>
</blockquote>


</section>
</section>

 ]]></description>
  <category>serveur web</category>
  <category>apache</category>
  <guid>https://dev.yosko.net/blog/2024/snippet-apache-port.html</guid>
  <pubDate>Thu, 02 May 2024 19:35:00 GMT</pubDate>
</item>
<item>
  <title>PHP : décompression d’arguments et arguments nommés</title>
  <link>https://dev.yosko.net/blog/2024/php-variadic-named.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/php-card.png" class="card img-fluid"></p>
<p>Au fil des versions, PHP offre de plus en plus de souplesse pour transmettre des arguments à une fonction. La syntaxe suivante est désormais possible :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&lt;?php</span></span>
<span id="cb1-2">example(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> ...[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'arg3'</span> =&gt; <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> arg5<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>Il était temps que je me mette à la page. Du coup, je vous partage ça…</p>
<section id="opérateur-de-décomposition-php-..." class="level2">
<h2 class="anchored" data-anchor-id="opérateur-de-décomposition-php-...">1. Opérateur de décomposition <code>#!php ...</code></h2>
<p>Disponible depuis <strong>PHP 5.6</strong>, il est aussi appelé <em>splat operator</em> ou <em>unpacking operator</em>. Il permet de faire 2 choses différentes&nbsp;:</p>
<section id="fonctions-variables-variadic-functions" class="level3">
<h3 class="anchored" data-anchor-id="fonctions-variables-variadic-functions">1.1 Fonctions variables (<em>variadic functions</em>)</h3>
<p>Il peut servir à définir des fonctions variables qui <strong>prennent un nombre indéterminé de paramètres</strong>&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&lt;?php</span></span>
<span id="cb2-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> variadicFunction(...<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$args</span>) {</span>
<span id="cb2-3">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">foreach</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$args</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$val</span>) {</span>
<span id="cb2-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">echo</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$val</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-5">  }</span>
<span id="cb2-6">}</span>
<span id="cb2-7">variadicFunction(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val1'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val2'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'val3'</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p><em>Les arguments sont accessible sous forme d’un <strong>tableau associatif</strong>.</em></p>
</section>
<section id="décompression-de-tableau" class="level3">
<h3 class="anchored" data-anchor-id="décompression-de-tableau">1.2 Décompression de tableau</h3>
<div class="callout callout-style-default callout-note callout-titled" title="Pour la suite de l'article, nous allons plutôt utiliser la fonction suivante">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Pour la suite de l’article, nous allons plutôt utiliser la fonction suivante
</div>
</div>
<div class="callout-body-container callout-body">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&lt;?php</span></span>
<span id="cb3-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> example(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$arg1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$arg2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$arg3</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$arg4</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$arg5</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) {</span>
<span id="cb3-3">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// ...</span></span>
<span id="cb3-4">}</span></code></pre></div></div>
<p><em>Autant ne pas la répéter 15 fois…</em></p>
</div>
</div>
<p>L’opérateur <code>...</code> peut aussi servir à l’inverse&nbsp;: transmettre à la fonction <strong>chaque élément d’un tableau dans des arguments distincts</strong>&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&lt;?php</span></span>
<span id="cb4-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// plutôt que ceci...</span></span>
<span id="cb4-3">variadicFunction(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-4"></span>
<span id="cb4-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// ...on peut faire cela...</span></span>
<span id="cb4-6"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$array</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]</span>
<span id="cb4-7">variadicFunction(...<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$array</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb4-8"></span>
<span id="cb4-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// ...ou directement (intérêt plus limité)</span></span>
<span id="cb4-10">variadicFunction(...[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>])<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p><em>Dans le cas présent, ils sont transmis dans l’ordre fourni.</em></p>
</section>
</section>
<section id="arguments-nommés-depuis-php-8.0" class="level2">
<h2 class="anchored" data-anchor-id="arguments-nommés-depuis-php-8.0">2. Arguments nommés (depuis PHP 8.0)</h2>
<p>Dans une syntaxe assez similaire à Python, PHP autorisé désormais à nommer les arguments optionnels.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&lt;?php</span></span>
<span id="cb5-2">example(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb5-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// ... est équivalent à :</span></span>
<span id="cb5-4">example(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> arg5<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p><em>Cela évite de transmettre inutilement à la main des valeurs par défaut pour des arguments dont on se fout.</em></p>
</section>
<section id="arguments-nommés-opérateur-de-décompression" class="level2">
<h2 class="anchored" data-anchor-id="arguments-nommés-opérateur-de-décompression">3. Arguments nommés &amp; opérateur de décompression</h2>
<p>Les deux peuvent être utilisé lors d’un même appel de fonction, et ce de deux manières différentes&nbsp;:</p>
<section id="utilisés-ensemble" class="level3">
<h3 class="anchored" data-anchor-id="utilisés-ensemble">3.1 Utilisés ensemble</h3>
<p>L’opérateur de décompression — s’il est utilisé avec un tableau <strong>associatif</strong> — fera le lien entre les clés du tableau et les noms de variables&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&lt;?php</span></span>
<span id="cb6-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$args</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'arg3'</span> =&gt; <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'arg5'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb6-3">example(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> ...<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$args</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p><em>Ici, <code>arg2</code> et <code>arg4</code> gardent leurs valeurs par défaut, tandis que <code>arg3</code> et <code>arg5</code> récupèrent les valeurs du tableau.</em></p>
</section>
<section id="utilisés-en-parallèle" class="level3">
<h3 class="anchored" data-anchor-id="utilisés-en-parallèle">3.2 Utilisés en parallèle</h3>
<p>Il est aussi possible d’utiliser les 2 syntaxes au sein d’un même appel&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb7-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&lt;?php</span></span>
<span id="cb7-2">example(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> ...[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'arg3'</span> =&gt; <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> arg5<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>Pour remettre un peu au clair, voici ce qu’il se passe pour chaque argument&nbsp;:</p>
<ol type="1">
<li>argument requis transmis : vaudra 1</li>
<li>argument facultatif non transmis : vaudra 0</li>
<li>argument facultatif transmis par tableau associatif (ce qui ciblera l’argument de façon «&nbsp;nommée&nbsp;») : vaudra 3</li>
<li>argument facultatif non transmis : vaudra 0</li>
<li>argument facultatif transmis de façon «&nbsp;nommée&nbsp;»&nbsp;: vaudra 5</li>
</ol>
</section>
<section id="attention-aux-doublons" class="level3">
<h3 class="anchored" data-anchor-id="attention-aux-doublons">3.3 Attention aux doublons</h3>
<p>Il ne faut évidemment pas mentionner un même argument 2 fois, au risque de recevoir une <code>Fatal error</code>&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&lt;?php</span></span>
<span id="cb8-2">example(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> ...[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'arg5'</span> =&gt; <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> arg5<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
</section>
</section>
<section id="référence-php.net" class="level2">
<h2 class="anchored" data-anchor-id="référence-php.net">Référence (php.net)</h2>
<ul>
<li><a href="https://www.php.net/manual/fr/functions.arguments.php#functions.variable-arg-list">Liste d’arguments à nombre variable</a></li>
<li><a href="https://www.php.net/manual/fr/functions.arguments.php#functions.named-arguments">Arguments nommés</a></li>
</ul>
<blockquote class="blockquote">
<p>“<em>Keep spreading and code on!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>php</category>
  <guid>https://dev.yosko.net/blog/2024/php-variadic-named.html</guid>
  <pubDate>Mon, 29 Apr 2024 11:12:00 GMT</pubDate>
</item>
<item>
  <title>[Snippet] Proportions d’une recette en JavaScript</title>
  <link>https://dev.yosko.net/blog/2024/snippet-js-recette.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/js-card.png" class="card img-fluid"></p>
<p>J’entretiens un blog persionnel privé où je note — entre autre — des recettes de cuisine. Et ça faisait un moment que je voulais pouvoir recalculer à la volée et simplement les quantités en fonction — par exemple — du nombre de convives.</p>
<p>Ayant passé ledit blog sur Mkdocs aussi récemment, j’ai cherché une solution qui ne nécessite pas de développer un plugin&nbsp;: reposer simplement sur JavaScript et HTML.</p>
<section id="objectif" class="level2">
<h2 class="anchored" data-anchor-id="objectif">Objectif</h2>
<p>À terme, je voulais avoir un HTML ressemblant à ceci&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource html number-lines code-with-copy"><code class="sourceCode html"><span id="cb1-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">ul</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> class</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ingredients"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-2">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">li</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">span</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> clas</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qty"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span>100<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">span</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span> g de farine de sarrasin<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">li</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-3">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">li</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">span</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> clas</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qty"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span>1<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">span</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span> oeuf<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">li</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-4">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">li</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">span</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> clas</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qty"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span>150<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">span</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span> mL de lait<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">li</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-5"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">ul</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-6"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">label</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-7">    Multiplier les quantités par :</span>
<span id="cb1-8">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">input</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"text"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> class</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"multiplier"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> value</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Possible formats: .5 — 2/3 — 2 — 3,5"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-9"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">label</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div></div>
<p>Les saisies dans le <code>#!html &lt;input&gt;</code> pourrait être un nombre entier ou décimal, avec un séparateur de décimal à la française (<code>,</code>) ou à l’anglaise (<code>.</code>) et un support basique des fractions serait intéressant aussi (<code>2/3</code>).</p>
</section>
<section id="nécrire-que-la-liste" class="level2">
<h2 class="anchored" data-anchor-id="nécrire-que-la-liste">N’écrire que la liste</h2>
<p>Dans chaque article, j’aimerais éviter d’avoir à écrire à la main à chaque fois le <code>#!html &lt;input&gt;</code> («&nbsp;copier-coller&nbsp;», c’est le mal&nbsp;!), donc autant l’insérer à la volée au chargement de la page après chaque liste d’ingrédients&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource js number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb2-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">--</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;--</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"snippets/recipe-ingredients-snip.js:insert"</span></span></code></pre></div></div>
</section>
<section id="alléger-lécriture-de-la-liste" class="level2">
<h2 class="anchored" data-anchor-id="alléger-lécriture-de-la-liste">Alléger l’écriture de la liste</h2>
<div class="callout callout-style-default callout-warning callout-titled" title="Cette partie est facultative et discutable">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Avertissement</span>Cette partie est facultative et discutable
</div>
</div>
<div class="callout-body-container callout-body">
<p>Vous pouvez tout aussi bien vous en passer et écrire directement les balises <code>&lt;li&gt;</code> comme évoqué plus haut pour avoir une meilleure accessibilité de votre site.</p>
</div>
</div>
<p>Certains n’aimeront peut-être pas cette approche, mais je tenais à diminuer la quantité de code à écrire à chaque fois que je rédige une liste d’ingrédients (l’essentiel de mon texte est en Markdown, je n’ai pas envie de me palucher du HTML lourdingue au milieu de ça).</p>
<p>J’ai donc fait le choix d’écrire plutôt&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource html number-lines code-with-copy"><code class="sourceCode html"><span id="cb3-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">ul</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> class</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ingredients"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb3-2">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">x-ingr</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> qty</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"100"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span>g de farine de sarrasin<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">x-ingr</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb3-3">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">x-ingr</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> qty</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"1"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span>oeuf<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">x-ingr</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb3-4">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">x-ingr</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> qty</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"150"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span>mL de lait<span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">x-ingr</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb3-5"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">ul</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div></div>
<p>J’en convient, le gain est minime&nbsp;: 10 caractères par ingrédient, sachant que ça ajoute 29 caractères pour le <code>#!html &lt;ul&gt;</code>, ça ne laisse — dans l’exemple présent — qu’un gain de <strong>1 caractère</strong>&nbsp;! :face_with_monocle:</p>
<p>Mais c’était aussi l’occasion pour moi d’expérimenter avec les éléments HTML personnalisés (<a href="https://developer.mozilla.org/fr/docs/Web/API/Web_components/Using_custom_elements"><em>cf</em> MDN</a>). J’envisageais au départ de distinguer 3 informations (quantité, unité de mesure, nom d’ingrédient), ce qui aurait pu rendre l’usage d’élément personnalisé plus intéressant, peut-être.</p>
<p>Pour déclarer l’élément personnalisé&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource js number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb4-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">--</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;--</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"snippets/recipe-ingredients-snip.js:custom"</span></span></code></pre></div></div>
<p><em>Fait étonnant&nbsp;: la norme nous imposer de choisir un nom d’élément <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#name">comportant un tiret</a>. Une contrainte qui rallonge le nom de ma balise personnalisée&nbsp;! :angry:</em></p>
</section>
<section id="recalculer-les-proportions" class="level2">
<h2 class="anchored" data-anchor-id="recalculer-les-proportions">Recalculer les proportions</h2>
<p><code>js hl_lines="6 11" --8&lt;-- "snippets/recipe-ingredients-snip.js:multiply"</code></p>
<ol type="1">
<li>Si vous ne voulez pas de gestion de fractions, supprimez la fonction <code>parseFraction</code> et remplacez son appel ici par la ligne avec <code>parseFloat</code> surlignée plus haut.</li>
</ol>
<p>Notez en particulier le mécanisme suivant&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource js number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb5-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">parseFloat</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">toPrecision</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div></div>
<ul>
<li><code>parseFloat()</code> permet de lire une valeur décimale dans une chaîne&nbsp;;</li>
<li><code>.toPrecision(3)</code> pour ne conserver que 3 chiffres significatifs (qu’ils soient avant ou après la virgule)&nbsp;;</li>
<li><code>1 *</code> afin de ne pas conserver de zéro inutile après la virgule (<code>1.00</code> deviendra <code>1</code>).</li>
</ul>
</section>
<section id="profit" class="level2">
<h2 class="anchored" data-anchor-id="profit"><em>Profit</em></h2>
<p>Le fichier complet&nbsp;:</p>
<p><code>js title="recipe-ingredients.js" linenums="1" --8&lt;-- "snippets/recipe-ingredients.js"</code></p>
<p><em><strong>NB</strong>&nbsp;: j’ai essayé de raccourci au maximum mon code pour qu’il cible l’essentiel et rentre en 40 lignes, parfois au dépend de la facilité de lecture.</em></p>
<blockquote class="blockquote">
<p>“<em>Keep cooking and KISS on!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>javascript</category>
  <guid>https://dev.yosko.net/blog/2024/snippet-js-recette.html</guid>
  <pubDate>Sun, 28 Apr 2024 20:30:00 GMT</pubDate>
</item>
<item>
  <title>Purin, 10 ans !</title>
  <link>https://dev.yosko.net/blog/2024/purin-10-ans.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/speech.jpg" class="card img-fluid"></p>
<p>Ça va faire 10 ans que je n’ai quasi rien posté ici&nbsp;! En fait, si, y’a 2 publications qui se courent après. Mais j’ai eu depuis 2016 chaque année un changement majeur dans ma vie qui me faisait revoir mes priorités (j’ai fait un <em>burnout</em>, changé de logement 4 fois, de vie 1 fois, de métier 2 fois et j’ai même trouvé le temps de devenir parent).</p>
<p>Me voilà enfin avec une année «&nbsp;pauvre&nbsp;» en nouveaux évènements&nbsp;: bref, une bonne occasion pour se remettre à poster&nbsp;!</p>
<p>Bon, pas de promesse, hein…</p>
<p>J’en profite pour <em>encore</em> changer de système de blog (après Blogotext puis Pluxml)… Je bascule sur :simple-materialformkdocs: <strong>Material for Mkdocs</strong>.</p>
<p>En effet, je ne voulais plus m’encombrer d’un outil web pour la rédaction d’articles/billets. J’espère ainsi diminuer ce qu’il m’en coûtait en termes d’écriture et de publication, et ainsi augmenter mes chances d’arriver à écrire (et à poster).</p>
<section id="mon-process-pour-linstant" class="level2">
<h2 class="anchored" data-anchor-id="mon-process-pour-linstant">Mon process (pour l’instant)</h2>
<ul>
<li>écriture en Markdown&nbsp;:
<ul>
<li>facile à lire et à écrire sans Internet ni logiciel spécial&nbsp;;</li>
<li>fichiers conservés sur ma machine donc sauvegarde aisée&nbsp;;</li>
</ul></li>
<li>synchronisation par Nextcloud entre mes machines&nbsp;: simple de continuer l’écriture en changement de manchine&nbsp;;</li>
<li>compilation en fichiers plats grâce à Mkdocs (nécessite qu’il soit installé avec tous ses plugins)&nbsp;;</li>
<li>envoi au server&nbsp; par <code>rsync</code> (oui, c’est très manuel, à terme, je basculerai sur <code>git</code> je pense)&nbsp;;</li>
<li><em>profit</em>!</li>
</ul>
</section>
<section id="autres-changements-notables" class="level2">
<h2 class="anchored" data-anchor-id="autres-changements-notables">Autres changements notables</h2>
<ul>
<li>abandon des statistiques (Piwik) : ça faisait longtemps que je n’en tirais rien de constructif de toute façon (pas sûr qu’elles fonctionnaient encore, depuis le temps…).</li>
<li>abandon des commentaire sur le site. À la place, vous pouvez me joindre par e-mail (voir page de <a href="../../à-propos.html">contact</a>)</li>
<li>je vais peut-être faire évoluer mes différents sites pour mieux refléter mon métier actuel (enseignant en informatique), donc mon dokuwiki, mon ancien shaarli et le présent blog seront peut-être fusionnés, j’y réfléchis encore.</li>
</ul>
</section>
<section id="écho-des-abysses" class="level2">
<h2 class="anchored" data-anchor-id="écho-des-abysses">Écho des abysses</h2>
<p>J’avais pas mal de projets qui ont avancé mais que je n’avais pas publié. Je n’ai hélas plus le nez dedans, et ce n’est pas gagné que je m’y remette dans l’immédiat. En vrac&nbsp;:</p>
<ul>
<li><a href="https://github.com/yosko/ddb">:fontawesome-brands-github: DDb v1</a> : elle a tout de même reçu quelques commits jusqu’en 2016&nbsp;;</li>
<li>DDb v2 (bascule sur mon framework maison Watamelo) : jamais finalisée, même si c’était fonctionnel. Il ne manquait que les fonctionnalité d’administration et l’import depuis la v1)&nbsp;;</li>
<li><a href="https://github.com/yosko/watamelo">:fontawesome-brands-github: Watamelo</a> : mon petit framework MVC a continué à évoluer, mais il prend déjà du retard par rapport à une variante que j’ai développé uniquement pour mes enseignements&nbsp;;</li>
<li>D’autres projets sont clairement endormis, même s’ils ont un peu évolué en 10 ans. On en trouve sur :fontawesome-brands-github:&nbsp;Github&nbsp;: <a href="https://github.com/yosko/easydump">Easydump</a>, <a href="https://github.com/yosko/jotter">Jotter</a>, <a href="https://github.com/yosko/yalig">Yalig</a>, <a href="https://github.com/yosko/yoslogin">YosLogin</a>, <a href="https://github.com/yosko/php-github-updater">PHP Github Updater</a> et sans doute plein d’autres trucs.</li>
</ul>
<p>Si vous êtes particulièrement intéressés pour que je remette le nez dans l’un de ces projets, n’hésitez pas à me faire signe.</p>
<blockquote class="blockquote">
<p>“<em>Keep living and write on!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>blabla</category>
  <guid>https://dev.yosko.net/blog/2024/purin-10-ans.html</guid>
  <pubDate>Tue, 16 Apr 2024 13:00:00 GMT</pubDate>
</item>
<item>
  <title>Permissions correctes pour serveur web</title>
  <link>https://dev.yosko.net/blog/2020/permissions-serveur-web.html</link>
  <description><![CDATA[ 




<p>Lorsqu’on met en place un serveur web sous Linux en vu d’y développer (ou au moins déposer) des sites, la question des permissions revient toujours. J’en avais marre de me la poser et j’ai décidé de me rédiger ce petit guide de démarrage.</p>
<p>Cet article est particulièrement rédigé pour Ubuntu/Apache, mais la logique resterait la même pour tout autres système et web serveur.</p>
<p>Pour aller directement aux commandes à exécuter, cliquer ici.</p>
<section id="le-constat" class="level2">
<h2 class="anchored" data-anchor-id="le-constat">Le constat</h2>
<p>Dans le cas d’Ubuntu/Apache, l’utilisateur du serveur web est <code>www-data</code>, et le dossier racine est <code>/var/www/html</code>. Les droits par défaut sur ce dossier sont&nbsp;:</p>
<pre><code>$ ls -al /var/www/html
drwxr-xr-x 2 root root  4096 mai 5 14:39 .
-rw-r--r-- 1 root root 10918 mai 5 14:39 index.html</code></pre>
<p>En conclusion :</p>
<ul>
<li>L’utilisateur propriétaire est <code>root</code> et a les droits de lecture, d’écriture et d’exécution sur le dossier, et de lecture et écriture sur les fichiers</li>
<li>Le groupe propriétaire est <code>root</code> et a les droits de lecture et d’écriture sur le dossier, et de lecture sur les fichiers (en bref, il perd les droits d’écriture, comparé à l’utilisateur).</li>
<li>Le reste du monde a les mêmes droits que le groupe propriétaire.</li>
</ul>
<p>En gros, seul <code>root</code> peut y écrire, et tout le monde (dont <code>www-data</code>) peut lire dans ce dossier. Sauf que :</p>
<ol type="1">
<li>En tant que developeur web, on aimerait bien pouvoir y écrire avec notre compte utilisateur sans avoir besoin de faire eds <code>sudo</code> et des <code>chmod 777</code> à tout va.</li>
<li>L’utilisateur <code>www-data</code>, qui exécute nos sites web, aura parfois lui aussi besoin de pouvoir écrire dans certains sous-dossiers (les dossiers de <strong>cache</strong> ou de <strong>log</strong> par exemple).</li>
</ol>
</section>
<section id="la-solution" class="level2">
<h2 class="anchored" data-anchor-id="la-solution">La solution</h2>
<p>Notre propre compte utilisateur va devenir propriétaire du dossier et de tout son contenu, afin d’avoir systématiquement les droits d’écriture. Le groupe <code>www-data</code> va devenir le groupe propriétaire, ainsi on pourra lui laisser un accès en lecture à ce dossier et en exécution (pour pouvoir les afficher dans le navigateur), et au cas par cas lui ajouter les droits d’écriture.</p>
<div class="callout callout-style-default callout-tip callout-titled" title="N'oublions pas *la règle de base des permissions sous Linux*">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Astuce</span>N’oublions pas <em>la règle de base des permissions sous Linux</em>
</div>
</div>
<div class="callout-body-container callout-body">
<p>Par sécurité, il faut toujours appliquer les permissions les plus stricts, ne donnant des droits que lorsque c’est nécessaire.</p>
</div>
</div>
<p>De ce fait, on va faire en sorte de retirer le droit d’exécution à tous, et de retirer le droit de lecture au reste du monde.</p>
</section>
<section id="les-commandes" class="level2">
<h2 class="anchored" data-anchor-id="les-commandes">Les commandes</h2>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># www-data devient propriétaire et le groupe $USER devient groupe prorpiétaire</span></span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> chown <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> www-data:<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$USER</span> /var/www/html</span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># le propriétaire peut lire, le groupe peut lire et écrire, et le monde ne peut plus rien faire dans ce dossier</span></span>
<span id="cb2-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> chmod <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> u=rx,g=rwX,o= /var/www/html</span></code></pre></div></div>
<p>Après, il suffit d’ajouter au cas par cas les droits d’écriture pour notre serveur web sur les sous-dossiers le nécessitant. Exemple&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource bash number-lines code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># "sudo" devrait être facultatif ici</span></span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sudo</span> chmod <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-R</span> u+w /var/www/html/sous/dossier</span></code></pre></div></div>
<ul>
<li><strong>Edit 19/04/2023</strong> : après réflexion, je préfère l’approche <code>www-data:$USER</code> (corrigé plus haut), plutôt que <code>$USER:www-data</code>, car certain outils exécutés par Apache peuvent vérifier s’ils sont propriétaires de leurs dossiers (comme Nextcloud).</li>
</ul>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Voilà tout ! Je trouve cette solution simple et élégante, tout en restant suffisamment complète pour le besoins de base. Il y aurait sans doute d’autres choses à améliorer donc n’hésitez pas à me faire vos remarques.</p>


</section>

 ]]></description>
  <category>serveur web</category>
  <category>apache</category>
  <guid>https://dev.yosko.net/blog/2020/permissions-serveur-web.html</guid>
  <pubDate>Fri, 05 Jun 2020 16:34:00 GMT</pubDate>
</item>
<item>
  <title>Réponse à : La honte</title>
  <link>https://dev.yosko.net/blog/2016/reponse-a-la-honte.html</link>
  <description><![CDATA[ 




<p>Ce billet est une réaction au billet de Zythom suivant : <a href="https://zythom.blogspot.fr/2016/12/la-honte.html">https://zythom.blogspot.fr/2016/12/la-honte.html</a></p>
<p>Zythom,</p>
<p>Peut-être liras-tu déjà beaucoup de réactions aujourd’hui, peut-être n’auras-tu pas l’occasion de me lire, je ne sais pas. En tout cas ce billet t’es adressé. Peut-être n’as-tu eu qu’une mauvaise passe un peu courte, aussi, et rien de ce que je dirai ne te parleras vraiment. Peut-être que, comme tu le dis, c’est juste une “petite déprime d’homme”. Mais juste au cas où…</p>
<p>Mais au cas où, je souhaitais te raconter ce que je connais, ce que j’ai personnellement traversé. Nos histoires sont sans doute très différentes, et pourtant… Peut-être y verras-tu un écho, quelque chose qui te rassurera un peu. Et peut-être y trouveras-tu quelque chose d’utile. Et peut-être n’en as-tu pas besoin, et est-ce là juste mon occasion à moi de faire comme toi, de transmettre ce que j’ai vécu et ce que j’ai trouvé, pour que ça puisse servir à quelqu’un un jour.</p>
<p>J’ai passé dix années à ne plus savoir ce que c’était que le bonheur. J’ai passé dix ans à mentir à mon entourage quand on me demandait si j’étais heureux, même aux plus proches. Même à ma femme.</p>
<p>Je voulais retrouver le chemin seul vers une vie qui me convenait, mais je ne savais pas comment faire, je ne voulais pas dépendre des autres, et je ne trouvais pas la force de faire ce qu’il fallait. Et ironiquement, j’étais plus dépendant que jamais d’eux.</p>
<p>Et j’avais honte.</p>
<p>J’avais honte d’aller mal, moi qui avait tout pour être heureux, moi qui était marié à une femme aimante et présente, qui me soutenait, moi qui avait une famille à l’écoute et relativement proche, qui avait des amis très proches, présents et attentifs, moi qui avait une situation stable, des études supérieures réussies sans grande difficulté dans cette période, puis un métier passionnant, bien que parfois prenant, et une situation financière relativement enviable. J’avais honte de ne pas être la réussite que tout le monde voyait. J’avais honte de renvoyer cette image fausse, aussi.</p>
<p>J’avais honte de frôler la dépression, sans vouloir admettre que j’avais déjà plus qu’un pied dedans. J’avais honte de frôler le burnout aussi depuis un an à cause du travail, mais même ça, je ne voulais pas reconnaitre à quel point j’en étais proche.</p>
<p>Je ne vais pas rentrer dans des détails personnel, mais j’ai touché le fond en Juillet après quelques chocs importants. Le genre de claque dans la tronche qui te donne exactement ce qu’il faut pour repartir. Je ne le revivrais pour rien au monde, mais je reconnais au moins que ça m’a apporté ce qu’il fallait, et bien plus encore, même si c’était peut-être juste avec 10 ans de retard…</p>
<p>Mais voilà, la remontée de la pente, c’est une étape compliquée aussi. Les envies d’en finir, j’en ai eu quelques unes, mais pendant toutes ces années “difficile”, les choses étaient diffuses, et ces pensées m’avaient un peu laissé tranquille.</p>
<p>Et cet été, j’avais l’entourage nécessaire pour me soutenir, avec enfin la mise à nue de mes problèmes à certains mes proches, prêts à beaucoup donner pour que je puisse m’en sortir. Et ça marchait déjà pas mal, dans l’ensemble.</p>
<p>Mais voilà, dans cette remontée, les envies ont trouvé à quelques occasion le moyen de remonter à la surface, tout comme les pleurs, les vagues de mélancolie. Peut-être est-ce parce que dans les phases de changement, on remue les choses, et même si l’essentiel qui en ressort est plutôt positif, les vagues ont toutes des creux.</p>
<p>Et n’ayons pas peur des mots : beaucoup des suicides ont lieux dans une période où la personne n’était plus au fond du trou, mais bien en train de remonter la pente…</p>
<p>Alors après un moment de grande mélancolie, un matin de Septembre dans la voiture (j’étais passager, hein…), j’ai fais comme toi : je suis allé regarder les symptômes de la dépression sur internet, j’ai regardé une description de ce qu’était la mélancolie. Et ça a frappé un peu trop près de moi pour que je ne me sente pas touché.</p>
<p>Je m’étais déjà posé la question : devrais-je consulter ? Devrais-je aller voir un psy ? Mais non, la réponse était toujours la même : je suis sur la bonne pente, donc pas besoin. J’avance. Je me reconstruis. Pour le meilleur. Le pire aussi ? Non non, il est passé. Ca ? Ce n’est qu’un “coup de mou”, il n’est que passager. Il n’y a rien à craindre…</p>
<p>Ce matin-là dans la voiture, j’ai repensé à un livre que j’avais lu récemment, qui concernait la manipulation, mais qui allait bien au-delà, qui parlait de dépression, de reproduire involontairement de schémas dans l’éducation des enfants. Puis j’ai pensé à cet enfant que nous essayons d’avoir avec ma femme. Et j’ai pensé à mon état.</p>
<p>Quel père allais-je être ? Comment pourrais-je me regarder dans la glace si je ne fais pas tout ce qui est en mon pouvoir pour être en bonne santé mentale lors que j’aurai un enfant à élever ? Est-ce que je ne risquais pas de faire souffrir avant l’heure un être pour lequel je souhaite tout le bonheur du monde, si je n’étais moi-même pas complètement stable ?</p>
<p>Alors j’ai pris la décision d’aller voir un psy. Je ne voulais pas le faire pour moi, alors je l’ai fait pour un hypothétique enfant. Parce que j’avais honte d’admettre que j’en avais besoin. J’aurais pu aller demander conseil à mon médecin traitant, mais j’ai choisis d’en parler à chacune des personnes qui étaient déjà là pour me soutenir. M’engager auprès d’eux était ma manière de ne pas faire machine arrière ensuite. Et j’en ai parlé surtout à ceux que je connaissais qui avaient déjà consulté. J’ai récupéré ainsi le numéro de la psy d’une amie.</p>
<p>Et ensuite, j’ai mis une bonne semaine avant d’oser l’appeler. On m’a dit que c’était bien, que certains mettent plusieurs semaines avant d’y arriver, voir plus encore.</p>
<p>Qu’est-ce qu’allait m’apporter une inconnue, là où mes proches, tous de bons communicants, sincères, attentionnés, ne suffisaient pas ? Je ne saurais l’expliquer, mais ce que je sais, c’est que je l’ai trouvé tout de même. J’ai pu exprimer ce qui s’était petit à petit accumulé, j’ai pu retrouver confiance en moi, j’ai pu retrouver la force d’assumer mon état.</p>
<p>Je ne regrette pas ma décision. Moi, aujourd’hui, je n’ai plus honte d’avoir décidé d’aller voir un psy. Je refuse toujours de considérer que je suis “malade” parce que c’est pas une manière agréable de voir les choses, ni vraiment simple à assumer. Mais j’assume de dire que j’ai besoin de faire ça. J’ai même osé le dire à mes parents. Ces parents auxquels je n’ai jamais osé parler de mes croyances ou de ma sexualité. Et voilà que je leur dit que je consulte un psy. Et qu’ils ne me jugent pas, mais me soutiennent même.</p>
<p>Peut-être cela ne te parles-t-il pas du tout. Peut-être n’as-tu pas autant touché le fond que moi. Peut-être n’en as-tu pas du tout besoin. Ou encore peut-être n’as-tu pas les moyens de l’envisager, que ce soit pour des raisons d’argent, pour des raisons de temps, ou des raisons plus personnelles.</p>
<p>Mais voilà, à toute personne qui a vu le fond d’un peu trop près, et qui s’estime être “en train de remonter la pente” : ne perdez pas de vu que consulter quand on va mal, ce n’est pas une raison d’avoir honte, que c’est normal de vouloir faire “tout ce qu’il faut” pour aller mieux, que ce soit pour vous ou pour votre entourage, et qu’il n’y a pas nécessairement que quand on touche le fond que ça mérite d’être envisagé.</p>
<p>Zythom, merci pour ton partage, qui m’aura donné à moi aussi le coup de pouce nécessaire pour m’exprimer un peu à mon tour. J’aime ta conclusion, simple. “<em>Je ne suis ni un héros, ni un zéro. Je fais de mon mieux. Et parfois, ce n’est pas terrible.</em>”. J’ajouterais juste qu’on n’est pas tenu à faire plus que cela.</p>
<p>Pour moi, 2016 aura été une année douloureuse, mais elle aura aussi été riche, forte et belle. Je te souhaites de le voir ainsi aussi. :)</p>
<p>Yosko</p>



 ]]></description>
  <category>blabla</category>
  <guid>https://dev.yosko.net/blog/2016/reponse-a-la-honte.html</guid>
  <pubDate>Fri, 16 Dec 2016 15:24:00 GMT</pubDate>
</item>
<item>
  <title>[Tuto] Comprendre et utiliser les évènements clavier en Javascript</title>
  <link>https://dev.yosko.net/blog/2014/javascript-évènements-clavier.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/js-card.png" class="card img-fluid"></p>
<p>De nos jour, les raccourcis claviers sont de plus en plus utilisés dans des applications web. Si Google Doc était l’un de ceux qui ont popularisé cette pratique, elle n’est aujourd’hui plus seulement restreinte au traitement de texte.</p>
<p>Nous allons voir aujourd’hui les mécanismes qui entrent en jeu pour capturer les raccourcis saisis par l’utilisateur, et comment les employer. Cet article peut sembler un peu long, mais il vise à expliquer le maximum de notions, qui sont trop souvent oubliées ou simplifiées dans les tutoriels sur le sujet.</p>
<p>Je parle avant tout de raccourcis claviers, mais sachez que tout ceci peut vous être utile dans d’autres cadres, comme la validation de champs de formulaire au fil de la saisie, par exemple.</p>
<ol type="1">
<li>Les évènements</li>
<li>L’objet <code>KeyboardEvent</code></li>
<li>Exemple d’exécution</li>
<li>Remplacer un raccourci navigateur</li>
<li>Méthode de contournement pour Firefox</li>
<li>Conclusion</li>
</ol>
<section id="les-évènements" class="level2">
<h2 class="anchored" data-anchor-id="les-évènements">Les évènements</h2>
<p>Il existe, en Javascript, 3 évènements différents générés par l’utilisation d’une touche de votre clavier :</p>
<ol type="1">
<li><code>keydown</code> / <code>onkeydown</code> : comme son nom l’indique, il est déclenché lorsque la touche est enfoncée.</li>
<li><code>keypress</code> / <code>onkeypress</code> : on dirait un synonyme de <code>keydown</code>. Il est d’ailleurs déclenché juste après, toujours quand on enfonce la touche.</li>
<li><code>keyup</code> / <code>onkeyup</code> : c’est le fait de retirer son doigt de la touche qui le déclenche.</li>
</ol>
<blockquote class="blockquote">
<p>“Quelle est l’utilité d’avoir 2 évènements différents (<code>keydown</code> et <code>keypress</code>) pour la même chose, me direz-vous ?”</p>
</blockquote>
<p>Comme l’explique <a href="http://www.bloggingdeveloper.com/post/KeyPress-KeyDown-KeyUp-The-Difference-Between-Javascript-Key-Events.aspx">ce blogueur</a>, il faut avant tout distinguer les touches servant à écrire des caractères (lettres, chiffres, caractères spéciaux, etc…) des autres touches (<kbd>Ctrl</kbd>, <kbd>Maj</kbd>, <kbd>Alt</kbd>, <kbd>Windows/Commande</kbd>, etc…). Les évènements <code>keydown</code> et <code>keyup</code> expriment le fait d’enfoncer ou relâcher une touche de votre clavier, quelle que soit sa fonction. Par contre <code>keypress</code> exprime <em>théoriquement</em> le fait d’écrire un caractère.</p>
<p>Je dis “<em>théoriquement</em>” car tous les navigateurs n’ont pas exactement le même comportement à ce propos. Tout ce qu’il faut retenir pour le moment, c’est que l’évènement <code>keypress</code> pourra être déclenché par l’appui sur la touche “A”, mais pas par l’appui sur la touche “Contrôle”.</p>
</section>
<section id="lobjet-keyboardevent" class="level2">
<h2 class="anchored" data-anchor-id="lobjet-keyboardevent">L’objet <code>KeyboardEvent</code></h2>
<p>Habituellement, en Javascript, quand on réalise une fonction appelée sur un évènement, celle-ci prend en paramètre un objet de type <code>Event</code>. C’est la variable <code>ev</code> dans les exemples ci-dessous :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource html number-lines code-with-copy"><code class="sourceCode html"><span id="cb1-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">window</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">onload</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(ev) {</span>
<span id="cb1-3">    ev<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">preventDefault</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-4">}</span>
<span id="cb1-5"></span>
<span id="cb1-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">document</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">getElementById</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'myId'</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">addEventListener</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'click'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (ev) {</span>
<span id="cb1-7">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">console</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">log</span>( ev<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">target</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">className</span> )<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-8">})<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-9"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div></div>
<p>Dans le cadre d’évènement issus des touches clavier, cet objet sera de type <code>KeyboardEvent</code>. C’est lui qui indique quelle touche (ou combinaison de touches) a été enfoncée. Voici une liste de ses attributs qui pourront nous être utiles :</p>
<ul>
<li><code>keyCode</code> (entier) : code numérique représentant de façon unique chaque caractère. La table des codes peut différer d’un navigateur/système à un autre (<a href="https://dev.yosko.net/ext/Javascript%20Keyboard%20Events/">tableau comparatif entre les navigateurs</a>)</li>
<li>Attributs indiquant si d’autres touches étaient enfoncées avant que celle-ci le soit aussi :
<ul>
<li><code>altKey</code> (booléen) : indique si la touche <kbd>Alt</kbd> était enfoncée ou non</li>
<li><code>ctrlKey</code> (booléen) : indique si la touche <kbd>Ctrl</kbd> était enfoncée ou non</li>
<li><code>metaKey</code> (booléen) : indique si la touche <kbd>Meta</kbd> (<kbd>Windows</kbd> sur Windows, <kbd>Commande</kbd> sur Mac) était enfoncée ou non</li>
<li><code>shiftKey</code> (booléen) : indique si la touche <kbd>Majuscule</kbd> était enfoncée ou non</li>
</ul></li>
</ul>
<p>Parmi les attributs non cités ci-dessus, on retrouve <code>char</code>, <code>charCode</code> et <code>which</code>, qui sont dépréciés, et doivent être remplacés par <code>key</code>, qui n’est pas actuellement implémenté (un comble !). En fait, même <code>keyCode</code> est déprécié, et sera remplacé par <code>key</code> au final (ils ont des fonctionnements très proches), mais en attendant, on continue à l’utiliser. Pour une liste exhaustive des attributs, <a href="https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent"><abbr title="Read The Friggin' Manual!">RTFM</abbr></a>.</p>
</section>
<section id="exemple-dexécution" class="level2">
<h2 class="anchored" data-anchor-id="exemple-dexécution">Exemple d’exécution</h2>
<p>Imaginons que vous souhaitez effectuer une combinaison de touches (prenons par exemple <code>Ctrl+S</code>, comme quand vous voulez sauvegarder une page). Dans la pratique, voici dans l’ordre les évènements qui ont lieu, ainsi que les valeurs des attributs de l’objet <code>KeyboardEvent</code> dans chaque cas (testé sur Firefox) :</p>
<ol type="1">
<li><code>keydown</code> (on vient d’appuyer sur <kbd>Contrôle</kbd>)
<ul>
<li><code>keyCode = 17</code> (code correspondant à la touche <kbd>Contrôle</kbd>)</li>
<li><code>altKey = false</code></li>
<li><code>ctrlKey = true</code></li>
</ul></li>
<li><code>keydown</code> (on vient d’appuyer sur <kbd>S</kbd>)
<ul>
<li><code>keyCode = 83</code> (code correspondant à la touche <kbd>S</kbd>)</li>
<li><code>altKey = false</code></li>
<li><code>ctrlKey = true</code></li>
</ul></li>
<li><code>keypress</code> (on vient d’appuyer sur <kbd>S</kbd>, la touche <kbd>Contrôle</kbd> est toujours enfoncée)
<ul>
<li><code>keyCode = 83</code> (code correspondant à la touche <kbd>S</kbd>)</li>
<li><code>altKey = false</code></li>
<li><code>ctrlKey = true</code></li>
</ul></li>
</ol>
<p>On constate bien que <code>keypress</code> n’a pas lieu quand on appui sur “Contrôle”. De même on constate que quand on appui sur <kbd>S</kbd>, les évènements <code>keydown</code> et <code>keypress</code> se suivent et comportent des informations identiques.</p>
<blockquote class="blockquote">
<p>“Mais du coup <code>keydown</code> nous suffit amplement, à quoi bon s’intéresser à <code>keypress</code>&nbsp;?”</p>
</blockquote>
<p>Vous avez parfaitement raison ! En <em>théorie</em> cet évènement est dépriécié (comme le reste de <a href="https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#event-type-keypress">DOM L3</a>. La norme HTML5 apporte, comme l’indique la <a href="https://developer.mozilla.org/en-US/docs/Web/Reference/Events/keypress">doc de Mozilla</a>, un remplaçant dans l’évènement <code>input</code>).</p>
<p>Hélas, tout ceci n’est bien que cela : de la <em>théorie</em>. Vous allez pouvoir vous en rendre compte dans le chapitre suivant.</p>
</section>
<section id="remplacer-un-raccourci-navigateur" class="level2">
<h2 class="anchored" data-anchor-id="remplacer-un-raccourci-navigateur">Remplacer un raccourci navigateur</h2>
<p>Reprenons notre exemple de raccourci : <kbd>Ctrl</kbd>+<kbd>S</kbd>. Si vous l’employez sur une page web dans votre navigateur, ce dernier vous proposera probablement d’enregistrer une sauvegarde de la page courante (c’est le cas de Firefox et Chrome, et sans doute d’autres).</p>
<p>Imaginons que vous réalisez une application web de prise de note (au hasard, <a href="https://github.com/yosko/jotter">Jotter</a>). Vous aurez besoin de laisser la possibilité à vos utilisateurs de sauvegarder ce qu’ils ont saisi vers le serveur de votre appli. Vous savez aussi que, sauf besoin très spécifique, ils n’auront pas besoin de sauvegarder le HTML de la page en cours vers leur ordinateur.</p>
<p>Naturellement, vous décider de remplacer le fonctionnement par défaut de votre navigateur par celui de votre application. Voici le code de base pour le réaliser :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource javascript number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb2-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">document</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">addEventListener</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'keydown'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (e){</span>
<span id="cb2-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ctrlKey</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keyCode</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'S'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">charCodeAt</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)) {</span>
<span id="cb2-3">        e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">preventDefault</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-4">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//app-specific code goes here</span></span>
<span id="cb2-5">    }</span>
<span id="cb2-6">})<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>Décorticons ce code. On commence par vérifier si l’évènement est survenu sur la combinaison de touches <kbd>Ctrl</kbd>+<kbd>S</kbd> grâce aux attributs <code>ctrlKey</code> et <code>keyCode</code>. <code>'S'.charCodeAt(0)</code> est une manière plus lisible d’indiquer le code de la lettre S (qui est 83 dans tous les navigateurs).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource javascript number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb3-1">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ctrlKey</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keyCode</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'S'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">charCodeAt</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)) {</span></code></pre></div></div>
<p>Ensuite, on demande d’annuler l’effet par défaut associé à cette combinaison de touches :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource javascript number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb4-1">        e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">preventDefault</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>Il ne reste ensuite plus qu’à réaliser les actions spécifiques à notre application (comme par exemple faire une requête ajax pour enregistrer sur le serveur les données saisies par l’utilisateur). C’est ce que j’ai désigné par :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource javascript number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb5-1">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//app-specific code</span></span></code></pre></div></div>
<p>Si vous utilisez ce code, vous constaterez que, en fonction du code spécifique que vous ajoutez, parfois Firefox proposera malgré tout à l’utilisateur de sauvegarder la page sur son ordinateur. Et là, vous vous dites :</p>
<figure class="figure">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="http://img.yosko.net/img/gif/wat/pourquoi.gif" class="img-fluid figure-img"></p>
<figcaption>Pourquoi ?!?</figcaption>
</figure>
</div>
<figcaption>
… et vous avez parfaitement raison !
</figcaption>
</figure>
<p>Explication fumeuse : Firefox se base sur <code>keypress</code> pour gérer les raccourcis clavier qu’il a de définis (ce qui n’est pas forcément le cas des autres navigateurs, à vérifier). Jusqu’ici tout va bien. Il respecte en théorie la norme qui dit que si l’évènement par défaut de <code>keydown</code> est stoppé (via <code>.preventDefault()</code>), alors celui de <code>keypress</code> devrait l’être aussi.</p>
<p>Et Firefox le fait, la plupart du temps. Mais il suffit que votre code “app-specific” contienne certains bouts de code (comme un bête <code>alert()</code>) pour que <code>.preventDefault()</code> ne suffise plus. En fait, même si vous utilisez l’un des deux bouts de code ci-dessous, rien n’y fera, et Firefox exécutera quand même le :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource javascript number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb6-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">document</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">addEventListener</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'keydown'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (e){</span>
<span id="cb6-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ctrlKey</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keyCode</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'S'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">charCodeAt</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)) {</span>
<span id="cb6-3">        e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">preventDefault</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb6-4">        e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stopPropagation</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb6-5">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//app-specific code</span></span>
<span id="cb6-6">    }</span>
<span id="cb6-7">})<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>Ou :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource javascript number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb7-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">document</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">addEventListener</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'keydown'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (e){</span>
<span id="cb7-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ctrlKey</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keyCode</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'S'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">charCodeAt</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)) {</span>
<span id="cb7-3">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//app-specific code</span></span>
<span id="cb7-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">false</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb7-5">    }</span>
<span id="cb7-6">})<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>Le pire est que dans ce cas précis, l’évènement <code>keypress</code> verra son <code>Event.keyCode</code> à 0 au lieu de 83 (pour S)…</p>
</section>
<section id="méthode-de-contournement-pour-firefox" class="level2">
<h2 class="anchored" data-anchor-id="méthode-de-contournement-pour-firefox">Méthode de contournement pour Firefox</h2>
<p>Du coup, la solution consiste à contrôler dès le <code>keydown</code> si on doit annuler l’évènement <code>keypress</code>, puisque ce dernier n’est même plus capable de savoir quelle touche a été enfoncée&nbsp;:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource javascript number-lines code-with-copy"><code class="sourceCode javascript"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//must be accessible from both keydown and keypress events</span></span>
<span id="cb8-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> cancelKeypress <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">false</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb8-3"></span>
<span id="cb8-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">document</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">addEventListener</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'keydown'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (e){</span>
<span id="cb8-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">ctrlKey</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">keyCode</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'S'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">charCodeAt</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)) {</span>
<span id="cb8-6">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//do this prior to anything else</span></span>
<span id="cb8-7">        cancelKeypress <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb8-8"></span>
<span id="cb8-9">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//might still be useful for other browsers</span></span>
<span id="cb8-10">        e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">preventDefault</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb8-11"></span>
<span id="cb8-12">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//app-specific code goes here</span></span>
<span id="cb8-13">    }</span>
<span id="cb8-14">})<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb8-15"></span>
<span id="cb8-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//workaround for Firefox:</span></span>
<span id="cb8-17"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">document</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">addEventListener</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'keypress'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (e){</span>
<span id="cb8-18">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//must probably be done prior to anything else</span></span>
<span id="cb8-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(cancelKeypress <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">===</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span>) {</span>
<span id="cb8-20">        e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">preventDefault</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb8-21">        cancelKeypress <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">false</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb8-22">    }</span>
<span id="cb8-23">})<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>Je vous l’avais bien dit que ce satané <code>keypress</code> nous servirait à quelque chose.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Vous avez désormais une base vraiment solide pour gérer les évènements clavier en Javascript. Nous avons abordé les logiques générales, et le reste pourra généralement se trouver dans la doc.</p>
<p>Nous avons malgré tout pu constater que certaines spécificités des différents navigateurs rendaient ce sujet un peu plus complexe que prévu. Si ces spécificités sont parfois documentées, vous aurez sans doute souvent à farfouiller les forums ou expérimenter par vous même pour trouver réponse à vos questions.</p>
<p>J’ajouterai aussi que même si les raccourcis claviers dans une appli web, ça peut avoir la classe, n’oubliez pas que cela n’est pas toujours judicieux, et que si vous remplacez les comportements d’un navigateur par quelque chose de nouveau, cela peut déstabiliser vos utilisateurs, au risque de les rendre insatisfaits.</p>
<blockquote class="blockquote">
<p>“<em>Keep typing &amp; rock on!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>javascript</category>
  <guid>https://dev.yosko.net/blog/2014/javascript-évènements-clavier.html</guid>
  <pubDate>Tue, 11 Feb 2014 18:50:00 GMT</pubDate>
</item>
<item>
  <title>L’effet sebsauvage /</title>
  <link>https://dev.yosko.net/blog/2013/effet-sebsauvage.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/speech.jpg" class="card img-fluid"></p>
<p>On a le sentiment de célébrité lorsqu’on s’étonne d’être cité par des personnes qu’on estime célèbres elles-mêmes, qu’on respecte, voire qu’on vénère. Mais finalement, la célébrité, n’est-ce pas s’étonner d’être cité par des personnes qu’on ne connait justement pas ?</p>
<p>Tout ça pour dire qu’après de nombreux autres, j’ai eu le droit moi aussi à mon effet sebsauvage<sup>™</sup>, et plusieurs fois même.</p>
<section id="lhistoire" class="level2">
<h2 class="anchored" data-anchor-id="lhistoire">L’histoire</h2>
<p>Pour ceux qui dormiraient dans une grotte depuis plus de deux ans (je ne vois que ça, parce que parmi mes lecteurs, qui ne lit pas sebsauvage ?), l’effet sebsauvage<sup>™</sup> est l’effet que <a href="http://sebsauvage.net/">sebsauvage</a> a sur les visites d’un site autre que le sien rien qu’en partageant un lien vers ledit site via <a href="http://sebsauvage.net/links/">son shaarli</a>.</p>
<p>Y’avait pas mal de monde à être passé par là :</p>
<ul>
<li><a href="http://blog.m0le.net/2011/12/20/dialogue-avec-sebsauvage-1-crypto-steno-tor-etc/">m0le, le 20/12/2011</a></li>
<li><a href="http://sametmax.com/leffet-sebsauvage/">Sam &amp; Max, le 04/05/2012</a></li>
<li><a href="http://wwz.suumitsu.eu/2012/06/20/leffet-sebsauvage/">Mitsu, le 20/06/2012</a></li>
<li><a href="http://www.warriordudimanche.net/article4/oyez-oyez-ouverture-d-un-blog-ha-mais-chuis-tout-seul">Bronco, le 05/10/2012</a></li>
<li><a href="http://tontof.net/?1349513259">Tontof, le 06/10/2012</a></li>
<li><a href="http://totaltotaltotal.wordpress.com/2012/10/27/o/">taxalot, le 27/10/2012</a></li>
<li><a href="http://orangina-rouge.org/blogotext/index.php?d=2012/12/13/09/37/26-leffet-seb-sauvage">OranginaRouge, le 20/12/2012</a></li>
<li><a href="http://www.korezian.net/2013/02/06/leffet-sebsauvage/#more-5740">Korezian, le 06/02/2013</a></li>
<li><a href="http://fox-photography.net63.net/leffet-sebsauvage/">Fox, le 02/03/2013</a></li>
<li><a href="http://chroniques-de-sammy.blogspot.fr/2013/04/teste-pour-vous-leffet-sebsauvage.html">Sammy, le 18/04/2013</a></li>
<li><a href="http://strak.ch/le-fameux-effet-sebsauvage/">Strak, le 02/09/2013</a></li>
<li><a href="http://www.ademcan.net/?d=2013/09/09/14/52/37-the-sebsauvage-effect">ademcan, le 10/09/2013</a></li>
<li>… et sans doute bien d’autres que j’ai oublié (Idleman, j’ai rien trouvé chez toi à ce propos…)</li>
</ul>
<p>Mais le plus important, ce que l’effet sebsauvage n’est pas la cause uniquement de Seb. En fait il n’est que l’élément déclencheur. Ce sont les nombreux visiteurs, ces gens connus ou inconnus, qui viennent grossir les logs de connexion de nos serveurs chéris.</p>
</section>
<section id="et-moi-et-moi-et-moi" class="level2">
<h2 class="anchored" data-anchor-id="et-moi-et-moi-et-moi">Et moi, et moi, et moi ?</h2>
<p>J’en avais rêvé. Eh bien j’ai eu non pas un effet, non pas deux effets, non pas trois effets, non pas quatre effets, non pas cinq effets, non pas six effets, mais bel et bien sept effets sebsauvage<sup>™</sup>&nbsp;!&nbsp;<sup>1</sup></p>
<p>Sans plus attendre :</p>
<figure class="figure">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://dev.yosko.net/blog/2013/assets/piwik-effet-sebsauvage.png" class="img-fluid figure-img"></p>
<figcaption>Statistiques visite du site (pics effet sebsauvage)</figcaption>
</figure>
</div>
</figure>
<p>Comme <a href="http://vivihome.net/2013/10/08/achievement-quote-sebsauvage-coche/">dirait Alban</a>, Achievement Unlocked&nbsp;:</p>
<figure class="figure">
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://dev.yosko.net/blog/2013/assets/achievement-sebsauvage.png" class="img-fluid figure-img"></p>
<figcaption>Achievement Unlocked - Explosez vos stats en vous faisant citer par Seb</figcaption>
</figure>
</div>
</figure>
<p>A noter que les deux plus petits sont en fait des coups de pouce de Bronco et Timo&nbsp;:)</p>
</section>
<section id="shaarli-nawel-et-ouverture" class="level2">
<h2 class="anchored" data-anchor-id="shaarli-nawel-et-ouverture">Shaarli, Nawel et ouverture</h2>
<p><em>Attention : cette section de l’article est bourrée de petits coeurs et de sentiments niais et dégoulinants. Lisez-la à vos risques et périls.</em></p>
<p>Du coup, merci à toi, Seb, et merci à tous les autres blogueurs ou shaarlieurs gravitant dans la même blogosphère et ayant éprouvé un quelconque intérêt à mes propos. Pour vous, je m’engage à persister dans mon travail et mes écrits pour vous apporter encore et toujours plus de choses qui éveilleront votre curiosité.</p>
<p>D’ailleurs, j’en profite pour vous exprimer tout le plaisir que j’ai à profiter de cette blogosphère, et à y participer, parce qu’elle est pour moi un monde de passion et d’ouverture. Ouverture au sens “open-source”, mais aussi au sens où tout un chacun peu y lire et y écrire librement.</p>
<p>Oh et merci à mon bienfaiteur (qui se reconnaitra) pour son cadeau de <a href="http://yome.ch/papa-nawel-surprise-des-shaarlieurs/">Nawel des shaarlieurs</a>.</p>
<blockquote class="blockquote">
<p>“<em>Keep blogging &amp; stay free!</em>”</p>
</blockquote>


</section>


<div id="quarto-appendix" class="default"><section id="footnotes" class="footnotes footnotes-end-of-document"><h2 class="anchored quarto-appendix-heading">Notes de bas de page</h2>

<ol>
<li id="fn1"><p>le premier à reconnaitre cette obscure référence gagnera un petit cadeau. Non non, je ne déconne pas. Faut juste être prêt à me donner votre adresse postale, et je vous envoie une récompense. J’exclus juste mes potes IRL, parce que je sais qu’ils la connaissent tous, donc c’est pas drôle :P↩︎</p></li>
</ol>
</section></div> ]]></description>
  <category>blabla</category>
  <guid>https://dev.yosko.net/blog/2013/effet-sebsauvage.html</guid>
  <pubDate>Tue, 17 Dec 2013 13:00:00 GMT</pubDate>
</item>
<item>
  <title>[Snippet #05 - PHP] téléchargement de fichiers par lots</title>
  <link>https://dev.yosko.net/blog/2013/snippet-php-batch-download.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/php-card.png" class="card img-fluid"></p>
<p>Je viens de me réaliser un petit script de “batch download” en PHP (téléchargement par lot, en bon français) et me disais qu’il pourrait être intéressant de vous le partager avec quelques petites explications.</p>
<section id="lhistoire" class="level2">
<h2 class="anchored" data-anchor-id="lhistoire">L’histoire</h2>
<p>Comme vous le savez peut-être déjà, le site <a href="http://wallbase.cc/">Wallbase.cc</a> (merveilleux site de wallpapers, sans pub, très agréable à naviguer et très bien fourni) <a href="https://links.yosko.net/?VMuYLw">est en train de mourir</a> depuis quelques mois, du fait de la disparition de son administrateur.</p>
<p>De plus, depuis peu quelqu’un (par le biais d’un bot&nbsp;?) est en train de supprimer tous les fonds d’écran du site, et <a href="http://wallbase.cc/forum/topic/5863/60">les modérateurs galèrent à freiner ce problème</a>. Ils conseillent donc de télécharger les wallpapers qu’on a mis en favoris avant que ceux-ci ne disparaissent.</p>
<p>C’est donc ce que j’ai fait, aidé d’un <a href="http://userscripts.org/scripts/show/180620">script Greasemonkey</a> pour récupérer plus rapidement les liens de téléchargement. Ensuite, j’aurais pu donner un petit coup de DownThemAll! et le tour était joué. Mais j’ai préféré scripter ça et envoyer direct sur mon propre serveur.</p>
<p><strong>Edit 2013-12-17 :</strong> j’ai même l’impression que c’est pire que cela. Le forum ne semble plus accessibles (certains fichiers manquants ?). Mais si c’est effectivement une attaque, elle me semble plutôt étrange…</p>
</section>
<section id="le-principe" class="level2">
<h2 class="anchored" data-anchor-id="le-principe">Le principe</h2>
<p>En réalité, tout repose sur une fonction PHP bien simple nommée <a href="http://www.php.net/manual/en/function.copy.php">copy()</a>. Celle-ci permet, comme vous vous en doutez, de copier un fichier d’un emplacement à un autre, et ce même depuis une URL (du moins depuis PHP 4.3).</p>
<p>Ainsi, pour copier une image d’un autre serveur vers le votre, il suffit de faire :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&lt;?php</span></span>
<span id="cb1-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$result</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">copy</span>(</span>
<span id="cb1-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'http://www.example.com/image.jpg'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/* other server */</span></span>
<span id="cb1-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/var/www/my-images/image.jpg'</span>      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/* your server */</span></span>
<span id="cb1-5">)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<p>Le reste de mon script n’est en fait qu’un ensemble de commodités :</p>
<ul>
<li><strong>multiples URLs</strong> : saisie dans un <code>textarea</code> des URLs de tous les fichiers à récupérer (une URL par ligne)</li>
<li><strong>Erreurs</strong> : affichage d’un log des réussites et échecs de téléchargement</li>
<li><strong>Téléchargement groupé</strong> : compression de tous les fichiers dans un ZIP pour pouvoir les télécharger en une fois</li>
</ul>
<p>Vous pouvez vous-même choisir le nom du zip généré. Si vous demandez à regénérer un zip du même nom, l’ancien sera écrasé. Ainsi, si vous avez besoin d’en créer plusieurs en vue de les récupérer plus tard, c’est possible.</p>
</section>
<section id="configuration-requise" class="level2">
<h2 class="anchored" data-anchor-id="configuration-requise">Configuration requise</h2>
<ul>
<li>PHP 4.3 ou supérieur (à vérifier, PHP 5 conseillé)</li>
<li>Droits d’écriture sur le dossier où vous placerez le script. A noter que des sous-dossier et des fichiers zips seront créés et supprimés, il est donc préférable de donner au script son propre dossier.</li>
</ul>
</section>
<section id="le-code-complet" class="level2">
<h2 class="anchored" data-anchor-id="le-code-complet">Le code complet :</h2>
<p><strong>Edit :</strong> J’ai créé <a href="https://gist.github.com/yosko/7989061">un Gist correspondant</a>, où je pourrai faire d’éventuelles révisions, et où vous pourrez me faire vos remarques.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb2-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;!</span>doctype html<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-2"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;!--</span></span>
<span id="cb2-3"><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">PHP</span> Batch Download Script</span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@</span>author Yosko <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>www<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>yosko<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>net<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-6"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@</span>copyright none<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">:</span> free <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">and</span> opensource</span>
<span id="cb2-7"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">@</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">link</span> https<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">:</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//www.yosko.net/2013/snippet-php-batch-download.html</span></span>
<span id="cb2-8"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>-&gt;</span>
<span id="cb2-9"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>html lang<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"en-US"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-10"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>head<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-11">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>meta charset<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"UTF-8"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-12">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>title<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>Batch Downloader<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>title<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-13">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-14">textarea {</span>
<span id="cb2-15">    width<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-16">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">min</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>height<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">:</span> <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>em<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-17">}</span>
<span id="cb2-18">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-19"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>head<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-20"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>body<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-21">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>h1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>Batch Downloader<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>h1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-22"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php</span>
<span id="cb2-23"></span>
<span id="cb2-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//config</span></span>
<span id="cb2-25"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">error_reporting</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">E_ALL</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">E_STRICT</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-26"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ini_set</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'display_errors'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'On'</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-27"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set_time_limit</span> ( <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">180</span> )<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span> <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//facultative: to avoid timeout</span></span>
<span id="cb2-28"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob_flush</span>()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">flush</span>()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-29"></span>
<span id="cb2-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//recursive rmdir from php.net</span></span>
<span id="cb2-31"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> delTree(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$dir</span>) {</span>
<span id="cb2-32">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$files</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">array_diff</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scandir</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$dir</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">array</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'.'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'..'</span>))<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-33">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">foreach</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$files</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$file</span>) {</span>
<span id="cb2-34">        (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">is_dir</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$dir</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$file</span>)) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span> delTree(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$dir</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$file</span>) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unlink</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$dir</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$file</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-35">    }</span>
<span id="cb2-36">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rmdir</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$dir</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-37">}</span>
<span id="cb2-38"></span>
<span id="cb2-39"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$errors</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">array</span>()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-40"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$urlString</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-41"></span>
<span id="cb2-42"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//a list of URLs to download was given</span></span>
<span id="cb2-43"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">isset</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$_POST</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'urls'</span>])</span>
<span id="cb2-44">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">isset</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$_POST</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'directory'</span>])</span>
<span id="cb2-45">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">strpos</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$_POST</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'directory'</span>]<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'..'</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">===</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">false</span></span>
<span id="cb2-46">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">strpos</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$_POST</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'directory'</span>]<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/'</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">===</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">false</span></span>
<span id="cb2-47">) {</span>
<span id="cb2-48"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span></span>
<span id="cb2-49">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>ul<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-50"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php</span>
<span id="cb2-51"></span>
<span id="cb2-52">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$urls</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">explode</span>(<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">PHP_EOL</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$_POST</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'urls'</span>])<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-53">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$directory</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">trim</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$_POST</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'directory'</span>])<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-54">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">empty</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$directory</span>)) { <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$directory</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'files'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span> }</span>
<span id="cb2-55">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$zipFile</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$directory</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'.zip'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-56"></span>
<span id="cb2-57">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//temporary directory to put the files into</span></span>
<span id="cb2-58">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">file_exists</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$directory</span>)) {</span>
<span id="cb2-59">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">mkdir</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$directory</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-60">    }</span>
<span id="cb2-61">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//temporary archive file for download</span></span>
<span id="cb2-62">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">file_exists</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$zipFile</span>)) {</span>
<span id="cb2-63">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unlink</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$zipFile</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-64">    }</span>
<span id="cb2-65"></span>
<span id="cb2-66">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//try and download each file</span></span>
<span id="cb2-67">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">foreach</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$urls</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$url</span>) {</span>
<span id="cb2-68">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$url</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">trim</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$url</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-69">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$filename</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">basename</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$url</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-70">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$success</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">copy</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$url</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$directory</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">DIRECTORY_SEPARATOR</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$filename</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-71">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$success</span>) {</span>
<span id="cb2-72">            <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'&lt;li&gt;'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$filename</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">' : OK&lt;/li&gt;'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-73">        } <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {</span>
<span id="cb2-74">            <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$errors</span>[] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$url</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-75">            <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'&lt;li&gt;'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$filename</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">' : KO (source = &lt;a href="'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$url</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'"&gt;'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$url</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'&lt;/a&gt;)&lt;/li&gt;'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-76">        }</span>
<span id="cb2-77">        <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ob_flush</span>()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">flush</span>()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-78">    }</span>
<span id="cb2-79"></span>
<span id="cb2-80">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//zip files</span></span>
<span id="cb2-81">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$zip</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">ZipArchive</span>()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-82">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$zip</span>-&gt;open(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$zipFile</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">ZIPARCHIVE</span>::<span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">CREATE</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">===</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span>) {</span>
<span id="cb2-83">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">foreach</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">glob</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$directory</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/*'</span>) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$file</span>) {</span>
<span id="cb2-84">            <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$zip</span>-&gt;addFile(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$file</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-85">        }</span>
<span id="cb2-86">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$zip</span>-&gt;close()<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-87">    }</span>
<span id="cb2-88"></span>
<span id="cb2-89">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//delete directory</span></span>
<span id="cb2-90">    delTree(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$directory</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-91"></span>
<span id="cb2-92"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span></span>
<span id="cb2-93">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>ul<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-94">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-95">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">echo</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$urls</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">file</span>(s)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-96">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">echo</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$urls</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$errors</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span> successe(s)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-97">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">echo</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">count</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$errors</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">error</span>(s)</span>
<span id="cb2-98">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-99">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>Download <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>a href<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"&lt;?php echo </span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$zipFile</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">; ?&gt;"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">echo</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$zipFile</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&lt;/</span>p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-100">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span>Errors <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">:</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>p<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-101">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>ul<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-102"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">foreach</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$errors</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$error</span>) { <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span></span>
<span id="cb2-103">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>li<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">echo</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$errors</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>li<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-104"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php } <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// end loop on errors </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span></span>
<span id="cb2-105">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>ul<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-106"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php } <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// end form post </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span></span>
<span id="cb2-107">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>form method<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"POST"</span> target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-108">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>input type<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"text"</span> name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"directory"</span> placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Destination file..."</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;.</span>zip</span>
<span id="cb2-109">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>textarea name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"urls"</span> placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Put each URL on a different line"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-110"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">?</span>php</span>
<span id="cb2-111"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">foreach</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$errors</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">as</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$error</span>) {</span>
<span id="cb2-112">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">echo</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$error</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">PHP_EOL</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-113">}</span>
<span id="cb2-114"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">?&gt;</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>textarea<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-115">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>input type<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"submit"</span> name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"submitURLs"</span> value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Download"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-116">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>form<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-117"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>body<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-118"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;/</span>html<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div></div>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Certes, le code est encore un peu grossier (“rough around the edges”, j’ai envie de dire). Mais à défaut de la vie, il m’aura au moins sauvé mes favoris Wallbase.cc. Comme toujours, si vous avez des critiques ou questions, je suis à votre écoute :)</p>
<blockquote class="blockquote">
<p>“<em>Keep calm &amp; download!</em>”</p>
</blockquote>


</section>

 ]]></description>
  <category>php</category>
  <guid>https://dev.yosko.net/blog/2013/snippet-php-batch-download.html</guid>
  <pubDate>Mon, 16 Dec 2013 15:30:00 GMT</pubDate>
</item>
<item>
  <title>Jotter, notebook manager</title>
  <link>https://dev.yosko.net/blog/2013/jotter-notebook-manager.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/blog/2013/assets/jotter.png" class="card img-fluid"></p>
<ul>
<li>Si vous rêvez de gérer vos notes en ligne</li>
<li>Si vous voulez un outil simple, léger et agréable</li>
<li>Si vous voulez héberger votre propre équivalent à KeepNote / EverNote</li>
</ul>
<p>Alors Jotter est fait pour vous !</p>
<section id="jotter-ˈdʒɒtə" class="level2">
<h2 class="anchored" data-anchor-id="jotter-ˈdʒɒtə">Jotter [ˈdʒɒtə]</h2>
<p><em><strong>UK, noun</strong>: a small book with blank pages for recording notes.</em></p>
<p>Jotter est un petit gestionnaire de notes en ligne à héberger sur votre serveur. Il est réalisé en PHP et ne nécessite pas de base de données.</p>
<p><img src="https://dev.yosko.net/blog/2013/assets/jotter-v0.1.png" class="img-fluid"></p>
<p>Principales fonctionnalités :</p>
<ul>
<li>Editeur <abbr title="What You See Is What You Get">WYSIWYG</abbr> moderne pour plus de confort, avec raccourcis claviers pour la sauvegarde et la mise en forme</li>
<li>Organistion des notes sous forme d’arborescence dans un bloc-note</li>
<li>Gestion de plusieurs blocs-notes</li>
<li>Gestion multi-utilisateur</li>
<li>Pas de base de données : tout est stocké sous forme de fichiers plats (JSON et Markdown)</li>
</ul>
</section>
<section id="téléchargement-et-informations" class="level2">
<h2 class="anchored" data-anchor-id="téléchargement-et-informations">Téléchargement et informations</h2>
<p>Le projet est disponible sur <a href="https://github.com/yosko/jotter">sa page GitHub</a>. <del><strong>Edit :</strong> et une démo est <a href="http://tools.yosko.net/demos/jotter/">disponible à cette adresse</a></del> (lien mort).</p>
<p>Vous y trouverez les dernières mises à jours, un guide d’installation, les fonctionnalités prévues pour les versions futures, les informations de license, etc…</p>
<p>Comme toujours, je vous invite à me transmettre toute remarque ou question à propos de Jotter, par mail ou via GitHub. Par contre, petit aveu : j’ai voulu faire léger, et j’ai parfois mis de côté la qualité du code. Ce n’est pas le plus beau code que vous verrez de moi… <sup></sup>’</p>
<blockquote class="blockquote">
<p>“<em>Keep calm &amp; take notes</em>”</p>
</blockquote>
<p><strong>Edit 2013-11-22 :</strong> une première mise-à-jour avec des correctifs et améliorations ergonomiques est disponible sur Github. Aperçu <em>indisponible</em></p>
<p>La suite devrait se passer là-bas aussi :-)</p>


</section>

 ]]></description>
  <category>projets</category>
  <category>php</category>
  <guid>https://dev.yosko.net/blog/2013/jotter-notebook-manager.html</guid>
  <pubDate>Fri, 15 Nov 2013 11:40:00 GMT</pubDate>
</item>
<item>
  <title>[Lecture] Digital Fortress, de Dan Brown</title>
  <link>https://dev.yosko.net/blog/2013/digital-fortress.html</link>
  <description><![CDATA[ 




<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://dev.yosko.net/blog/2013/assets/digital-fortress.jpg" class="img-fluid figure-img" data-align="right"></p>
<figcaption>Couverture de Digital Fortress</figcaption>
</figure>
</div>
<p>J’ai terminé il y a peu le roman “Digital Fortress”, de Dan Brown, et je ne résiste pas à l’envie de vous en parler.</p>
<p>Pour Rappel, Dan Brown est l’auteur à succès qui nous a apporté Da Vinci Code et Anges et Démons. Digital Fotress est son tout premier roman, sorti en 1998, et parlant… des cryptographes de la NSA.</p>
<p>Et c’est fou comme son oeuvre est criante de vérité. Alors bien sûr, il ne faut pas oublier qu’il s’agit d’une oeuvre de fiction. Mais les parallèles avec l’affaire Snowden sont assez faciles à faire. D’autant plus que, comme je le disais, cette oeuvre date de 1998, période à laquelle la NSA n’avait pas encore l’excuse du 11 Septembre 2001.</p>
<section id="lhistoire" class="level2">
<h2 class="anchored" data-anchor-id="lhistoire">L’histoire</h2>
<p>Je vais vous spoiler un peu le livre : l’héroïne, Susan Fletcher, bosse pour la section Crypto de la NSA, sous la direction de Trevor Strathmore. Vers le début, le livre évoque leurs déboires avec l’EFF (<a href="https://fr.wikipedia.org/wiki/Electronic_Frontier_Foundation">définition</a>) et les implications éthiques de leur antagonisme (ça commence plutôt bien), puis le scandale causé par Strathmore quelques années auparavant lorsqu’il avait glissé une backdoor dans un algo de cryptage destiné au grand public, mais révélé par un cryptographe de génie (que la NSA a fini par engager).</p>
<p>D’autres méthodes douteuses (et fictives ? :D ) de la NSA y sont évoquées, et même employées au cours du récit, à commencer par le mensonge (justification de l’emploi d’outils de surveillance de masse en <a href="http://www.numerama.com/magazine/27146-la-nsa-admet-avoir-exagere-la-menace-terroriste-pour-justifier-la-surveillance.html">grossissant les chiffres du terrorisme</a>), les assassinats ou les arrestations injustifiées des opposants pacifistes, etc….</p>
<p>Au moment où se déroule le récit, ces trois personnages travaillent sur TRANSLATR, un super-ordinateur gigantesque tournant 24h/24 et 7j/7 pour brute-forcer (<a href="https://fr.wikipedia.org/wiki/Attaque_par_force_brute">définition</a>) des fichiers cryptés en tous genres. Il passe généralement entre 1/2 seconde et 11 minutes sur chaque fichier.</p>
<p>La méthode de collecte des fichiers craqués par TRANSLATR n’est pas précisée, même si une organisation complexe découpée en services est décrite, laissant facilement imaginer un PRISM pas loin.</p>
<p>Un génie du nom d’Ensei Tankado, ancien de leur service mais qui les avait quittés pour des raisons morales (Edward Snowden, c’est toi ?), sort un nouvel algorithme soi-disant incraquable, et ne le révèle qu’à un nombre limité de personnes, dans le but de faire du chantage à la NSA : “révélez l’existence de votre TRANSLATR ou bien je file mon algo à tout le monde et vous ne pourrez plus jamais lire les conversations privées des gens”. Il fournit le code source de son algo publiquement, mais sous forme cryptée (via ledit algo), et menace de fournir la clé sous 24h la clé permettant d’accéder au code source.</p>
<p>Evidemment, TRANSLATR se casse les dents sur le fichier, et commence alors une course contre la montre pour mettre la main sur la clé.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Je ne vous en raconte pas plus pour ne pas trop vous spoiler. Je vous conseille la lecture de ce roman, qui réserve de nombreuses surprises comme Dan Brown en a le secret, dont quelques révélations qu’on peut qualifier aisément “d’actualité”.</p>
<p>Et je félicite l’auteur pour avoir su retranscrire l’un des nombreux univers de l’informatique sans raconter n’importe quoi, et tout en sachant le rendre accessible à tous. Chapeau, ce n’était pas une mince affaire… et le plus fou, c’est que rien de ce qu’il aborde n’a vieilli, à l’exception peut-être des valeurs (volume de stockage et vitesse de téléchargement)</p>
<p>Oh, et dernière remarque : le livre évoque le fait qu’en 1998, seuls 3% des américains sont au courant de l’existence de la NSA. Je me demande si ce chiffre est véridique…</p>


</section>

 ]]></description>
  <category>sécurité</category>
  <category>vie privée</category>
  <guid>https://dev.yosko.net/blog/2013/digital-fortress.html</guid>
  <pubDate>Wed, 13 Nov 2013 16:20:00 GMT</pubDate>
</item>
<item>
  <title>[Snippet #04 - PHP] EasyDump</title>
  <link>https://dev.yosko.net/blog/2013/snippet-php-easydump.html</link>
  <description><![CDATA[ 




<p><img src="https://dev.yosko.net/assets/cards/php-card.png" class="card img-fluid"></p>
<p>Hier, Bronco nous faisait <a href="http://www.warriordudimanche.net/shaarli/?6MYs_Q">découvrir Kint</a>, un outil pour PHP de deboguage et d’affichage de variables assez poussé.</p>
<p>Je n’avais pas vraiment envie d’installer tout une librairie dans mes projets pour remplacer ma fonction de debug, mais cela m’a donné quelques idées d’améliorations.</p>
<p><strong>EasyDump</strong> revoit donc complètement l’affichage de variable qu’on fait habituellement avec notre cher <code>var_dump</code>.</p>
<section id="fonctionnalités" class="level2">
<h2 class="anchored" data-anchor-id="fonctionnalités">Fonctionnalités</h2>
<section id="avantages-et-fonctionnalités" class="level3">
<h3 class="anchored" data-anchor-id="avantages-et-fonctionnalités">Avantages et fonctionnalités</h3>
<ul>
<li><strong><code>&lt;pre&gt;</code></strong> : l’affichage est automatiquement encadré d’un <code>&lt;pre&gt;</code> pour que vous n’ayez pas à le faire.</li>
<li><strong>Affichage compact</strong> : réduit sensiblement l’espace pris comparé à <code>var_dump()</code></li>
<li><strong>Mise en forme</strong> : un peu de couleurs pour y retrouver ses petits (cette version s’inspire de mon très cher <a href="../../blog/2013/colo-syntaxique-blog.html">Earthsong</a>, encore !)</li>
<li><strong>Htmlentities</strong> : les variables qui contiennent du code html/xml ne seront pas interprétées, mais bien affichées textuellement</li>
<li><strong>Noms courts</strong> : des noms de variables très courts sont disponibles pour faciliter la saisie (inspirés là encore de Kint dans sa version lite)</li>
<li><strong>Multi dump</strong> : comme pour <code>var_dump()</code> et Kint, vous pouvez passer plusieurs variables en même temps à EasyDump.</li>
</ul>
</section>
<section id="axes-damélioration" class="level3">
<h3 class="anchored" data-anchor-id="axes-damélioration">Axes d’amélioration</h3>
<ul>
<li><strong>Nom des variables</strong> : contrairement à Kint (mais comme <code>var_dump()</code>), EasyDump n’est pas capable d’afficher le nom des variables que vous lui transmettez. C’est très compliqué à faire, mais serait bien utile lorsqu’on enchaine les dumps…</li>
<li><strong>Paramétrer les couleurs</strong> : pour que chacun puisse personnaliser le bousin en fonction des besoins/envies.</li>
<li><strong>Type “objects”</strong> : les variables de type “objects” sont actuellement affichées via un <code>var_dump()</code>, et je ne sais pas trop comment faire autrement.</li>
</ul>
</section>
</section>
<section id="utilisation" class="level2">
<h2 class="anchored" data-anchor-id="utilisation">Utilisation</h2>
<ol type="1">
<li><p><a href="../../files/easydump-v0.2.zip">Téléchargez le code ici</a> (ou sur <a href="https://github.com/yosko/easydump">Github pour la dernière version</a>) et placez le dans le dossier de votre projet.</p></li>
<li><p>Importez le fichier d’EasyDump : <code>php  &lt;?php  require_once( 'easydump.php');</code></p>
<p>Puis appelez simplement les fonctions d’affichage :</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource php number-lines code-with-copy"><code class="sourceCode php"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&lt;?php</span></span>
<span id="cb1-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$var1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"toto"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-3"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$var2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">array</span>(</span>
<span id="cb1-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'titi'</span> =&gt; <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tonton'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tata'</span> =&gt; <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'toutou'</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb1-6">)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-7">EasyDump::debug(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$var1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$var2</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">756</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb1-8"></span>
<span id="cb1-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//immediatly stop the script after the dump:</span></span>
<span id="cb1-10">EasyDump::debugExit(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$var1</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$var2</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">756</span>)<span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div></li>
<li><p>Pour simplifier la saisie, des noms de variables très courts sont possibles (si vous n’utilisez pas déjà ces noms dans votre code) : <code>php  &lt;?php  d($var1, $var2, 756);    //same as EasyDump::debug()  de($var1, $var2, 756);   //same as EasyDump::debugExit()</code></p></li>
</ol>
<p>Et voilà le résultat :</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://dev.yosko.net/blog/2013/assets/easydump.png" class="img-fluid figure-img"></p>
<figcaption>Capture d’écran Easydump</figcaption>
</figure>
</div>
</section>
<section id="et-maintenant" class="level2">
<h2 class="anchored" data-anchor-id="et-maintenant">Et maintenant ?</h2>
<p>J’améliorerai au fil du temps en fonction de vos remarques et mes besoins. Peut-être même que je mettrai ça sur Github, un de ces 4…</p>
<p><em>Keep dumping &amp; rock on, baby!</em></p>
<p><strong>Edit 11/09/2013 à 14h :</strong> petite correction sur l’affichage des booléens (affichage de “true” et “false” au lieu de “1” ou rien du tout). Le lien de téléchargement a été mis à jour.</p>
<p><strong>Edit 16/09/2013 à 15h :</strong> prise en compte des ressources (opendir, fopen et autres…) et améliorations mineures. Publication sur <a href="https://github.com/yosko/easydump">Github</a>.</p>


</section>

 ]]></description>
  <category>projets</category>
  <category>php</category>
  <guid>https://dev.yosko.net/blog/2013/snippet-php-easydump.html</guid>
  <pubDate>Tue, 10 Sep 2013 14:05:00 GMT</pubDate>
</item>
</channel>
</rss>
