URL Safari Oddities

Ma seconde machine est un mac sur lequel j’utilise Safari. Lors d’un partage d’URL, je constate que lorsque je copie l’adresse d’un site avec un accent dans le chemin, il embarque

https://jadetognet3.wixsite.com/cap-eana/je-découvre-mon-école-1

Alors que Chrome et Firefox utilisent

https://jadetognet3.wixsite.com/cap-eana/je-d%C3%A9couvre-mon-%C3%A9cole-1

C’est un biais de ces dernières années d’afficher dans la barre d’adresse l’URL déséchapée et de copier l’URL réelle. Safari a tort ce qui pose des problèmes lors de la réutilisation de l’URL (par exemple document traitement de texte) même si Pages.app s’en accommode fort bien.

Cela me semble l’occasion de s’amuser un peu avec Automator.app avec pour objectif de mettre un lien avec l’URL bien échappée et le libellé du lien bien normalisé donc deux expressions d’une même adresse.

Je crée donc un workflow qui accepte en entrée des URLs depuis Safari.app, puis j’utilise le module « Get current web page from Safari » (qui envoie l’URL brute échappée), puis le module « Run shell Script » dans lequel je sélectionne perl et « pass input as arguments ». Reste à copie ce script:

#!/usr/bin/perl
use URI::Escape;
$str = $ARGV[0];
$tito = uri_unescape($str);
print `echo "<meta charset="utf8"><a href="\&quot;$str\&quot;">$tito</a> " | textutil -stdin -format html -convert rtf -stdout | pbcopy`;

Le gros hook dans ce script est de bien inclure le meta charset dans le bout de html passé à textutil puis pbcopy (j’ai perdu pas mal de temps avec des problèmes d’encodage).

Plus qu’a créer un raccourci clavier dans les préférences d’accessibilité et le tour est joué. Cependant, sous Monterey, Automator.app est en cours de déprécation. Je passe conduire sur Shortcuts.app avec quelques hooks en raison de bugs de leur part ou d’incompréhensions de ma part. Reste que la solution suivante est fonctionnelle:

Je mets ici le script:

use URI::Escape;
$loco = $ARGV[0];
open(J,'<',$loco);
$str = <J>; 
chomp($str);
close(J);
print($str);
$tito = uri_unescape($str);
print `echo "<meta charset='utf8'><a href='$str'>$tito</a>" | textutil -stdin -format html -convert rtf -stdout | pbcopy`;
Cheers

curl cert apache2 2.2

