OVH Cloud OVH Cloud

Nouveau script pour d=c3=a9coder les ent=c3=aates MIME

35 réponses
Avatar
Olivier Miakinen
Bonjour,

J'ai fait une nouvelle version de mon script. Au lieu de prendre en
paramètre une ou plusieurs chaînes à décoder, il prend en paramètre
un ou plusieurs noms de fichiers contenant les entêtes complets.
On peut aussi lui faire lire les données sur stdin si on ne met pas
de paramètre, ou qu'on met « - » à la place d'un nom de fichier.

Par exemple, si on saisit :

decode_headers <<POTIRON
Message-ID: <c5a9-1@part.org>
From: Arvo =?UTF-8?Q?P=C3=A4rt?= <arvo@part.org>
To: =?Latin1?Q?Fr=E9d=E9ric_Chopin?= <fred@chopin.org>,
=?Latin2?Q?Anton=EDn_Dvo=F8=E1k?= <anton@dvorak.org>
References: <A65R-4d@chopin.org> <c5a7-3@part.org>
<A72Q-5a@chopin.org>
In-Reply-To: <A72Q-5a@chopin.org>
Subject: Re: Going to =?Shift-JIS?B?k4yLngo=?= (Tokyo) =?UTF-8?B?zpEK?=
=?UTF-8?B?zrjOrs69zrEK?= (Athens) and =?ISO-8859-5?Q?=BC=DE=E1=DA?=
=?ISO-8859-5?Q?=D2=D0?= (Moscow)
POTIRON

On obtiendra :

Message-ID: <c5a9-1@part.org>
From: Arvo Pärt <arvo@part.org>
To: Frédéric Chopin <fred@chopin.org>, Antonín Dvořák <anton@dvorak.org>
References: <A65R-4d@chopin.org> <c5a7-3@part.org> <A72Q-5a@chopin.org>
In-Reply-To: <A72Q-5a@chopin.org>
Subject: Re: Going to 東京 (Tokyo) Αθήνα (Athens) and Москва (Moscow)

(Note : le mot POTIRON n'a rien de spécial, c'est juste pour aider
OuiOui à améliorer son karma)


Voici le script. Attention, pour l'adapter au Mac il faudra modifier les
variables CUT, DECODE_QP, DECODE_B64, TR et ICONV définies vers le début
du fichier.

========================================================================
#!/bin/bash
####################################################################
# Name:
# decode_headers
#
# Description:
# Script used for decoding RFC 2047 MIME encoded headers.
#
# Example:
# decode_headers <<POTIRON
# Message-ID: <c5a9-1@part.org>
# From: Arvo =?UTF-8?Q?P=C3=A4rt?= <arvo@part.org>
# To: =?Latin1?Q?Fr=E9d=E9ric_Chopin?= <fred@chopin.org>,
# =?Latin2?Q?Anton=EDn_Dvo=F8=E1k?= <anton@dvorak.org>
# References: <A65R-4d@chopin.org> <c5a7-3@part.org>
# <A72Q-5a@chopin.org>
# In-Reply-To: <A72Q-5a@chopin.org>
# Subject: Re: Going to =?Shift-JIS?B?k4yLngo=?= (Tokyo) =?UTF-8?B?zpEK?=
# =?UTF-8?B?zrjOrs69zrEK?= (Athens) and =?ISO-8859-5?Q?=BC=DE=E1=DA?=
# =?ISO-8859-5?Q?=D2=D0?= (Moscow)
# POTIRON
# ->
# Message-ID: <c5a9-1@part.org>
# From: Arvo Pärt <arvo@part.org>
# To: Frédéric Chopin <fred@chopin.org>, Antonín Dvořák <anton@dvorak.org>
# References: <A65R-4d@chopin.org> <c5a7-3@part.org> <A72Q-5a@chopin.org>
# In-Reply-To: <A72Q-5a@chopin.org>
# Subject: Re: Going to 東京 (Tokyo) Αθήνα (Athens) and Москва (Moscow)
#
# Known bugs:
# Can't handle encoded-words which are not clearly separated
# from non-blank characters, e.g. in comments: (=?...?.?...?=)
####################################################################

