From 41a85f826ce15708d93c0cc9095ac778a80060b6 Mon Sep 17 00:00:00 2001 From: Sigbjorn Finne Date: Sun, 14 Sep 2008 10:39:59 -0700 Subject: added encoder + recognize soft line breaks on the decoding side --- Codec/MIME/QuotedPrintable.hs | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/Codec/MIME/QuotedPrintable.hs b/Codec/MIME/QuotedPrintable.hs index d6c058e..72fbaa6 100644 --- a/Codec/MIME/QuotedPrintable.hs +++ b/Codec/MIME/QuotedPrintable.hs @@ -11,15 +11,51 @@ -------------------------------------------------------------------- -module Codec.MIME.QuotedPrintable where +module Codec.MIME.QuotedPrintable + ( decode -- :: String -> String + , encode -- :: String -> String + ) where import Data.Char +-- | 'decode' incoming quoted-printable content, stripping +-- out soft line breaks and decode :: String -> String decode "" = "" +decode ('=':'\r':'\n':xs) = decode xs -- soft line break. decode ('=':x1:x2:xs) | isHexDigit x1 && isHexDigit x2 = chr (digitToInt x1 * 16 + digitToInt x2) : decode xs decode ('=':xs) = '=':decode xs -- make it explicit that we propagate other '=' occurrences. decode (x1:xs) = x1:decode xs + +-- | 'encode' converts a sequence of characeter _octets_ into +-- quoted-printable form; suitable for transmission in MIME +-- payloads. Note the stress on _octets_; it is assumed that +-- you have already converted Unicode into a <=8-bit encoding +-- (UTF-8, most likely.) +encode :: String -> String +encode xs = encodeLength 0 xs + +encodeLength :: Int -> String -> String +encodeLength _ "" = "" +encodeLength n ('=':xs) + | n <= 72 = '=':'3':'D':encodeLength (n+3) xs + | otherwise = '=':'\r':'\n': encodeLength 0 ('=':xs) +encodeLength n (x:xs) + | n >= 75 = '=':'\r':'\n':encodeLength 0 (x:xs) + | ox >= 0x21 && ox <= 0x7e = x : encodeLength (n+1) xs + | (ox == 0x09 || ox == 0x20) && n < 74 = x : encodeLength (n+1) xs + | ox >= 0x100 = error ("QuotedPrintable.encode: encountered > 8 bit character: " ++ show (x,ox)) + + | n <= 72 = '=':showH (ox `div` 16) : showH (ox `mod` 16) : encodeLength (n+3) xs + | otherwise = '=':'\r':'\n':encodeLength 0 (x:xs) + where + ox = ord x + showH v + | v < 10 = chr (ord_0 + v) + | otherwise = chr (ord_A + (v-10)) + + ord_0 = ord '0' + ord_A = ord 'A' -- cgit v1.2.3