<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>PragmaGeek</title><link href="https://www.pragmageek.fr/" rel="alternate"/><link href="https://www.pragmageek.fr/feeds/all.atom.xml" rel="self"/><id>https://www.pragmageek.fr/</id><updated>2026-04-20T16:44:48.283062+02:00</updated><subtitle>Need it? Hack it!</subtitle><entry><title>Ignorez les conseils des automobilistes, faites du vélo</title><link href="https://www.pragmageek.fr/2026/04/ignorez-les-conseils-des-automobilistes-faites-du-velo/" rel="alternate"/><published>2026-04-20T00:00:00+02:00</published><updated>2026-04-20T16:44:48.283062+02:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2026-04-20:/2026/04/ignorez-les-conseils-des-automobilistes-faites-du-velo/</id><summary type="html">&lt;p&gt;Quand j’ai préparé mon déménagement en Guadeloupe l’été dernier, les gens m’ont dit “Ici, les routes sont trop dangereuses, il n’y a pas d’infrastructures adaptées, les gens roulent n’importe comment, personne ne fait de vélo, il n’y a pas de chemins &lt;span class="caps"&gt;VTT&lt;/span&gt;, les coins intéressants dans le Parc National sont interdits aux &lt;span class="caps"&gt;VTT&lt;/span&gt;, ne prend pas ton vélo, tu devras tout faire en voiture”.&lt;/p&gt;
&lt;p&gt;J’étais très déçu …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Quand j’ai préparé mon déménagement en Guadeloupe l’été dernier, les gens m’ont dit “Ici, les routes sont trop dangereuses, il n’y a pas d’infrastructures adaptées, les gens roulent n’importe comment, personne ne fait de vélo, il n’y a pas de chemins &lt;span class="caps"&gt;VTT&lt;/span&gt;, les coins intéressants dans le Parc National sont interdits aux &lt;span class="caps"&gt;VTT&lt;/span&gt;, ne prend pas ton vélo, tu devras tout faire en voiture”.&lt;/p&gt;
&lt;p&gt;J’étais très déçu. Je suis cycliste dans l’âme. Je n’en fais pas autant que je devrais, en particulier pour le loisir, mais j’avais pris l’habitude de me déplacer à vélo pour les petits trajets dans mon village et dans les villages voisins, par principe. Ça m’aérait, me faisait du bien, de l’exercice.&lt;/p&gt;
&lt;p&gt;J’ai donc hésité à prendre mes vélos dans le déménagement. C’est que c’est volumineux un vélo, et chaque mètre cube coûte cher quand on voyage à l’autre bout du monde. J’ai laissé mon vélo électrique long-tail en métropole (ma belle-sœur l’utilise désormais dans Lyon), mais j’ai par principe quand même pris mon &lt;span class="caps"&gt;VTC&lt;/span&gt; avec porte-bagage, et mon vieux mais fiable &lt;span class="caps"&gt;VTT&lt;/span&gt;, au cas où (je suis cycliste dans l’âme, je vous dis).&lt;/p&gt;
&lt;p&gt;Au début, effectivement, grosse déception. Routes étroites et en mauvais état, quasiment aucune piste ou bande cyclable. Des centre-bourg dans lesquels il n’y a que peu de commerces, ces derniers se concentrant dans des zones commerciales géantes, accessible exclusivement en voiture. Il y a quand même quelques stations de vélo en libre service dont personne ne se sert (on se demande bien pourquoi), probables vestiges d’une époque où des crédits européens étaient dédiés à leur développement.&lt;/p&gt;
&lt;p&gt;En Guadeloupe, tout le monde prend sa bagnole pour aller au travail, à la boulangerie, faire ses courses, à la plage, pour ses loisirs, pour tout. C’est comme en métropole, mais en pire. Ici, on prend sa voiture pour faire 1 km pour rejoindre la voie verte sur laquelle on peut ensuite courir en sécurité. On fait 30km de route pour aller chercher un coin de nature où faire du &lt;span class="caps"&gt;VTT&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Résultat : des bouchons, monstrueux, tous les jours aux heures de pointe. Un réseau routier qui n’est pas dimensionné. 45 minutes pour faire 2km sur la voie rapide. Des axes routiers sans passerelle piéton qui séparent les lieux de vie et les lieux de commerce. Les plus démunis, se déplaçant à pied, doivent traverser des 2×3 voies à 90km/h pour faire leurs courses (c’est pas pour rien que &lt;a href="https://la1ere.franceinfo.fr/guadeloupe/assises-regionales-de-la-securite-routiere-54-morts-sur-les-routes-en-2024-une-hecatombe-qui-inquiete-les-autorites-1563184.html"&gt;la Guadeloupe a une mortalité routière trois fois supérieur à celle de l’Hexagone&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Le développement urbain a visiblement été anarchique. Les maisons individuelles s’étalent sur des kilomètres le long des routes, là où se trouvaient auparavant des pâtures ou des plantations. Les centre-villes sont généralement les quartiers les plus pauvres, où s’agglutinent des petites maisonnettes de plain-pied, pour certaines en très mauvais état. Le centre-ville de Pointe-à-Pitre, principalement constitué d’immeubles de plusieurs étages, comprend de nombreux bâtiments indignes, presque à l’état de ruine. Les commerces ne sont pas accessibles à pied, donc les gens prennent la bagnole, et quand on vit à Bagnole-Land, la plus grosse difficulté, c’est de se rendre compte qu’un monde sans voiture est possible. Il faut faire ce que personne n’ose : se lancer, défricher le terrain, et montrer que c’est possible.&lt;/p&gt;
&lt;p&gt;Il m’a donc fallu 6 mois pour me motiver à utiliser mon vélo, dans un premier temps pour aller à l’école de musique à 10 minutes de trajet. C’est un peu vallonné, mais pas insurmontable. Faut savoir par où passer, mais c’est globalement sûr, à 80% dans des lotissements calmes, hors des gros axes routiers, 10% sur les trottoirs, et 10% dans la circulation urbaine (pas le choix, pas de trottoir).&lt;/p&gt;
&lt;p&gt;Fun fact : il faut faire un tel détour en voiture pour rejoindre cette école de musique, que ça prend 9 minutes C’est donc presque aussi rapide d’y aller à vélo (le retour se fait par contre sans détour, donc l’avantage est clairement à la voiture, mais ce n’est pas la question).&lt;/p&gt;
&lt;p&gt;Puis ce weekend, n’ayant pas de contrainte horaire, j’ai poussé jusqu’à aller à ma répétition hebdomadaire du Jazz Band à Pointe-à-Pitre à vélo. À peine plus de 10 km, contre 8.5km en voiture. 35 minutes de trajet, dont la moitié sur une belle piste cyclable. Quelques épisodes de pluie fine m’ont rafraîchi. J’avais prévu le vêtement de pluie dans le sac, mais je ne l’ai pas sorti. Je suis arrivé un peu humide, mais pas trempé. Par 30°C, ça n’est pas problématique.&lt;/p&gt;
&lt;p&gt;De toute manière, avec la température et l’exercice, j’aurais été humide de transpiration. Le principal, c’est d’être propre pour éviter de sentir le chien mouillé. J’ai évité de justesse une averse plus forte, qui est passée durant la répétition. Une pluie tropicale ultra-intense, assez habituelle ici, du genre gros orage d’été qui ravine tout en 10 minutes, avant que le soleil ne revienne aussi vite qu’il est parti.&lt;/p&gt;
&lt;p&gt;Mes camarades musiciens ont tous été positivement intrigués par mon trajet en vélo. Certains m’ont demandé si j’étais passé par la 2×2 voies à 90km/h… Je leur ai rappelé qu’il y avait quand même des pistes cyclables, des passerelles piéton, etc. Ça a fait parler. Ça a montré que c’était possible.&lt;/p&gt;
&lt;p&gt;Le retour, vers 18 heures, s’est bien passé, au sec, juste avant la nuit, avec mes petites lumières rouges et blanches de chez Décathlon, satisfait de mon activité. Je me suis prouvé à moi-même qu’il était possible de se déplacer sans voiture sur ce trajet “semi-long”.&lt;/p&gt;
&lt;p&gt;J’ai repensé à ceux qui me disaient que je ne ferai pas de vélo en Guadeloupe. Bien évidemment, c’était des gens qui n’étaient pas eux-mêmes cyclistes, et qui exagéraient le problème. Ils n’imaginaient pas qu’on pouvait traverser les lotissements calmes pour aller faire ses courses, qu’il y avait quand même quelques pistes cyclables, qu’on pouvait sans trop de difficulté éviter les routes les plus dangereuses en passant par le réseau secondaire/tertiaire.&lt;/p&gt;
&lt;p&gt;Morale de l’histoire : N’écoutez pas les bagnolards, ils vous diront forcément qu’on ne peut pas faire de vélo. Osez, défrichez le terrain, montrez l’exemple, pour votre bien-être, et pour avoir une chance de susciter des vocations.&lt;/p&gt;
&lt;p&gt;Ah, et j’aurais dû emporter mon long-tail électrique. Il m’aurait été utile…&lt;/p&gt;</content><category term="Divers"/><category term="Cyclisme"/><category term="Écologie"/></entry><entry><title>Sélectionner la disposition clavier sur GDM</title><link href="https://www.pragmageek.fr/2024/11/selectionner-disposition-clavier-gdm/" rel="alternate"/><published>2024-11-24T00:00:00+01:00</published><updated>2024-11-28T13:50:10.913370+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2024-11-24:/2024/11/selectionner-disposition-clavier-gdm/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo Gnome Display Manager" class="left" src="https://www.pragmageek.fr/images/2024/LogoGDM.png" style="width: 256px; height: auto; max-width: 100%;"/&gt;
Depuis quelques années, l’écran de connexion Gnome Display Manager, autrement appelé &lt;span class="caps"&gt;GDM&lt;/span&gt;, ne bascule plus automatiquement la configuration du clavier vers celle configurée par défaut par l’utilisateur pour lequel il demande le mot de passe. C’est problématique pour les gens qui utilisent au quotidien une disposition de clavier particulière (Colemak, Dvorak, ou Bépo dans mon cas), mais qui doivent laisser par défaut la configuration du système en Azerty pour permettre son utilisation …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo Gnome Display Manager" class="left" src="https://www.pragmageek.fr/images/2024/LogoGDM.png" style="width: 256px; height: auto; max-width: 100%;"/&gt;
Depuis quelques années, l’écran de connexion Gnome Display Manager, autrement appelé &lt;span class="caps"&gt;GDM&lt;/span&gt;, ne bascule plus automatiquement la configuration du clavier vers celle configurée par défaut par l’utilisateur pour lequel il demande le mot de passe. C’est problématique pour les gens qui utilisent au quotidien une disposition de clavier particulière (Colemak, Dvorak, ou Bépo dans mon cas), mais qui doivent laisser par défaut la configuration du système en Azerty pour permettre son utilisation par d’autres personnes.&lt;/p&gt;
&lt;p&gt;Cela oblige donc l’utilisateur d’une disposition alternative à s’authentifier avec un clavier azerty, avant de retrouver le confort de sa disposition fétiche une fois la session ouverte. &lt;/p&gt;
&lt;p&gt;Après plusieurs années de souffrance (oui, oui, sortez les mouchoirs), je viens de trouver comment avoir accès à plusieurs dispositions du clavier dès l’écran de connexion.&lt;/p&gt;
&lt;p&gt;Il se trouve que &lt;span class="caps"&gt;GDM&lt;/span&gt; ne donne accès qu’aux dispositions configurées pour le système, qui est donc Azerty (ou Qwerty) par défaut, mais le système peut en avoir plusieurs. &lt;span class="caps"&gt;GDM&lt;/span&gt; les prend toutes en compte, et permet de basculer facilement de l’une à l’autre. Voyons comment faire.&lt;/p&gt;
&lt;p&gt;La manipulation est valable sur Debian (Trixie/Testing dans mon cas), donc elle devrait être similaire sur tous les dérivés de Debian, et adaptable pour les autres distributions.&lt;/p&gt;
&lt;p&gt;La disposition par défaut du système est enregistrée dans le fichier &lt;em&gt;/etc/default/keyboard&lt;/em&gt; (ou dans &lt;em&gt;/etc/vconsole.conf&lt;/em&gt;, qui est un lien symbolique vers celui-ci).&lt;/p&gt;
&lt;p&gt;Par défaut, sur un système avec clavier Azerty, ce fichier contient ceci :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# KEYBOARD CONFIGURATION FILE

# Consult the keyboard(5) manual page.

XKBMODEL="pc105"
XKBLAYOUT="fr"
XKBVARIANT="latin9"
XKBOPTIONS=""

BACKSPACE="guess"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Si on configure le système pour avoir le clavier Bépo, ça donne ceci de différent (testez avec &lt;code&gt;sudo dpkg-reconfigure keyboard-configuration&lt;/code&gt;) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;XKBLAYOUT="fr"
XKBVARIANT="bepo"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Par défaut, l’utilitaire &lt;code&gt;dpkg-reconfigure&lt;/code&gt; ne semble permettre de paramétrer qu’une seule disposition, mais pour en avoir deux, il suffit de les noter ensemble, séparés d’une virgule :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;XKBLAYOUT="fr,fr"
XKBVARIANT="latin9,bepo"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class="caps"&gt;GDM&lt;/span&gt; propose désormais le choix entre les deux dispositions, via un menu en haut de l’écran. &lt;/p&gt;
&lt;p&gt;&lt;img alt="Capture d'écran de GDM avec le menu de choix du clavier" src="https://www.pragmageek.fr/images/2024/CaptureÉcranGDMBasculeClavier.png" style="width: 900px; height: auto; max-width: 100%;"/&gt;&lt;/p&gt;
&lt;p&gt;Le raccourci clavier &lt;em&gt;Meta&lt;/em&gt; + &lt;em&gt;Espace&lt;/em&gt; permet même de basculer rapidement de l’un à l’autre. Un véritable bonheur.&lt;/p&gt;
&lt;p&gt;Les autres utilisateurs de l’ordinateur continueront d’utiliser la disposition Azerty correspondant à ce qui est inscrit physiquement sur le clavier physique, et je pourrai rapidement basculer en Bépo pour entrer mon mot de passe aisément. J’aurais préféré que ce soit automatique pour moi, comme c’était le cas il y a quelques années, mais je m’en contenterai.&lt;/p&gt;</content><category term="Logiciels"/><category term="Linux"/><category term="Gnome"/></entry><entry><title>La bonne manière de faire un script Nautilus en Bash</title><link href="https://www.pragmageek.fr/2022/01/la-bonne-maniere-de-faire-un-script-nautilus-en-bash/" rel="alternate"/><published>2022-01-05T00:00:00+01:00</published><updated>2022-11-21T13:38:44+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2022-01-05:/2022/01/la-bonne-maniere-de-faire-un-script-nautilus-en-bash/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo Gnome Files" class="left" src="https://www.pragmageek.fr/images/2022/Gnome-Files-logo.png"&gt;On trouve toutes sortes de scripts Nautilus sur internet, car ils peuvent rendre des services aussi variés que précieux, mais beaucoup de ceux que l&amp;#8217;on croise présentent des défauts de conception majeurs : ils n&amp;#8217;itèrent pas, ou mal, sur la liste des fichiers qui leurs sont fournis, et ils ne peuvent pas gérer des fichiers situés sur un système virtuel distant monté par &lt;span class="caps"&gt;GFVS&lt;/span&gt;, typiquement un partage Samba, Webdav ou (S)&lt;span class="caps"&gt;FTP&lt;/span&gt;. Ce billet va tenter de définir une manière fiable et universelle de gérer les fichiers sélectionnés et fournis aux scripts&amp;nbsp;Nautilus.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo Gnome Files" class="left" src="https://www.pragmageek.fr/images/2022/Gnome-Files-logo.png" style="width: 128px; height: auto; max-width: 100%;"/&gt;
On trouve toutes sortes de scripts Nautilus sur internet, car ils peuvent rendre des services aussi variés que précieux, mais beaucoup de ceux que l’on croise présentent des défauts de conception majeurs : ils n’itèrent pas, ou mal, sur la liste des fichiers qui leurs sont fournis, et ils ne peuvent pas gérer des fichiers situés sur un système virtuel distant monté par &lt;span class="caps"&gt;GFVS&lt;/span&gt;, typiquement un partage Samba, Webdav ou (S)&lt;span class="caps"&gt;FTP&lt;/span&gt;. Ce billet va tenter de définir une manière fiable et universelle de gérer les fichiers sélectionnés et fournis aux scripts Nautilus.&lt;/p&gt;
&lt;h1 id="les-scripts-nautilus-kezako"&gt;Les scripts Nautilus, kézako ?&lt;/h1&gt;
&lt;p&gt;Nautilus est le nom historique du navigateur de fichiers du &lt;a href="https://www.gnome.org/"&gt;projet Gnome&lt;/a&gt;. Il s’appelle désormais &lt;a href="https://wiki.gnome.org/Apps/Files"&gt;Gnome Files&lt;/a&gt;. On en retrouve des dérivés nommées &lt;a href="https://doc.ubuntu-fr.org/caja"&gt;Caja&lt;/a&gt; ou &lt;a href="https://doc.ubuntu-fr.org/nemo"&gt;Nemo&lt;/a&gt;, qui possèdent eux aussi un support pour ces scripts. Si vous ne savez pas ce que sont ces “scripts Nautilus”, il s’agit de scripts que l’on peut appliquer sur un ou plusieurs fichiers et dossiers afin d’effectuer des actions prédéfinies.&lt;/p&gt;
&lt;p&gt;Les scripts Nautilus sont des programmes exécutables placés dans le répertoire &lt;em&gt;$&lt;span class="caps"&gt;HOME&lt;/span&gt;/.local/share/nautilus/scripts&lt;/em&gt; et ses sous-dossiers. Nautilus détectera tous les fichiers exécutables dans cette arborescence et proposera de les invoquer via le menu contextuel, dans le sous-menu “Scripts”. Pour désactiver un script, il n’est donc pas nécessaire de le supprimer du dossier, il suffit de le rendre non exécutable.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Exemple menu script Nautilus" src="https://www.pragmageek.fr/images/2022/Exemple-script-nautilus.jpg" style="width: 890px; height: auto; max-width: 100%;"/&gt;&lt;/p&gt;
&lt;p&gt;Ces scripts peuvent être développés dans n’importe quel langage de programmation. Il en existe en Python et en Perl, mais s’agissant de petits scripts dont le but est de manipuler des fichiers ou d’interagir avec un système Linux, le langage Bash est utilisé la plupart du temps.&lt;/p&gt;
&lt;p&gt;Lorsqu’on donne des fichiers et dossiers classiques aux scripts Nautilus, tout fonctionne comme prévu. Mais par “classique”, entendez “sur un système de fichier local” et “avec un nom de fichier sans caractère problématique”.&lt;/p&gt;
&lt;p&gt;Nous allons voir que des problèmes se posent dans deux situations :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quand, depuis Nautilus, on accède à des systèmes de fichier distants montés par &lt;span class="caps"&gt;GIO&lt;/span&gt;/&lt;span class="caps"&gt;GVFS&lt;/span&gt; (partages Samba, Webdav, &lt;span class="caps"&gt;SFTP&lt;/span&gt;, etc.) ;&lt;/li&gt;
&lt;li&gt;Quand les fichiers ont un retour à la ligne dans leur nom.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Afin de prévoir d’éventuelles spécificités liées aux versions des logiciels utilisés, je précise que je travaille sur un système &lt;span class="caps"&gt;GNU&lt;/span&gt;/Linux Ubuntu 20.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; avec Nautilus version 3.36.3.&lt;/p&gt;
&lt;h1 id="les-variables-specifiques"&gt;Les variables spécifiques&lt;/h1&gt;
&lt;p&gt;Nautilus va fournir au script invoqué plusieurs informations relatives aux éléments sélectionnés. Le script pourra ensuite en faire usage si besoin.&lt;/p&gt;
&lt;p&gt;Au delà des variables habituelles (&lt;code&gt;$@&lt;/code&gt;, &lt;code&gt;$*&lt;/code&gt;, &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt;, etc.), nous avons à disposition les variables spécifiques suivantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NAUTILUS_SCRIPT_SELECTED_FILE_PATHS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NAUTILUS_SCRIPT_SELECTED_URIS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NAUTILUS_SCRIPT_CURRENT_URI&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NAUTILUS_SCRIPT_WINDOW_GEOMETRY&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;D’autre part la variable &lt;code&gt;$PWD&lt;/code&gt;, moins connue mais toujours disponible en Bash, va nous être utile car elle indique le répertoire de travail courant (celui visible dans Nautilus).&lt;/p&gt;
&lt;h1 id="testons-un-script-basique"&gt;Testons un script basique&lt;/h1&gt;
&lt;p&gt;Pour les besoin de ce tutoriel, on va créer un script tout simple qui affiche le contenu des variables mentionnées ci-dessus. Le script n’étant pas exécuté dans un shell interactif, il est nécessaire de créer un fichier de log dans lequel on pourra suivre son déroulement (par exemple avec &lt;code&gt;tail -f&lt;/code&gt;)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/nautilus-script-&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;basename&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.log"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\$@=&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\$1=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\$2=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\$3=&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"\$4=&lt;/span&gt;&lt;span class="nv"&gt;$4&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PWD=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NAUTILUS_SCRIPT_SELECTED_FILE_PATHS='&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAUTILUS_SCRIPT_SELECTED_FILE_PATHS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NAUTILUS_SCRIPT_SELECTED_URIS='&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAUTILUS_SCRIPT_SELECTED_URIS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NAUTILUS_SCRIPT_CURRENT_URI='&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NAUTILUS_SCRIPT_WINDOW_GEOMETRY='&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAUTILUS_SCRIPT_WINDOW_GEOMETRY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Créons une arborescence de fichiers de test en insérant volontairement des espaces dans les noms des éléments, ainsi qu’un retour à la ligne dans un nom de fichier :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/demo/sous dossier"&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;touch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/demo/fichier 1.txt"&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;touch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/demo/fichier 2&lt;/span&gt;
&lt;span class="s2"&gt;&amp;gt; avec newline.txt"&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;touch&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/demo/sous dossier/fichier 3.txt"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Sélectionnons ces trois fichiers et invoquons le script. Voici ce que ça donne :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;
&lt;span class="normal"&gt;15&lt;/span&gt;
&lt;span class="normal"&gt;16&lt;/span&gt;
&lt;span class="normal"&gt;17&lt;/span&gt;
&lt;span class="normal"&gt;18&lt;/span&gt;
&lt;span class="normal"&gt;19&lt;/span&gt;
&lt;span class="normal"&gt;20&lt;/span&gt;
&lt;span class="normal"&gt;21&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sous&lt;span class="w"&gt; &lt;/span&gt;dossier/fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.txt&lt;span class="w"&gt; &lt;/span&gt;fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.txt&lt;span class="w"&gt; &lt;/span&gt;fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
avec&lt;span class="w"&gt; &lt;/span&gt;newline.txt
&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sous&lt;span class="w"&gt; &lt;/span&gt;dossier/fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.txt
&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.txt
&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
avec&lt;span class="w"&gt; &lt;/span&gt;newline.txt
&lt;span class="nv"&gt;$4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;

&lt;span class="nv"&gt;PWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/vetetix/demo

&lt;span class="nv"&gt;NAUTILUS_SCRIPT_SELECTED_FILE_PATHS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'/home/vetetix/demo/sous dossier/fichier 3.txt&lt;/span&gt;
&lt;span class="s1"&gt;/home/vetetix/demo/fichier 1.txt&lt;/span&gt;
&lt;span class="s1"&gt;/home/vetetix/demo/fichier 2&lt;/span&gt;
&lt;span class="s1"&gt;avec newline.txt&lt;/span&gt;
&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="nv"&gt;NAUTILUS_SCRIPT_SELECTED_URIS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'file:///home/vetetix/demo/sous%20dossier/fichier%203.txt&lt;/span&gt;
&lt;span class="s1"&gt;file:///home/vetetix/demo/fichier%201.txt&lt;/span&gt;
&lt;span class="s1"&gt;file:///home/vetetix/demo/fichier%202%0Aavec%20newline.txt&lt;/span&gt;
&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="nv"&gt;NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'file:///home/vetetix/demo'&lt;/span&gt;
&lt;span class="nv"&gt;NAUTILUS_SCRIPT_WINDOW_GEOMETRY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'1310x694+56+27'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;On remarque que : &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;les variables &lt;code&gt;NAUTILUS_SCRIPT_SELECTED_FILE_PATHS&lt;/code&gt; (ligne 11) et &lt;code&gt;NAUTILUS_SCRIPT_SELECTED_URIS&lt;/code&gt; (ligne 16) contiennent la liste des fichiers séparés par des retours à la ligne ;&lt;/li&gt;
&lt;li&gt;Ces variables ont un retour à la ligne comme dernier caractère.&lt;br/&gt;
  Il pourrait être nécessaire de le retirer manuellement pour pouvoir itérer proprement sur leur contenu. Sans cela, on générerait une itération supplémentaire sur une ligne vide avec un &lt;code&gt;while read&lt;/code&gt;.&lt;br/&gt;
  Ça peut se faire simplement avec l’&lt;a href="https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html"&gt;expansion de paramètres Bash (en)&lt;/a&gt; &lt;code&gt;${var%$'\n'}&lt;/code&gt; qui retire un éventuel retour à la ligne en fin de chaîne ;&lt;/li&gt;
&lt;li&gt;La variable &lt;code&gt;NAUTILUS_SCRIPT_SELECTED_FILE_PATHS&lt;/code&gt; gère mal les retours à la ligne dans les noms de fichiers (cf lignes 13 et 14).&lt;br/&gt;
  On ne peut donc pas l’utiliser pour itérer sur les noms de fichier.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On pourrait donc soit itérer sur la variable &lt;code&gt;$@&lt;/code&gt; (&lt;code&gt;for fichier in "$@"; do…&lt;/code&gt;), soit sur la variable &lt;code&gt;$NAUTILUS_SCRIPT_SELECTED_URIS&lt;/code&gt; (après suppression du dernier retour à la ligne).&lt;/p&gt;
&lt;h1 id="testons-ce-meme-script-basique-sur-un-repertoire-monte-par-gvfs"&gt;Testons ce même script basique sur un répertoire monté par gvfs&lt;/h1&gt;
&lt;p&gt;Dans l’étape précédente, on a utilisé le script sur le système de fichier local. Mais si on l’utilise sur un système de fichier virtuel monté par gvfs, en l’occurrence le partage webdav d’un compte Nextcloud, regardons ce que ça donne :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt; 1&lt;/span&gt;
&lt;span class="normal"&gt; 2&lt;/span&gt;
&lt;span class="normal"&gt; 3&lt;/span&gt;
&lt;span class="normal"&gt; 4&lt;/span&gt;
&lt;span class="normal"&gt; 5&lt;/span&gt;
&lt;span class="normal"&gt; 6&lt;/span&gt;
&lt;span class="normal"&gt; 7&lt;/span&gt;
&lt;span class="normal"&gt; 8&lt;/span&gt;
&lt;span class="normal"&gt; 9&lt;/span&gt;
&lt;span class="normal"&gt;10&lt;/span&gt;
&lt;span class="normal"&gt;11&lt;/span&gt;
&lt;span class="normal"&gt;12&lt;/span&gt;
&lt;span class="normal"&gt;13&lt;/span&gt;
&lt;span class="normal"&gt;14&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;$4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;

&lt;span class="nv"&gt;PWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/run/user/1000/gvfs/dav:host&lt;span class="o"&gt;=&lt;/span&gt;monserveur.net,ssl&lt;span class="o"&gt;=&lt;/span&gt;true,user&lt;span class="o"&gt;=&lt;/span&gt;vetetix,prefix&lt;span class="o"&gt;=&lt;/span&gt;%2Fremote.php%2Fwebdav

&lt;span class="nv"&gt;NAUTILUS_SCRIPT_SELECTED_FILE_PATHS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;
&lt;span class="nv"&gt;NAUTILUS_SCRIPT_SELECTED_URIS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'davs://vetetix@monserveur.net/remote.php/webdav/sous%20dossier/Nouveau%20fichier.txt&lt;/span&gt;
&lt;span class="s1"&gt;davs://vetetix@monserveur.net/remote.php/webdav/monfichier.txt&lt;/span&gt;
&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;span class="nv"&gt;NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'davs://vetetix@monserveur.net/remote.php/webdav'&lt;/span&gt;
&lt;span class="nv"&gt;NAUTILUS_SCRIPT_WINDOW_GEOMETRY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'1310x694+56+27'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;On constate que les variables classiques (&lt;code&gt;$@&lt;/code&gt;, &lt;code&gt;$1&lt;/code&gt; et suivantes), ainsi que &lt;code&gt;NAUTILUS_SCRIPT_SELECTED_FILE_PATHS&lt;/code&gt; sont vides, et donc non disponibles. Un script nautilus à vocation généraliste, que l’on pourrait partager sur internet, ne doit donc pas se baser sur ces variables puisqu’il ne fonctionnerait pas dans toutes les conditions.&lt;/p&gt;
&lt;p&gt;On ne peut donc plus se baser que sur la variable &lt;code&gt;$NAUTILUS_SCRIPT_SELECTED_URIS&lt;/code&gt;, qui est la seule qui est disponible dans toutes les conditions, en gérant correctement les retours à la ligne.&lt;/p&gt;
&lt;h1 id="comment-iterer-sur-nautilus_script_selected_uris"&gt;Comment itérer sur NAUTILUS_SCRIPT_SELECTED_URIS&lt;/h1&gt;
&lt;p&gt;On a vu que la variable &lt;code&gt;$NAUTILUS_SCRIPT_SELECTED_URIS&lt;/code&gt; contient chaque &lt;span class="caps"&gt;URI&lt;/span&gt; suivie d’un retour à la ligne.&lt;/p&gt;
&lt;p&gt;De plus, chaque &lt;span class="caps"&gt;URI&lt;/span&gt; présente ses caractères spéciaux encodés, en particulier les espaces, retours à la ligne et autres “whitespaces” de &lt;code&gt;IFS&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On a donc deux possibilité : une boucle &lt;code&gt;for&lt;/code&gt; et une boucle &lt;code&gt;while read&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="avec-une-boucle-for"&gt;Avec une boucle for&lt;/h2&gt;
&lt;p&gt;On peut simplement itérer sur la variable non quotée :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;selected_uri&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$NAUTILUS_SCRIPT_SELECTED_URIS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;do_something&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$selected_uri&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pour éviter d’itérer sur une variable non quotée, on peut préfèrer la transformer en array, puis itérer sur celui-ci :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;selected_uris&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NAUTILUS_SCRIPT_SELECTED_URIS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;selected_uri&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;selected_uris&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;do_something&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$selected_uri&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="avec-une-boucle-while"&gt;Avec une boucle while&lt;/h2&gt;
&lt;p&gt;Ici aussi, on va itérer sur chaque ligne de la variable, dont supprime le retour à la ligne final :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;selected_uri&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;do_something&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$selected_uri&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAUTILUS_SCRIPT_SELECTED_URIS&lt;/span&gt;&lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="s1"&gt;$'\n'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Comme les espaces contenues dans les &lt;span class="caps"&gt;URI&lt;/span&gt; sont encodées, il n’est pas nécessaire de modifier l’&lt;span class="caps"&gt;IFS&lt;/span&gt;, contrairement à ce qui se fait habituellement avec ce type de boucle.&lt;/p&gt;
&lt;p&gt;La première solution est néanmoins la plus simple, tout en restant sûre.&lt;/p&gt;
&lt;h1 id="transformer-une-uri-en-chemin-local"&gt;Transformer une &lt;span class="caps"&gt;URI&lt;/span&gt; en chemin local&lt;/h1&gt;
&lt;p&gt;On a vu qu’on devait boucler sur les URIs contenues dans &lt;code&gt;$NAUTILUS_SCRIPT_SELECTED_URIS&lt;/code&gt;, mais on ne peut pas fournir directement une &lt;span class="caps"&gt;URI&lt;/span&gt; à un programme :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;file:///home/vetetix/demo/fichier%201.txt
ls:&lt;span class="w"&gt; &lt;/span&gt;impossible&lt;span class="w"&gt; &lt;/span&gt;d&lt;span class="s1"&gt;'accéder à '&lt;/span&gt;file:///home/vetetix/demo/fichier%201.txt&lt;span class="err"&gt;'&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;Aucun&lt;span class="w"&gt; &lt;/span&gt;fichier&lt;span class="w"&gt; &lt;/span&gt;ou&lt;span class="w"&gt; &lt;/span&gt;dossier&lt;span class="w"&gt; &lt;/span&gt;de&lt;span class="w"&gt; &lt;/span&gt;ce&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Il faut donc transformer ces &lt;span class="caps"&gt;URI&lt;/span&gt; en chemins locaux. On a pour cela deux options : l’utilisation de &lt;code&gt;gio&lt;/code&gt;, ou une solution “à la main”.&lt;/p&gt;
&lt;h2 id="utiliser-gio-pour-transformer-une-uri-en-chemin-local"&gt;Utiliser &lt;span class="caps"&gt;GIO&lt;/span&gt; pour transformer une &lt;span class="caps"&gt;URI&lt;/span&gt; en chemin local&lt;/h2&gt;
&lt;p&gt;Les systèmes de fichiers virtuels étant créés par &lt;span class="caps"&gt;GVFS&lt;/span&gt;, on peut utiliser &lt;code&gt;gio&lt;/code&gt; pour traduire les URIs en chemins locaux, car celui-ci sait par définition quel est le point de montage local d’un système de fichier virtuel &lt;span class="caps"&gt;GVFS&lt;/span&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;gio&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;file:///home/vetetix/demo/fichier%201.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"local path"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cut&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;-
/home/vetetix/demo/fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;.txt

vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;gio&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;davs://vetetix@monserveur.net/remote.php/webdav/sous%20dossier/Nouveau%20fichier.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"local path"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;cut&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;-
/run/user/1000/gvfs/dav:host&lt;span class="o"&gt;=&lt;/span&gt;monserveur.net,ssl&lt;span class="o"&gt;=&lt;/span&gt;true,user&lt;span class="o"&gt;=&lt;/span&gt;vetetix,prefix&lt;span class="o"&gt;=&lt;/span&gt;%2Fremote.php%2Fwebdav/sous&lt;span class="w"&gt; &lt;/span&gt;dossier/Nouveau&lt;span class="w"&gt; &lt;/span&gt;fichier.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ça a l’air de bien fonctionner. Par contre, la solution ci-dessus pose problème avec des retours à la ligne, puisque le nom du fichier se retrouve affichée sur plusieurs lignes, alors qu’on ne récupère que la première :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vetetix@ordi:~$ gio info file:///home/vetetix/demo/fichier%202%0Aavec%20newline.txt | grep "local path" | cut -d ' ' -f 3-
/home/vetetix/demo/fichier 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On doit donc utiliser plus finement &lt;code&gt;grep&lt;/code&gt; pour récupérer tout le chemin local, sur plusieurs lignes, avec l’option “-A 1” (s’il y a un seul retour à la ligne) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;gio&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;file:///home/vetetix/demo/fichier%202%0Aavec%20newline.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'^local path: '&lt;/span&gt;
&lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;path:&lt;span class="w"&gt; &lt;/span&gt;/home/vetetix/demo/fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
avec&lt;span class="w"&gt; &lt;/span&gt;newline.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;S’il y a plus d’un retour à la ligne dans le chemin complet (dans le nom du fichier ou dans ses répertoires parents), il faut les compter, puis prendre ce nombre en compte :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"file:///home/vetetix/demo/fichier%202%0Aavec%20newline.txt"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-Fo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'%0A'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="k"&gt;)&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;gio&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;file:///home/vetetix/demo/fichier%202%0Aavec%20newline.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$N&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'^local path: '&lt;/span&gt;
&lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;path:&lt;span class="w"&gt; &lt;/span&gt;/home/vetetix/demo/fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
avec&lt;span class="w"&gt; &lt;/span&gt;newline.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Maintenant, il faut juste retirer le début de ligne (“local path: “) pour obtenir le chemin local complet :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;N&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"file:///home/vetetix/demo/fichier%202%0Aavec%20newline.txt"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-Fo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'%0A'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="k"&gt;)&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;var&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;gio&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;file:///home/vetetix/demo/fichier%202%0Aavec%20newline.txt&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$N&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'^local path: '&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'%s'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;var&lt;/span&gt;&lt;span class="p"&gt;#local path: &lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
/home/vetetix/demo/fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
avec&lt;span class="w"&gt; &lt;/span&gt;newline.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dans une fonction, cela donne ceci :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;
&lt;span class="normal"&gt;6&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;get_path_from_uri&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;newlines&lt;span class="w"&gt; &lt;/span&gt;path_lines
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;newlines&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-Fo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'%0A'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wc&lt;span class="w"&gt; &lt;/span&gt;-l&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;path_lines&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;gio&lt;span class="w"&gt; &lt;/span&gt;info&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-A&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$newlines&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'^local path: '&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;path_lines&lt;/span&gt;&lt;span class="p"&gt;#local path: &lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Mais… il y a un “mais” : cette solution utilisant la sortie de &lt;code&gt;gio&lt;/code&gt; impose l’utilisation de &lt;a href="https://unix.stackexchange.com/a/248229"&gt;command substitution&lt;/a&gt; dont la sortie est assignée à une variable (&lt;code&gt;var=$(command)&lt;/code&gt;). Cela fait que si notre nom de fichier se termine par un ou plusieurs retours à la ligne, ceux-ci seront supprimés et le script plantera.&lt;/p&gt;
&lt;p&gt;D’autre part, on utilise aussi la fonction &lt;code&gt;grep&lt;/code&gt;, qui a la fâcheuse caractéristique de renvoyer un code de sortie non nul lorsqu’elle ne trouve aucune des chaines recherchées. Les gens qui utilisent le &lt;a href="http://redsymbol.net/articles/unofficial-bash-strict-mode/"&gt;unofficial bash strict mode&lt;/a&gt; (&lt;code&gt;set -euo pipefail&lt;/code&gt; ou mieux, &lt;code&gt;set -eEuo pipefail&lt;/code&gt;) préfèreront s’en passer.&lt;/p&gt;
&lt;p&gt;On doit donc abattre notre dernière carte, la solution “a la mano”.&lt;/p&gt;
&lt;h2 id="transformer-manuellement-une-uri-en-chemin-local"&gt;Transformer manuellement une &lt;span class="caps"&gt;URI&lt;/span&gt; en chemin local&lt;/h2&gt;
&lt;p&gt;Il est possible de transformer une &lt;span class="caps"&gt;URI&lt;/span&gt; en chemin local à la main, avec les élements dont on dispose déjà, et sans utiliser de substitution de commande.&lt;/p&gt;
&lt;p&gt;On constatera que la valeur initiale de &lt;code&gt;$PWD&lt;/code&gt; représente le chemin local de &lt;code&gt;$NAUTILUS_SCRIPT_CURRENT_URI&lt;/code&gt;, et qu’il contient donc le point de montage d’un éventuel système de fichier virtuel :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Sur un système de fichier local :&lt;/span&gt;
&lt;span class="nv"&gt;PWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/vetetix/demo
&lt;span class="nv"&gt;NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'file:///home/vetetix/demo'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;!-- --&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Sur un système de fichier virtuel :&lt;/span&gt;
&lt;span class="nv"&gt;PWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/run/user/1000/gvfs/dav:host&lt;span class="o"&gt;=&lt;/span&gt;monserveur.net,ssl&lt;span class="o"&gt;=&lt;/span&gt;true,user&lt;span class="o"&gt;=&lt;/span&gt;vetetix,prefix&lt;span class="o"&gt;=&lt;/span&gt;%2Fremote.php%2Fwebdav
&lt;span class="nv"&gt;NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'davs://vetetix@monserveur.net/remote.php/webdav'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On va donc utiliser la valeur initiale de &lt;code&gt;$PWD&lt;/code&gt; associée à l’&lt;span class="caps"&gt;URI&lt;/span&gt; dont on aura retiré le préfixe correspondant à &lt;code&gt;$NAUTILUS_SCRIPT_CURRENT_URI&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Attention, la valeur de &lt;code&gt;$PWD&lt;/code&gt; peut changer si une commande (par exemple un &lt;code&gt;cd&lt;/code&gt;) change le répertoire actuel. Il faut donc très tôt en récupérer la valeur dans une autre variable, pour la sanctuariser (je l’appellerai &lt;code&gt;$IWD&lt;/code&gt; pour Initial Working Directory).&lt;/p&gt;
&lt;h3 id="recuperer-la-partie-finale-du-chemin"&gt;Récupérer la partie finale du chemin&lt;/h3&gt;
&lt;p&gt;Pour enlever la première partie de l’&lt;span class="caps"&gt;URI&lt;/span&gt;, on va à nouveau utiliser une expansion de paramètre de Bash : &lt;code&gt;${MON_URI#"$NAUTILUS_SCRIPT_CURRENT_URI"}&lt;/code&gt; (ici, MON_URI est la variable à traiter).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MON_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'file:///home/vetetix/demo/sous%20dossier/fichier%203.txt'&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'file:///home/vetetix/demo'&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MON_URI&lt;/span&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
/sous%20dossier/fichier%203.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="decoder-les-caracteres-encodes-de-luri"&gt;Décoder les caractères encodés de l’&lt;span class="caps"&gt;URI&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Il faut aussi décoder les caractères spéciaux de l’&lt;span class="caps"&gt;URI&lt;/span&gt; qui font l’objet d’un &lt;a href="https://developer.mozilla.org/fr/docs/Glossary/percent-encoding"&gt;encodage-pourcent&lt;/a&gt;, ce que l’on va faire en les convertissant en encodage hexadécimal (il suffit de remplacer “%” par “\x”), puis en interprétant ceux-ci avec la commande &lt;code&gt;printf&lt;/code&gt; et le format de sortie&lt;code&gt;'%b'&lt;/code&gt; en lieu et place de l’habituel &lt;code&gt;'%s'&lt;/code&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;percent_var&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/sous%20dossier/fichier%203.txt"&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;hex_var&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;percent_var&lt;/span&gt;&lt;span class="p"&gt;//%/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$hex_var&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
/sous&lt;span class="se"&gt;\x&lt;/span&gt;20dossier/fichier&lt;span class="se"&gt;\x&lt;/span&gt;&lt;span class="m"&gt;203&lt;/span&gt;.txt
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'%b'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$hex_var&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
/sous&lt;span class="w"&gt; &lt;/span&gt;dossier/fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="la-partie-de-lego-pour-tout-mettre-ensemble"&gt;La partie de lego pour tout mettre ensemble&lt;/h3&gt;
&lt;p&gt;On retrouve alors le chemin “local” en concaténant la valeur de &lt;code&gt;$PWD&lt;/code&gt; (&lt;code&gt;$IWD&lt;/code&gt;) avec la fin de l’&lt;span class="caps"&gt;URI&lt;/span&gt; décodée :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;IWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/vetetix/demo
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"file:///home/vetetix/demo"&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MON_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"file:///home/vetetix/demo/fichier%202%0Aavec%20newline.txt"&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;FIN_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MON_URI&lt;/span&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;CHEMIN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'%s%b'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IWD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FIN_URI&lt;/span&gt;&lt;span class="p"&gt;//%/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
vetetix@ordi:~$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CHEMIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
/home/vetetix/demo/fichier&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
avec&lt;span class="w"&gt; &lt;/span&gt;newline.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dans une fonction, cela pourrait donner ceci :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;readonly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;IWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;
set_path_from_uri&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;uri_end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;selected_path&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'%s%b'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IWD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uri_end&lt;/span&gt;&lt;span class="p"&gt;//%/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Vous aurez remarqué que cette fonction ne renvoit rien, mais définit la valeur de la variable (globale) &lt;code&gt;selected_path&lt;/code&gt;. À l’utilisateur de faire ce qui est nécessaire pour ne pas casser le contenu de cette variable par la suite.&lt;/p&gt;
&lt;h1 id="conclusion-un-script-moins-simple-mais-plus-sain"&gt;Conclusion : un script moins simple, mais plus sain&lt;/h1&gt;
&lt;p&gt;Maintenant qu’on a trouvé toutes les briques nécessaires pour invoquer un script Nautilus sans se prendre les pieds dans le tapis que sont retours à la ligne et les systèmes de fichier virtuels, mettons le tout dans un script basique qui va simplement faire un &lt;code&gt;ls -ld&lt;/code&gt; sur chaque fichier ou dossier sélectionné.&lt;/p&gt;
&lt;p&gt;J’ai une préférence pour la conversion directe de l’&lt;span class="caps"&gt;URI&lt;/span&gt; en chemin sans passer par une fonction ni une variable globale :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;
&lt;span class="normal"&gt;6&lt;/span&gt;
&lt;span class="normal"&gt;7&lt;/span&gt;
&lt;span class="normal"&gt;8&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nb"&gt;readonly&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;IWD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;selected_uri&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$NAUTILUS_SCRIPT_SELECTED_URIS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;uri_end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;selected_uri&lt;/span&gt;&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$NAUTILUS_SCRIPT_CURRENT_URI&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;selected_path&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'%s%b'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IWD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;uri_end&lt;/span&gt;&lt;span class="p"&gt;//%/&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Do something here:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-ld&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$selected_path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Ce code devrait servir de base pour toute création de script Nautilus en Bash, car il n’est finalement pas très compliqué et permet d’éviter bien des écueils.&lt;/p&gt;
&lt;p&gt;J’ai testé ce code, qui fonction avec tous les fichiers que je leur ai soumis :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;avec des espaces (heureusement) ;&lt;/li&gt;
&lt;li&gt;avec des retours à la ligne, y compris en fin de nom ;&lt;/li&gt;
&lt;li&gt;avec des astérisques ou des points d’interrogation ;&lt;/li&gt;
&lt;li&gt;avec des backslash (bien que &lt;code&gt;ls&lt;/code&gt; affiche mal le résultat dans ce cas, mais ce n’est pas la faute des scripts Nautilus).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour rappel, la méthode la plus courante pour itérer sur les fichiers fait trois lignes de moins, mais nous avons vu qu’elle n’est pas universelle :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;&lt;span class="normal"&gt;1&lt;/span&gt;
&lt;span class="normal"&gt;2&lt;/span&gt;
&lt;span class="normal"&gt;3&lt;/span&gt;
&lt;span class="normal"&gt;4&lt;/span&gt;
&lt;span class="normal"&gt;5&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;arg&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# Do something here:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;-ld&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$arg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Si vous avez une solution plus claire, plus concise, ou plus générale, n’hésitez pas à me la soumettre afin que je mette à jour mon billet.&lt;/p&gt;
&lt;h1 id="ressources-supplementaires"&gt;Ressources supplémentaires&lt;/h1&gt;
&lt;p&gt;Quelques ressources si vous voulez explorer un peu plus ces scripts Nautilus :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://help.ubuntu.com/community/NautilusScriptsHowto/"&gt;Sur le wiki de la communauté Ubuntu anglophone (en)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://doc.ubuntu-fr.org/nautilus_scripts"&gt;Sur le wiki de la communauté Ubuntu francophone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/title/GNOME/Files#Custom_scripts"&gt;Sur le wiki Archlinux (en)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ou encore, &lt;a href="https://lmgtfy.app/#gsc.q=nautilus%20scripts"&gt;la très classique&lt;/a&gt; recherche sur les interwebs…&lt;/li&gt;
&lt;/ul&gt;</content><category term="Logiciels"/><category term="Gnome"/><category term="Nautilus"/><category term="Bash"/><category term="trucs et astuces"/></entry><entry><title>La vanlife est-elle écologique ?</title><link href="https://www.pragmageek.fr/2020/12/la-vanlife-est-elle-ecologique/" rel="alternate"/><published>2020-12-10T00:00:00+01:00</published><updated>2021-03-24T23:40:08+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2020-12-10:/2020/12/la-vanlife-est-elle-ecologique/</id><summary type="html">&lt;p&gt;&lt;img alt="Image van" class="left" src="https://www.pragmageek.fr/images/2024/VanVehicleMinibusCarAI.webp" title="https://www.rawpixel.com/image/12572410/van-vehicle-minibus-car-generated-image-rawpixel"&gt; Ah, qu&amp;#8217;ils sont enviables ces vanlifers, avec leur liberté. Ces nouveaux hippies #flowerpower qui nous font rêver avec leurs pages Instagram et leurs photos, planches de surf à la main, chaussures de randonnée aux pieds, dans des lieux tous plus magnifiques les uns que les autres. Ils exhibent une vie simple, minimaliste, proche de la nature, respectueuse de l&amp;#8217;environnement. Écolo et&amp;nbsp;durable.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Image van" class="left" src="https://www.pragmageek.fr/images/2024/VanVehicleMinibusCarAI.webp" style="width: 800px; height: auto; max-width: 100%;" title="https://www.rawpixel.com/image/12572410/van-vehicle-minibus-car-generated-image-rawpixel"/&gt; Ah, qu’ils sont enviables ces vanlifers, avec leur liberté. Ces nouveaux hippies #flowerpower qui nous font rêver avec leurs pages Instagram et leurs photos, planches de surf à la main, chaussures de randonnée aux pieds, dans des lieux tous plus magnifiques les uns que les autres. Ils exhibent une vie simple, minimaliste, proche de la nature, respectueuse de l’environnement. Écolo et durable.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Vue de la mer depuis l'intérieur d'un van aménagé" src="https://www.pragmageek.fr/images/2020/manuel-meurisse-flWsg878m_I-unsplash.jpg" style="width: 640px; height: auto; max-width: 100%;" title='&amp;lt;span&amp;gt;Photo by &amp;lt;a href="https://unsplash.com/@manuelmeurisse?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&amp;gt;Manuel Meurisse&amp;lt;/a&amp;gt; on &amp;lt;a href="https://unsplash.com/s/photos/vanlife?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&amp;gt;Unsplash&amp;lt;/a&amp;gt;&amp;lt;/span&amp;gt;'/&gt;&lt;/p&gt;
&lt;p&gt;Et ces youtubers exceptionnels, partis vivre le nomadisme en famille, faisant le tour du monde de pays en pays, offrants à leurs enfants une expérience unique à bord d’un camping car ou, mieux, d’un véritable poids lourd aménagé ? Le rêve, tout quitter, avec ceux qu’on aime, se mettre freelance pour gagner sa croûte et faire l’éducation des enfants “à la maison” avec le &lt;span class="caps"&gt;CNED&lt;/span&gt;. Pas d’attache, pas de contrainte (sauf en temps de pandémie virale, mais là c’est exceptionnel).&lt;/p&gt;
&lt;p&gt;Il y a aussi les camping caristes plus classiques, ceux qu’on connaît dans la vraie vie, qu’on croise tous les jours sur les routes. Vous savez, ceux qui, retraités, sont en vacances toute l’année et parcourent l’Europe et le Maghreb six mois durant. Le véhicule en hivernage de novembre à avril, la maison en &lt;a href="https://www.interieur.gouv.fr/A-votre-service/Ma-securite/Conseils-pratiques/A-votre-domicile/Zen-en-vacances-Beneficiez-de-l-Operation-Tranquillite-Vacances"&gt;&lt;span class="caps"&gt;OTV&lt;/span&gt;&lt;/a&gt; de mai à octobre, le mois de juillet au bord des routes pour suivre une étape du tour de France sur deux. L’aboutissement d’une vie, le camping car acheté une fois le crédit de la maison remboursé, une retraite bien méritée après une vie à trimer.&lt;/p&gt;
&lt;p&gt;Enfin, il y a moi, qui me suis laissé tenter par &lt;a href="https://www.fourgonlesite.com/fourgon-neuf/29024-free-540-blue-evolution-discret-par-la-taille-moins-par-le-style/"&gt;l’achat d’un fourgon aménagé&lt;/a&gt;, pour les vacances et les weekends, après avoir validé le concept en van aménagé pour mon voyage de noces. C’est un gros investissement financier, mais à moi la vie simple, les week-ends au grand air loin du quotidien, le minimalisme d’un petit espace de vie, l’économie des ressources rares que sont l’eau, l’électricité ou le gaz dans ces véhicules.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Hymer free 540 blue evolution 2021" src="https://www.pragmageek.fr/images/2020/Hymer_Free_540_BlueEvolution_Exterior_View-1.jpg" style="width: 500px; height: auto; max-width: 100%;"/&gt;&lt;/p&gt;
&lt;h1 id="la-comparaison-avec-notre-mode-de-vie-polluant"&gt;La comparaison avec notre mode de vie polluant&lt;/h1&gt;
&lt;p&gt;C’est pourtant vrai, quand on y pense, on a des vies de dingues au quotidien dans nos vastes logements. On pollue, on laisse les lumières allumées, on prend de longues douches chaudes, on jette des kilos de plastiques et autres déchets tous les jours, on a largement la place pour stocker tous les gadgets inutiles que les marketeux nous ont persuadé d’acheter (parce qu’au fond de nous, on ne savait pas que c’était indispensable jusqu’à ce qu’on en voit la pub au milieu de Koh Lanta) et on prend cette saleté de bagnole dès qu’on peut. Bref, on détruit notre planète, inconséquents que nous sommes (#nofutur #yolo pour que les plus jeunes comprennent), et par dessus tout on se prive des bienfaits de la nature.&lt;/p&gt;
&lt;p&gt;Mais la vanlife, qu’elle soit permanente ou occasionnelle, seul, en couple ou en famille, est-elle écolo ? Est-elle vraiment un mode de vie responsable ? Est-elle compatible avec le respect de la nature que le réveil écologique ambiant de ces dernières années édicte ? Personnellement je n’en suis pas bien certain, et je ne suis &lt;a href="https://www.bonjourcaravaning.fr/actualites/ecologique-le-camping-car/"&gt;pas le seul à me poser des questions&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id="la-vanlife-eco-responsable"&gt;La vanlife éco-responsable&lt;/h1&gt;
&lt;p&gt;Alors oui, il y a ces initiatives, ici ou là, pour construire un projet éco-responsable, une itinérance sociale basée sur le troc et l’entraide, avec des toilettes sèches installées dans un fourgon de 25 ans d’âge aménagé avec du bois de récupération. Le camping car électrique n’est pourtant que &lt;a href="https://camping-car.org/article/camping-cars/page/lesCampingCarsElectriquesEtHybrides"&gt;chimère&lt;/a&gt; (allez mettre &lt;a href="https://blogs.mediapart.fr/jean-lucien-hardy/blog/270318/une-tesla-transporte-600-kilos-de-batteries-au-lithium-cest-un-fait"&gt;600kg de batteries&lt;/a&gt; dans un véhicule qui fait déjà 3 tonnes), et la version à pile à combustible, carburant à l’hydrogène, n’existe qu’&lt;a href="https://www.camping-car.com/actus-des-marques/24392-un-camping-car-tres-ecolo"&gt;à l’état de prototype&lt;/a&gt;. &lt;a href="http://monptipote.com/camping-car-cest-anti-ecolo/"&gt;Certains vanlifers&lt;/a&gt; argueront qu’ils économisent des dizaines de milliers de litres d’eau et des centaines de kilowattheures d’électricité par an. Certes. Mais pas besoin d’une maison sur roues pour cela. Une vie simple et éco-responsable, emprunte de minimalisme, zéro déchet, cuisine maison, vegan locale, sans achat compulsif, ça peut se mettre en place dans un appartement ou une maison, pour peu que cette dernière ne soit pas une passoire thermique chauffée au fioul.&lt;/p&gt;
&lt;h1 id="le-critere-qui-met-tout-le-monde-au-tapis-les-emissions-de-co2"&gt;Le critère qui met tout le monde au tapis : les émissions de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt;&lt;/h1&gt;
&lt;p&gt;Parce qu’il est là, le critère numéro un, celui qui met tous les autres au tapis : les émissions de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt;. Peu importe que tu aies consommé peu d’eau dans l’année ou que tu aies mangé vegan sans exploiter la souffrance animale. Si tu balances plus de deux tonnes de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; par an et par personne, tu diriges le monde lentement vers un écocide qui sera gravement préjudiciable à l’espèce humaine.&lt;/p&gt;
&lt;p&gt;Et combien ça émet de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; un vanlifer, juste pour bouger son véhicule ? Un fourgon aménagé récent sur Fiat Ducato, ça annonce une conso moyenne de 8 litres aux 100 kilomètres. C’est souvent optimiste ces annonces, je m’attends plus à du 10L/100km en conditions réelles avec famille et bagages, &lt;span class="caps"&gt;PTAC&lt;/span&gt; de 3T5 atteint. De même, un gros integral et sa prise au vent, ça doit consommer du 12L/100. Pour ce qui est des véritables vans de vanlifers nord-américains qui nous font rêver, un Mercedes Sprinter 4x4, c’est du 17L/100. Et on en parle, du &lt;a href="https://www.youtube.com/c/Thevadrouilleursforr%C3%AAveur/about"&gt;poids lourd de 5 ou 6 tonnes pour déplacer une famille de 5 personnes&lt;/a&gt; ? 25 litres aux cent ?&lt;/p&gt;
&lt;p&gt;&lt;img alt="Gaz d'échappement" src="https://www.pragmageek.fr/images/2020/268416998_4edb6382d2_b.jpg" style="width: 512px; height: auto; max-width: 100%;" title="Pollution! by Dr. Keats is licensed with CC BY-NC 2.0."/&gt;&lt;/p&gt;
&lt;p&gt;Mais d’ailleurs, combien de kilomètres on fait en simple fourgon à 10L/100, pour atteindre les 2 tonnes de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; émises ? Rapide calcul :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 litre de gasoil pur et parfaitement brulé émet &lt;a href="https://www.econologie.com/emissions-CO2-litre-carburant-essence-diesel-ou-gpl/"&gt;2,6 kg de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt;&lt;/a&gt; ;&lt;/li&gt;
&lt;li&gt;10 litres génèrent donc 26 kg (pour 100 km) ;&lt;/li&gt;
&lt;li&gt;En 1 km on génère donc 0.26kg de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; (260 grammes — vous l’aviez vue venir, la petite règle de trois ?).&lt;/li&gt;
&lt;li&gt;Pour générer 2 tonnes (2000 kg) de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt;, il suffit donc de parcourir 2000/0,26=7692km&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Arrondissons à 8000 km (c’est l’ordre de grandeur qui est important, pas le chiffre exact).&lt;/p&gt;
&lt;p&gt;Un vanlifer, camping cariste ou autre touriste qui se déplace seul, une fois qu’il a parcouru 8000 km, il doit arrêter de vivre, consommer, manger, boire ou faire l’entretien de son van s’il ne veut pas participer à la destruction du climat, puisque toute activité supplémentaire générerait des grammes de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; que la planète n’est pas en mesure d’assimiler.&lt;/p&gt;
&lt;p&gt;Avec une famille de 4 personnes ça fait théoriquement le quadruple, soit environ 32 000 km (donc pas encore assez pour faire le tour du monde) et toujours en supposant qu’à coté de ça le chef de famille assume d’allouer la totalité du “crédit carbone” de son foyer au réservoir de son véhicule et laisse tout le monde crever de faim et de soif (vous le saviez, qu’un simple café représente environ 50 grammes de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; ?).&lt;/p&gt;
&lt;p&gt;Un &lt;a href="https://go-van.com/transit-sprinter-promaster-quelle-van-choisir/"&gt;vanlifer américain avec un véhicule 4x4 à 17L/100&lt;/a&gt; atteint les 2 tonnes en 4500 km. Vous vous voyez traverser le Canada et les grandes plaines américaines en vous limitant à la moitié de ça (pour garder de la marge pour s’habiller, boire, manger… Survivre) ? À mes yeux, ça n’est pas compatible avec la “grande vie vanlife”, qui nécessite d’être totalement libre pour pouvoir s’épanouir.&lt;/p&gt;
&lt;h1 id="alors-on-fait-quoi"&gt;Alors, on fait quoi ?&lt;/h1&gt;
&lt;p&gt;La vérité c’est qu’on nous vend du rêve, celui de la liberté absolue tant qu’on en a les moyens financiers, celui de la vie d’avant, celui pour lequel nos parents se sont battus, mais qui se révèle aujourd’hui être une détestable illusion générant frustration et colère quand on en prend conscience : consommer rendrait heureux. Ce n’est pas le cas. Tout n’est pourtant pas interdit, mais ça doit se faire à petites doses, avec mesure, avec prudence.&lt;/p&gt;
&lt;p&gt;Un kilogramme de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt; émis aujourd’hui aura le même effet qu’un autre émis en 2050 (date à laquelle l’ensemble des pays signataires des accord de Paris se sont engagés à être neutres en carbone pour limiter le réchauffement climatique à 2°C). Se dire qu’on peut sans conséquence émettre autant qu’on veut aujourd’hui et réduire lentement ses émissions jusqu’à la neutralité en 2050, ça n’est pas une gestion responsable, “en bon père de famille”. C’est de l’égoïsme.&lt;/p&gt;
&lt;p&gt;Dans ce cas, que pouvons nous faire ? Faisons des petits trajets, des petits week-end de 150 ou 200km pour trouver un coin de nature près de chez soi. Oublions les road trip à travers l’Europe. Limitons-nous à 2000, 3000 ou 4000 km par an et par famille, ça ne fera que 500 kg ou 1 tonne de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt;. C’est déjà beaucoup (peut-être trop ?), mais c’est suffisant pour profiter tout en commençant à faire la différence à long terme si c’est associé à de sérieux efforts au quotidien pour atteindre un mode de vie durable.&lt;/p&gt;
&lt;p&gt;En 2050, théoriquement, si la France respecte ses engagements et qu’à titre individuel on doit se restreindre pour être dans la limite de 2 tonnes de &lt;span class="caps"&gt;CO&lt;/span&gt;&lt;sub&gt;2&lt;/sub&gt;, ce qu’on n’atteindra qu’avec difficulté en respectant nos besoin vitaux de base (manger, s’abriter, se chauffer et se soigner), la question de dépenser ne serait-ce que 25% de cette quantité d’émission pour un seul loisir ne se posera plus : on ne le fera pas.&lt;/p&gt;
&lt;p&gt;De toute façon et avant cette échéance, quand le gazole sera à 5€ le litre, voire plus (à cause des taxes carbone ou de l’augmentation du prix du baril), on ne pourra plus se permettre, financièrement cette fois, d’être inconséquent. On se souviendra avec nostalgie de la liberté des vanlifer d’antan et on acceptera nos nouvelles contraintes, de gré ou de force.&lt;/p&gt;</content><category term="Divers"/><category term="vanlife"/><category term="camping-car"/><category term="réchauffement climatique"/></entry><entry><title>Filtrer les messages d’erreur de zenity au sujet d’un “transient parent”</title><link href="https://www.pragmageek.fr/2020/06/filtrer-message-erreur-zenity/" rel="alternate"/><published>2020-06-13T00:00:00+02:00</published><updated>2020-12-30T06:57:02.265538+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2020-06-13:/2020/06/filtrer-message-erreur-zenity/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo Bash" class="left" src="https://www.pragmageek.fr/images/2018/Bash-logo.png"&gt;Lorsqu&amp;#8217;on développe un &amp;#8220;petit&amp;#8221; script bash, on peut parfois vouloir y ajouter une interface graphique basique. Le plus simple pour cela est d&amp;#8217;utiliser &lt;a href="https://help.gnome.org/users/zenity/3.24/"&gt;zenity&lt;/a&gt;. Cet utilitaire fournit des boites de dialogue en Gtk pour différents usages. &lt;em&gt;Zenity&lt;/em&gt; est très pratique, mais souffre d&amp;#8217;un bug&amp;nbsp;horripilant.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo Bash" class="left" src="https://www.pragmageek.fr/images/2018/Bash-logo.png" style="width: 128px; height: auto; max-width: 100%;"/&gt;
Lorsqu’on développe un “petit” script bash, on peut parfois vouloir y ajouter une interface graphique basique. Le plus simple pour cela est d’utiliser &lt;a href="https://help.gnome.org/users/zenity/3.24/"&gt;zenity&lt;/a&gt;. Cet utilitaire fournit des boites de dialogue en Gtk pour différents usages.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Zenity&lt;/em&gt; est très pratique, mais souffre d’un bug horripilant. Regardez plutôt :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;zenity&lt;span class="w"&gt; &lt;/span&gt;--info
&lt;/span&gt;&lt;span class="go"&gt;Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;En fonction de la version de &lt;em&gt;zenity&lt;/em&gt;, ce message d’erreur est systématique et s’affiche à chaque appel du programme. Il &lt;a href="https://forum.ubuntu-fr.org/viewtopic.php?id=2001190"&gt;gêne&lt;/a&gt; &lt;a href="https://forum.ubuntu-fr.org/viewtopic.php?id=1996551"&gt;beaucoup&lt;/a&gt; &lt;a href="https://www.linuxquestions.org/questions/debian-26/%5Bsolved%5D-gtk-message-gtkdialog-mapped-without-a-transient-parent-this-is-discouraged-4175550278/"&gt;de&lt;/a&gt; &lt;a href="https://askubuntu.com/questions/844323/error-message-when-running-zenity-under-16-04-gtk-message-gtkdialog-mapped-wit"&gt;monde&lt;/a&gt; car bien qu’envoyé sur &lt;span class="caps"&gt;STDERR&lt;/span&gt; donc ne bloquant pas le fonctionnement normal de &lt;em&gt;zenity&lt;/em&gt; (dont on exploite uniquement la sortie standard &lt;span class="caps"&gt;STDOUT&lt;/span&gt; et les statuts de sortie $?), mais pollue visuellement la console si vous suivez ce qu’il s’y passe pendant l’exécution de votre script.&lt;/p&gt;
&lt;p&gt;La solution qui est proposée à chaque fois est de se débarrasser de &lt;span class="caps"&gt;STDERR&lt;/span&gt;, de cette manière : &lt;code&gt;zenity --info 2&amp;gt;/dev/null&lt;/code&gt;. Hop, plus de message d’erreur, et on peut même rendre cette &lt;a href="https://askubuntu.com/questions/896935/how-to-make-zenity-transient-parent-warning-disappear-permanently/896940#896940"&gt;solution plus “permanente”&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sauf que… on n’a plus de message d’erreur du tout, pas uniquement celle qui nous gêne.&lt;/p&gt;
&lt;p&gt;J’ai donc recherché une solution plus élégante et moins radicale et j’ai trouvé mon bonheur sur &lt;a href="http://www.burgerbum.com/stderr_pipe.html"&gt;ce billet de blog (en)&lt;/a&gt; qui explique comment bidouiller avec les fichiers de sortie pour filtrer &lt;span class="caps"&gt;STDOUT&lt;/span&gt; avec &lt;em&gt;grep&lt;/em&gt;, puis j’ai complété la solution avec &lt;a href="https://stackoverflow.com/questions/1221833/pipe-output-and-capture-exit-status-in-bash/1221870#1221870"&gt;cette réponse sur Stackoverflow (en)&lt;/a&gt; pour pouvoir continuer à exploiter le statut de sortie de &lt;em&gt;zenity&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;On en arrive à la solution ci-dessous :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;zenity&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;zenity&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"transient"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PIPESTATUS&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;La même, mieux formatée sur plusieurs lignes :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;zenity&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;zenity&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"transient"&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PIPESTATUS&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Insérez ce code au début de votre script, ou dans votre &lt;em&gt;bashrc&lt;/em&gt;, et utilisez &lt;em&gt;zenity&lt;/em&gt; comme avant, sans être pollué par ce message, tout en conservant les autres éventuels messages d’erreur.&lt;/p&gt;</content><category term="Logiciels"/><category term="Bash"/><category term="Zenity"/><category term="Trucs et astuces"/></entry><entry><title>Installer Aurora Services avec adb</title><link href="https://www.pragmageek.fr/2020/06/installer-aurora-services-avec-adb/" rel="alternate"/><published>2020-06-12T00:00:00+02:00</published><updated>2020-12-30T06:56:04.186694+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2020-06-12:/2020/06/installer-aurora-services-avec-adb/</id><summary type="html">&lt;p&gt;&lt;img alt="Aurora Services Logo" class="left" src="https://www.pragmageek.fr/images/2020/aurora-services-logo.png"&gt;Aurora est un magasin d&amp;#8217;applications alternatif permettant d&amp;#8217;accéder au catalogue du Google Play Store. Il est utile quand on a choisi d&amp;#8217;utiliser une &lt;span class="caps"&gt;ROM&lt;/span&gt; Android alternative sans les services Google Play. Par défaut, il ne permet néanmoins pas d&amp;#8217;installer automatiquement les applications et leurs mises à jour. Afin d&amp;#8217;éviter de pénibles actions manuelles, nous allons voir comment installer les &lt;em&gt;Services Aurora&lt;/em&gt;.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Aurora Services Logo" class="left" src="https://www.pragmageek.fr/images/2020/aurora-services-logo.png" style="width: 179px; height: auto; max-width: 100%;"/&gt;
Aurora est un magasin d’applications alternatif permettant d’accéder au catalogue du Google Play Store. Il est utile quand on a choisi d’utiliser une &lt;span class="caps"&gt;ROM&lt;/span&gt; Android alternative sans les services Google Play. Par défaut, il ne permet néanmoins pas d’installer automatiquement les applications et leurs mises à jour. Afin d’éviter de pénibles actions manuelles, nous allons voir comment installer les &lt;em&gt;Services Aurora&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;La procédure à suivre est &lt;em&gt;vaguement&lt;/em&gt; indiquée sur le &lt;a href="https://gitlab.com/AuroraOSS/AuroraServices/-/blob/master/README.md"&gt;&lt;span class="caps"&gt;README&lt;/span&gt; officiel&lt;/a&gt;. Ce n’est pas assez détaillé pour qu’un non initié y comprenne quoi que ce soit, donc je détaille ici la marche à suivre.&lt;/p&gt;
&lt;h1 id="installation-sur-un-telephone-non-roote"&gt;Installation sur un téléphone non rooté&lt;/h1&gt;
&lt;p&gt;Le postulat de départ est qu’on a affaire à un téléphone avec une &lt;span class="caps"&gt;ROM&lt;/span&gt; alternative, non rooté mais avec un recovery custom (par exemple &lt;span class="caps"&gt;TWRP&lt;/span&gt;).&lt;/p&gt;
&lt;h2 id="prerequis"&gt;Prérequis&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Un ordinateur avec &lt;a href="https://developer.android.com/studio/command-line/adb"&gt;adb&lt;/a&gt; ;&lt;/li&gt;
&lt;li&gt;Un téléphone Android ;&lt;/li&gt;
&lt;li&gt;Un câble &lt;span class="caps"&gt;USB&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Téléchargez les fichiers nécessaires (consultez la &lt;a href="https://gitlab.com/AuroraOSS/AuroraServices/-/releases"&gt;page de téléchargement&lt;/a&gt; pour vous assurer de récupérer la dernière version disponible − 1.0.6 lors de la rédaction de ce billet) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;wget https://gitlab.com/AuroraOSS/AuroraServices/uploads/c80bee54c1dc782df78a31065c710e59/AuroraServices-v1.0.6.apk
wget https://gitlab.com/AuroraOSS/AuroraServices/raw/master/app/src/main/assets/permissions_com.aurora.services.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="redemarrez-le-telephone"&gt;Redémarrez le téléphone&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Redémarrez en mode recovery (la manipulation dépend du modèle de téléphone que vous avez) ;&lt;/li&gt;
&lt;li&gt;Dans le recovery, montez la partition &lt;em&gt;System&lt;/em&gt; (Ne cochez bien évidemment pas la case “Mount system partition read-only”) ;&lt;/li&gt;
&lt;li&gt;Branchez le téléphone à l’ordinateur avec un câble &lt;span class="caps"&gt;USB&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Assurez-vous que votre téléphone est bien reconnu. &lt;code&gt;adb devices&lt;/code&gt; devrait vous lister un périphérique “recovery”. Si la liste est vide, c’est que vous avez loupé quelque chose.&lt;/p&gt;
&lt;h2 id="utilisez-adb"&gt;Utilisez &lt;span class="caps"&gt;ADB&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Assurez-vous que vous avez accès à /system. La commande &lt;code&gt;adb shell ls /system&lt;/code&gt; doit vous retourner une liste non vide :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;$&lt;span class="w"&gt; &lt;/span&gt;adb&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;/system
&lt;/span&gt;addon.d
app
bin
build.prop
compatibility_matrix.xml
etc
fake-libs
fake-libs64
fonts
framework
lib
lib64
lost+found
media
priv-app
product
recovery-from-boot.bak
usr
vendor
xbin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Si c’est tout bon, installez les deux fichiers téléchargés à leur emplacement. On les renomme au passage pour respecter la cohérence avec leurs voisins :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;adb push AuroraServices-v1.0.6.apk /system/priv-app/AuroraServices/AuroraServices.apk
adb push permissions_com.aurora.services.xml /system/etc/permissions/com.aurora.services.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Si vous obtenez le message d’erreur suivant, c’est que la partition &lt;em&gt;system&lt;/em&gt; est montée en lecture seule :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;adb: error: failed to copy 'AuroraServices-v1.0.6.apk' to '/system/priv-app/AuroraServices/AuroraServices.apk': remote couldn't create file: Read-only file system
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="sur-un-telephone-roote-avec-magisk"&gt;Sur un téléphone rooté avec Magisk&lt;/h1&gt;
&lt;p&gt;Installez le &lt;a href="https://gitlab.com/AuroraOSS/AuroraServices/uploads/2e0d0989cfa5ecf4771633fdf139311a/AuroraServices-v1.0.6-magisk.zip"&gt;module Magisk officiel&lt;/a&gt;. Je n’en sais pas plus, je n’utilise pas cette méthode.&lt;/p&gt;
&lt;h1 id="sur-un-telephone-roote-sans-magisk"&gt;Sur un téléphone rooté sans Magisk&lt;/h1&gt;
&lt;p&gt;Avec un téléphone rooté, il n’est pas nécessaire de passer par le recovery. Il est possible d’accorder à adb les droits root (et donc la possibilité d’écrire dans la partition &lt;em&gt;system&lt;/em&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Activer le &lt;a href="https://www.frandroid.com/comment-faire/tutoriaux/184906_comment-acceder-au-mode-developpeur-sur-android"&gt;mode développeur&lt;/a&gt; ;&lt;/li&gt;
&lt;li&gt;Dans les “Options pour les développeurs” nouvellement apparues, activer le “Dégage Android” (activer l’interface Android Debug Bridge) ;&lt;/li&gt;
&lt;li&gt;Accorder l’accès root à &lt;span class="caps"&gt;ADB&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Brancher le téléphone à l’ordinateur avec un câble &lt;span class="caps"&gt;USB&lt;/span&gt;. Lorsque le téléphone vous le demandera, indiquez-lui de faire confiance à l’ordinateur (Note : il est possible d’utiliser &lt;span class="caps"&gt;ADB&lt;/span&gt; en Wi-Fi après avoir activé l’option idoine sur le téléphone puis avoir couplé les deux appareils avec la commande &lt;code&gt;adb connect IP_DU_TÉLÉPHONE:PORT&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Assurez-vous que votre téléphone est bien reconnu. &lt;code&gt;adb devices&lt;/code&gt; devrait vous lister un périphérique “device”. Si la liste est vide ou que le périphérique est indiqué comme étant “unauthorized”, c’est que vous avez loupé quelque chose.&lt;/p&gt;
&lt;p&gt;Utilisez maintenant &lt;span class="caps"&gt;ADB&lt;/span&gt; comme décrit plus haut.&lt;/p&gt;
&lt;p&gt;À la fin de vos manipulations, pensez à désactiver le “mode débogage &lt;span class="caps"&gt;USB&lt;/span&gt;”.&lt;/p&gt;
&lt;h1 id="utilisation-des-fonctionnalites"&gt;Utilisation des fonctionnalités&lt;/h1&gt;
&lt;p&gt;Redémarrez le téléphone et lancez l’application &lt;em&gt;Aurora Services&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Acceptez les permissions demandées par l’application, puis accordez les privilèges nécessaires à l’application &lt;em&gt;Aurora&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Dans les “Réglages” de l’application &lt;em&gt;Aurora&lt;/em&gt;, dans la section “Installations”, choisissez la méthode d’installation “Services Aurora”.&lt;/p&gt;
&lt;p&gt;Profitez désormais des installations et mises à jour ne nécessitant plus d’interventions manuelles.&lt;/p&gt;
&lt;h1 id="aparte"&gt;Aparté&lt;/h1&gt;
&lt;p&gt;La méthode détaillée dans ce billet est aussi applicable à l’installation de l’extension &lt;a href="https://f-droid.org/fr/packages/org.fdroid.fdroid.privileged/"&gt;F-Droid Privileged Extension&lt;/a&gt;, lorsque celle-ci n’est pas installée par défaut par le mainteneur de votre &lt;span class="caps"&gt;ROM&lt;/span&gt;. Le fichier &lt;em&gt;privapp-permissions-org.fdroid.fdroid.privileged.xml&lt;/em&gt; doit alors contenir :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;permissions&amp;gt;
    &amp;lt;privapp-permissions package="org.fdroid.fdroid.privileged"&amp;gt;
        &amp;lt;permission name="android.permission.DELETE_PACKAGES"/&amp;gt;
        &amp;lt;permission name="android.permission.INSTALL_PACKAGES"/&amp;gt;
    &amp;lt;/privapp-permissions&amp;gt;
&amp;lt;/permissions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="Logiciels"/><category term="Android"/><category term="Aurora"/><category term="AuroraOSS"/><category term="adb"/></entry><entry><title>Nextcloud - Please update your PHP version</title><link href="https://www.pragmageek.fr/2020/05/nextcloud-please-update-your-php-version/" rel="alternate"/><published>2020-05-31T00:00:00+02:00</published><updated>2020-12-30T06:56:12.590527+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2020-05-31:/2020/05/nextcloud-please-update-your-php-version/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo de Nextcloud" class="left" src="https://www.pragmageek.fr/images/2020/nextcloud-logo.png"&gt;Depuis la mise à jour de Nextcloud en version 18 sur Yunohost, je rencontre une erreur assez pénible liée à la version de &lt;span class="caps"&gt;PHP&lt;/span&gt; exécutée par défaut. On va s&amp;#8217;attacher à décrire puis à corriger ce&amp;nbsp;problème.&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo de Nextcloud" class="left" src="https://www.pragmageek.fr/images/2020/nextcloud-logo.png" style="width: 134px; height: auto; max-width: 100%;"/&gt;
Depuis la mise à jour de Nextcloud en version 18 sur Yunohost, je rencontre une erreur assez pénible liée à la version de &lt;span class="caps"&gt;PHP&lt;/span&gt; exécutée par défaut.&lt;/p&gt;
&lt;p&gt;On va s’attacher à décrire puis à corriger ce problème.&lt;/p&gt;
&lt;h1 id="description-du-probleme"&gt;Description du problème&lt;/h1&gt;
&lt;p&gt;Nextcloud 18 nécessite un environnement &lt;span class="caps"&gt;PHP&lt;/span&gt; en version 7.2 minimum. Sur Yunohost les version 5, 7.0 et 7.3 sont disponibles. Pour une raison que j’ignore Yunohost force la version par défaut à 7.0, ce qui engendre un “léger” contretemps. Lorsque le &lt;a href="https://docs.nextcloud.com/server/18/admin_manual/configuration_server/background_jobs_configuration.html"&gt;cron de Nextcloud&lt;/a&gt; est lancé toutes les 15 minutes avec l’exécutable &lt;code&gt;php&lt;/code&gt;, l’exécution échoue :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cron &lt;a href="mailto:nextcloud@cloud"&gt;nextcloud@cloud&lt;/a&gt; php -f /var/www/nextcloud/cron.php 2&amp;gt;&amp;amp;1&lt;/p&gt;
&lt;p&gt;This version of Nextcloud requires at least &lt;span class="caps"&gt;PHP&lt;/span&gt; 7.2&lt;br/&gt;You are currently running 7.0.33-29+0~20200514.36+debian9~1.gbp126f6f. Please update your &lt;span class="caps"&gt;PHP&lt;/span&gt; version.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Je reçois donc cet e-mail toutes les 15 minutes, soit 96 fois par jour… C’est plutôt pénible.&lt;/p&gt;
&lt;h1 id="comment-corriger-ce-probleme"&gt;Comment corriger ce problème&lt;/h1&gt;
&lt;p&gt;Il existe deux moyens de corriger ce problème.&lt;/p&gt;
&lt;h2 id="solution-1-retablir-la-version-par-defaut-de-php-du-systeme"&gt;Solution 1 : Rétablir la version par défaut de &lt;span class="caps"&gt;PHP&lt;/span&gt; du système&lt;/h2&gt;
&lt;p&gt;Il suffit de lancer (en root ou sudo) : &lt;code&gt;update-alternatives --config php&lt;/code&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Il existe 3 choix pour l'alternative php (qui fournit /usr/bin/php).

  Sélection   Chemin           Priorité  État
------------------------------------------------------------
  0            /usr/bin/php7.3   73        mode automatique
  1            /usr/bin/php5     50        mode manuel
* 2            /usr/bin/php7.0   70        mode manuel
  3            /usr/bin/php7.3   73        mode manuel

Appuyez sur &amp;lt;Entrée&amp;gt; pour conserver la valeur par défaut[*] ou choisissez le numéro sélectionné :0
update-alternatives: utilisation de « /usr/bin/php7.3 » pour fournir « /usr/bin/php » (php) en mode automatique
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;C’est une solution que j’avais déjà mise en place. Elle est simple et rapide, mais elle n’a pas survécu à une mise à jour de Yunohost.&lt;/p&gt;
&lt;h2 id="solution-2-specifier-manuellement-la-version-de-php-de-cron"&gt;Solution 2 : Spécifier manuellement la version de &lt;span class="caps"&gt;PHP&lt;/span&gt; de cron&lt;/h2&gt;
&lt;p&gt;On peut tout simplement éditer le fichier cron (&lt;code&gt;crontab -u nextcloud -e&lt;/code&gt;) et modifier la dernière ligne :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;*/15  *  *  *  * php -f /var/www/nextcloud/cron.php 2&amp;gt;&amp;amp;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;qui doit devenir :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;*/15  *  *  *  * /usr/bin/php7.3 -f /var/www/nextcloud/cron.php 2&amp;gt;&amp;amp;1&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Il n’y a plus qu’à espérer que cette modification soit plus pérène, avant que le bug ne soit définitivement corrigé dans Yunohost.&lt;/p&gt;</content><category term="Auto-hébergement"/><category term="Nexcloud"/><category term="Yunohost"/><category term="PHP"/><category term="Auto-Hébergement"/></entry><entry><title>Installer Tribal Trouble sur Ubuntu 18.10</title><link href="https://www.pragmageek.fr/2019/03/installer-tribal-trouble-ubuntu-1810/" rel="alternate"/><published>2019-03-11T00:00:00+01:00</published><updated>2019-03-12T00:00:00+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2019-03-11:/2019/03/installer-tribal-trouble-ubuntu-1810/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo Tribal Trouble" class="left" src="https://www.pragmageek.fr/images/2019/tribaltrouble-logo.png" style="width: 140px; height: auto; max-width: 100%;"/&gt;Il y a cinq ans, j’avais publié &lt;a href="https://blog.arnoux.lu/2014/03/08/installer-tribaltrouble-ubuntu13.10/"&gt;un billet&lt;/a&gt; sur mon ancien blog afin de ne pas oublier comment faire fonctionner le jeu &lt;a href="http://oddlabs.com/tribaltrouble"&gt;Tribal Trouble&lt;/a&gt; sur une version “récente” de Ubuntu (en effet, c’est un jeu sorti en 2005, qui a été prévu pour fonctionner sur un système 32 bits. Je suis étonné qu’il soit encore possible de le lancer). Je mets ici à jour le tutoriel en question, car il n …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo Tribal Trouble" class="left" src="https://www.pragmageek.fr/images/2019/tribaltrouble-logo.png" style="width: 140px; height: auto; max-width: 100%;"/&gt;Il y a cinq ans, j’avais publié &lt;a href="https://blog.arnoux.lu/2014/03/08/installer-tribaltrouble-ubuntu13.10/"&gt;un billet&lt;/a&gt; sur mon ancien blog afin de ne pas oublier comment faire fonctionner le jeu &lt;a href="http://oddlabs.com/tribaltrouble"&gt;Tribal Trouble&lt;/a&gt; sur une version “récente” de Ubuntu (en effet, c’est un jeu sorti en 2005, qui a été prévu pour fonctionner sur un système 32 bits. Je suis étonné qu’il soit encore possible de le lancer). Je mets ici à jour le tutoriel en question, car il n’est plus d’actualité.&lt;/p&gt;
&lt;div class="toc"&gt;&lt;span class="toctitle"&gt;Table des matières&lt;/span&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#installation-du-jeu"&gt;Installation du jeu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#bidouilles-pour-que-tout-fonctionne"&gt;Bidouilles pour que tout fonctionne&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#activer-le-son"&gt;Activer le son&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#avoir-acces-au-clavier-pendant-le-jeu"&gt;Avoir accès au clavier pendant le jeu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#jouer"&gt;Jouer !&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#integration-au-systeme"&gt;Intégration au système&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#creer-un-fichier-desktop"&gt;Créer un fichier .desktop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#remplacer-licone-du-jeu"&gt;Remplacer l’icône du jeu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#activer-la-version-complete-du-jeu"&gt;Activer la version complète du jeu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#autres-astuces"&gt;Autres astuces&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#avoir-acces-a-la-deuxieme-campagne"&gt;Avoir accès à la deuxième campagne&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#avoir-acces-aux-codes-de-triche"&gt;Avoir accès aux codes de triche&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#remarques-diverses"&gt;Remarques diverses&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p&gt;Le jeu est désormais open-source et gratuit, &lt;a href="https://github.com/sunenielsen/tribaltrouble"&gt;libéré sur Github&lt;/a&gt;. Une reprise du code avait été entreprise par un groupe de développeurs, sous le nom de &lt;a href="https://web.archive.org/web/20180823134127/https://www.tribaltroubleremastered.com/"&gt;Tribal Trouble Remastered&lt;/a&gt;, mais le projet a rapidement été abandonné.&lt;/p&gt;
&lt;p&gt;Je vais donc m’atteler à expliquer en détail les étapes nécessaires à une installation complète de la version originale de Tribal Trouble sur Ubuntu 18.10 (version actuelle).&lt;/p&gt;
&lt;h1 id="installation-du-jeu"&gt;Installation du jeu&lt;/h1&gt;
&lt;p&gt;Il faut télécharger le binaire d’installation sur github et l’exécuter :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkdir ~/Jeux/
cd ~/Jeux/
wget https://github.com/sunenielsen/tribaltrouble/raw/master/binaries/TribalTroubleSetup.sh
sh TribalTroubleSetup.sh
cd tribaltrouble
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Il est nécessaire d’installer quelques dépendances pour que tout fonctionne :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt install libgl1:i386 libxrandr2:i386 libxcursor1:i386 libopenal1:i386
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="bidouilles-pour-que-tout-fonctionne"&gt;Bidouilles pour que tout fonctionne&lt;/h1&gt;
&lt;p&gt;Il reste quelques manipulations à effectuer pour corriger quelques problèmes.&lt;/p&gt;
&lt;h2 id="activer-le-son"&gt;Activer le son&lt;/h2&gt;
&lt;p&gt;Par défaut, le son ne fonctionne pas, il faut remplacer une bibliothèque fournie avec le jeu par celle que nous venons d’installer avec &lt;em&gt;apt&lt;/em&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mv gamedata/data-1/native/.svn/text-base/libopenal.so.svn-base{,.bak}
ln -s /usr/lib/i386-linux-gnu/libopenal.so.1 gamedata/data-1/native/.svn/text-base/libopenal.so.svn-base
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="avoir-acces-au-clavier-pendant-le-jeu"&gt;Avoir accès au clavier pendant le jeu&lt;/h2&gt;
&lt;p&gt;Pour rendre le clavier accessible (ne serait-ce que pour pouvoir mettre en pause ou quitter une partie avant la fin), il faut appliquer une modification trouvée sur ce &lt;a href="https://doc.ubuntu-fr.org/minecraft#clavier_ne_fonctionnant_pas"&gt;tutoriel relatif à Minecraft&lt;/a&gt; (lui aussi développé en Java) :&lt;/p&gt;
&lt;p&gt;Il faut lancer Tribal Trouble en utilisant l’option &lt;span class="caps"&gt;XMODIFIERS&lt;/span&gt;. Éditez le fichier &lt;em&gt;tribaltrouble&lt;/em&gt; et modifiez la dernière ligne comme ceci :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;XMODIFIERS= $JAVA -Xmx80000000 -cp loader.jar com.oddlabs.loader.Loader $JAVA loader.jar com.oddlabs.tt.Main --silent
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="jouer"&gt;Jouer !&lt;/h1&gt;
&lt;p&gt;Testez donc le jeu en le lançant avec la commande &lt;code&gt;./tribaltrouble&lt;/code&gt; dans un terminal. Cela permettra de vérifier que tout fonctionne sans erreur, et ça créera le dossier de configuration (~/.TribalTrouble).&lt;/p&gt;
&lt;h1 id="integration-au-systeme"&gt;Intégration au système&lt;/h1&gt;
&lt;p&gt;Quelques manipulations sont nécessaires pour intégrer le jeu au système et pouvoir le lancer comme toute autre application.&lt;/p&gt;
&lt;h3 id="creer-un-fichier-desktop"&gt;Créer un fichier .desktop&lt;/h3&gt;
&lt;p&gt;Afin de pouvoir lancer le jeu depuis les menus du système, on va créer le fichier &lt;em&gt;.desktop&lt;/em&gt; approprié. Éditez le fichier &lt;code&gt;~/.local/share/application/tribaltrouble.desktop&lt;/code&gt; et mettez ceci dedans :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[Desktop Entry]&lt;br/&gt;
Type=Application&lt;br/&gt;
Name=TribalTrouble&lt;br/&gt;
Categories=Game;StrategyGame;&lt;br/&gt;
Comment=”Jeu libre de stratégie en temps réel”&lt;br/&gt;
Exec=/home/”VOTRE_USER”/Jeux/tribaltrouble/tribaltrouble&lt;br/&gt;
Icon=/home/”VOTRE_USER”/Jeux/tribaltrouble/tribaltrouble.png&lt;br/&gt; Terminal=false&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="remplacer-licone-du-jeu"&gt;Remplacer l’icône du jeu&lt;/h3&gt;
&lt;p&gt;Pour une raison que j’ignore, l’icone du jeu semble corrompue, et ne s’affiche donc pas dans le menu système, on va donc la remplacer par un autre, trouvée sur internet :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mv tribaltrouble.png{,.bak}
wget https://dl2.macupdate.com/images/icons128/18613.png?d=1331563899 -O tribaltrouble.png
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="activer-la-version-complete-du-jeu"&gt;Activer la version complète du jeu&lt;/h2&gt;
&lt;p&gt;Le jeu a été libéré tel quel, sans modification de la part de ses créateurs. Ainsi, bien que désormais gratuit, il demande toujours une activation pour avoir accès à toutes les fonctionnalités. Ses créateurs fournissent donc un &lt;a href="https://github.com/sunenielsen/tribaltrouble/blob/master/binaries/registration"&gt;fichier d’activation&lt;/a&gt; à placer dans le dossier des paramètres :&lt;/p&gt;
&lt;p&gt;Téléchargez le fichier &lt;a href="https://www.pragmageek.fr/static/2019/registration"&gt;registration&lt;/a&gt; et placez-le dans &lt;code&gt;~/.TribalTrouble/registration&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id="autres-astuces"&gt;Autres astuces&lt;/h1&gt;
&lt;p&gt;J’ajoute ici quelques éléments supplémentaires, qui étaient disponibles sur feu le site officiel.&lt;/p&gt;
&lt;h2 id="avoir-acces-a-la-deuxieme-campagne"&gt;Avoir accès à la deuxième campagne&lt;/h2&gt;
&lt;p&gt;Pour avoir accès à la deuxième campagne sans avoir terminé la première, il suffit d’ajouter cette ligne au   fichier &lt;em&gt;~/.TribalTrouble/settings&lt;/em&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;has_native_campaign=true&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="avoir-acces-aux-codes-de-triche"&gt;Avoir accès aux codes de triche&lt;/h2&gt;
&lt;p&gt;Au cours d’une partie en solo (le seul mode de jeu encore disponible), il est possible d’activer les codes de triche en ouvrant une invite de dialogue (touche &lt;em&gt;Entrer&lt;/em&gt;), et de taper &lt;code&gt;/iamacheater&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On a alors accès aux codes suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;F1: Insert peon&lt;/li&gt;
&lt;li&gt;F2: Insert rock warrior&lt;/li&gt;
&lt;li&gt;F3: Insert iron warrior&lt;/li&gt;
&lt;li&gt;F4: Insert chicken warrior&lt;/li&gt;
&lt;li&gt;F5: Insert chieftain&lt;/li&gt;
&lt;li&gt;F6: Kill selected unit/building&lt;/li&gt;
&lt;li&gt;F7: Toggle tree visibility&lt;/li&gt;
&lt;li&gt;F8: Toggle wireframe mode&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="remarques-diverses"&gt;Remarques diverses&lt;/h2&gt;
&lt;p&gt;Il n’y a désormais plus de bug concernant le passage du jeu en plein écran, ça semble être un progrès par rapport au dernier tutoriel. Par contre, je note aussi qu’il m’a été impossible de lancer le jeu lorsque j’étais sous Ubuntu 17.10, utilisant Wayland en lieu et place de X11. Ce dernier étant voué à disparaitre au profit du premier, je crains qu’un jour il ne soit plus possible de jouer à Tribal Trouble.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bon jeu !&lt;/strong&gt;&lt;/p&gt;</content><category term="Jeux"/><category term="TribalTrouble"/><category term="Linux"/><category term="RTS"/></entry><entry><title>Héberger son propre serveur de calendrier et de contacts</title><link href="https://www.pragmageek.fr/2015/08/serveur-calendrier-contacts/" rel="alternate"/><published>2015-08-12T00:00:00+02:00</published><updated>2020-12-30T06:56:10.658565+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2015-08-12:/2015/08/serveur-calendrier-contacts/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo Radicale" class="left" src="https://www.pragmageek.fr/images/2015/radicale-logo.png" style="width: 110px; height: auto; max-width: 100%;"/&gt;Un des services indispensables pour s’affranchir de Google en s’auto-hébergeant est le serveur de calendrier et de contacts. On va ici installer le logiciel Radicale, serveur calDAV et cardDAV simple.&lt;/p&gt;
&lt;p&gt;Il existe plusieurs alternatives (DAVical, Baïkal, OwnCloud, etc.), mais Radicale est l’un des plus simples à mettre en œuvre pour un serveur auto-hébergé familial. Il ne demande aucune base de donnée, et n’ayant pas d’interface d’administration il se personnalise …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo Radicale" class="left" src="https://www.pragmageek.fr/images/2015/radicale-logo.png" style="width: 110px; height: auto; max-width: 100%;"/&gt;Un des services indispensables pour s’affranchir de Google en s’auto-hébergeant est le serveur de calendrier et de contacts. On va ici installer le logiciel Radicale, serveur calDAV et cardDAV simple.&lt;/p&gt;
&lt;p&gt;Il existe plusieurs alternatives (DAVical, Baïkal, OwnCloud, etc.), mais Radicale est l’un des plus simples à mettre en œuvre pour un serveur auto-hébergé familial. Il ne demande aucune base de donnée, et n’ayant pas d’interface d’administration il se personnalise facilement via des fichiers de configuration.&lt;/p&gt;
&lt;div class="toc"&gt;&lt;span class="toctitle"&gt;Table des matières&lt;/span&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#installation"&gt;Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configuration"&gt;Configuration&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#configuration-de-radicale"&gt;Configuration de Radicale&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configuration-du-fichier-rights"&gt;Configuration du fichier “rights”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configuration-du-serveur-web"&gt;Configuration du serveur web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#configuration-des-dns"&gt;Configuration des &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#creation-des-collections"&gt;Création des collections&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#etapes-supplementaires"&gt;Étapes supplémentaires&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#integration-a-fail2ban"&gt;Intégration à fail2ban&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#suivi-du-projet"&gt;Suivi du projet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h1 id="installation"&gt;Installation&lt;/h1&gt;
&lt;p&gt;La version présente dans les dépôts de Ubuntu 14.04 &lt;span class="caps"&gt;LTS&lt;/span&gt; est assez ancienne (0.8, au lieu de 0.10 à l’heure où je rédige ce tutoriel), il vaut donc mieux l’installer par une méthode alternative. Il est possible de l’installer par un &lt;code&gt;sudo pip install radicale&lt;/code&gt;, de créer un utilisateur dédié, de mettre en place un script &lt;em&gt;init&lt;/em&gt;, etc. mais j’ai trouvé mieux.&lt;/p&gt;
&lt;p&gt;Ce logiciel étant très simple, sans dépendances particulières (python et adduser, autant dire rien du tout), est possible d’aller chercher &lt;a href="http://packages.ubuntu.com/wily/radicale"&gt;les packages &lt;em&gt;.deb&lt;/em&gt; de la version 0.10 sur les dépôts d’Ubuntu 15.10&lt;/a&gt; et de les installer manuellement :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;wget http://fr.archive.ubuntu.com/ubuntu/pool/universe/r/radicale/radicale_0.10-2_all.deb
wget http://fr.archive.ubuntu.com/ubuntu/pool/universe/r/radicale/python-radicale_0.10-2_all.deb
sudo dpkg -i python-radicale_0.10-2_all.deb
sudo dpkg -i radicale_0.10-2_all.deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Radicale est désormais installée proprement, avec son utilisateur, ses dossiers de travail, son script init, etc.&lt;/p&gt;
&lt;p&gt;Comme j’utiliserai l’authentification via &lt;span class="caps"&gt;LDAP&lt;/span&gt;, je dois installer le paquet python-ldap :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo aptitude install python-ldap
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="configuration"&gt;Configuration&lt;/h1&gt;
&lt;p&gt;Dans un premier temps, il faut activer le daemon via un &lt;code&gt;sudo vim /etc/default/radicale&lt;/code&gt; et décommenter  la ligne &lt;code&gt;ENABLE_RADICALE=yes&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Le service peut désormais se lancer avec un :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo service radicale start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="configuration-de-radicale"&gt;Configuration de Radicale&lt;/h2&gt;
&lt;p&gt;La configuration se fait dans le dossier &lt;em&gt;/etc/radicale/&lt;/em&gt;, dans le fichier &lt;em&gt;config&lt;/em&gt;. Pour exemple, voici le mien, sans les commentaires et nettoyé des informations personnelles :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;[server]
hosts = 0.0.0.0:5232, [::]:5232
base_prefix = /radicale/
realm = Radicale - Mot de passe necessaire

[encoding]
request = utf-8
stock = utf-8

[well-known]
caldav = '/%(user)s/caldav/'
carddav = '/%(user)s/carddav/'

[auth]
type = LDAP
ldap_url = ldap://localhost:389/
ldap_base = ou=user,dc=exemple,dc=fr
ldap_attribute = mail
ldap_filter = (objectClass=posixAccount)
ldap_scope = OneLevel

[git]

[rights]
type = from_file
file = /etc/radicale/rights

[storage]
type = filesystem
filesystem_folder = /var/lib/radicale/collections

[logging]
config = /etc/radicale/logging
#debug = True
#full_environment = False

[headers]
#Access-Control-Allow-Origin = *
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Une fois le fichier modifié, un &lt;code&gt;sudo service radicale restart&lt;/code&gt; est requis.&lt;/p&gt;
&lt;p&gt;Pour information, vous pouvez trouver l’ensemble des options par défaut (qui n’ont donc pas besoin d’être inscrites explicitement dans le fichier &lt;em&gt;config&lt;/em&gt;, sauf en cas de modification) directement dans &lt;a href="https://github.com/Kozea/Radicale/blob/master/radicale/config.py"&gt;la source du logiciel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vous remarquerez que je n’active pas le chiffrement de la communication, car c’est le serveur web (Nginx) qui s’en chargera avant de “proxifier” les requêtes.&lt;/p&gt;
&lt;p&gt;En cas de souci, vous pouvez procéder par étapes (utiliser l’authentification locale avec un fichier htpasswd, ou bien les droits “None”, etc.), tout en activant les logs Debug (attention, c’est très, très, verbeux).&lt;/p&gt;
&lt;h2 id="configuration-du-fichier-rights"&gt;Configuration du fichier “rights”&lt;/h2&gt;
&lt;p&gt;Comme nous avons choisi de gérer des droits manuellement, il faut créer le fichier &lt;em&gt;/etc/radicale/rights&lt;/em&gt;. Voici le mien :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;## Configurations par défaut ##
# Ce sont les options par défaut proposées pour l'authentification.
# Voici ce à quoi elles correspondent exactement.

# "authenticated" #
#[authenticated-rw]
#user:.+
#collection:.*
#permission:rw

# "owner_write" #
#[authenticated-r]
#user:.+
#collection:.*
#permission:r

#[owner-write-w]
#user:.+
#collection:^%(login)s(/.*)?$
#permission:w

# "owner_only" #
[owner-only]
user:.+
collection:^%(login)s(/.*)?$
permission:rw

## Ajouts personnels ##
# Collections publiquement lisibles si elles sont nommées public-abc123
[anon-read-public]
user: .*
collection: ^.+/public-.+$
permission: r

# Collections accessibles en lecture et écriture par les autres utilisateurs
# authentifiés, nommées shared-rw-abc123
[users-read-write-shared]
user: .+
collection: ^.+/shared-rw-.+$
permission: rw

# Collections accessibles en lecture par les autres utilisateurs authenifiés,
# nommées shared-r-abc123
[users-read-shared]
user: .+
collection: ^.+/shared-r-.+$
permission: r

# On peut créer un dossier complet dans lequel toutes les collections seront
# accessibles en lecture, ici le dossier /public/
#[public]
#user: .*
#collection: ^public(/.+)?$
#permission: r

# On peut utiliseur le nom de domaine des utilisateurs pour leur donner des
# accès particuliers
#[domain-wide-access]
#user: ^.+@(.+)\..+$
#collection: ^{0}/.+$
#permission: r
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On peut ensuite ajouter des règles spécifiques à un utilisateur ou une collection précis. De plus, l’ordre dans lequel les règles sont créées importe peu.&lt;/p&gt;
&lt;p&gt;Personnellement, je me méfie grandement de la possibilité qui serait donnée à un utilisateur anonyme (“.*”) d’écrire quoi que ce soit sur mon serveur, donc je n’active pas cette options.&lt;/p&gt;
&lt;h2 id="configuration-du-serveur-web"&gt;Configuration du serveur web&lt;/h2&gt;
&lt;p&gt;Maintenant que Radicale est configuré et lancé, il faut configurer le serveur web, Nginx dans mon cas.&lt;/p&gt;
&lt;p&gt;Créons (ou complétons) le fichier &lt;em&gt;/etc/nginx/sites-available/machin.exemple.fr&lt;/em&gt; et mettons ceci dedans :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Dans un premier temps, on redirige tout vers le port 443 sécurisé&lt;/span&gt;
&lt;span class="k"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;listen&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;listen&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;machin.exemple.fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;rewrite&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;^&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$server_name$request_uri?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;permanent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Ensuite, on configure le tout dans la section dédiée au https&lt;/span&gt;
&lt;span class="k"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;listen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;[::]:443&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;server_name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;machin.exemple.fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;root&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="s"&gt;/var/www/machin.exemple.fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;index&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;index.html&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;index.htm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;index.php&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;access_log&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s"&gt;/var/log/nginx/cloud.arnoux.lu.access.log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;error_log&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/var/log/nginx/cloud.arnoux.lu.error.log&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;ssl_certificate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/chemin/vers/certificat-ssl.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/chemin/vers/cle-privee-ssl.key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# On gère les redirections utiles&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;rewrite&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;^/.well-known/carddav&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/radicale/&lt;/span&gt;&lt;span class="nv"&gt;$remote_user/carddav/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;rewrite&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;^/.well-known/caldav&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/radicale/&lt;/span&gt;&lt;span class="nv"&gt;$remote_user/caldav/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# On "proxifie" les requêtes à destination de /radicale/&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;# On ajoute quelques entêtes utiles pour que Radicale ait accès à l'adresse IP réelle du client&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kn"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/radicale&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_pass&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;http://localhost:5232&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;X-Real-IP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="configuration-des-dns"&gt;Configuration des &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;Dans la configuration du serveur web, on a défini les &lt;a href="https://tools.ietf.org/html/rfc5785"&gt;&lt;span class="caps"&gt;URI&lt;/span&gt; “.well-known”&lt;/a&gt;, qui facilitent l’auto-configuration de certains clients, et la découverte des &lt;em&gt;collections&lt;/em&gt; (calendriers ou carnets d’adresses) existantes.&lt;/p&gt;
&lt;p&gt;Dans le cas où le nom d’utilisateur que nous utilisons est une adresse email, il est possible d’activer une étape supplémentaire d’auto-configuration, [grâce à un enregistrement &lt;span class="caps"&gt;SRV&lt;/span&gt;](https://tools.ietf.org/html/rfc6764#section-3].&lt;/p&gt;
&lt;p&gt;Pour des adresse email de la forme utilisateur@domaine.com, et un serveur Radical qui se trouve sur l’ordi machin.exemple.fr, ajoutons ces enregistrements dans la zone &lt;span class="caps"&gt;DNS&lt;/span&gt; de domaine.com :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;\_caldavs.\_tcp 10800   IN  SRV 0 1 443 machin.exemple.fr.
\_carddavs.\_tcp 10800  IN  SRV 0 1 443 machin.exemple.fr.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Je n’ai volontairement pas mis les enregistrements non sécurisés (_caldav._tcp et _carddav._tcp), puisque je ne veux que des accès sécurisés à mon serveur.&lt;/p&gt;
&lt;h1 id="creation-des-collections"&gt;Création des collections&lt;/h1&gt;
&lt;p&gt;Certains clients, tel que DAVdroid, nécessitent que les collections existent déjà pour pouvoir les utiliser. Il faut donc les créer préalablement à toute utilisation. Comme l’explique &lt;a href="http://www.enricozini.org/2014/radicale-davdroid/"&gt;ce billet similaire au mien(en)&lt;/a&gt;, il est possible d’utiliser le programme &lt;a href="http://www.webdav.org/cadaver/"&gt;cadaver&lt;/a&gt;, mais dans le cas de Radicale, il y a plus simple : simplement en accédant au calendrier à l’aide d’un navigateur internet.&lt;/p&gt;
&lt;p&gt;Dans notre navigateur favori (Firefox, bien évidemment), il suffit d’accéder à la ressource “https://machin.exemple.fr/radicale/user@domaine.com/calendrier.ics/”. Entrez un nom d’utilisateur qui a un droit d’écriture sur cette ressource (user@domaine.com dans notre cas) ainsi que son mot de passe, et vous récupérerez un calendrier vide, qui aura été créé à la volée par Radicale.&lt;/p&gt;
&lt;p&gt;Terminez bien l’&lt;span class="caps"&gt;URL&lt;/span&gt; par un “/”. Vous pouvez nommez les calendriers et listes de tâche avec ou sans extension “.ics” (“calendrier.ics”, “todo.ics”, ou bien simplement “calendrier”), mais les carnets d’adresse doivent avoir l’extension “.vcf” (“adressbook.vcf”) afin de ne pas être identifiés comme des calendriers. Cela créera un fichier du même nom dans l’arborescence des collections de Radicale.&lt;/p&gt;
&lt;h1 id="etapes-supplementaires"&gt;Étapes supplémentaires&lt;/h1&gt;
&lt;h2 id="integration-a-fail2ban"&gt;Intégration à fail2ban&lt;/h2&gt;
&lt;p&gt;Par sécurité, comme pour tout service ouvert sur l’extérieur et offrant un système d’authentification, il faut surveiller les tentatives ratées d’authentification.&lt;/p&gt;
&lt;p&gt;Cela se fait avec fail2ban, mais il faut avoir accès à un fichier de log dans lequel apparait l’adresse &lt;span class="caps"&gt;IP&lt;/span&gt; du client. Par défaut, ce n’est pas possible dans Radicale, mais j’ai trouvé une astuce nécessitant de modifier le logiciel lui-même.&lt;/p&gt;
&lt;p&gt;C’est d’ailleurs pour cela que j’ai ajouté l’entête &lt;a href="https://en.wikipedia.org/wiki/X-Forwarded-For"&gt;X_Forwarded_For&lt;/a&gt; dans la configuration de Nginx. Il faut désormais accéder à cet entête.&lt;/p&gt;
&lt;p&gt;Cela se passe dans le fichier &lt;em&gt;/usr/lib/python2.7/dist-packages/radicale/__init__.py&lt;/em&gt;. Éditez-le en root, et modifiez la ligne suivante (qui devrait se trouver à la ligne 339) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;log.LOGGER.info("%s refused" % (user or "Anonymous user")
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Afin qu’elle ressemble à cela :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;log.LOGGER.info("%s refused from host %s" % (user or "Anonymous user", environ.get("HTTP_X_FORWARDED_FOR").split(", ")[0]))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;fail2ban pourra désormais accéder à l’adresse &lt;span class="caps"&gt;IP&lt;/span&gt; du client dont l’authentification a échoué, ou auquel un accès a été refusé, via le fichier de log &lt;em&gt;/var/log/radicale/radicale.log&lt;/em&gt;. La configuration de fail2ban fera l’objet d’un autre billet.&lt;/p&gt;
&lt;h2 id="suivi-du-projet"&gt;Suivi du projet&lt;/h2&gt;
&lt;p&gt;Afin de suivre les évolutions du projet, et de rester vigilant quant aux possibles découvertes de failles de sécurité, abonnez-vous au &lt;a href="http://radicale.org/rss/"&gt;flux &lt;span class="caps"&gt;RSS&lt;/span&gt; de Radicale&lt;/a&gt;, et à la mailing list du projet (envoyez un mail, peu importe son contenu, à &lt;a href="mailto:radicale@librelist.com"&gt;cette adresse&lt;/a&gt;. Ce premier mail sera supprimé après avoir lancé la procédure d’inscription).&lt;/p&gt;
&lt;p&gt;Sources :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;https://blogobramje.nl/posts/How_to_run_radicale_behind_nginx/&lt;/li&gt;
&lt;li&gt;http://www.rezine.org/documentation/auto-hebergement/services/agenda-contact/serveurs-cal-card/#index3h1&lt;/li&gt;
&lt;li&gt;http://www.pihomeserver.fr/2013/08/17/raspberry-pi-home-server-installer-radicale-pour-gerer-vos-contacts-et-calendriers/&lt;/li&gt;
&lt;/ul&gt;</content><category term="Auto-hébergement"/><category term="Calendrier"/><category term="Contacts"/><category term="Carnet d'adresse"/><category term="CalDAV"/><category term="CardDAV"/><category term="Radicale"/></entry><entry><title>Contrôler OpenELEC via HDMI-CEC avec une télécommande Samsung</title><link href="https://www.pragmageek.fr/2015/05/kodi-openelec-cec-telecommande-samsung/" rel="alternate"/><published>2015-05-12T00:00:00+02:00</published><updated>2020-12-30T06:56:02.058737+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2015-05-12:/2015/05/kodi-openelec-cec-telecommande-samsung/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo OpenELEC" class="left" src="https://www.pragmageek.fr/images/2015/Openelec_logo.png" style="width: 270px; height: auto; max-width: 100%;"/&gt;
Je possède un media-center sous &lt;a href="http://OpenELEC.tv/"&gt;OpenELEC&lt;/a&gt; 5 (&lt;a href="http://kodi.tv/"&gt;Kodi&lt;/a&gt; 14), que je viens d’équiper d’un “récepteur” &lt;span class="caps"&gt;HDMI&lt;/span&gt;-&lt;span class="caps"&gt;CEC&lt;/span&gt; de Pulse-Eight. Cela permet beaucoup de souplesse et d’automatisation quant au contrôle, allumage et extinction des appareils, le tout avec une seule télécommande (celle de la télévision). Malgré tout, il y a quelques réglages à faire pour que tout fonctionne comme je veux. Je vais donc détailler tout cela.&lt;/p&gt;
&lt;p&gt;Dans un premier temps, je vais …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo OpenELEC" class="left" src="https://www.pragmageek.fr/images/2015/Openelec_logo.png" style="width: 270px; height: auto; max-width: 100%;"/&gt;
Je possède un media-center sous &lt;a href="http://OpenELEC.tv/"&gt;OpenELEC&lt;/a&gt; 5 (&lt;a href="http://kodi.tv/"&gt;Kodi&lt;/a&gt; 14), que je viens d’équiper d’un “récepteur” &lt;span class="caps"&gt;HDMI&lt;/span&gt;-&lt;span class="caps"&gt;CEC&lt;/span&gt; de Pulse-Eight. Cela permet beaucoup de souplesse et d’automatisation quant au contrôle, allumage et extinction des appareils, le tout avec une seule télécommande (celle de la télévision). Malgré tout, il y a quelques réglages à faire pour que tout fonctionne comme je veux. Je vais donc détailler tout cela.&lt;/p&gt;
&lt;p&gt;Dans un premier temps, je vais rapidement détailler les réglages de contrôle mutuel de mes appareils (allumage et extinction) qui me conviennent. Dans un second temps, je vais configurer OpenELEC pour qu’il exploite au maximum les commandes provenant de la télécommande Samsung.&lt;/p&gt;
&lt;p&gt;Articulation de ce billet :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#conf-allumage-extinction"&gt;Configuration d’allumage et d’extinction&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#besoins"&gt;Expression des besoins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#reglages"&gt;Réglages à modifier&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#telecommande"&gt;Réglage de la télécommande&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#identifier-codes"&gt;Identifier les codes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#touche-action"&gt;Associer chaque touche à une action appropriée&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="conf-allumage-extinction"&gt;Configuration d’allumage et d’extinction&lt;/h1&gt;
&lt;p&gt;Selon les équipements, la norme &lt;a href="http://elinux.org/CEC_%28Consumer_Electronics_Control%29_over_HDMI"&gt;&lt;span class="caps"&gt;HDMI&lt;/span&gt;-&lt;span class="caps"&gt;CEC&lt;/span&gt; (en)&lt;/a&gt; permet d’allumer et d’éteindre les différents appareils indépendamment ou automatiquement.&lt;/p&gt;
&lt;p&gt;J’ai donc une télévision &lt;a href="http://www.samsung.com/fr/consumer/tv-audio-video/television/tv-led/UE46ES6710SXZF"&gt;Samsung &lt;span class="caps"&gt;UE46ES6710&lt;/span&gt;&lt;/a&gt; connecté via un port &lt;span class="caps"&gt;HDMI&lt;/span&gt; (&lt;span class="caps"&gt;CEC&lt;/span&gt; et &lt;span class="caps"&gt;ARC&lt;/span&gt;) à un ampli &lt;a href="http://marantz.fr/fr/Products/Pages/ProductDetails.aspx?CatId=HomeTheatre&amp;amp;SubCatId=AVReceiver&amp;amp;ProductId=NR1403"&gt;Marantz &lt;span class="caps"&gt;NR1403&lt;/span&gt;&lt;/a&gt;. À cet ampli est aussi connecté, en &lt;span class="caps"&gt;HDMI&lt;/span&gt;, mon media-center OpenELEC.&lt;/p&gt;
&lt;p&gt;Premier constat : pour une raison inconnue, ma télévision,  ne permet pas d’allumer tous les appareils à partir de sa télécommande (le réglage en question se réinitialise à chaque extinction de la tv). Tant mieux, ce n’est pas ce que je veux faire.&lt;/p&gt;
&lt;h2 id="besoins"&gt;Expression des besoins&lt;/h2&gt;
&lt;p&gt;Je présente ici mes besoins personnels. Les vôtres peuvent différer. Voici ce que je veux faire :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;La télévision est indépendante. Elle s’allume sans allumer le reste des éléments, et elle s’éteint sans les éteindre ;&lt;/li&gt;
&lt;li&gt;Par contre, elle est en retour contrôlée par les autres éléments. Quand j’allume le media-center, il allume l’ampli et sélectionne le media-center comme source, puis il allume la télévision (si elle est éteinte), et sélectionne la sortie &lt;span class="caps"&gt;HDMI&lt;/span&gt; vers l’ampli comme source vidéo.&lt;/li&gt;
&lt;li&gt;Lorsque je veux écouter de la musique, je peux lancer une playlist, puis éteindre la télévision. La musique continuera d’être jouée sur l’ampli.&lt;/li&gt;
&lt;li&gt;Lorsque j’éteins le media-center, cela éteint l’ampli, mais pas la tv. En effet, il m’arrive souvent de couper le media-center et de regarder les infos à la télé, par exemple.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tout ceci est possible en personnalisant quelques réglages sur chacun des appareils concernés.&lt;/p&gt;
&lt;h2 id="reglages"&gt;Réglages à modifier&lt;/h2&gt;
&lt;h3 id="sur-la-television"&gt;Sur la télévision&lt;/h3&gt;
&lt;p&gt;Dans le &lt;em&gt;Menu&amp;gt;Système&amp;gt;Anynet+ (&lt;span class="caps"&gt;HDMI&lt;/span&gt;-&lt;span class="caps"&gt;CEC&lt;/span&gt;)&lt;/em&gt;, je met les réglages suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Anynet+ (&lt;span class="caps"&gt;HDMI&lt;/span&gt;-&lt;span class="caps"&gt;CEC&lt;/span&gt;) : Activé (Pour activer la prise en charge générale des contrôles par &lt;span class="caps"&gt;HDMI&lt;/span&gt;-&lt;span class="caps"&gt;CEC&lt;/span&gt;) ;&lt;/li&gt;
&lt;li&gt;Arrêt automatique : Non (Pour désactiver l’extinction des autres appareils à l’arrêt de la télévision) ;&lt;/li&gt;
&lt;li&gt;Récepteur : Activé (je n’ai pas vu de différence en le désactivant).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="sur-lamplificateur"&gt;Sur l’amplificateur&lt;/h3&gt;
&lt;p&gt;Dans le &lt;em&gt;&lt;span class="caps"&gt;SETUP&lt;/span&gt;&amp;gt;Vidéo&amp;gt;Config. &lt;span class="caps"&gt;HDMI&lt;/span&gt;&lt;/em&gt;, je mets les réglages suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class="caps"&gt;HDMI&lt;/span&gt; Contrôle : Marche (Activation générale);&lt;/li&gt;
&lt;li&gt;Désactiver cmde : Tous (pour que l’ampli puisse quand même être éteint par le média-center).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Laissez les autres paramètres par défaut.&lt;/p&gt;
&lt;h3 id="sur-le-media-center"&gt;Sur le media-center&lt;/h3&gt;
&lt;p&gt;Il faut aller dans le menu &lt;em&gt;Système (Paramètres)&amp;gt;Système&amp;gt;Périphériques&amp;gt;Périphériques&lt;/em&gt;. Sélectionnez alors le périphérique nous intéressant. Pour moi il s’appelle “&lt;span class="caps"&gt;CEC&lt;/span&gt; Adapter”. Modifiez alors les options suivantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dispositifs à démarrer au démarrage de Kodi : &lt;span class="caps"&gt;TV&lt;/span&gt; et ampli ;&lt;/li&gt;
&lt;li&gt;Éteindre les dispositifs à l’arrêt de Kodi : Ampli ;&lt;/li&gt;
&lt;li&gt;Quand la &lt;span class="caps"&gt;TV&lt;/span&gt; est éteinte : Ignorer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Capture décran paramètres CEC Kodi" src="https://www.pragmageek.fr/images/2015/paramètres-cec-kodi.png" style="width: 400px; height: auto; max-width: 100%;"/&gt;&lt;/p&gt;
&lt;p&gt;Et voilà, mon système réagit désormais comme je l’entends.&lt;/p&gt;
&lt;h1 id="telecommande"&gt;Réglage de la télécommande&lt;/h1&gt;
&lt;p&gt;On va maintenant chercher à lier chaque pression de bouton sur la télécommande de la télévision à une action précise dans OpenELEC. Pour savoir de quoi on parle, j’ai mis une photo de ma télécommande.&lt;/p&gt;
&lt;p&gt;Il existe de &lt;a href="http://blog.jl42.de/2013/01/changed-remote-layout-for-my-samsung-tv-with-raspbmc/"&gt;nombreux&lt;/a&gt; &lt;a href="https://wardiesworld.wordpress.com/2012/09/22/raspbmc-mapping-samsung-remote/"&gt;billets&lt;/a&gt; &lt;a href="http://forum.kodi.tv/showthread.php?tid=139145"&gt;et&lt;/a&gt; &lt;a href="http://forum.osmc.tv/showthread.php?tid=2033"&gt;autres&lt;/a&gt; &lt;a href="http://openelec.tv/forum/124-raspberry-pi/38830-cec-openelec"&gt;discussions&lt;/a&gt; qui traitent de ce sujet. Le présent billet ne fait que reprendre toutes ces informations en les réorganisant.&lt;/p&gt;
&lt;p&gt;Les concepts sont les suivants :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quand un récepteur &lt;span class="caps"&gt;HDMI&lt;/span&gt;-&lt;span class="caps"&gt;CEC&lt;/span&gt; est connecté à la &lt;span class="caps"&gt;TV&lt;/span&gt;, celle-ci lui envoie des codes à chaque pression de certains boutons sur la télécommande ;&lt;/li&gt;
&lt;li&gt;Certains boutons ne génèrent aucun code &lt;span class="caps"&gt;HDMI&lt;/span&gt;-&lt;span class="caps"&gt;CEC&lt;/span&gt;, ils ne sont gérés que par la &lt;span class="caps"&gt;TV&lt;/span&gt; sans être transmis aux autres appareils ;&lt;/li&gt;
&lt;li&gt;Pour chaque télécommande, de chaque marque, il faut déterminer quels sont ces codes, et à quel bouton ils correspondent ;&lt;/li&gt;
&lt;li&gt;Une fois que l’on connaît tous les codes de notre télécommande, il faut éditer un fichier de configuration dans Kodi ;&lt;/li&gt;
&lt;li&gt;Ce fichier de configuration permet de corriger certaines comportements par défaut qui sont erronés, et d’ajouter des actions, en fonction du contexte. Il existe un fichier de configuration par défaut, mais on en crée un deuxième qui prend le dessus pour les quelques touches que l’on modifie.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On va voir tout ça, étape par étape.&lt;/p&gt;
&lt;h2 id="identifier-codes"&gt;Identifier les codes&lt;/h2&gt;
&lt;p&gt;Dans un premier temps, il faut identifier les codes qui sont reçus par le media-center à chaque appui de touche. Pour ce faire, on va activer les logs de Kodi, et surveiller les événements à chaque appui de touche.&lt;/p&gt;
&lt;h3 id="activer-les-logs-de-kodi"&gt;Activer les logs de Kodi&lt;/h3&gt;
&lt;p&gt;La gestion des logs de Kodi est expliquée en détail &lt;a href="http://kodi.wiki/view/Log_file/Advanced"&gt;sur le wiki officiel&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;On peut les activer dans l’interface (menu &lt;em&gt;SYSTÈME (Paramètres)&amp;gt;Système&amp;gt;Debogage&lt;/em&gt;) : activer le mode debug, activer le journal spécifique aux composants, et sélectionner le composant &lt;span class="caps"&gt;CEC&lt;/span&gt; uniquement, pour avoir des logs très détaillés.&lt;/p&gt;
&lt;p&gt;On peut aussi les activer dans la console, en se connectant en ssh au media-center, et en éditant un fichier :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;vetetix@localhost:~$ &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;root@ip-du-mediacenter
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;kodi-salon:~ # &lt;/span&gt;nano&lt;span class="w"&gt; &lt;/span&gt;/storage/.kodi/userdata/advancedsettings.xml
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Dans ce fichier, ajoutez le loglevel et le debug, entre les balises globales :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&amp;lt;advancedsettings&amp;gt;
  &amp;lt;loglevel&amp;gt;1&amp;lt;/loglevel&amp;gt;
  &amp;lt;debug&amp;gt;
    &amp;lt;extralogging&amp;gt;true&amp;lt;/extralogging&amp;gt;
    &amp;lt;setextraloglevel&amp;gt;64,2048,32768&amp;lt;/setextraloglevel&amp;gt;
    &amp;lt;/debug&amp;gt;
&amp;lt;/advancedsettings&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Enregistrez le fichier (Ctrl+x), puis redémarrez le media-center.&lt;/p&gt;
&lt;h3 id="lire-les-codes"&gt;Lire les codes&lt;/h3&gt;
&lt;p&gt;Maintenant, reconnectez-vous au media-center, surveillez le fichier de log, et appuyez sur les touches de votre télécommandes :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;XBMC-salon:~ # &lt;/span&gt;tail&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;/storage/.kodi/temp/kodi.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Voici ce que ça donne pour un appui sur la touche “Exit” :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="go"&gt;12:12:24 T:140479907747584   DEBUG: CecLogMessage - &amp;gt;&amp;gt; 01:44:0d&lt;/span&gt;
&lt;span class="go"&gt;12:12:24 T:140479907747584   DEBUG: CecLogMessage - &amp;gt;&amp;gt; TV (0) -&amp;gt; Recorder 1 (1): user control pressed (44)&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;12:12:24 T:140479907747584   DEBUG: CecLogMessage - key pressed: exit (d)&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;12:12:24 T:140479907747584   DEBUG: PushCecKeypress - received key d8 duration 0&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;12:12:24 T:140480410220416   DEBUG: OnKey: menu (0xd8) pressed, action is Back&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;12:12:24 T:140480410220416   DEBUG: CGUIWindowManager::PreviousWindow: Deactivate&lt;/span&gt;
&lt;span class="go"&gt;12:12:24 T:140479907747584   DEBUG: CecLogMessage - &amp;gt;&amp;gt; 01:45&lt;/span&gt;
&lt;span class="go"&gt;12:12:24 T:140479907747584   DEBUG: CecLogMessage - &amp;gt;&amp;gt; TV (0) -&amp;gt; Recorder 1 (1): user control release (45)&lt;/span&gt;
&lt;span class="go"&gt;12:12:24 T:140479907747584   DEBUG: CecLogMessage - key released: exit (d)&lt;/span&gt;
&lt;span class="go"&gt;12:12:24 T:140479907747584   DEBUG: PushCecKeypress - received key d8 duration 344&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;À la ligne 3, on voit bien que c’est la touche “exit” qui a été utilisée, et à la ligne 5 que ça a engendré l’action “Back”.&lt;/p&gt;
&lt;p&gt;À partir de là, une recherche dans le fichier &lt;em&gt;/usr/share/kodi/system/keymaps/remote.xml&lt;/em&gt; nous indique que c’est le code bouton “back” qui génère l’action.&lt;/p&gt;
&lt;p&gt;On en déduit donc que la touche “Exit” de la télécommande correspond au code bouton “back” de Kodi.&lt;/p&gt;
&lt;p&gt;Notons que chaque bouton n’a pas le même comportement (la même “action”) dans tous les contextes. En testant dans un menu, et pendant la lecture d’un film, on aura un résultat différent. Cela 
permet de différencier certains boutons ayant le même comportement dans un contexte précis.&lt;/p&gt;
&lt;p&gt;De cette manière, et en me basant sur le travail &lt;a href="https://wardiesworld.wordpress.com/2012/11/14/raspbmc-samsung-remote-key-codes/"&gt;de ce blogueur&lt;/a&gt;, j’ai édité ce tableau qui correspond à ma télécommande (boutons de gauche à droite, de haut en bas) :&lt;/p&gt;
&lt;p&gt;&lt;img alt="Photo telecommande" class="left" src="https://www.pragmageek.fr/images/2015/Telecommande-Samsung.png" style="width: 142px; height: auto; max-width: 100%;"/&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Touche&lt;/th&gt;
&lt;th&gt;Transmis&lt;/th&gt;
&lt;th&gt;Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Alim&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;HDMI&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;one&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;two&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;three&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;four&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;five&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;six&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;seven&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;eight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;nine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;TTX&lt;/span&gt;/&lt;span class="caps"&gt;MIX&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;zero&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;PRE&lt;/span&gt;-&lt;span class="caps"&gt;CH&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;teletext&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vol+&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;Non exploitable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;MUTE&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;Non exploitable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prog+&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;pageplus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vol-&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;Non exploitable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;CH&lt;/span&gt; &lt;span class="caps"&gt;LIST&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;livetv&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prog-&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;pageminus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;MENU&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;SMART&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;GUIDE&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;guide&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;TOOLS&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;UP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;INFO&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;LEFT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;left&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;ENTER&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;select&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RIGHT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;right&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RETURN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;DOWN&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;down&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;EXIT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;back&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;red&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;green&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;yellow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;blue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Family Story&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;SEARCH&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3D&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;SUPPORT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P.&lt;span class="caps"&gt;SIZE&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;AD&lt;/span&gt;/&lt;span class="caps"&gt;SUBT&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Non&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;RW&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;reverse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;PAUSE&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;pause&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;FF&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;forward&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;REC&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;PLAY&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;play&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span class="caps"&gt;STOP&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;Oui&lt;/td&gt;
&lt;td&gt;stop&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="sil-manque-une-touche"&gt;S’il manque une touche&lt;/h3&gt;
&lt;p&gt;J’ai fait ce travail avec une &lt;span class="caps"&gt;TV&lt;/span&gt; Samsung, mais les &lt;span class="caps"&gt;TV&lt;/span&gt; d’autres constructeurs peuvent envoyer des codes différents. Il faut parfois faire quelques essais pour trouver la correspondance touche/code.&lt;/p&gt;
&lt;p&gt;Par exemple, la touche &lt;em&gt;&lt;span class="caps"&gt;CH&lt;/span&gt; &lt;span class="caps"&gt;LIST&lt;/span&gt;&lt;/em&gt; pouvait correspondre à &lt;em&gt;livetv&lt;/em&gt; ou &lt;em&gt;mytv&lt;/em&gt;. J’ai dû modifier l’action liée à ces deux codes pour les différencier et trouver le bon (voir section suivante).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://forum.kodi.tv/showthread.php?tid=139145&amp;amp;pid=1285390#pid1285390"&gt;Ce post dans le forum de Kodi&lt;/a&gt; explique comment on peut retrouver le code d’à peu près toutes les touches (il mentionne le fichier &lt;a href="https://github.com/xbmc/xbmc/blob/master/xbmc/input/ButtonTranslator.cpp"&gt;ButtonTranslator.cpp&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="touche-action"&gt;Associer chaque touche à une action appropriée&lt;/h2&gt;
&lt;p&gt;On va désormais modifier le fichier &lt;em&gt;remote.xml&lt;/em&gt; pour le corriger et le personnaliser. Il ne faut pas toucher au fichier initial, mais en créer un second dans le dossier &lt;em&gt;.kodi/userdata/keymaps/&lt;/em&gt;, dont le contenu complétera celui du premier, tout en ayant priorité dessus.&lt;/p&gt;
&lt;p&gt;On peut en créer un vierge, mais je préfère partir d’un fichier complet et virer ce qui ne m’est pas utile. Cela permet de voir ce qui est configuré par défaut, de le corriger, et de découvrir certaines actions utiles mais liées à un bouton non exploité.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;XBMC-salon:~ # &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;/usr/share/kodi/system/keymaps/remote.xml&lt;span class="w"&gt; &lt;/span&gt;/storage/.kodi/userdata/keymaps/remote.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Maintenant, il ne reste plus qu’à éditer le fichier, soit en ligne de commande avec &lt;code&gt;nano&lt;/code&gt;, soit avec un éditeur “graphique” en allant le chercher via l’accès samba (chez moi ça se trouve à l’adresse “smb://kodi-salon/userdata/keymaps”).&lt;/p&gt;
&lt;p&gt;La chose la plus problématique est le fait que le bouton “Exit” (code “back”) joue le rôle du bouton “Back” (code “title”), et que celui-ci ouvre un menu contextuel. Dans un premier temps, je dois donc systématiquement commenter les actions de “title” et remplacer &lt;code&gt;&amp;lt;back&amp;gt;Action&amp;lt;/back&amp;gt;&lt;/code&gt; par &lt;code&gt;&amp;lt;title&amp;gt;Action&amp;lt;/title&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ensuite, il ne reste plus qu’à étudier la configuration existante, et à modifier ou ajouter des règles. On connait les codes, et &lt;a href="http://kodi.wiki/view/Keyboard.xml#Actions"&gt;les actions disponibles sont listées ici&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Personnellement, j’ai voulu configurer les actions suivantes :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Un lien pour montrer le panneau des favoris (ActivateWindow(Favourites)) ;&lt;/li&gt;
&lt;li&gt;Un lien vers la sélection (grâce à une playlist) des films et séries en français (ActivateWindow(VideoLibrary,special://profile/playlists/video/&lt;span class="caps"&gt;FR&lt;/span&gt;.xsp)) ;&lt;/li&gt;
&lt;li&gt;Un lien pour lancer le “Party Mode” (PlayerControl(PartyMode))&lt;/li&gt;
&lt;li&gt;En lecture, des liens rapides pour chercher les sous-titres (ActivateWindow(SubtitleSearch)), passer de l’un à l’autre (NextSubtitle), ou la même chose pour la langue de l’audio (AudioNextLanguage).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Le fichier complet &lt;a href="https://www.pragmageek.fr/static/2015/remote.xml"&gt;est disponible ici&lt;/a&gt;. Regardez-le pour le comprendre en détails. Pour chaque section du fichier, qui correspond à un environnement dans l’interface de Kodi, il faut configurer chaque touche (ou les laisser par défaut, ce qui est souvent suffisant). Internet regorge d’autres exemples, je vous laisse les trouver (&lt;a href="https://duckduckgo.com/?q=openelec+remote.xml"&gt;le canard est ton ami&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Redémarrez, et profitez de votre télécommande, confortablement installés dans votre canapé.&lt;/p&gt;
&lt;p&gt;Ressources :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.mediahd.fr/fr/htpc/28-adaptateur-usb-cec-pulseeight-0609132847769.html"&gt;Acheter le récepteur &lt;span class="caps"&gt;HDMI&lt;/span&gt;-&lt;span class="caps"&gt;CEC&lt;/span&gt; sur mediahd.fr&lt;/a&gt; (c’est le moins cher que j’ai trouvé).&lt;/li&gt;
&lt;/ul&gt;</content><category term="Logiciels"/><category term="Samsung"/><category term="remote"/><category term="télécommande"/><category term="CEC"/><category term="HDMI-CEC"/><category term="Kodi"/><category term="OpenELEC"/></entry><entry><title>Sécuriser l’accès SSH d’OpenELEC</title><link href="https://www.pragmageek.fr/2015/05/securiser-openelec-ssh/" rel="alternate"/><published>2015-05-02T00:00:00+02:00</published><updated>2020-12-30T06:55:59.942779+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2015-05-02:/2015/05/securiser-openelec-ssh/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo OpenSSH" class="left" src="https://www.pragmageek.fr/images/2015/Openssh-logo.gif" style="width: 194px; height: auto; max-width: 100%;"/&gt;
Si comme moi vous êtes l’heureux possesseur d’un media center sous OpenELEC, vous êtes peut-être restés perplexes devant le fait que le mot de passe root du système ne peut pas être modifié. Ainsi, toute personne ayant accès à votre réseau local et connaissant l’adresse &lt;span class="caps"&gt;IP&lt;/span&gt; de votre media center peut s’y connecter en root.&lt;/p&gt;
&lt;p&gt;Voyons ensemble comment sécuriser cela au mieux : Comme on ne peut pas modifier le mot de …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo OpenSSH" class="left" src="https://www.pragmageek.fr/images/2015/Openssh-logo.gif" style="width: 194px; height: auto; max-width: 100%;"/&gt;
Si comme moi vous êtes l’heureux possesseur d’un media center sous OpenELEC, vous êtes peut-être restés perplexes devant le fait que le mot de passe root du système ne peut pas être modifié. Ainsi, toute personne ayant accès à votre réseau local et connaissant l’adresse &lt;span class="caps"&gt;IP&lt;/span&gt; de votre media center peut s’y connecter en root.&lt;/p&gt;
&lt;p&gt;Voyons ensemble comment sécuriser cela au mieux : Comme on ne peut pas modifier le mot de passe, on va &lt;a href="http://wiki.openelec.tv/index.php?title=OpenELEC_FAQ#SSH_Password_change"&gt;activer l’authenification par clé &lt;span class="caps"&gt;SSH&lt;/span&gt; puis désactiver l’authentification par mot de passe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Les premières étapes sont expliquées en détail sur ce &lt;a href="http://www.thegeekstuff.com/2008/11/3-steps-to-perform-ssh-login-without-password-using-ssh-keygen-ssh-copy-id/"&gt;billet de blog (en)&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="creer-une-cle-dauthentification"&gt;Créer une clé d’authentification&lt;/h2&gt;
&lt;p&gt;Si on n’a pas encore de clé &lt;span class="caps"&gt;SSH&lt;/span&gt;, il faut utiliser la commande &lt;code&gt;ssh-keygen&lt;/code&gt;, pour en générer une :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;vetetix@localhost:~$ &lt;/span&gt;ssh-keygen
&lt;/span&gt;&lt;span class="go"&gt;Generating public/private rsa key pair.&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Enter file in which to save the key (/home/vetetix/.ssh/id_rsa): [Entrer]&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;Created directory '/home/vetetix/.ssh'.&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Enter passphrase (empty for no passphrase): "password" [Entrer]&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;Enter same passphrase again: "password" [Entrer]&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;Your identification has been saved in /home/vetetix/.ssh/id_rsa.&lt;/span&gt;
&lt;span class="go"&gt;Your public key has been saved in /home/vetetix/.ssh/id_rsa.pub.&lt;/span&gt;
&lt;span class="go"&gt;The key fingerprint is:&lt;/span&gt;
&lt;span class="go"&gt;a8:27:5f:26:60:45:aa:8a:93:55:dd:6e:9a:89:34:d5 vetetix@localhost&lt;/span&gt;
&lt;span class="go"&gt;The key's randomart image is:&lt;/span&gt;
&lt;span class="go"&gt;+---[RSA 2048]----+&lt;/span&gt;
&lt;span class="go"&gt;|      .          |&lt;/span&gt;
&lt;span class="go"&gt;|     + o         |&lt;/span&gt;
&lt;span class="go"&gt;|    o + E        |&lt;/span&gt;
&lt;span class="go"&gt;|   o o o         |&lt;/span&gt;
&lt;span class="go"&gt;|  o = . S        |&lt;/span&gt;
&lt;span class="go"&gt;|.+ o = =         |&lt;/span&gt;
&lt;span class="go"&gt;|=   + * o        |&lt;/span&gt;
&lt;span class="go"&gt;| .   + +         |&lt;/span&gt;
&lt;span class="go"&gt;|      .          |&lt;/span&gt;
&lt;span class="go"&gt;+-----------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="copier-cette-cle-sur-le-media-center"&gt;Copier cette clé sur le media center&lt;/h2&gt;
&lt;p&gt;On copie ensuite cette clé sur le serveur, à l’aide de l’utilitaire &lt;code&gt;ssh-copy-id&lt;/code&gt;. Elle va se mettre dans le fichier &lt;em&gt;.ssh/authorized_keys&lt;/em&gt; d’OpenELEC.&lt;/p&gt;
&lt;p&gt;Récupérons l’adresse &lt;span class="caps"&gt;IP&lt;/span&gt; du media center (Dans &lt;em&gt;SYSTÈME&amp;gt;Informations système&lt;/em&gt; par exemple). Dans la commande ci-dessous, il faut remplacer ip-du-mediacenter par cette adresse &lt;span class="caps"&gt;IP&lt;/span&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;vetetix@localhost:~$ &lt;/span&gt;ssh-copy-id&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;~/.ssh/id_rsa.pub&lt;span class="w"&gt; &lt;/span&gt;root@ip-du-mediacenter
&lt;/span&gt;&lt;span class="go"&gt;/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed&lt;/span&gt;
&lt;span class="go"&gt;/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;root@kodi-salon's password: [Openelec - Entrer]&lt;/span&gt;
&lt;/span&gt;
&lt;span class="go"&gt;Number of key(s) added: 1&lt;/span&gt;

&lt;span class="go"&gt;Now try logging into the machine, with:   "ssh 'root@id-du-mediacenter'"&lt;/span&gt;
&lt;span class="go"&gt;and check to make sure that only the key(s) you wanted were added.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Vérifions que la clé a bien été activée :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;vetetix@localhost:~$ &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;root@ip-du-mediacenter
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Le shell devrait nous connecter sans demander de mot de passe (ou éventuellement celui de la clé &lt;span class="caps"&gt;SSH&lt;/span&gt; qu’on vient de créer.&lt;/p&gt;
&lt;h2 id="desactiver-lacces-ssh-par-mot-de-passe"&gt;Désactiver l’accès &lt;span class="caps"&gt;SSH&lt;/span&gt; par mot de passe&lt;/h2&gt;
&lt;p&gt;Une fois toutes les étapes précédentes réalisées, on peut sereinement désactiver l’accès &lt;span class="caps"&gt;SSH&lt;/span&gt; par mot de passe, dans l’interface de OpenELEC.&lt;/p&gt;
&lt;p&gt;Cela se passe dans le menu &lt;em&gt;SYSTÈME (OpenELEC)&amp;gt;Services&lt;/em&gt;. Il faut cocher l’option “Désactiver le mot de passe &lt;span class="caps"&gt;SSH&lt;/span&gt;”.&lt;/p&gt;
&lt;p&gt;L’accès au media center est désormais sécurisé. On ne peut s’y connecter que si l’on possède la partie privée de la clé &lt;span class="caps"&gt;SSH&lt;/span&gt; configurée dans le fichier &lt;em&gt;authorized_keys&lt;/em&gt;.&lt;/p&gt;</content><category term="Logiciels"/><category term="OpenELEC"/><category term="Sécurité"/><category term="SSH"/></entry><entry><title>Renouvellement de ma clé PGP</title><link href="https://www.pragmageek.fr/2015/04/renouvellement-cle-pgp/" rel="alternate"/><published>2015-04-28T00:00:00+02:00</published><updated>2020-12-30T06:55:58.122815+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2015-04-28:/2015/04/renouvellement-cle-pgp/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo GnuPG" class="left" src="https://www.pragmageek.fr/images/2015/Gnupg_logo.png" style="width: 200px; height: auto; max-width: 100%;"/&gt;
J’ai décidé de renouveller ma clé pgp, qui commence à être un peu ancienne. En effet, ma toute première clé &lt;span class="caps"&gt;PGP&lt;/span&gt; date de 2007, et je l’ai remplacée en 2008. Ma clé &lt;span class="caps"&gt;PGP&lt;/span&gt; actuelle a donc 6 ans, et les algorithmes qu’elle utilise sont vieillissants (avec par exemple l’utilisation de clés 1024 bits alors qu’aujourd’hui on conseille l’utilisation de 4096 bits).&lt;/p&gt;
&lt;p&gt;Je me suis un peu documenté, et …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo GnuPG" class="left" src="https://www.pragmageek.fr/images/2015/Gnupg_logo.png" style="width: 200px; height: auto; max-width: 100%;"/&gt;
J’ai décidé de renouveller ma clé pgp, qui commence à être un peu ancienne. En effet, ma toute première clé &lt;span class="caps"&gt;PGP&lt;/span&gt; date de 2007, et je l’ai remplacée en 2008. Ma clé &lt;span class="caps"&gt;PGP&lt;/span&gt; actuelle a donc 6 ans, et les algorithmes qu’elle utilise sont vieillissants (avec par exemple l’utilisation de clés 1024 bits alors qu’aujourd’hui on conseille l’utilisation de 4096 bits).&lt;/p&gt;
&lt;p&gt;Je me suis un peu documenté, et j’écris désormais ce billet pour me souvenir de mes recherches. Je me suis basé sur un &lt;a href="http://www.bortzmeyer.org/nouvelle-cle-pgp.html"&gt;tutoriel de Stéphane Bortzmeyer&lt;/a&gt;, qui se base lui-même sur un &lt;a href="https://alexcabal.com/creating-the-perfect-gpg-keypair/"&gt;article de référence d’Alex Cabal (en)&lt;/a&gt; et &lt;a href="http://keyring.debian.org/creating-key.html"&gt;le guide du projet Debian (en)&lt;/a&gt;, ainsi qu’&lt;a href="https://wiki.debian.org/fr/Subkeys"&gt;une section sur les sous-clés&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Je vais essayer de faire un guide complet. Voici les différentes étapes que je vais détailler :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="#creation-pgp"&gt;Création d’une clé &lt;span class="caps"&gt;PGP&lt;/span&gt;&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#configuration-gnupg"&gt;Configuration des options par défaut de gnupg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#creation-cle-pgp"&gt;Création d’une nouvelle clé &lt;span class="caps"&gt;PGP&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#creation-sous-cle"&gt;Création d’une sous-clé de signature supplémentaire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#ajout-uid"&gt;Ajout d’autres &lt;span class="caps"&gt;UID&lt;/span&gt; (adresses courriel et identité)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#remplacement-ancienne-cle"&gt;Remplacement des anciennes clés par la nouvelle&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#signature-cle"&gt;Signature de la nouvelle clé par l’ancienne clé&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#publication-cle"&gt;Publication de la nouvelle clé&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#revocation-cle"&gt;Révocation de l’ancienne clé&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#bonnes-pratiques"&gt;Bonnes pratiques de sécurité et de sauvegarde&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#certificat-revocation"&gt;Création du certificat de révocation de la nouvelle clé&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#stockage-sauvegarde"&gt;Stockage et sauvegarde de la clé complète (avec une version papier)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#version-partielle"&gt;Création d’une version partielle de la nouvelle clé&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#usage-exemples"&gt;Usage et exemples particuliers&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#montage-cle"&gt;Montage de la clé&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#prolongation-validite"&gt;Prolongation de la validité de la clé&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#signatures-cles"&gt;Signatures d’autres clés&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#revocation-sous-cle"&gt;Révocation d’une sous-clé&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#revocation-definitive"&gt;Révocation définitive de la clé&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id="creation-pgp"&gt;Création d’une clé &lt;span class="caps"&gt;PGP&lt;/span&gt;&lt;/h1&gt;
&lt;h2 id="configuration-gnupg"&gt;Configuration des options par défaut de gnupg&lt;/h2&gt;
&lt;p&gt;Dans un premier temps, on va lancer gpg une première fois, afin d’initialiser les fichiers de configuration :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gpg --list-key
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ensuite, on modifie le fichier &lt;em&gt;~/.gnupg/gpg.conf&lt;/em&gt; et on rajoute ceci à la fin :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;### Modifications personnelles ###
# Crypto preferences
personal-digest-preferences SHA256

# For the keys we create
cert-digest-algo SHA256

# For the signatures and other things we generate
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="creation-cle-pgp"&gt;Création d’une nouvelle clé &lt;span class="caps"&gt;PGP&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;On peut désormais passer à la génération de la nouvelle clé &lt;span class="caps"&gt;PGP&lt;/span&gt;, qui aura les bonnes options par défaut :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--gen-key
&lt;/span&gt;&lt;span class="go"&gt;[…]&lt;/span&gt;
&lt;span class="go"&gt;Sélectionnez le type de clef désiré :&lt;/span&gt;
&lt;span class="go"&gt;   (1) RSA et RSA (par défaut)&lt;/span&gt;
&lt;span class="go"&gt;   (2) DSA et Elgamal&lt;/span&gt;
&lt;span class="go"&gt;   (3) DSA (signature seule)&lt;/span&gt;
&lt;span class="go"&gt;   (4) RSA (signature seule)&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Quel est votre choix ? 1&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;les clefs RSA peuvent faire entre 1024 et 4096 bits de longueur.&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Quelle taille de clef désirez-vous ? (2048) 4096&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;La taille demandée est 4096 bits&lt;/span&gt;
&lt;span class="go"&gt;Veuillez indiquer le temps pendant lequel cette clef devrait être valable.&lt;/span&gt;
&lt;span class="go"&gt;         0 = la clef n'expire pas&lt;/span&gt;
&lt;span class="go"&gt;      &amp;lt;n&amp;gt;  = la clef expire dans n jours&lt;/span&gt;
&lt;span class="go"&gt;      &amp;lt;n&amp;gt;w = la clef expire dans n semaines&lt;/span&gt;
&lt;span class="go"&gt;      &amp;lt;n&amp;gt;m = la clef expire dans n mois&lt;/span&gt;
&lt;span class="go"&gt;      &amp;lt;n&amp;gt;y = la clef expire dans n ans&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Pendant combien de temps la clef est-elle valable ? (0) 2y&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;La clef expire le sam. 09 septembre 2016 21:36:51 CEST&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Est-ce correct ? (o/N) o&lt;/span&gt;
&lt;/span&gt;
&lt;span class="go"&gt;Une identité est nécessaire à la clef ; le programme la construit à partir&lt;/span&gt;
&lt;span class="go"&gt;du nom réel, d'un commentaire et d'une adresse électronique de cette façon :&lt;/span&gt;
&lt;span class="go"&gt;   « Heinrich Heine (le poète) &amp;lt;heinrichh@duesseldorf.de&amp;gt; »&lt;/span&gt;

&lt;span class="hll"&gt;&lt;span class="go"&gt;Nom réel : Jean Dupont&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;Adresse électronique : thomas@exemple.net&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;Commentaire : Main ID&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;Vous avez sélectionné cette identité :&lt;/span&gt;
&lt;span class="go"&gt;    « Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt; »&lt;/span&gt;

&lt;span class="go"&gt;Faut-il modifier le (N)om, le (C)ommentaire, l'(A)dresse électronique&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;ou (O)ui/(Q)uitter ? O&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;Une phrase de passe est nécessaire pour protéger votre clef secrète.&lt;/span&gt;

&lt;span class="go"&gt;[…]&lt;/span&gt;

&lt;span class="go"&gt;gpg: clef 4EA58FE3 marquée de confiance ultime.&lt;/span&gt;
&lt;span class="go"&gt;les clefs publique et secrète ont été créées et signées.&lt;/span&gt;

&lt;span class="go"&gt;gpg: vérification de la base de confiance&lt;/span&gt;
&lt;span class="go"&gt;gpg: 3 marginale(s) nécessaire(s), 1 complète(s) nécessaire(s),&lt;/span&gt;
&lt;span class="go"&gt;     modèle de confiance PGP&lt;/span&gt;
&lt;span class="go"&gt;gpg: profondeur : 0  valables :   1  signées :   0&lt;/span&gt;
&lt;span class="go"&gt;     confiance : 0 i., 0 n.d., 0 j., 0 m., 0 t., 1 u.&lt;/span&gt;
&lt;span class="go"&gt;gpg: la prochaine vérification de la base de confiance aura lieu le 2016-09-09&lt;/span&gt;
&lt;span class="go"&gt;pub   4096R/4EA58FE3 2014-09-10 [expire : 2016-09-09]&lt;/span&gt;
&lt;span class="go"&gt;      Empreinte de la clef = AE08 AB5C D9E8 4C9D 1D8C  E78D 4FE7 0F12 4EA5 8FE3&lt;/span&gt;
&lt;span class="go"&gt;uid                  Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt;&lt;/span&gt;
&lt;span class="go"&gt;sub   4096R/87EAB420 2014-09-10 [expire : 2016-09-09]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notre clé &lt;span class="caps"&gt;PGP&lt;/span&gt; est désormais utilisable, mais on va paufiner quelques détails qui n’en sont pas.&lt;/p&gt;
&lt;h2 id="creation-sous-cle"&gt;Création d’une sous-clé de signature supplémentaire&lt;/h2&gt;
&lt;p&gt;On va créer une sous-clé de signature, qui sera utilisée au quotidien, sur l’ordinateur portable, voire sur le téléphone portable, pendant que la clé de signature initiale sera bien en sécurité.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--edit-key&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3&lt;span class="w"&gt; &lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;gpg (GnuPG) 1.4.16; Copyright (C) 2013 Free Software Foundation, Inc.&lt;/span&gt;
&lt;span class="go"&gt;This is free software: you are free to change and redistribute it.&lt;/span&gt;
&lt;span class="go"&gt;There is NO WARRANTY, to the extent permitted by law.&lt;/span&gt;

&lt;span class="go"&gt;La clef secrète est disponible.&lt;/span&gt;

&lt;span class="go"&gt;pub  4096R/4EA58FE3  créé : 2014-09-10  expire : 2016-09-09  utilisation : SC  &lt;/span&gt;
&lt;span class="go"&gt;                     confiance : ultime        validité : ultime&lt;/span&gt;
&lt;span class="go"&gt;sub  4096R/87EAB420  créé : 2014-09-10  expire : 2016-09-09  utilisation : E   &lt;/span&gt;
&lt;span class="go"&gt;[  ultime ] (1). Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt;&lt;/span&gt;

&lt;span class="hll"&gt;&lt;span class="go"&gt;gpg&amp;gt; addkey &lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;La clef est protégée.&lt;/span&gt;

&lt;span class="go"&gt;Une phrase de passe est nécessaire pour déverrouiller la clef secrète de&lt;/span&gt;
&lt;span class="go"&gt;l'utilisateur : « Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt; »&lt;/span&gt;
&lt;span class="go"&gt;clef RSA de 4096 bits, identifiant 4EA58FE3, créée le 2014-09-10&lt;/span&gt;

&lt;span class="go"&gt;Sélectionnez le type de clef désiré :&lt;/span&gt;
&lt;span class="go"&gt;   (3) DSA (signature seule)&lt;/span&gt;
&lt;span class="go"&gt;   (4) RSA (signature seule)&lt;/span&gt;
&lt;span class="go"&gt;   (5) Elgamal (chiffrement seul)&lt;/span&gt;
&lt;span class="go"&gt;   (6) RSA (chiffrement seul)&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Quel est votre choix ? 4&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;les clefs RSA peuvent faire entre 1024 et 4096 bits de longueur.&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Quelle taille de clef désirez-vous ? (2048) 4096&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;La taille demandée est 4096 bits&lt;/span&gt;
&lt;span class="go"&gt;Veuillez indiquer le temps pendant lequel cette clef devrait être valable.&lt;/span&gt;
&lt;span class="go"&gt;         0 = la clef n'expire pas&lt;/span&gt;
&lt;span class="go"&gt;      &amp;lt;n&amp;gt;  = la clef expire dans n jours&lt;/span&gt;
&lt;span class="go"&gt;      &amp;lt;n&amp;gt;w = la clef expire dans n semaines&lt;/span&gt;
&lt;span class="go"&gt;      &amp;lt;n&amp;gt;m = la clef expire dans n mois&lt;/span&gt;
&lt;span class="go"&gt;      &amp;lt;n&amp;gt;y = la clef expire dans n ans&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Pendant combien de temps la clef est-elle valable ? (0) 2y&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;La clef expire le dim. 07 août 2016 13:44:34 CEST&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Est-ce correct ? (o/N) o&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;Faut-il vraiment la créer ? (o/N) o&lt;/span&gt;
&lt;/span&gt;
&lt;span class="go"&gt;[…]&lt;/span&gt;

&lt;span class="go"&gt;pub  4096R/4EA58FE3  créé : 2014-09-10  expire : 2016-09-09  utilisation : SC  &lt;/span&gt;
&lt;span class="go"&gt;                     confiance : ultime        validité : ultime&lt;/span&gt;
&lt;span class="go"&gt;sub  4096R/87EAB420  créé : 2014-09-10  expire : 2016-09-09  utilisation : E   &lt;/span&gt;
&lt;span class="go"&gt;sub  4096R/E8DC29F1  créé : 2014-09-11  expire : 2016-09-10  utilisation : S   &lt;/span&gt;
&lt;span class="go"&gt;[  ultime ] (1). Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="ajout-uid"&gt;Ajout d’autres &lt;span class="caps"&gt;UID&lt;/span&gt; (adresses courriel et identité)&lt;/h2&gt;
&lt;p&gt;On peut désormais ajouter d’autres uid (User &lt;span class="caps"&gt;ID&lt;/span&gt;), correspondant à d’autres adresses email, xmpp ou autres.
Toujours dans la même “session” gpg :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;gpg&amp;gt; adduid&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;Nom réel : Jean Dupont&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;Adresse électronique : vetetix@domaine.fr&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;Commentaire : &lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;Vous avez sélectionné cette identité :&lt;/span&gt;
&lt;span class="go"&gt;    « Jean Dupont &amp;lt;vetetix@domaine.fr&amp;gt; »&lt;/span&gt;

&lt;span class="go"&gt;Faut-il modifier le (N)om, le (C)ommentaire, l'(A)dresse électronique&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;ou (O)ui/(Q)uitter ? o&lt;/span&gt;
&lt;/span&gt;
&lt;span class="go"&gt;Une phrase de passe est nécessaire pour déverrouiller la clef secrète de&lt;/span&gt;
&lt;span class="go"&gt;l'utilisateur : « Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt; »&lt;/span&gt;
&lt;span class="go"&gt;clef RSA de 4096 bits, identifiant 4EA58FE3, créée le 2014-09-10&lt;/span&gt;


&lt;span class="go"&gt;pub  4096R/4EA58FE3  créé : 2014-09-10  expire : 2016-09-09  utilisation : SC  &lt;/span&gt;
&lt;span class="go"&gt;                     confiance : ultime        validité : ultime&lt;/span&gt;
&lt;span class="go"&gt;sub  4096R/87EAB420  créé : 2014-09-10  expire : 2016-09-09  utilisation : E   &lt;/span&gt;
&lt;span class="go"&gt;sub  4096R/E8DC29F1  créé : 2014-09-11  expire : 2016-09-10  utilisation : S   &lt;/span&gt;
&lt;span class="go"&gt;[  ultime ] (1)  Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt;&lt;/span&gt;
&lt;span class="go"&gt;[ inconnue] (2). Jean Dupont &amp;lt;vetetix@domaine.fr&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Et n’oublions pas, pour quitter la “session” gpg, de sauvegarder proprement nos changements :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;gpg&amp;gt; save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="remplacement-ancienne-cle"&gt;Remplacement des anciennes clés par la nouvelle&lt;/h1&gt;
&lt;p&gt;Maintenant qu’on a une clé &lt;span class="caps"&gt;PGP&lt;/span&gt; définitivement fonctionnelle, occupons-nous de remplacer l’ancienne clé par cette dernière.&lt;/p&gt;
&lt;h2 id="signature-cle"&gt;Signature de la nouvelle clé par l’ancienne clé&lt;/h2&gt;
&lt;p&gt;Si comme moi vous avez déjà une clé &lt;span class="caps"&gt;PGP&lt;/span&gt;, la première étape est d’officialiser la nouvelle clé en la signant avec l’ancienne (mon ancienne clé a pour empreinte &lt;em&gt;&lt;span class="caps"&gt;078AF6AD&lt;/span&gt;&lt;/em&gt;, et la nouvelle &lt;em&gt;&lt;span class="caps"&gt;4EA58FE3&lt;/span&gt;&lt;/em&gt;) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--default-key&lt;span class="w"&gt; &lt;/span&gt;078AF6AD&lt;span class="w"&gt; &lt;/span&gt;--sign-key&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3
&lt;/span&gt;
&lt;span class="go"&gt;pub  4096R/4EA58FE3  créé : 2014-09-10  expire : 2016-09-09  utilisation : SC  &lt;/span&gt;
&lt;span class="go"&gt;                     confiance : ultime        validité : ultime&lt;/span&gt;
&lt;span class="go"&gt;sub  4096R/87EAB420  créé : 2014-09-10  expire : 2016-09-09  utilisation : E   &lt;/span&gt;
&lt;span class="go"&gt;sub  4096R/E8DC29F1  créé : 2014-09-11  expire : 2016-09-10  utilisation : S   &lt;/span&gt;
&lt;span class="go"&gt;[  ultime ] (1). Jean Dupont &amp;lt;vetetix@domaine.fr&amp;gt;&lt;/span&gt;
&lt;span class="go"&gt;[  ultime ] (2)  Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt;&lt;/span&gt;

&lt;span class="hll"&gt;&lt;span class="go"&gt;Voulez-vous vraiment signer toutes les identités ? (o/N) o&lt;/span&gt;
&lt;/span&gt;
&lt;span class="go"&gt;pub  4096R/4EA58FE3  créé : 2014-09-10  expire : 2016-09-09  utilisation : SC  &lt;/span&gt;
&lt;span class="go"&gt;                     confiance : ultime        validité : ultime&lt;/span&gt;
&lt;span class="go"&gt; Empreinte clef princip. : AE08 AB5C D9E8 4C9D 1D8C  E78D 4FE7 0F12 4EA5 8FE3&lt;/span&gt;

&lt;span class="go"&gt;     Jean Dupont &amp;lt;vetetix@domaine.fr&amp;gt;&lt;/span&gt;
&lt;span class="go"&gt;     Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt;&lt;/span&gt;

&lt;span class="go"&gt;Cette clef va expirer le 2016-09-09.&lt;/span&gt;
&lt;span class="go"&gt;Voulez-vous vraiment signer cette clef avec votre&lt;/span&gt;
&lt;span class="go"&gt;clef « Jean Dupont &amp;lt;thomas@exemple.net&amp;gt; » (078AF6AD)&lt;/span&gt;

&lt;span class="hll"&gt;&lt;span class="go"&gt;Voulez-vous vraiment signer ? (o/N) o&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;[…]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="publication-cle"&gt;Publication de la nouvelle clé&lt;/h2&gt;
&lt;p&gt;Votre nouvelle clé est désormais prête à être publiée sur un serveur de clés :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--send-keys&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3
&lt;/span&gt;&lt;span class="go"&gt;gpg: envoi de la clef 4EA58FE3 au serveur hkp keys.gnupg.net&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Les différents serveurs de clés se synchronisent entre eux automatiquement et assez rapidement, donc il n’est pas nécessaire d’envoyer votre clé sur d’autres serveurs (&lt;em&gt;pgp.mit.edu&lt;/em&gt;, &lt;em&gt;keyserver.ubuntu.com&lt;/em&gt;, etc.)&lt;/p&gt;
&lt;h2 id="revocation-cle"&gt;Révocation de l’ancienne clé&lt;/h2&gt;
&lt;p&gt;On n’a désormais plus besoin de l’ancienne clé, qui est devenue obsolète. On va donc la révoquer, en choisissant l’option &lt;em&gt;2&lt;/em&gt; (clé remplacée), et en indiquant dans le commentaire l’&lt;span class="caps"&gt;ID&lt;/span&gt; de la nouvelle clé :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--gen-revoke&lt;span class="w"&gt; &lt;/span&gt;078AF6AD&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;revcert.txt
&lt;/span&gt;
&lt;span class="go"&gt;sec  1024D/078AF6AD 2008-11-20 Jean Dupont &amp;lt;thomas@exemple.net&amp;gt;&lt;/span&gt;

&lt;span class="hll"&gt;&lt;span class="go"&gt;Faut-il créer un certificat de révocation pour cette clef ? (o/N) o&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;choisissez la cause de la révocation :&lt;/span&gt;
&lt;span class="go"&gt;  0 = Aucune raison indiquée&lt;/span&gt;
&lt;span class="go"&gt;  1 = La clef a été compromise&lt;/span&gt;
&lt;span class="go"&gt;  2 = La clef a été remplacée&lt;/span&gt;
&lt;span class="go"&gt;  3 = La clef n'est plus utilisée&lt;/span&gt;
&lt;span class="go"&gt;  Q = Annuler&lt;/span&gt;
&lt;span class="gp gp-VirtualEnv"&gt;(Vous devriez sûrement sélectionner 1 ici)&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Quelle est votre décision ? 2&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;Entrez une description facultative, en terminant par une ligne vide :&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;&amp;gt; New key ID 4EA58FE3 thomas@exemple.net&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;&amp;gt; &lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;Cause de révocation : La clef a été remplacée&lt;/span&gt;
&lt;span class="go"&gt;New key ID 4EA58FE3 thomas@exemple.net&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;Est-ce d'accord ? (o/N) o&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;[…]&lt;/span&gt;

&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--import&lt;span class="w"&gt; &lt;/span&gt;revcert.txt&lt;span class="w"&gt; &lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;[…]&lt;/span&gt;

&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--send-keys&lt;span class="w"&gt; &lt;/span&gt;078AF6AD
&lt;/span&gt;&lt;span class="go"&gt;[…]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="bonnes-pratiques"&gt;Bonnes pratiques de sécurité et de sauvegarde&lt;/h1&gt;
&lt;p&gt;On a créé une nouvelle clé &lt;span class="caps"&gt;PGP&lt;/span&gt;, et on a révoqué l’ancienne clé, mais il reste quelques petites choses à faire.&lt;/p&gt;
&lt;h2 id="certificat-revocation"&gt;Création du certificat de révocation de la nouvelle clé&lt;/h2&gt;
&lt;p&gt;Dans un premier temps, on va créer un certificat de révocation pour la nouvelle clé, que l’on stockera par la suite sur un support sécurisé. Il sera utile si on se fait voler la clé privée, ou si on la perd.&lt;/p&gt;
&lt;p&gt;Ce certificat, publié sur un serveur de clés, permettra à lui-seul d’annoncer à tous nos contacts que la clé ne doit plus être utilisée.&lt;/p&gt;
&lt;p&gt;En premier lieu, on modifie le umask pour éviter que les fichiers générés soient lisibles par un autre utilisateur :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$ umask 177
$ gpg --gen-revoke 4EA58FE3 &amp;gt; 4EA58FE3.revocation.asc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="stockage-sauvegarde"&gt;Export, stockage et sauvegarde de la clé complète (avec une version papier)&lt;/h2&gt;
&lt;p&gt;On va désormais “archiver” notre clé complète, et la stocker en un lieu sûr.&lt;/p&gt;
&lt;h3 id="sauvegarde-sur-une-cle-usb"&gt;Sauvegarde sur une clé &lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Dans un premier temps, on va sauvegarder la clé complète, en exportant d’abord sa partie privée, puis sa partie publique :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;umask&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;177&lt;/span&gt;
&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--export-secret-keys&lt;span class="w"&gt; &lt;/span&gt;--armor&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3.private.asc
&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--export&lt;span class="w"&gt; &lt;/span&gt;--armor&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3.public.asc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;La clé “privée” ainsi créée est la plus importante. Elle contient la totalité de votre clé &lt;span class="caps"&gt;GPG&lt;/span&gt;. Elle peut être ré-importée dans un système vierge si vous avez perdu l’originale.&lt;/p&gt;
&lt;p&gt;La clé “publique” est celle que vous donnez à vos correspondants. Elle peut être recréée à partir de la clé “privée”.&lt;/p&gt;
&lt;p&gt;Le certificat de révocation peut aussi être recréé à partir de la clé “privée”. Il ne doit absolument pas être publié. Toute personne mettant la main dessus peut révoquer définitivement votre clé &lt;span class="caps"&gt;GPG&lt;/span&gt; sans votre consentement.&lt;/p&gt;
&lt;p&gt;Il ne vous reste plus qu’à stocker ces trois fichiers, sur une clé &lt;span class="caps"&gt;USB&lt;/span&gt; ou un disque dur chiffré (je conseille l’utilisation de &lt;a href="https://fr.wikipedia.org/wiki/LUKS"&gt;cryptsetup/&lt;span class="caps"&gt;LUKS&lt;/span&gt;&lt;/a&gt;, le plus simplement du monde en utilisant l’outil graphique “Disques” sous Ubuntu)&lt;/p&gt;
&lt;h3 id="sauvegarde-sur-un-support-papier"&gt;Sauvegarde sur un support papier&lt;/h3&gt;
&lt;p&gt;Il est possible de créer une sauvegarde de dernier recours, en version papier, de votre clé &lt;span class="caps"&gt;PGP&lt;/span&gt;. Le détail des opérations se trouve sur &lt;a href="http://schnouki.net/posts/2010/03/22/howto-backup-your-gnupg-secret-key-on-paper/"&gt;ce billet de Schnouki&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Le principe est simple :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Vous utilisez un utilitaire pour réduire la taille de la clé en en supprimant les informations inutiles ;&lt;/li&gt;
&lt;li&gt;Le fichier résultant étant toujours trop volumineux, vous le découpez en plusieurs fichiers plus petits ;&lt;/li&gt;
&lt;li&gt;Vous encodez ces fichiers pour créer des codes barre 2D imprimables ;&lt;/li&gt;
&lt;li&gt;Vous imprimez ces codes 2D, chacun sur une feuille A4.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Et voilà, vous avez une copie de sauvegarde sur papier de votre clé. Pour la récupérer en cas de besoin :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Vous scannez chacun des codes 2D à partir de la version imprimée ;&lt;/li&gt;
&lt;li&gt;Vous décodez ces codes scannés, ce qui vous donne les bouts de fichiers initiaux ;&lt;/li&gt;
&lt;li&gt;Vous recollez les bouts ensemble, pour recréer la clé &lt;span class="caps"&gt;PGP&lt;/span&gt; complète.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ce n’est pas plus compliqué que cela.&lt;/p&gt;
&lt;h3 id="installation-du-dossier-de-travail-gnupg"&gt;Installation du dossier de travail .gnupg&lt;/h3&gt;
&lt;p&gt;Sous Linux l’ensemble des données se trouvent par défaut dans le dossier &lt;code&gt;.gnupg&lt;/code&gt; qui se trouve à la racine de votre répertoire personnel.&lt;/p&gt;
&lt;p&gt;Sur clé &lt;span class="caps"&gt;USB&lt;/span&gt; (différente de la clé de sauvegarde mentionnée précédemment), dont on se servira à chaque fois qu’on aura besoin de la clé &lt;span class="caps"&gt;PGP&lt;/span&gt; complète (avec sa partie privée), on va placer une copie de ce répertoire &lt;code&gt;.gnupg&lt;/code&gt;. Vous pouvez suivre &lt;a href="https://help.ubuntu.com/community/GPGKeyOnUSBDrive"&gt;ce tutoriel un peu complexe utilisant cryptsetup et dm-crypt (en)&lt;/a&gt;, mais personnellement je ne m’embarrasse pas de cela. Je copie juste mon dossier &lt;code&gt;.gnupg&lt;/code&gt; à la racine de la clé &lt;span class="caps"&gt;USB&lt;/span&gt;, que j’ai préalablement chiffrée avec &lt;span class="caps"&gt;LUKS&lt;/span&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.gnupg/&lt;span class="w"&gt; &lt;/span&gt;/media/vetetix/cle-usb/gnupg
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ce dossier &lt;code&gt;gnupg&lt;/code&gt; contient donc votre clé &lt;span class="caps"&gt;PGP&lt;/span&gt; complète.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Un dernier rappel avant de passer à la suite :&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vous ne devez pas perdre votre clé privée (toujours en avoir une copie quelque part) ;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Même si elle n’est utilisable qu’avec un mot de passe, personne d’autre que vous ne doit y avoir accès ;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Absolument personne ne doit avoir accès à votre certificat de révocation.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="version-partielle"&gt;Création d’une version partielle de la nouvelle clé&lt;/h2&gt;
&lt;p&gt;Souvenez-vous, on a ajouté une sous-clé de signature supplémentaire. On va maintenant garder une clé amputée de sa principale sous-clé privée de signature pour notre usage quotidien, en supprimant cette dernière (dont on a fait une sauvegarde sur une clé &lt;span class="caps"&gt;USB&lt;/span&gt;).&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Dans un premier temps, exportez les sous-clés privées :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;umask&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;177&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--export-secret-subkeys&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;subkeys
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ensuite, on supprime la clé privée principale (répondez par l’affirmative aux questions et avertissements) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--delete-secret-key&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3
&lt;/span&gt;&lt;span class="go"&gt;[…]&lt;/span&gt;
&lt;span class="go"&gt;sec  4096R/4EA58FE3 2014-09-10 Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt;&lt;/span&gt;

&lt;span class="hll"&gt;&lt;span class="go"&gt;Faut-il supprimer cette clef du porte-clefs ? (o/N) o&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;C'est une clef secrète — faut-il vraiment la supprimer ? (o/N) o&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Réimportez maintenant les sous-clés, et supprimez le fichier temporaire :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--import&lt;span class="w"&gt; &lt;/span&gt;subkeys
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;shred&lt;span class="w"&gt; &lt;/span&gt;--remove&lt;span class="w"&gt; &lt;/span&gt;subkeys
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Vérifiez que tout s’est bien passé (votre clé est listée avec un # devant sa clé secrète, indiquant qu’elle est absente) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;-K
&lt;/span&gt;&lt;span class="go"&gt;/home/vetetix/.gnupg/secring.gpg&lt;/span&gt;

&lt;span class="hll"&gt;&lt;span class="go"&gt;sec#  4096R/4EA58FE3 2014-09-10 [expire : 2016-09-09]&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;uid                  Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt;&lt;/span&gt;
&lt;span class="go"&gt;uid                  Jean Dupont &amp;lt;vetetix@domaine.fr&amp;gt;&lt;/span&gt;
&lt;span class="go"&gt;ssb   4096R/87EAB420 2014-09-10&lt;/span&gt;
&lt;span class="go"&gt;ssb   4096R/E8DC29F1 2014-09-11&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Précisons que l’option “-K” est un raccourcis pour “—list-secret-keys”.&lt;/p&gt;
&lt;p&gt;« Et voilà ! », comme diraient nos amis anglophones. La clé que vous utilisez au quotidien, sur votre ordinateur portable, ne dispose plus de votre clé privée, celle-ci étant en sécurité sur une clé &lt;span class="caps"&gt;USB&lt;/span&gt;.&lt;/p&gt;
&lt;h1 id="usage-exemples"&gt;Usage et exemples particuliers&lt;/h1&gt;
&lt;p&gt;Maintenant qu’on a placé la partie privée de la clé &lt;span class="caps"&gt;PGP&lt;/span&gt; sur une clé &lt;span class="caps"&gt;USB&lt;/span&gt;, il faut savoir comment l’utiliser concrètement.&lt;/p&gt;
&lt;h2 id="montage-cle"&gt;Montage de la clé&lt;/h2&gt;
&lt;p&gt;Commençons par monter la clé &lt;span class="caps"&gt;USB&lt;/span&gt; contenant notre clé &lt;span class="caps"&gt;GPG&lt;/span&gt; complète. Dans notre exemple elle se monte dans &lt;code&gt;/media/vetetix/usb-key&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On peut alors travailler avec en utilisant l’option &lt;code&gt;--home&lt;/code&gt; de gnupg, que l’on pointe sur le répertoire de travail contenu sur la clé :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$  &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--home&lt;span class="o"&gt;=&lt;/span&gt;/media/vetetix/usb-key/gnupg&lt;span class="w"&gt; &lt;/span&gt;-K
&lt;/span&gt;&lt;span class="go"&gt;/media/vetetix/usb-key/gnupg/secring.gpg&lt;/span&gt;
&lt;span class="go"&gt;---------------------------------------&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;sec   4096R/4EA58FE3 2014-09-10 [expire : 2016-09-09]&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;uid                  Jean Dupont (Main ID) &amp;lt;thomas@exemple.net&amp;gt;&lt;/span&gt;
&lt;span class="go"&gt;uid                  Jean Dupont &amp;lt;vetetix@domaine.fr&amp;gt;&lt;/span&gt;
&lt;span class="go"&gt;ssb   4096R/87EAB420 2014-09-10&lt;/span&gt;
&lt;span class="go"&gt;ssb   4096R/E8DC29F1 2014-09-11&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On constate que la clé secrète n’est pas suivie d’un &lt;code&gt;#&lt;/code&gt;. Elle est donc présente.&lt;/p&gt;
&lt;h2 id="prolongation-validite"&gt;Prolongation de la validité de la clé&lt;/h2&gt;
&lt;p&gt;En créant ma clé, j’ai mis une durée de validité de deux ans. Pour prolonger cette validité, il suffit d’utiliser la commande &lt;em&gt;expire&lt;/em&gt; de gpg, et à nouveau de choisir “2y”, ou toute autre durée :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--home&lt;span class="o"&gt;=&lt;/span&gt;/media/vetetix/usb-key/gnupg&lt;span class="w"&gt; &lt;/span&gt;--edit-key&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3
&lt;/span&gt;&lt;span class="go"&gt;[…]&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;gpg&amp;gt; expire&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;[…]&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;gpg&amp;gt; save&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--home&lt;span class="o"&gt;=&lt;/span&gt;/media/vetetix/usb-key/gnupg&lt;span class="w"&gt; &lt;/span&gt;--send-keys&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="signatures-cles"&gt;Signatures d’autres clés&lt;/h2&gt;
&lt;p&gt;Pour signer une autre clé, on va récupérer la clé en question (à partir de son &lt;span class="caps"&gt;ID&lt;/span&gt; dans notre exemple) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--home&lt;span class="o"&gt;=&lt;/span&gt;/media/vetetix/usb-key/gnupg&lt;span class="w"&gt; &lt;/span&gt;--recv-keys&lt;span class="w"&gt; &lt;/span&gt;ABCD1234
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ensuite on la signe, et on exporte la signature dans un format lisible (option &lt;code&gt;--armor&lt;/code&gt;) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--home&lt;span class="o"&gt;=&lt;/span&gt;/media/vetetix/usb-key/gnupg&lt;span class="w"&gt; &lt;/span&gt;--sign-key&lt;span class="w"&gt; &lt;/span&gt;ABCD1234
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--home&lt;span class="o"&gt;=&lt;/span&gt;/media/vetetix/usb-key/gnupg&lt;span class="w"&gt; &lt;/span&gt;--armor&lt;span class="w"&gt; &lt;/span&gt;--output&lt;span class="w"&gt; &lt;/span&gt;ABCD1234.signed-by.4EA58FE3.asc&lt;span class="w"&gt; &lt;/span&gt;--export&lt;span class="w"&gt; &lt;/span&gt;ABCD1234
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Maintenant qu’on a signé la clé publique de la personne, on n’uploade pas la signature soi-même. La personne dont on a vérifié l’identité peut très bien avoir menti sur l’adresse email ou xmpp qu’il a montrée. Pour éviter tout problème, on envoie la signature par email ou xmpp au titulaire de l’adresse, en chiffrant le message avec la clé publique qu’on vient de signer.&lt;/p&gt;
&lt;p&gt;Le récipiendaire du message sera ainsi le titulaire de l’adresse email, et de la clé qu’on vient de signer. Il déchiffrera le message, importera la signature dans son trousseau GnuPG, et l’uploadera lui-même sur un serveur de clé.&lt;/p&gt;
&lt;h2 id="revocation-sous-cle"&gt;Révocation d’une sous-clé&lt;/h2&gt;
&lt;p&gt;En cas de souci (vol de la clé, ou autre désastre), on peut avoir besoin de révoquer la sous-clé de signature de notre clé. Avantage de notre système de sous-clé additionnelle : la clé principale n’a pas à être révoquée, elle reste donc en service et on ne perd pas le bénéfice du &lt;em&gt;Web of Trust&lt;/em&gt; existant.&lt;/p&gt;
&lt;p&gt;Pour générer le certificat de révocation de la sous-clé, il faut avoir accès à la clé de signature principale, donc il faut utiliser la clé &lt;span class="caps"&gt;USB&lt;/span&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="hll"&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--home&lt;span class="o"&gt;=&lt;/span&gt;/media/vetetix/usb-key/gnupg&lt;span class="w"&gt; &lt;/span&gt;--edit-key&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;gpg&amp;gt; list # Pour voir le détail des sous-clés et identités&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;[…]&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;gpg&amp;gt; key 2 # Pour sélectionner la deuxième sous-clé, compromise&lt;/span&gt;
&lt;/span&gt;&lt;span class="go"&gt;[…]&lt;/span&gt;
&lt;span class="hll"&gt;&lt;span class="go"&gt;gpg&amp;gt; revkey # Pour générer le certificat de révocation de la sous-clé sélectionnée&lt;/span&gt;
&lt;/span&gt;&lt;span class="hll"&gt;&lt;span class="go"&gt;gpg&amp;gt; save&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Il faut désormais recréer une sous-clé de signature, tel qu’expliqué précédemment, et republier notre clé modifiée avec la commande &lt;code&gt;gpg --send-keys ID&lt;/code&gt; (puis recréer une version amputée de la clé en vue de son utilisation quotidienne).&lt;/p&gt;
&lt;p&gt;Il ne reste plus qu’à vos correspondants de mettre à jour leur version de votre clé publique via &lt;code&gt;gpg --recv-keys ID&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Note : Il semble déconseillé de supprimer les sous-clés et identités corrompues, car de toute façon, elles ne disparaitraient pas sur les serveurs de clé, ou dans notre clé publique chez nos correspondants.&lt;/p&gt;
&lt;h2 id="revocation-definitive"&gt;Révocation définitive de la clé&lt;/h2&gt;
&lt;p&gt;Si la clé a été définitivement compromise, ou qu’après plusieurs années de bons et loyaux service on la remplace pour utiliser des algorithmes plus robustes, on peut la révoquer.&lt;/p&gt;
&lt;p&gt;Cela peut se faire à partir du certificat de révocation créé préalablement :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--import&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3.revocation.asc
&lt;span class="gp"&gt;$ &lt;/span&gt;gpg&lt;span class="w"&gt; &lt;/span&gt;--send-keys&lt;span class="w"&gt; &lt;/span&gt;4EA58FE3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;La clé est désormais inutilisable :-( Paix à son âme.&lt;/p&gt;
&lt;p&gt;Si on n’a pas prévu de certificat de révocation, on peut en créez un à partir de la clé privée complète. Si en plus on a perdu la clé privée complète, on ne pourra jamais la révoquer.&lt;/p&gt;
&lt;h1 id="autres-ressources"&gt;Autres ressources&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.gnupg.org/gph/en/manual.html"&gt;Le manuel officiel du projet GnuPG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gnupg.org/faq/gnupg-faq.html"&gt;La foire aux questions officielle&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Logiciels"/><category term="PGP"/><category term="GPG"/><category term="GnuPG"/><category term="Sécurité"/><category term="Chiffrement"/></entry><entry><title>Installer Gajim sur Ubuntu</title><link href="https://www.pragmageek.fr/2015/04/installer-gajim-ubuntu/" rel="alternate"/><published>2015-04-27T00:00:00+02:00</published><updated>2020-12-30T06:55:52.942918+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2015-04-27:/2015/04/installer-gajim-ubuntu/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo Gajim" class="left" src="https://www.pragmageek.fr/images/2015/gajim.png" style="width: 128px; height: auto; max-width: 100%;"/&gt;
Quand on veut exploiter à fond son serveur &lt;span class="caps"&gt;XMPP&lt;/span&gt;, en particulier ses fonctionnalités avancées, il faut installer un “vrai” client. On ne peut pas se contenter d’&lt;a href="https://wiki.gnome.org/action/show/Apps/Empathy"&gt;Empathy&lt;/a&gt;, il faut passer à &lt;a href="http://gajim.org"&gt;Gajim&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;L’installation propre et complète de Gajim sur Ubuntu n’est malheureusement pas complètement triviale. Voici ce que j’ai fait pour avoir un logiciel complet.&lt;/p&gt;
&lt;h2 id="installation-de-gajim"&gt;Installation de Gajim&lt;/h2&gt;
&lt;p&gt;Tout d’abord, on va installer la version présente dans les dépôts officiels …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo Gajim" class="left" src="https://www.pragmageek.fr/images/2015/gajim.png" style="width: 128px; height: auto; max-width: 100%;"/&gt;
Quand on veut exploiter à fond son serveur &lt;span class="caps"&gt;XMPP&lt;/span&gt;, en particulier ses fonctionnalités avancées, il faut installer un “vrai” client. On ne peut pas se contenter d’&lt;a href="https://wiki.gnome.org/action/show/Apps/Empathy"&gt;Empathy&lt;/a&gt;, il faut passer à &lt;a href="http://gajim.org"&gt;Gajim&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;L’installation propre et complète de Gajim sur Ubuntu n’est malheureusement pas complètement triviale. Voici ce que j’ai fait pour avoir un logiciel complet.&lt;/p&gt;
&lt;h2 id="installation-de-gajim"&gt;Installation de Gajim&lt;/h2&gt;
&lt;p&gt;Tout d’abord, on va installer la version présente dans les dépôts officiels d’Ubuntu (le ppa n’a pas été mis à jour depuis des années, tout comme la version &lt;em&gt;pip&lt;/em&gt;, et je n’ai pas envie de l’installer via les sources) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo apt-get install gajim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="activation-des-fonctionnalites-supplementaires"&gt;Activation des fonctionnalités supplémentaires&lt;/h2&gt;
&lt;p&gt;Ensuite, on va installer les paquets suivants, pour activer certaines fonctionnalités supplémentaires. Toutes ces fonctionnalités sont détaillées, ainsi que les paquets nécessaires, dans le menu ‘Aide&amp;gt;Fonctionnalités’ :&lt;/p&gt;
&lt;p&gt;&lt;img alt="Fonctionnalités Gajim" src="https://www.pragmageek.fr/images/2015/gajim-fonctionnalités.png" style="width: 407px; height: auto; max-width: 100%;"/&gt;&lt;/p&gt;
&lt;p&gt;Regardez quelles fonctionnalités non activées vous intéressent, et installez leurs dépendances. Pour moi ça donne ça :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo aptitude install python-farstream libgstreamer-plugins-bad1.0-0 python-avahi gnome-keyring python-gnomekeyring python-gnome2 python-gupnp-igd libgtkspell0 python-docutils
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="installation-de-plugins"&gt;Installation de plugins&lt;/h2&gt;
&lt;p&gt;Depuis quelques temps, Gajim supporte les plugins, qui peuvent être installés via l’interface dédiée. Certains plugins ont des dépendances à satisfaire avant de fonctionner.&lt;/p&gt;
&lt;p&gt;Par exemple, pour intégrer Gajim à l’App Indicator d’Ubuntu, il faut activer le plugin &lt;code&gt;Appindicator integration&lt;/code&gt;, puis installer le paquet &lt;code&gt;python-appindicator&lt;/code&gt; par &lt;em&gt;aptitude&lt;/em&gt;. Je n’ai pas encore trouvé comment intégrer proprement Gajim au menu “messaging”, ça nécessitera peut-être de développer un autre plugin…&lt;/p&gt;
&lt;h2 id="integration-au-navigateur"&gt;Intégration au navigateur&lt;/h2&gt;
&lt;p&gt;Il peut être utile que les &lt;a href="http://wiki.xmpp.org/web/XMPP_URIs"&gt;&lt;span class="caps"&gt;URI&lt;/span&gt; &lt;span class="caps"&gt;XMPP&lt;/span&gt;&lt;/a&gt; cliquables du type &lt;code&gt;xmpp:gajim@conference.gajim.org?join&lt;/code&gt; s’ouvrent dans Gajim.&lt;/p&gt;
&lt;p&gt;Pour ce faire, dans un premier temps ouvrez le &lt;em&gt;about:config&lt;/em&gt; de Firefox, et créez une nouvelle entrée booléenne nommée “network.protocol-handler.expose.xmpp” avec pour valeur “false”.&lt;/p&gt;
&lt;p&gt;Ensuite ouvrez “l’éditeur de configuration avancée” dans les préferences de Gajim (onglet “Avancées”). Cherchez le paramètre “remote_control” et activez-le. Cela permettra le contrôle de Gajim par l’utilitaire gajim-remote.&lt;/p&gt;
&lt;p&gt;Cliquez maintenant sur une &lt;span class="caps"&gt;URI&lt;/span&gt; &lt;span class="caps"&gt;XMPP&lt;/span&gt; (par exemple &lt;a href="http://gajim.org/dev.php"&gt;dans la doc de Gajim&lt;/a&gt;, et associez ce type d’&lt;span class="caps"&gt;URI&lt;/span&gt; à gajim-remote (que l’on trouve dans /usr/bin/gajim-remote).&lt;/p&gt;
&lt;p&gt;Plus de documentation :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Le &lt;a href="https://trac.gajim.org/wiki?lang=fr"&gt;wiki officiel de gajim&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Logiciels"/><category term="XMPP"/><category term="Jabber"/><category term="Gajim"/><category term="Ubuntu"/></entry><entry><title>Qu’y a-t-il derrière les noms de domaine de premier niveau ?</title><link href="https://www.pragmageek.fr/2015/02/noms-de-domaine-premier-niveau/" rel="alternate"/><published>2015-02-07T00:00:00+01:00</published><updated>2020-12-30T06:56:57.405634+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2015-02-07:/2015/02/noms-de-domaine-premier-niveau/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo ICANN" class="left" src="https://www.pragmageek.fr/images/2015/icann-logo.png" style="width: 260px; height: auto; max-width: 100%;"/&gt;
En faisant quelques essais avec &lt;a href="https://yunohost.org"&gt;YUNohost&lt;/a&gt;, j’ai trouvé dans la documentation du projet un lien vers une &lt;a href="http://www.iletaitunefoisinternet.fr/dns-bortzmeyer/"&gt;conférence par Stéphane Bortzmeyer&lt;/a&gt; expliquant le fonctionnement global du &lt;span class="caps"&gt;DNS&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;On sait tous que “wikipedia.org” renvoit vers la page d’accueil de l’encyclopédie, et “fr.wikipedia.org” renvoit vers sa version française. Je me suis alors demandé vers quoi renvoyaient les noms de domaine de premier niveau : si on veut aller sur “org”, ou sur …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo ICANN" class="left" src="https://www.pragmageek.fr/images/2015/icann-logo.png" style="width: 260px; height: auto; max-width: 100%;"/&gt;
En faisant quelques essais avec &lt;a href="https://yunohost.org"&gt;YUNohost&lt;/a&gt;, j’ai trouvé dans la documentation du projet un lien vers une &lt;a href="http://www.iletaitunefoisinternet.fr/dns-bortzmeyer/"&gt;conférence par Stéphane Bortzmeyer&lt;/a&gt; expliquant le fonctionnement global du &lt;span class="caps"&gt;DNS&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;On sait tous que “wikipedia.org” renvoit vers la page d’accueil de l’encyclopédie, et “fr.wikipedia.org” renvoit vers sa version française. Je me suis alors demandé vers quoi renvoyaient les noms de domaine de premier niveau : si on veut aller sur “org”, ou sur “com”, que va-t-il se passer ?&lt;/p&gt;
&lt;p&gt;Premier constat : si on rentre simplement “org” dans la barre d’&lt;span class="caps"&gt;URL&lt;/span&gt; de notre navigateur (Firefox dans mon cas), ça fait une recherche du mot clé “org” sur le moteur de recherche par défaut. J’ai alors tenté “org.”, en incluant donc le point final, représentant &lt;a href="https://fr.wikipedia.org/wiki/Serveur_racine_du_DNS"&gt;la racine de l’arborescence &lt;span class="caps"&gt;DNS&lt;/span&gt;&lt;/a&gt;. Ça ne fonctionne pas non plus, ça recherche “org.” sur DuckDuckGo. &lt;/p&gt;
&lt;p&gt;J’ai alors pensé à inclure le protocole dans la barre d’url : “http://org”. Ça ne fonctionne toujours pas Firefox me renvoyant vers le site “http://www.org.com”. C’est encore pire, parce que les sites renvoyés de cette manière ont visiblement mauvaise réputation sur &lt;a href="https://www.mywot.com/"&gt;&lt;span class="caps"&gt;WOT&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;La solution : entrer “http://org.”, avec le point final.&lt;/p&gt;
&lt;p&gt;Cela nous donne finalement cela, souvent après plusieurs redirections :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;org (http://org.) : &lt;a href="http://www.w3.org/"&gt;http://www.w3.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;fr : &lt;a href="https://www.afnic.fr/"&gt;https://www.afnic.fr/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;com : &lt;a href="http://www.www.com/"&gt;http://www.www.com/&lt;/a&gt; (visiblement du grand &lt;span class="caps"&gt;WTF&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;net : Ne semble pas fonctionner&lt;/li&gt;
&lt;li&gt;lu : &lt;a href="http://www.luxembourg.public.lu/fr/index.html"&gt;http://www.luxembourg.public.lu/fr/index.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;es : Ne semble pas fonctionner&lt;/li&gt;
&lt;li&gt;info : &lt;a href="http://www.info./"&gt;http://www.info./&lt;/a&gt; (ou tout simplement &lt;a href="http://www.info"&gt;http://www.info&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;uk : Ne semble pas fonctionner&lt;/li&gt;
&lt;li&gt;co.uk : Ne semble pas fonctionner non plus&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Enfin, “http://.” n’est pas interprêté correctement par Firefox. C’est normal, “.” n’est pas un nom de domain, c’est juste la racine.&lt;/p&gt;
&lt;p&gt;Je vous laisse vous amuser avec d’autres recherches. Si vous trouvez des exemples intéressants, n’hésitez pas à les partager (en commentaire, si j’installe le plugin sur ce blog).&lt;/p&gt;</content><category term="Internet"/><category term="Internet"/><category term="DNS"/><category term="Noms de domaine"/><category term="YUNoHost"/><category term="Bortzmeyer"/></entry><entry><title>La Quadrature du Net a besoin de nous</title><link href="https://www.pragmageek.fr/2014/12/LQDN-a-besoin-de-nous/" rel="alternate"/><published>2014-12-19T00:00:00+01:00</published><updated>2020-12-30T06:56:16.898441+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2014-12-19:/2014/12/LQDN-a-besoin-de-nous/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo de La Quadrature Du Net" class="left" src="https://www.pragmageek.fr/images/2014/lqdn-logo.png" style="width: 150px; height: auto; max-width: 100%;"/&gt;&lt;a href="http://laquadrature.net/"&gt;&lt;em&gt;La Quadrature du Net&lt;/em&gt;&lt;/a&gt;, association de défense de l’internet libre, qui s’oppose régulièrement aux nombreux projets de loi nationaux ou internationaux s’attaquant à l’internet, a urgemment besoin de fonds.&lt;/p&gt;
&lt;p&gt;Elle fait régulièrement des campagnes de dons, mais il semblerait qu’en ce moment, les donateurs sont très peu nombreux. Il se trouve que par hasard, j’ai fait un petit don il y a trois jours, mais c’est une goutte …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo de La Quadrature Du Net" class="left" src="https://www.pragmageek.fr/images/2014/lqdn-logo.png" style="width: 150px; height: auto; max-width: 100%;"/&gt;&lt;a href="http://laquadrature.net/"&gt;&lt;em&gt;La Quadrature du Net&lt;/em&gt;&lt;/a&gt;, association de défense de l’internet libre, qui s’oppose régulièrement aux nombreux projets de loi nationaux ou internationaux s’attaquant à l’internet, a urgemment besoin de fonds.&lt;/p&gt;
&lt;p&gt;Elle fait régulièrement des campagnes de dons, mais il semblerait qu’en ce moment, les donateurs sont très peu nombreux. Il se trouve que par hasard, j’ai fait un petit don il y a trois jours, mais c’est une goutte d’eau face à leurs besoins financiers.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://korben.info/la-quadrature-du-net-cest-termine.html"&gt;Un billet de Korben&lt;/a&gt; publié aujourd’hui m’indique que la situation est critique, alors rendez-vous sur &lt;a href="https://soutien.laquadrature.net/2316788c9a61179830bbe49c5e767369"&gt;la page de soutien de &lt;em&gt;La Quadrature du Net&lt;/em&gt;&lt;/a&gt;, munissez-vous de votre carte bancaire, et donnez ne serait-ce que 10 ou 20€, soit le prix d’un McDo. Les petits torrents font les grandes rivières, donc tout don compte.&lt;/p&gt;
&lt;p&gt;Pour être franc, j’aurais les boules qu’une association comme &lt;em&gt;&lt;span class="caps"&gt;LQDN&lt;/span&gt;&lt;/em&gt; ferme se portes quelques semaines seulement après que je leur ai fait un don pour la première fois, mais les enjeux vont au delà de mon amour-propre, alors soyons généreux.&lt;/p&gt;</content><category term="Divers"/><category term="LQDN"/><category term="Quadrature"/><category term="Libertés"/><category term="Internet"/><category term="Association"/><category term="Don"/><category term="Argent"/></entry><entry><title>Régler un problème de mise à jour Spamassassin</title><link href="https://www.pragmageek.fr/2014/12/r/" rel="alternate"/><published>2014-12-07T00:00:00+01:00</published><updated>2020-12-30T06:56:06.422650+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2014-12-07:/2014/12/r/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo Spamassassin" class="left" src="https://www.pragmageek.fr/images/2014/SpamAssassin_logo.png" style="width: 320px; height: auto; max-width: 100%;"/&gt;
Si comme moi, vous avez installé votre propre serveur mail, et que vous gérez la détection des courriers indésirables avec &lt;a href="https://en.wikipedia.org/wiki/SpamAssassin"&gt;&lt;em&gt;spamassassin&lt;/em&gt;&lt;/a&gt;, vous avez peut-être recontré l’erreur suivante dans les logs de votre &lt;em&gt;cron.daily&lt;/em&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/etc/cron.daily/spamassassin:
error: unable to refresh mirrors file for channel updates.spamassassin.org, using old file
channel: could not find working mirror, channel failed
sa-update failed for unknown reasons
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;J’ai eu cette erreur pendant plusieurs semaines, sans …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo Spamassassin" class="left" src="https://www.pragmageek.fr/images/2014/SpamAssassin_logo.png" style="width: 320px; height: auto; max-width: 100%;"/&gt;
Si comme moi, vous avez installé votre propre serveur mail, et que vous gérez la détection des courriers indésirables avec &lt;a href="https://en.wikipedia.org/wiki/SpamAssassin"&gt;&lt;em&gt;spamassassin&lt;/em&gt;&lt;/a&gt;, vous avez peut-être recontré l’erreur suivante dans les logs de votre &lt;em&gt;cron.daily&lt;/em&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;/etc/cron.daily/spamassassin:
error: unable to refresh mirrors file for channel updates.spamassassin.org, using old file
channel: could not find working mirror, channel failed
sa-update failed for unknown reasons
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;J’ai eu cette erreur pendant plusieurs semaines, sans réussir à la corriger, ça me rendait fou (et ça empêchait la base de &lt;em&gt;spamassassin&lt;/em&gt; de se mettre à jour, ce qui n’est pas négligeable).&lt;/p&gt;
&lt;p&gt;J’ai enfin trouvé le problème : Il faut que la commande &lt;code&gt;sa-update&lt;/code&gt; soit lancée avec l’utilisateur auquel appartiennent les fichiers contenus dans &lt;em&gt;/var/lib/spamassassin/&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Le problème apparait donc soit quand vous lancez la commande manuellement (forcément en root, ou avec &lt;em&gt;sudo&lt;/em&gt;), les fichiers sont alors attribués à l’utilisateur &lt;em&gt;root&lt;/em&gt;, et les mises à jour suivantes échouent, soit parce que le script cron lancé quotidiennement n’est pas configuré correctement.&lt;/p&gt;
&lt;p&gt;Selon les tutoriels et documentations que vous aurez lus, l’utilisateur est &lt;em&gt;spamd&lt;/em&gt;, &lt;em&gt;debian-spamd&lt;/em&gt;, ou &lt;em&gt;spamassassin&lt;/em&gt;. Dans mon cas, j’ai décidé de rester avec &lt;em&gt;spamd&lt;/em&gt;, le plus simplement du monde. Le script se lançait par contre avec &lt;em&gt;debian-spamd&lt;/em&gt;, générant ainsi une erreur. J’ai donc lancé les commandes suivantes :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo chown -R spamd:spamd /var/lib/spamassassin
sudo sed -i 's/debian-spamd/spamd/g' /etc/cron.daily/spamassassin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Et voilà, plus d’erreurs, et ma base &lt;em&gt;spamassassin&lt;/em&gt; est à jour.&lt;/p&gt;</content><category term="Auto-hébergement"/><category term="Spamassassin"/><category term="Spam"/><category term="Mise à jour"/><category term="Droits"/><category term="Auto-Hébergement"/></entry><entry><title>Sécuriser son serveur : le pare-feu</title><link href="https://www.pragmageek.fr/2014/12/s/" rel="alternate"/><published>2014-12-07T00:00:00+01:00</published><updated>2020-12-30T06:56:08.374611+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2014-12-07:/2014/12/s/</id><summary type="html">&lt;p&gt;&lt;img alt="Logo Gufw" class="left" src="https://www.pragmageek.fr/images/2014/gufw-logo.png" style="width: 128px; height: auto; max-width: 100%;"/&gt;Une des premières chose à faire pour sécuriser son serveur est d’empêcher les méchants pirates d’y accéder à distance par des portes grandes ouvertes. On va donc installer un pare-feu.&lt;/p&gt;
&lt;p&gt;Par défaut, aucun pare-feu n’est activé sur notre serveur (on peut par exemple vérifier que iptables est désactivé en listant les règles actives : &lt;code&gt;iptables -L&lt;/code&gt; pour IPv4, et &lt;code&gt;ip6tables -L&lt;/code&gt; pour IPv6). Il est important de fermer tous les ports entrants, et …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="Logo Gufw" class="left" src="https://www.pragmageek.fr/images/2014/gufw-logo.png" style="width: 128px; height: auto; max-width: 100%;"/&gt;Une des premières chose à faire pour sécuriser son serveur est d’empêcher les méchants pirates d’y accéder à distance par des portes grandes ouvertes. On va donc installer un pare-feu.&lt;/p&gt;
&lt;p&gt;Par défaut, aucun pare-feu n’est activé sur notre serveur (on peut par exemple vérifier que iptables est désactivé en listant les règles actives : &lt;code&gt;iptables -L&lt;/code&gt; pour IPv4, et &lt;code&gt;ip6tables -L&lt;/code&gt; pour IPv6). Il est important de fermer tous les ports entrants, et de n’ouvrir que ceux strictement nécessaires.&lt;/p&gt;
&lt;h2 id="le-choix-du-logiciel"&gt;Le choix du logiciel&lt;/h2&gt;
&lt;p&gt;Pour mon serveur, j’ai choisi d’utiliser le bien nommé &lt;em&gt;ufw&lt;/em&gt; (Uncomplicated FireWall), après avoir eu quelques déconvenues dans l’utilisation de &lt;em&gt;iptables&lt;/em&gt;, que je trouve très compliqué à prendre en main. Tout comme ce dernier, &lt;em&gt;ufw&lt;/em&gt; est désactivé par défaut, mais Une fois activé, il se lancera à chaque redémarrage du serveur en réactivant les règles existantes. Pas besoin de gérer manuellement des scripts d’activation/désactivation au démarrage des interfaces réseau, ou de maintenir deux versions, pour IPv4 et IPv6. &lt;em&gt;ufw&lt;/em&gt; est plus ou moins une surcouche à &lt;em&gt;iptables&lt;/em&gt; qui permet d’automatiser tout cela.&lt;/p&gt;
&lt;p&gt;De plus, pour une utilisation “simple” du pare-feu (une seule interface réseau, simplement bloquée en &lt;span class="caps"&gt;INPUT&lt;/span&gt; par défaut, etc.), je n’atteindrai jamais les limites de &lt;em&gt;ufw&lt;/em&gt; par rapport à &lt;em&gt;iptables&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Comme je me connecte à mon serveur en &lt;em&gt;&lt;span class="caps"&gt;SSH&lt;/span&gt;&lt;/em&gt;, la première chose à faire avant d’activer &lt;em&gt;ufw&lt;/em&gt; est d’autoriser le protocole en question. La syntaxe est assez souple et complète, et peut se montrer complexe (mais pas autant que celle de &lt;em&gt;iptables&lt;/em&gt;), mais dans le cas présent, c’est plutôt simple. &lt;/p&gt;
&lt;p&gt;Il est possible d’utiliser au choix une des commandes suivantes :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo ufw allow 22/tcp # choix totalement manuel du port 22 et du protocole tcp

sudo ufw allow ssh/tcp # utilisation du fichier /etc/services et du protocole tcp

sudo ufw allow app OpenSSH # utilisation du profil d'application de ufw
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ensuite, il ne reste plus qu’à activer &lt;em&gt;ufw&lt;/em&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo ufw enable
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;La documentation la plus complète que j’ai trouvée en dehors du &lt;a href="http://manpages.ubuntu.com/manpages/utopic/en/man8/ufw.8.html"&gt;manuel officiel&lt;/a&gt;, est &lt;a href="https://help.ubuntu.com/community/UFW" title="version anglaise"&gt;celle du wiki communautaire Ubuntu&lt;/a&gt;. Je vous en conseille la lecture.&lt;/p&gt;
&lt;h2 id="introduction-aux-applications"&gt;Introduction aux “applications”&lt;/h2&gt;
&lt;p&gt;J’ai fait le choix d’utiliser principalement les “app”, parce que celles-ci peuvent configurer plusieurs ports, sur différents protocoles, pour un seul service et que ça ne génère qu’une seule entrée dans la liste de statut de &lt;em&gt;ufw&lt;/em&gt;, avec le nom du service, et non le port dont on ne se souvient pas toujours de l’utilité. C’est donc beaucoup plus clair.&lt;/p&gt;
&lt;h3 id="quelques-commandes-utiles-concernant-les-profils-dapplications"&gt;Quelques commandes utiles concernant les profils d’applications&lt;/h3&gt;
&lt;p&gt;Lister les profils disponibles (pour information, il n’y a par défaut quasiment aucun profil, ceux-ci s’ajoutent à l’installation des service concernés via &lt;em&gt;apt&lt;/em&gt;) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo ufw app list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Voir les détails d’un profil (ici avec OpenSSH) :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo ufw app info OpenSSH
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Utiliser le profil dans une règle&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;sudo ufw allow app OpenSSH # (Autoriser SSH pour tout le monde)
sudo ufw allow app OpenSSH from 192.168.0.0/24 # (Autoriser SSH pour le réseau local)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Il ne vous reste plus qu’à autoriser tous les services qui le nécessitent.&lt;/p&gt;
&lt;p&gt;Il faut noter qu’il est possible de créer soi-même de nouveaux profils. &lt;a href="http://jhansonxi.blogspot.com.es/2010/10/ufw-application-profiles.html"&gt;C’est ce qu’a fait ce bloggeur par exemple&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Dans le billet qui traitera de &lt;em&gt;fail2ban&lt;/em&gt;, on reparlera de &lt;em&gt;ufw&lt;/em&gt;. &lt;/p&gt;
&lt;h2 id="quelques-conseils-complementaires"&gt;Quelques conseils complémentaires&lt;/h2&gt;
&lt;p&gt;L’ordre des règles &lt;em&gt;ufw&lt;/em&gt; a son importance. Les règles sont numérotées (utiliser &lt;code&gt;sudo ufw status numbered&lt;/code&gt; pour voir ces numéros). Il est possible d’insérer une règle à l’endroit voulu en utilisant l’option &lt;code&gt;insert #&lt;/code&gt; au début de la commande : &lt;code&gt;sudo ufw insert 3 allow 44&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ufw&lt;/em&gt; étant une surcouche à &lt;em&gt;iptables&lt;/em&gt;, il permet de faire tout ce que ce dernier permet, soit avec des commandes, soit en modifiant divers fichiers de configuration.&lt;/p&gt;</content><category term="Auto-hébergement"/><category term="auto-hébergement"/><category term="iptables"/><category term="ufw"/><category term="pare-feu"/><category term="sécurité"/></entry><entry><title>Hello World!</title><link href="https://www.pragmageek.fr/2014/12/hello/" rel="alternate"/><published>2014-12-06T00:00:00+01:00</published><updated>2020-12-30T06:56:14.674485+01:00</updated><author><name>vetetix</name></author><id>tag:www.pragmageek.fr,2014-12-06:/2014/12/hello/</id><summary type="html">&lt;p&gt;&lt;img alt="PragmaGeek logo" class="left" src="https://www.pragmageek.fr/images/theme/pragmageek-logo.png" style="width: 128px; height: auto; max-width: 100%;"/&gt;
PragmaGeek, le blog d’un geek pragmatique, démarre officiellement aujourd’hui. Vous en lisez le premier billet.&lt;/p&gt;
&lt;p&gt;PragmaGeek, c’est une aventure, un voyage plusieurs fois entrepris, maintes fois écourté, celui vers l’auto-hébergement. C’est donc avant tout un recueil de documentations, de tutoriels et de ressources pour m’accompagner dans mon apprentissage du “cloud personnel”, et pour aider ceux qui entameraient eux-mêmes cette aventure formatrice.&lt;/p&gt;
&lt;p&gt;PragmaGeek, c’est aussi un blog qui suit …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;img alt="PragmaGeek logo" class="left" src="https://www.pragmageek.fr/images/theme/pragmageek-logo.png" style="width: 128px; height: auto; max-width: 100%;"/&gt;
PragmaGeek, le blog d’un geek pragmatique, démarre officiellement aujourd’hui. Vous en lisez le premier billet.&lt;/p&gt;
&lt;p&gt;PragmaGeek, c’est une aventure, un voyage plusieurs fois entrepris, maintes fois écourté, celui vers l’auto-hébergement. C’est donc avant tout un recueil de documentations, de tutoriels et de ressources pour m’accompagner dans mon apprentissage du “cloud personnel”, et pour aider ceux qui entameraient eux-mêmes cette aventure formatrice.&lt;/p&gt;
&lt;p&gt;PragmaGeek, c’est aussi un blog qui suit mes pérégrinations sur la toile, et qui me permet de partager mes diverses passions, mes trouvailles, ou tout ce qui me semble digne d’intérêt. En cela, il prend le relais de &lt;a href="http://blog.arnoux.lu"&gt;mon ancien blog&lt;/a&gt;, qui devrait sommeiller plus encore qu’avant, mais rester en ligne.&lt;/p&gt;</content><category term="Divers"/><category term="Blog"/></entry></feed>