#
# The following constants should be adapted for your system.
# For example, the executable base64 could be at /usr/local/bin instead
# of /usr/bin, and it could require parameter -D instead of -d.
#
CUT="/usr/bin/cut"
DECODE_QP="/usr/bin/qprint -d"
DECODE_B64="/usr/bin/base64 -d"
TR="/usr/bin/tr"
ICONV="/usr/bin/iconv"

#
# This script uses the following global variables
# VARY
# used when a function has to return a string and not only a number
# DECODED_LINE
# The current state of a header being currently decoded
# STATUS
# Has three possible values:
# - "none" at the beginning of a new header
# - "decoded-word" after a correctly decoded MIME part
# - "normal" after any other string
#
VARY=""
DECODED_LINE=""
STATUS="none"

#
# Function: usage
#
usage()
{
printf "Usage: %s [OPTION...] [FILE...]\n" $0
printf "Decode headers from given files for RFC 2047 MIME encodings.\n"
printf "\n"
printf "With no FILE, or when FILE is -, read standard input.\n"
printf "\n"
printf " -h, --help Give this help list\n"
exit 1
}

#
# Function: decode_word
#
# Description:
# Check that the parameter is an encoded word, then decode it and
# convert it to UTF-8.
#
# Parameter:
# A single (possibly MIME-encoded) word.
#
# Return value:
# If decoding is ok, set the result into VARY and return 0
# Otherwise return 1
#
decode_word()
{
word="$*"
###################################################################
# An encoded word contains only ASCII characters in range from
# '!' (Ascii value 0x21) to '~' (Ascii value 0x7e). This excludes
# in particular the SPACE (Ascii 0x20) and the TAB (Ascii 0x09).
#
# More specifically, it consists of five parts separated by
# question marks '?'
# 1. A character "="
# 2. The charset, e.g. "UTF-8" or "ISO-8859-1"
# 3. The encoding, B or Q in upper or lower case
# 4. The encoded text
# 5. A character "="
###################################################################

# Check that:
# - there is no character outside range from '!' to '~'
# - the 1st part is a "="
# - the 5th part is a "=" and it is the end of the string
if [ $(LANG=C expr "_$word" : '_=?[!-~]*=$') = 0 ]; then return 1; fi
end=$(printf "$word" | $CUT -f 5- -d '?')
if [ "$end" != "=" ]; then return 1; fi

# Extract charset, encoding, and encoded text
charset=$(printf "$word" | $CUT -f 2 -d '?')
encoding=$(printf "$word" | $CUT -f 3 -d '?')
encoded=$(printf "$word" | $CUT -f 4 -d '?')

case $encoding in
B | b)
decoded=$(printf "$encoded" | $DECODE_B64 2>/dev/null)
if [ $? != 0 ]; then return 1; fi
;;
Q | q)
decoded=$(printf "$encoded" | $TR "_" " " | $DECODE_QP 2>/dev/null)
if [ $? != 0 ]; then return 1; fi
;;
*)
return 1
;;
esac

VARY=$(printf "$decoded" | $ICONV -f $charset -t UTF-8 2>/dev/null)
return $?
}

#
# Function: add_word
#
# Description:
# Try to decode a new word, and update DECODED_LINE and STATUS
# depending on the result and the previous STATUS.
#
# Parameter:
# A single (possibly MIME-encoded) word.
#
# Return value:
# None
#
# Side effects:
# Change DECODED_LINE and STATUS
#
add_word()
{
word="$*"
if decode_word "$word"; then
if [ "$STATUS" = "normal" ]; then
DECODED_LINE="${DECODED_LINE} "
fi
DECODED_LINE="${DECODED_LINE}${VARY}"
STATUS="decoded-word"
else
if [ "$STATUS" != "none" ]; then
DECODED_LINE="${DECODED_LINE} "
fi
DECODED_LINE="${DECODED_LINE}${word}"
STATUS="normal"
fi
}

#
# Function: flush_line
#
# Description:
# Before beginning to manage a new header, or just before ending
# the script, print the pending DECODED_LINE if any.
#
# Parameter:
# None
#
# Return value:
# None
#
# Side effects:
# Print things to stdout
# Change DECODED_LINE and STATUS
#
flush_line()
{
if [ -n "${DECODED_LINE}" ]; then
printf "%s\n" "${DECODED_LINE}"
DECODED_LINE=""
STATUS="none"
fi
}

