X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FMultipartForm.hs;h=8d09d701fbe460a37059c6ed196e99b06d0f855d;hb=dfc778742934b8f2ac6a6709741c79ecd40c5ff1;hp=4dcf076c93c13be34f7fd3bc0986f24652601616;hpb=02d702c138d918386135245021d5778676ee6d0e;p=Lucu.git diff --git a/Network/HTTP/Lucu/MultipartForm.hs b/Network/HTTP/Lucu/MultipartForm.hs index 4dcf076..8d09d70 100644 --- a/Network/HTTP/Lucu/MultipartForm.hs +++ b/Network/HTTP/Lucu/MultipartForm.hs @@ -1,8 +1,8 @@ {-# LANGUAGE DoAndIfThenElse , OverloadedStrings + , RecordWildCards , ScopedTypeVariables - , UnboxedTuples , UnicodeSyntax #-} module Network.HTTP.Lucu.MultipartForm @@ -11,20 +11,19 @@ module Network.HTTP.Lucu.MultipartForm ) where import Control.Applicative hiding (many) -import Data.Ascii (Ascii, CIAscii, AsciiBuilder) +import Data.Ascii (Ascii, CIAscii) import qualified Data.Ascii as A import Data.Attoparsec.Char8 import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy.Char8 as LS -import Data.Char -import Data.List +import Data.Map (Map) +import qualified Data.Map as M import Data.Maybe import Data.Monoid.Unicode import Data.Text (Text) -import Network.HTTP.Lucu.Headers -import Network.HTTP.Lucu.Parser.Http -import Network.HTTP.Lucu.Response -import Network.HTTP.Lucu.Utils +import Network.HTTP.Lucu.Headers +import Network.HTTP.Lucu.Parser.Http +import Network.HTTP.Lucu.RFC2231 import Prelude.Unicode -- |This data type represents a form value and possibly an uploaded @@ -49,7 +48,7 @@ instance HasHeaders Part where data ContDispo = ContDispo { dType ∷ !CIAscii - , dParams ∷ ![(CIAscii, Ascii)] + , dParams ∷ !(Map CIAscii Text) } printContDispo ∷ ContDispo → Ascii @@ -57,25 +56,11 @@ printContDispo d = A.fromAsciiBuilder $ ( A.toAsciiBuilder (A.fromCIAscii $ dType d) ⊕ - ( if null $ dParams d then - (∅) - else - A.toAsciiBuilder "; " ⊕ - joinWith "; " (map printPair $ dParams d) ) ) - where - printPair ∷ (CIAscii, Ascii) → AsciiBuilder - printPair (name, value) - = A.toAsciiBuilder (A.fromCIAscii name) ⊕ - A.toAsciiBuilder "=" ⊕ - ( if BS.any ((¬) ∘ isToken) $ A.toByteString value then - quoteStr value - else - A.toAsciiBuilder value ) + printParams (dParams d) ) multipartFormP ∷ Ascii → Parser [(Text, FormData)] multipartFormP boundary - = try $ - do parts ← many (partP boundary) + = do parts ← many $ try $ partP boundary _ ← string "--" _ ← string $ A.toByteString boundary _ ← string "--" @@ -84,8 +69,7 @@ multipartFormP boundary partP ∷ Ascii → Parser Part partP boundary - = try $ - do _ ← string "--" + = do _ ← string "--" _ ← string $ A.toByteString boundary crlf hs ← headersP @@ -95,8 +79,7 @@ partP boundary bodyP ∷ Ascii → Parser LS.ByteString bodyP boundary - = try $ - do body ← manyCharsTill anyChar $ + = do body ← manyCharsTill anyChar $ try $ do crlf _ ← string "--" @@ -121,18 +104,18 @@ partToFormPair pt partName ∷ Monad m ⇒ Part → m Text {-# INLINEABLE partName #-} -partName pt - = case find ((≡ "name") ∘ fst) $ dParams $ ptContDispo pt of - Just (_, name) +partName (Part {..}) + = case M.lookup "name" $ dParams ptContDispo of + Just name → return name Nothing → fail ("form-data without name: " ⧺ - A.toString (printContDispo $ ptContDispo pt)) + A.toString (printContDispo ptContDispo)) partFileName ∷ Part → Maybe Text {-# INLINEABLE partFileName #-} -partFileName pt - = snd <$> (find ((== "filename") ∘ fst) $ dParams $ ptContDispo pt) +partFileName (Part {..}) + = M.lookup "filename" $ dParams ptContDispo getContDispo ∷ Monad m ⇒ Headers → m ContDispo {-# INLINEABLE getContDispo #-} @@ -155,16 +138,6 @@ getContDispo hdr ]) contDispoP ∷ Parser ContDispo -contDispoP = try $ - do dispoType ← A.toCIAscii <$> token - params ← many paramP +contDispoP = do dispoType ← A.toCIAscii <$> token + params ← paramsP return $ ContDispo dispoType params - where - paramP ∷ Parser (CIAscii, Ascii) - paramP = do skipMany lws - _ ← char ';' - skipMany lws - name ← A.toCIAscii <$> token - _ ← char '=' - value ← token <|> quotedStr - return (name, value)