@@ -29,6 +29,10 @@ import Data.Function (on)
2929import System.Directory (removeFile, getTemporaryDirectory)
3030import System.IO (hClose, openBinaryTempFile, Handle)
3131import Network.Wai
32+import Control.Applicative ((<$>))
33+import Data.Enumerator (($$), Iteratee)
34+import qualified Data.Enumerator as E
35+import Control.Monad.IO.Class (liftIO)
3236
3337uncons :: S.ByteString -> Maybe (Word8, S.ByteString)
3438uncons s
@@ -177,80 +181,54 @@ parseRequestBody sink req = do
177181 -- NOTE: in general, url-encoded data will be in a single chunk.
178182 -- Therefore, I'm optimizing for the usual case by sticking with
179183 -- strict byte strings here.
180− bs <- sourceToBs $ requestBody req
181− return (parseQueryString bs, [])
184+ bs <- E.run_ $ requestBody req $$ E.consume
185+ return (parseQueryString $ S.concat bs, [])
182186 Just (Just bound) -> -- multi-part
183187 let bound' = S8.pack "--" `S.append` bound
184− in parsePieces sink bound' (S.empty, Just $ requestBody req)
188+ in error "FIXME" parsePieces sink bound' (S.empty, Just $ requestBody req)
185189 where
186190 urlenc = S8.pack "application/x-www-form-urlencoded"
187191 formBound = S8.pack "multipart/form-data; boundary="
188192
189−sourceToBs :: Source -> IO S.ByteString
190−sourceToBs = fmap S.concat . go id
191− where
192− go front (Source src) = do
193− res <- src
194− case res of
195− Nothing -> return $ front []
196− Just (bs, src') -> go (front . (:) bs) src'
197−
198−type Source' = (S.ByteString, Maybe Source)
199−
200−takeLine :: Source' -> IO (Maybe (S.ByteString, Source'))
201−takeLine (s, msrc)
202− | S.null s = case msrc of
203− Nothing -> return Nothing
204− Just (Source src) -> do
205− res <- src
206− case res of
207− Nothing -> return Nothing
208− Just (x, y) -> takeLine (x, Just y)
209−takeLine (s, msrc) =
210− let (x, y) = S.break (== 10) s -- newline
211− in if S.null y
212− then do
213− case msrc of
214− Nothing -> return $ Just (x, (y, msrc))
215− Just (Source src) -> do
216− res <- src
217− case res of
218− Nothing -> return $ Just (x, (y, Nothing))
219− Just (s', src') ->
220− takeLine (s `S.append` s', Just src')
221− else return $ Just (killCarriage x, (S.drop 1 y, msrc))
193+takeLine :: Iteratee S.ByteString IO (Maybe S.ByteString)
194+takeLine = do
195+ mbs <- E.head
196+ case mbs of
197+ Nothing -> return Nothing
198+ Just bs ->
199+ let (x, y) = S.break (== 10) bs -- LF
200+ in if S.null y
201+ then do
202+ x' <- takeLine
203+ case x' of
204+ Nothing -> return $ Just x
205+ Just x'' -> return $ Just $ S.append x x''
206+ else do
207+ E.yield () $ E.Chunks [S.drop 1 y]
208+ return $ Just $ killCarriage x
222209 where
223210 killCarriage bs
224211 | S.null bs = bs
225212 | S.last bs == 13 = S.init bs -- carriage return
226213 | otherwise = bs
227214
228−takeLines :: Source' -> IO (Maybe ([S.ByteString], Source'))
229−takeLines src = do
230− res <- takeLine src
215+takeLines :: Iteratee S.ByteString IO [S.ByteString]
216+takeLines = do
217+ res <- takeLine
231218 case res of
232− Nothing -> return Nothing
233− Just (l, src') ->
234− if S.null l
235− then return $ Just ([], src')
236− else do
237− res' <- takeLines src'
238− case res' of
239− Nothing -> return $ Just ([l], src')
240− Just (ls, src'') -> return $ Just (l : ls, src'')
219+ Nothing -> return []
220+ Just l -> do
221+ ls <- takeLines
222+ return $ l : ls
241223
242−parsePieces :: Sink x y -> S.ByteString -> Source'
243− -> IO ([Param], [File y])
244−parsePieces sink bound src = do
245− res <- takeLine src
246− src' <- case res of
247− Nothing -> return (S.empty, Nothing)
248− -- The _bs here should only contain boundary information
249− Just (_bs, src') -> return src'
250− res' <- takeLines src'
224+parsePieces :: Sink x y -> S.ByteString
225+ -> Iteratee S.ByteString IO ([Param], [File y])
226+parsePieces sink bound = do
227+ _boundLine <- takeLine
228+ res' <- takeLines
251229 case res' of
252− Nothing -> return ([], [])
253− Just (ls, src'') -> do
230+ [] -> return ([], [])
231+ ls -> do
254232 let ls' = map parsePair ls
255233 let x = do
256234 cd <- lookup contDisp ls'
@@ -263,37 +241,36 @@ parsePieces sink bound src = do
263241 case x of
264242 Just (mct, name, Just filename) -> do
265243 let ct = fromMaybe "application/octet-stream" mct
266− seed <- sinkInit sink
267− (seed', wasFound, msrc''') <-
268− sinkTillBound bound src'' (sinkAppend sink) seed
269− y <- sinkClose sink seed'
244+ seed <- liftIO $ sinkInit sink
245+ (seed', wasFound) <-
246+ sinkTillBound bound (sinkAppend sink) seed
247+ y <- liftIO $ sinkClose sink seed'
270248 let fi = FileInfo filename ct y
271249 let y' = (name, fi)
272250 (xs, ys) <-
273251 if wasFound
274− then parsePieces sink bound msrc'''
252+ then parsePieces sink bound
275253 else return ([], [])
276254 return (xs, y' : ys)
277255 Just (_ct, name, Nothing) -> do
278256 let seed = id
279257 let iter front bs = return $ front . (:) bs
280− (front, wasFound, msrc''') <-
281− sinkTillBound bound src'' iter seed
258+ (front, wasFound) <-
259+ sinkTillBound bound iter seed
282260 let bs = S.concat $ front []
283261 let x' = (name, qsDecode bs)
284262 (xs, ys) <-
285263 if wasFound
286− then parsePieces sink bound msrc'''
264+ then parsePieces sink bound
287265 else return ([], [])
288266 return (x' : xs, ys)
289267 _ -> do
290268 -- ignore this part
291269 let seed = ()
292270 iter () _ = return ()
293− ((), wasFound, msrc''') <-
294− sinkTillBound bound src'' iter seed
271+ ((), wasFound) <- sinkTillBound bound iter seed
295272 if wasFound
296− then parsePieces sink bound msrc'''
273+ then parsePieces sink bound
297274 else return ([], [])
298275 where
299276 contDisp = S8.pack "Content-Disposition"
@@ -325,11 +302,11 @@ findBound b bs = go [0..S.length bs - 1]
325302 | otherwise = True
326303
327304sinkTillBound :: S.ByteString
328− -> Source'
329305 -> (x -> S.ByteString -> IO x)
330306 -> x
331− -> IO (x, Bool, Source')
332−sinkTillBound bound (bs, msrc) iter seed = do
307+ -> Iteratee S.ByteString IO (x, Bool)
308+sinkTillBound bound iter seed = error "FIXME"
309+{-
333310 case findBound bound bs of
334311 NoBound -> do
335312 case msrc of
@@ -375,6 +352,7 @@ sinkTillBound bound (bs, msrc) iter seed = do
375352 Just (bs', src') -> do
376353 let bs'' = bs `S.append` bs'
377354 sinkTillBound bound (bs'', Just src') iter seed
355+-}
378356
379357parseAttrs :: S.ByteString -> [(S.ByteString, S.ByteString)]
380358parseAttrs = map go . S.split 59 -- semicolon