#
# Function: manage_line
#
# Description:
# Manage a new line, which can be either the beginning or the
# continuation of a mail/news header.
# This function prints the previous line if this is a new one,
# then it adds successive parts to the new DECODED_LINE, while
# updating STATUS as needed.
#
# Parameter:
# An input
line.========================================================================

#
# Return value:
# None
#
# Side effects:
# Print things to stdout
# Change DECODED_LINE and STATUS
#
manage_line()
{
line="$*"

# Is it a continuation line?
if [ $(LANG=C expr "$line" : "[ \t]") = 0 ]; then
# No: new header
flush_line
fi

for word in $line; do
add_word "$word"
done
}

#
# Function: manage_file
#
# Description:
# Call manage_line for each line in a given file
#
# Parameter:
# A file name, or "-" for stdin
#
# Return value:
# None
#
# Side effects:
# Same as manage_line
#
manage_file()
{
file=${1--} # POSIX-compliant; ${1:--} can be used either.
while IFS= read -r line; do
manage_line "$line"
done < <(cat -- "$file")
}

#
# Parse arguments for -h or --help
#
for i in "$@"; do
case $i in
-h | --help)
usage
;;
-)
;;
-*)
printf "Unknown argument '%s'\n" "$i"
usage
;;
esac
done

#
# Main loop.
# Call manage_file for each filename in parameters,
# then print the last pending DECODED_LINE if any.
#
for file in "$@"; do
manage_file "$file"
done
flush_line

exit 0
========================================================================

--
Olivier Miakinen

10 réponses

1 2 3 4
Avatar
josephb
M.V. soupira de lassitude :
j'obtiens maintenant les mêmes résultats positifs et négatifs que
toi.
Je pense que c'est cette histoire de retours chariot qui m'a foutu
dedans. Pourtant lundi, je n'avais pas eu de problème avec ce
point-là.
Ça me fatigue !!!

Ça rend chèvre, tu veux dire ;-)
En tout cas, mon script AS qui utilise la première version du script
d'Olivier a l'air de rouler comme c'est pas permis :

Si le mariage de la carpe et du lapin donne de si bons résultats, il va
falloir lancer un élevage :-))
Bon, je vais le tester et regarder comment tu as contourné les points de
blocage : on est quand même plus à l'aise avec AS qu'avec le Shell,
c'est un euphémisme.
Bonne nuit les petits octets…
--
J. B.
Avatar
josephb
M.V. wrote:
Je sélectionne le texte, lance le script et en un instant j'obtiens :
**********

Message-ID:
From: Arvo Pärt
To: Frédéric Chopin , Antonín Dvo?ák (Frédéric
Chopin)
References:
In-Reply-To:
Subject: Re: Going to ?? (Tokyo) ????? (Athens) and ?????? (Moscow)
**********

je confirme ! Décodage de tout l'entête avec respect des lignes de
rubriques, même si cet ancêtre Macsoup ne gère pas l'UTF-8 pour
le prouver ici, et c'est instantané.
Une optimisation parfaite du premier script d'Olivier. Clap-clap-clap
--
J. B.
Avatar
Olivier Miakinen
Le 17/10/2019 20:44, M.V. a écrit :
MV$ head /usr/local/bin/olivier2.sh

exit 0MacBook-Air-MV:bin MV$ DECODED_LINE if any.,sed either.==========v/null)

Haha, c'était un grand n'importe quoi ! Mais j'ai compris que le
problème était avec les CR au lieu de LF.
--
Olivier Miakinen
Avatar
Olivier Miakinen
Le 17/10/2019 20:51, Manfred La Cassagnère a écrit :
Le 17 octobre 2019, Olivier Miakinen a demandé:
Histoire que je me couche moins bête (et que je sache répondre aux
questions de Michel), tu aurais une doc AppleScript à me conseiller ?

http://trad.applescript.free.fr/generalas.html


