module Network.HTTP.Server.HtmlForm
( FormFields
, fieldNames, hasField
, lookupString, lookupRead
, toList
, fromRequest
) where
import qualified Data.Text as T
import Codec.MIME.Parse
import Codec.MIME.Type
import Network.HTTP
import Codec.Binary.UTF8.String as UTF8
import Data.Char(isSpace)
newtype FormFields = FF [(String,String)] deriving Show
fieldNames :: FormFields -> [String]
fieldNames (FF xs) = map fst xs
hasField :: FormFields -> String -> Bool
hasField (FF xs) x = x `elem` map fst xs
lookupString :: FormFields -> String -> Maybe String
lookupString (FF xs) x = (drop_r . UTF8.decodeString) `fmap` lookup x xs
where drop_r ('\r' : '\n' : cs) = '\n' : drop_r cs
drop_r (c:cs) = c : drop_r cs
drop_r [] = []
lookupRead :: Read a => FormFields -> String -> Maybe a
lookupRead xs x = do y <- lookupString xs x
case reads y of
[(n,cs)] | all isSpace cs -> return n
_ -> Nothing
toList :: FormFields -> [(String,String)]
toList (FF xs) = xs
fromRequest :: Request String -> Maybe FormFields
fromRequest r = let mv = mime_request r
in case mimeType (mime_val_type mv) of
Multipart FormData -> Just (FF (toMap mv))
_ -> Nothing
where toMap mv = case mime_val_content mv of
Multi vs -> concatMap toMap vs
Single v -> [ (T.unpack k,T.unpack v)
| k <- keys (mime_val_disp mv) ]
keys (Just x) = [ k | Name k <- dispParams x ]
keys Nothing = []
mime_request :: Request String -> MIMEValue
mime_request req
= let hdrs = map (\ (Header a b) -> MIMEParam { paramName = T.pack (show a), paramValue = T.pack b }) (rqHeaders req)
body = T.pack $ rqBody req
in parseMIMEBody hdrs body