Grand fan de l’initiative letsencrypt (https://letsencrypt.org/) dont parle souvent l’EFF (https://www.eff.org/) (je suis membre), j’ai eu des problèmes avec la vérification des certificats générés par ce service sur un serveur avec une installation un peu ancienne. curl et LWP me refusaient en raison de problèmes de certificats.
https://community.letsencrypt.org/t/certificate-verification-errors-when-using-curl/105335 a attiré mon attention sur le fait qu’il me manquait la ligne, à priori propre à apache 2,2 suivante, à adapter au bon domaine, dans ma config apache:
SSLCertificateChainFile /etc/letsencrypt/live/privatestash.org/chain.pem


Une fois en place, plus besoin de bypass de la vérification des certificats dans LWP (use IO::Socket::SSL; $ua->ssl_opts( SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE, verify_hostname =>0);) et plus besoin des mêmes options dans curl (-k), ce qui est bien plus satisfaisant.

Le truc bizarre est que les browsers ne pâtissaient pas de ce point.

Samesite cookies & rails & clueless monkey patch

Une vieille application Ruby on Rails 3. C’était par tourisme de dev et j’aime bien, malgré les particularités de ruby (typage et scope) . Des browsers qui commencent à se plaindre du mauvais voir du manque d’attribut same site sur les cookies (dans mon cas des cookies de session).

https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Set-Cookie/SameSite

Je commence par bien flipper. Entre toutes les versions de rails, des heures de recherche, j’étais presque résolu à monkey-patcher les libraires mais, étant bien incapable de localiser où frapper, je commençais à désespérer.

Le site étant service par un apache2 sous mod_passenger, la lumière la plus évidente m’est enfin apparue. J’installe et j’active le mod headers d’apache2 puis je rajoute ce segment dans la section qui vas bien de la config apache du site en question:

<ifmodule mod_headers.c>
Header always edit Set-Cookie (.*) "$1; SameSite=strict"
</ifmodule> 

Je redémarre mon apache et mon firefox ne se plaint plus. Magique !!

NoUTF8MB4

Dans un job d’indexation de données externes, essentiellement RSS mais aussi tweets (cf poste précédent), je me suis retrouvé bien en difficulté d’encodage, collation et stockage dans une base de contenus avec des emojis. J’avais pourtant passé la table d’utf8 à utf8mb4 mais cela ne marchait pas (peut-être un bug dans DBI mais je pense pas car j’ai déjà réussi ailleurs). Après pas mal de recherches, j’ai eu l’idée de ce patch qui a pour objet de garder les emojis sous forme d’entités hautes tout en conservant le texte en bas (les entitiés nommées) de l’unicode en direct.

$s = encode_entities($s);
(@entits) = $s =~ /(&.*?;)/g;
foreach $entit (@entits) {
  $deco = encode('utf-8',decode_entities($entit));
  $s =~ s/$entit/$deco/g unless($entit =~ /&#x/);
}

Plus qu’à décoder pour injection dans solR, ou conserver tel quel lors de l’inclusion dans le HTML. Petit hack qui évite bien des tracas.

twittRSS.cgi

J’en avais besoin, voici mon script qui utilise l’API Twitter pour générer des flux RSS. Assez simple, le plus chiant est sans doute d’obtenir les credentials et le token. Le plus long (mais simple) est d’installer le module Net::Twitter depuis le CPAN.

#!/usr/bin/perl

use CGI;
use XML::RSS;
use Net::Twitter;
use HTML::Entities;
my $twt = Net::Twitter->new(
  traits => [qw/API::RESTv1_1/],
  consumer_key => VOTRE_CLEF_DEVELOPPEUR,
  consumer_secret => VOTRE_MOT_DE_PASSE_DEVELOPPEUR,
  access_token => TOKEN_APPLICATION,
  access_token_secret => MOT_DE_PASSE_DU_TOKEN
);
$cgi = new CGI();
if ($login = $cgi->param('login')) {
  eval {
    my $statuses = $twt->user_timeline({ count => 64, screen_name => $login });
    $rss = XML::RSS->new (version => '2.0');
    $rss->channel(
      title => "Tweets de $login",
      link => "https://twitter.com/$login");
    foreach $status (@$statuses) {
      $rss->add_item(
        title => decode_entities($status->{text}),
        link => "https://twitter.com/$login/status/".$status->{id};
    }
  };
  if($@) {
    print "Content-type: text/plain\n\nProblem because: $@\n";
  } else {
    print "Content-type: application/rss+xml\n\n".$rss->as_string;
  }
} else {
  print "Content-type: text/plain\n\nWho can you trust ?";
}

A vos quotas, prêts, partez !

Perl Image::ExifTool

Je le mets ici car j’ai un peu trimé pour trouver les infos nécessaires.

ExifTool marche parfaitement mais ne pas oublier d’aller voir sur https://metacpan.org/pod/Image::ExifTool#DESCRIPTION que le type d’accès qu’offre le module en fonction du type fichier que vous visez (par example MP3 en lecture, PDF en compl<et).

#!/usr/bin/perl
use Image::ExifTool;
$exifTool = new Image::ExifTool;
$exifTool->ExtractInfo($ARGV[0]);
if ($ARGV[2]) {
$val = $exifTool->GetValue($ARGV[1],'ValueConv');
if (ref $val eq 'ARRAY') {
@values = split(/,\s*/g,$ARGV[2]);
$exifTool->SetNewValue($ARGV[1] => \@values, { Replace=>1, AddValue => 2 });
} else {
$exifTool->SetNewValue($ARGV[1],[$ARGV[2]]);
}
$exifTool->WriteInfo($ARGV[0]);
}
$exifTool->ExtractInfo($ARGV[0]);
foreach $tag (grep { !($_ =~ /\s(1)$/) } sort $exifTool->GetFoundTags()) {
$tt = $tag;
$tt .= ' (1)' if (grep { $_ eq $tt.' (1)'} $exifTool->GetFoundTags());
printf("%-21s : %s\n",$tag,$exifTool->GetValue($tt));
}

Notes: https://exiftool.org/ExifTool.html

Regex Article

Ici

$ra = ‘\s*(?:(([Aa][Nn][Nn][Ee][Xx][Ee]\s[A-Za-z0-9]+)?|([Tt][Aa][Bb][Ll][Ee][Aa][Uu]\s*[Nn]?°?\s?[A-Z0-9]*\s?)?)|\*?[LRDAO]*\.?\s?\**\.?\s?\d+(\-\d+)*\-?\s?[A-Z]*)(\s?(?:tricies|bis|ter|quater|quinquies|sexies|septies|octies|nonies|unvicies|quinquies|novovicies|tertricies|terdecies|duotricies|untrecies|quatertricies|decies|undecies|duodecies|terdecies|quaterdecies|quindecies|sexdecies|septdecies|octodecies|novodecies|vicies|unvecies|duovicies|tervecies|quatervicies|quinvicies|sexvicies|septvicies|octovicies|tervicies)?\s?[A-Z0-9\-]*\s?(?:bis|ter|quater|quinquies|sexies|septies)?\s?[A-Z0-9\-]*\-?\d?)?’;

Taux de réussite: 99.61 % au jour d’aujourd’hui

Bilan: 140.804 articles qui correspondent sur un total de 141.504

.

On examine ensuite la liste des matchs par ordre de longueur décroissante, on évalue au besoin la distance entre chaque match et le nom du code, et on confronte alors les résultats avec des tables de correspondances numéro:identifiant legifrance, …