module Network.HTTP.Encoding.Character
(getContentTypeAndCharacterEncoding
,setCharacterEncoding
,tryAsUTF8) where
import Network.HTTP
import Codec.Text.IConv
import Codec.MIME.Parse
import Codec.MIME.Type
import Control.Applicative hiding (many, (<|>))
import Data.Char (toLower, ord)
import Data.ByteString.Lazy.UTF8 (uncons)
import Data.ByteString.Lazy (ByteString)
import Control.Monad
getContentTypeAndCharacterEncoding :: [Header] ->
(Maybe Type, Maybe EncodingName)
getContentTypeAndCharacterEncoding [] = (Nothing, Nothing)
getContentTypeAndCharacterEncoding (Header HdrContentType str:_) =
parseContentTypeHdr str
getContentTypeAndCharacterEncoding (_:hs) = getContentTypeAndCharacterEncoding hs
setCharacterEncoding :: EncodingName -> [Header] -> [Header]
setCharacterEncoding enc [] = [plainText enc]
setCharacterEncoding enc ((Header HdrContentType str):rest) =
let (mtype, _) = parseContentTypeHdr str
newhdr = case mtype of
Nothing -> plainText enc
Just ty -> Header HdrContentType $ showType $ setMIMEEncoding ty enc
in newhdr:rest
plainText :: EncodingName -> Header
plainText enc = Header HdrContentType $ showType $
Type {mimeType = (Text "plain")
,mimeParams = [("charset", enc)]}
setMIMEEncoding :: Type -> EncodingName -> Type
setMIMEEncoding ty enc = ty {mimeParams = map replaceEnc $ mimeParams ty}
where replaceEnc (pname, _) | pname == "charset" = (pname, enc)
replaceEnc x = x
parseContentTypeHdr :: String -> (Maybe Type, Maybe EncodingName)
parseContentTypeHdr str =
case parseContentType str of
Nothing -> (Nothing, Nothing)
Just ctype -> (Just ctype,
(map toLower) <$> lookup "charset" (mimeParams ctype))
tryAsUTF8 :: ByteString -> Maybe String
tryAsUTF8 bs = uncons bs >>= \(c, bs') ->
if (ord c == 0xFFFD) then mzero
else tryAsUTF8 bs' >>= \s -> return (c:s)