Ouf, ça n'a pas l'air simple ! Entretemps j'ai trouvé une doc expliquant
comment appeler depuis AppleScript un script shell qui lit stdin, mais
j'ai oublié de noter la référence. Je l'aurai demain.
--
Olivier Miakinen
Avatar
Olivier Miakinen
Le 17/10/2019 22:12, Joseph-B a écrit :
["do shell script"]
mais il existe aussi une note technique plus détaillée
<https://developer.apple.com/library/archive/technotes/tn2065/_index.html>

Oui, c'est bien ça que je devrais essayer de comprendre.
--
Olivier Miakinen
Avatar
Olivier Miakinen
Le 17/10/2019 22:12, Joseph-B a écrit :
Tu peux faire un copier/coller du script d'Olivier tel que tu l'as
chez toi pour que je regarde pourquoi ça ne fonctionne pas du tout
chez moi ?

Je te l'envoie par mail et en dessous.
Mais à part la ligne 210 dont je n'avais pas vu la correction par
Olivier et que j'avais commentée,
et aussi
DECODE_QP="/usr/local/bin/qprint -d"
DECODE_B64="/usr/bin/base64 -D"

Est-ce que tu peux me dire si ça fonctionne toujours en remplaçant
ces deux lignes par les sept suivantes ?
if [ "$(uname)" = "Darwin" ]; then
DECODE_QP="/usr/local/bin/qprint -d"
DECODE_B64="/usr/bin/base64 -D"
else
DECODE_QP="/usr/bin/qprint -d"
DECODE_B64="/usr/bin/base64 -d"
fi
--
Olivier Miakinen
Avatar
M.V.
Le 18 octobre 2019, Olivier Miakinen a pris le temps d'écrire :
Est-ce que tu peux me dire si ça fonctionne toujours en remplaçant
ces deux lignes par les sept suivantes ?
if [ "$(uname)" = "Darwin" ]; then
DECODE_QP="/usr/local/bin/qprint -d"
DECODE_B64="/usr/bin/base64 -D"
else
DECODE_QP="/usr/bin/qprint -d"
DECODE_B64="/usr/bin/base64 -d"
fi

Avec ce remplacement, l'envoi de :
**********
echo "From: Arvo =?UTF-8?Q?Pärt?= " | /usr/local/bin/olivier2.sh
**********
dans le Terminal ne donne aucun résultat : le Terminal est complètement muet.
Bonne journée.
--
Michel VAUQUOIS - http://michelvauquois.fr
Avatar
M.V.
Le 18 octobre 2019, Olivier Miakinen a pris le temps d'écrire :
Tu peux essayer :
Organization: =?NF_Z_62-010_(1973)?Q?C'{tait_o|_d{?? >
Avec mon tout dernier script, ça donne :

Marche pas !
Bonne journée.
--
Michel VAUQUOIS - http://michelvauquois.fr
Avatar
M.V.
Olivier Miakinen a suggéré en date du 18 octobre 2019 :
Organization: =?NF_Z_62-010_(1973)?Q?C'{tait_o|_d{??
(mais c'est un faux problème si tu n'y arrives pas, parce que même si
iconv connaît ce charset il est interdit dans un entête MIME)

Ce charset ne figure pas, ici, dans la liste donnée par "iconv -l" !
Bonne journée.
--
Michel VAUQUOIS - http://michelvauquois.fr
Avatar
Olivier Miakinen
Le 18/10/2019 09:46, M.V. a écrit :
Le 18 octobre 2019, Olivier Miakinen a pris le temps d'écrire :
Est-ce que tu peux me dire si ça fonctionne toujours en remplaçant
ces deux lignes par les sept suivantes ?
if [ "$(uname)" = "Darwin" ]; then
DECODE_QP="/usr/local/bin/qprint -d"
DECODE_B64="/usr/bin/base64 -D"
else
DECODE_QP="/usr/bin/qprint -d"
DECODE_B64="/usr/bin/base64 -d"
fi

Avec ce remplacement, l'envoi de :
**********
echo "From: Arvo =?UTF-8?Q?Pärt?= " | /usr/local/bin/olivier2.sh
**********
dans le Terminal ne donne aucun résultat : le Terminal est complètement muet.

Que donnent les commandes suivantes ?
MV$ uname
MV$ uname -s
D'après le nain Ternet, ça devrait être « Darwin » dans les deux cas.
--
Olivier Miakinen
1 2 3 4