quoted-printable

Richard Suchenwirth 2004-05-12 - "Quoted-printable" is a way of encoding 8-bit characters by using only 7-bit ASCII characters, by replacing them with =XX, XX being two hex digits. This is used for instance in MIME mail attachments ( http://www.faqs.org/rfcs/rfc2045.html has many details). Decoding this type of data goes in a one-liner with subst:

 proc quoted-printable s {subst -nocom -novar [string map {\\ \\\\ =\n "" = \\u00} $s]}

The other way it seems to need explicit iteration:

 proc to-quoted-printable s {
    set res ""
    foreach char [split $s ""] {
        scan $char %c i
        if {$i>255} {error "character $i does not fit in 8 bits"}
        append res [expr {$i<128? $char: [format =%02X $i]}]
    }
    set res
 }
# Test and demo:
 % to-quoted-printable "Schöne Grüße"
 Sch=F6ne Gr=FC=DFe

Note that \u00XX was used in the decoder in place of \xXX, which is "greedy" and takes as many hex characters as it can get, working only on the last two of them.

Lars H: I added a doubling of the backslashes in [quoted-printable], to prevent unwanted substitutions. Also, I think [to-quoted-printable] should quote = as well as the non-ASCII characters.

For moderately long texts, it should be better to do it as follows

 proc to-quoted-printable s {
    set QP [list = =3D]
    for {set i 128} {$i<256} {incr i} {
       lappend QP [format %c $i] [format =%02X $i]
    }
    return [string map $QP $s]
 }

daapp: I found that package mime v1.3.6 from tcllib1.6 contain two undocumented, but very useful procedures: mime::word_encode and mime::word_decode which encode and decode string as described in MIME -- Multipurpose Internet Mail Extensions part three. Example:

    foreach {charset encoding decodedString} [mime::decode encodedString] break
    set originalString [encoding convertfrom $charset $decodedString]

Where:

  • charset - name of charset of decodedString.
  • encoding - base64 or quoted-printable
  • decodedString - you know

After decoding you need to convert string to specified charset.