5 -- |Provide facilities to encode/decode MIME parameter values in
6 -- character sets other than US-ASCII. See:
7 -- http://www.faqs.org/rfcs/rfc2231.html
8 module Network.HTTP.Lucu.RFC2231
13 import Data.Ascii (Ascii, CIAscii, AsciiBuilder)
14 import qualified Data.Ascii as A
16 import qualified Data.ByteString.Char8 as BS
18 import qualified Data.Map as M
19 import Data.Monoid.Unicode
20 import Data.Text (Text)
21 import qualified Data.Text as T
22 import Data.Text.Encoding
24 import Network.HTTP.Lucu.Parser.Http
25 import Network.HTTP.Lucu.Utils
26 import Prelude.Unicode
28 printParams ∷ Map CIAscii Text → AsciiBuilder
31 | otherwise = A.toAsciiBuilder "; " ⊕
32 joinWith "; " (map printPair $ M.toList params)
34 printPair ∷ (CIAscii, Text) → AsciiBuilder
35 printPair (name, value)
36 | T.any (> '\xFF') value
37 = printPairInUTF8 name value
39 = printPairInAscii name (A.unsafeFromByteString $ encodeUtf8 value)
41 printPairInUTF8 ∷ CIAscii → Text → AsciiBuilder
42 printPairInUTF8 name value
43 = A.toAsciiBuilder (A.fromCIAscii name) ⊕
44 A.toAsciiBuilder "*=utf-8''" ⊕
45 escapeUnsafeChars (encodeUtf8 value) (∅)
47 printPairInAscii ∷ CIAscii → Ascii → AsciiBuilder
48 printPairInAscii name value
49 = A.toAsciiBuilder (A.fromCIAscii name) ⊕
50 A.toAsciiBuilder "=" ⊕
51 if BS.any ((¬) ∘ isToken) (A.toByteString value) then
54 A.toAsciiBuilder value
56 escapeUnsafeChars ∷ BS.ByteString → AsciiBuilder → AsciiBuilder
57 escapeUnsafeChars bs b
58 = case BS.uncons bs of
61 | isToken c → escapeUnsafeChars bs' $
62 b ⊕ A.toAsciiBuilder (A.unsafeFromString [c])
63 | otherwise → escapeUnsafeChars bs' $
64 b ⊕ toHex (fromIntegral $ fromEnum c)
66 toHex ∷ Word8 → AsciiBuilder
67 toHex o = A.toAsciiBuilder "%" ⊕
68 A.toAsciiBuilder (A.unsafeFromString [ toHex' (o `shiftR` 8)
69 , toHex' (o .&. 0x0F) ])
73 | o ≤ 0x09 = toEnum $ fromIntegral $ fromEnum '0' + fromIntegral o
74 | otherwise = toEnum $ fromIntegral $ fromEnum 'A' + fromIntegral (o - 0x0A)
77 decode ∷ [(CIAscii, Ascii)] → Map CIAscii Text
78 {-# INLINEABLE decode #-}
79 decode = error "FIXME: not implemented"