#!/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@part.org (=?ASCII?Q?Arvo?= =?L1?Q?=20?= =?UTF-8?Q?P=C3=A4rt?=)
# To: =?Latin1?Q?Fr=E9d=E9ric_Chopin?= <fred@chopin.org>,
# =?Latin2?Q?Anton=EDn_Dvo=F8=E1k?= <anton@dvorak.org>
# Cc: Arvo =?UTF-8?Q?P=C3=A4rt?= <arvo@part.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@part.org (Arvo Pärt)
# To: Frédéric Chopin <fred@chopin.org>, Antonín Dvořák <anton@dvorak.org>
# Cc: Arvo Pärt <arvo@part.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)
####################################################################
#
# 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"
TR="/usr/bin/tr"
ICONV="/usr/bin/iconv"
if [ "$(uname)" = "Linux" ]; then
# GNU/Linux
DECODE_QP="/usr/bin/qprint -d"
DECODE_B64="/usr/bin/base64 -d"
else
# MacOS X
DECODE_QP="/usr/local/bin/qprint -d"
DECODE_B64="/usr/bin/base64 -D"
fi
#
# 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
part1=$(printf "$word" | $CUT -f 1 -d '?')
part5=$(printf "$word" | $CUT -f 5- -d '?')
if [ "$part1" != "=" -o "$part5" != "=" ]; then return 1; fi
#
# 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="$*"
prefix=""
suffix=""
# Manage possible initial and final parentheses
while [ $(LANG=C expr "_$word" : '_[()]') != 0 ]; do
prefix="${prefix}${word:0:1}"
word="${word:1}"
done
while [ $(LANG=C expr "_$word" : '_.*[()]$') != 0 ]; do
suffix="${word: -1}${suffix}"
word="${word:0: -1}"
done
if decode_word "$word"; then
word="${prefix}${VARY}${suffix}"
if [ "$STATUS" = "normal" ]; then
DECODED_LINE="${DECODED_LINE} "
elif [ "$STATUS" != "none" -a -n "${prefix}" ]; then
DECODED_LINE="${DECODED_LINE} "
fi
DECODED_LINE="${DECODED_LINE}${word}"
if [ -n "${suffix}" ]; then
STATUS="normal"
else
STATUS="decoded-word"
fi
else
word="${prefix}${word}${suffix}"
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.
#
if [ "$*" = "" ]; then
manage_file "-"
else
for file in "$@"; do
manage_file "$file"
done
fi
flush_line
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
M.V.
Olivier Miakinen a suggéré en date du 18 octobre 2019 :
#!/bin/bash
********** MV$ echo "From: Arvo =?UTF-8?Q?Pärt?= " | /usr/local/bin/olivier2.sh From: Arvo Pärt ********** Ça a donc l'air de fonctionner. ;-) Mais : ********** MV$ echo "Organization: =?NF_Z_62-010_(1973)?Q?C'{tait_o|_d{??=" | /usr/local/bin/olivier2.sh Organization: =?NF_Z_62-010_(1973)?Q?C'{tait_o|_d{?? ********** C'est donc raté pour ce charset (NB mon iconv ne reconnaît pas ce charset). Maintenant, comment je fais pour tester avec un texte du genre de celui que tu as donné en exemple ? -- Michel VAUQUOIS - http://michelvauquois.fr
Olivier Miakinen a suggéré en date du 18 octobre 2019 :
#!/bin/bash
**********
MV$ echo "From: Arvo =?UTF-8?Q?Pärt?= <arvo@part.org>" | /usr/local/bin/olivier2.sh
From: Arvo Pärt <arvo@part.org>
**********
Olivier Miakinen a suggéré en date du 18 octobre 2019 :
#!/bin/bash
********** MV$ echo "From: Arvo =?UTF-8?Q?Pärt?= " | /usr/local/bin/olivier2.sh From: Arvo Pärt ********** Ça a donc l'air de fonctionner. ;-) Mais : ********** MV$ echo "Organization: =?NF_Z_62-010_(1973)?Q?C'{tait_o|_d{??=" | /usr/local/bin/olivier2.sh Organization: =?NF_Z_62-010_(1973)?Q?C'{tait_o|_d{?? ********** C'est donc raté pour ce charset (NB mon iconv ne reconnaît pas ce charset). Maintenant, comment je fais pour tester avec un texte du genre de celui que tu as donné en exemple ? -- Michel VAUQUOIS - http://michelvauquois.fr
Elephant Man
Le 18/10/2019 à 11:24, Olivier Miakinen a écrit :
#!/bin/bash #################################################################### # Name: # decode_headers # # Description: # Script used for decoding RFC 2047 MIME encoded headers.
Et sinon, tu connais le Python aussi un peu ? :)
Le 18/10/2019 à 11:24, Olivier Miakinen a écrit :
#!/bin/bash
####################################################################
# Name:
# decode_headers
#
# Description:
# Script used for decoding RFC 2047 MIME encoded headers.
#!/bin/bash #################################################################### # Name: # decode_headers # # Description: # Script used for decoding RFC 2047 MIME encoded headers.
Et sinon, tu connais le Python aussi un peu ? :)
Très peu, mais j'ai déjà écrit quelques scripts qui fonctionnent en lisant la doc. C'est vrai que je devrais peut-être essayer d'écrire tout ça en python plutôt qu'en bash, déjà ça aurait plus de chances de donner les mêmes résultats sur Mac que sur GNU/Linux (et pourquoi pas Windows, soyons fou). -- Olivier Miakinen
Le 18/10/2019 11:41, Elephant Man a écrit :
Le 18/10/2019 à 11:24, Olivier Miakinen a écrit :
#!/bin/bash
####################################################################
# Name:
# decode_headers
#
# Description:
# Script used for decoding RFC 2047 MIME encoded headers.
Et sinon, tu connais le Python aussi un peu ? :)
Très peu, mais j'ai déjà écrit quelques scripts qui fonctionnent en
lisant la doc. C'est vrai que je devrais peut-être essayer d'écrire
tout ça en python plutôt qu'en bash, déjà ça aurait plus de chances
de donner les mêmes résultats sur Mac que sur GNU/Linux (et pourquoi
pas Windows, soyons fou).
#!/bin/bash #################################################################### # Name: # decode_headers # # Description: # Script used for decoding RFC 2047 MIME encoded headers.
Et sinon, tu connais le Python aussi un peu ? :)
Très peu, mais j'ai déjà écrit quelques scripts qui fonctionnent en lisant la doc. C'est vrai que je devrais peut-être essayer d'écrire tout ça en python plutôt qu'en bash, déjà ça aurait plus de chances de donner les mêmes résultats sur Mac que sur GNU/Linux (et pourquoi pas Windows, soyons fou). -- Olivier Miakinen
josephb
Olivier Miakinen <om+ écrivit :
C'est vrai que je devrais peut-être essayer d'écrire tout ça en python plutôt qu'en bash, déjà ça aurait plus de chances de donner les mêmes résultats sur Mac que sur GNU/Linux (et pourquoi pas Windows, soyons fou).
Partant sans doute du principe que c'est dans les vieux pots qu'on fait la bonne soupe, les Python, Ruby ou Perl livrés avec l'OS X courant ont toujours plusieurs versions de retard. Et à partir de Catalina, Apple ne livrera plus ces langages, il faudra se les installer soi-même. -- J. B.
Olivier Miakinen <om+news@miakinen.net> écrivit :
C'est vrai que je devrais peut-être essayer d'écrire
tout ça en python plutôt qu'en bash, déjà ça aurait plus de chances
de donner les mêmes résultats sur Mac que sur GNU/Linux (et pourquoi
pas Windows, soyons fou).
Partant sans doute du principe que c'est dans les vieux pots qu'on fait
la bonne soupe, les Python, Ruby ou Perl livrés avec l'OS X courant ont
toujours plusieurs versions de retard.
Et à partir de Catalina, Apple ne livrera plus ces langages, il faudra
se les installer soi-même.
C'est vrai que je devrais peut-être essayer d'écrire tout ça en python plutôt qu'en bash, déjà ça aurait plus de chances de donner les mêmes résultats sur Mac que sur GNU/Linux (et pourquoi pas Windows, soyons fou).
Partant sans doute du principe que c'est dans les vieux pots qu'on fait la bonne soupe, les Python, Ruby ou Perl livrés avec l'OS X courant ont toujours plusieurs versions de retard. Et à partir de Catalina, Apple ne livrera plus ces langages, il faudra se les installer soi-même. -- J. B.
Olivier Miakinen
Le 18/10/2019 14:54, Joseph-B a écrit :
Olivier Miakinen <om+ wrote:
ICONV="/usr/bin/iconv"
Pour ton information "Mac", son iconv du bash, ou du zsh, (iconv -l) connaît les encodages suivants : [...]
Merci pour ça. Et pour ta propre information, la transformation que me fait le NF_Z_62-010_(1973) semble correspondre exactement à ce que faisait le petit switch sur un Apple II que j'avais dans les années 1980, basculant entre US-ASCII et une version francisée ! -- Olivier Miakinen
Le 18/10/2019 14:54, Joseph-B a écrit :
Olivier Miakinen <om+news@miakinen.net> wrote:
ICONV="/usr/bin/iconv"
Pour ton information "Mac", son iconv du bash, ou du zsh, (iconv -l) connaît les encodages suivants :
[...]
Merci pour ça. Et pour ta propre information, la transformation que me fait
le NF_Z_62-010_(1973) semble correspondre exactement à ce que faisait le
petit switch sur un Apple II que j'avais dans les années 1980, basculant
entre US-ASCII et une version francisée !
Pour ton information "Mac", son iconv du bash, ou du zsh, (iconv -l) connaît les encodages suivants : [...]
Merci pour ça. Et pour ta propre information, la transformation que me fait le NF_Z_62-010_(1973) semble correspondre exactement à ce que faisait le petit switch sur un Apple II que j'avais dans les années 1980, basculant entre US-ASCII et une version francisée ! -- Olivier Miakinen