@@ -4,21 +4,15 @@ module Network.Wai.Parse
44 ( parseQueryString
55 ) where
66
7−import Network.Wai
87import qualified Data.ByteString as S
98import Data.Word (Word8)
109import Data.Bits
10+import Data.Maybe (fromMaybe)
1111
12−type BufferedBS = ([Word8], S.ByteString)
13−
14−uncons :: BufferedBS -> Maybe (Word8, BufferedBS)
15−uncons ((w:ws), s) = Just (w, (ws, s))
16−uncons ([], s)
12+uncons :: S.ByteString -> Maybe (Word8, S.ByteString)
13+uncons s
1714 | S.null s = Nothing
18− | otherwise = Just (S.head s, ([], S.tail s))
19−
20−cons :: Word8 -> BufferedBS -> BufferedBS
21−cons w (ws, s) = (w:ws, s)
15+ | otherwise = Just (S.head s, S.tail s)
2216
2317breakDiscard :: Word8 -> S.ByteString -> (S.ByteString, S.ByteString)
2418breakDiscard w s =
@@ -40,52 +34,28 @@ breakDiscard w s =
4034parseQueryString :: S.ByteString -> [(S.ByteString, S.ByteString)]
4135parseQueryString q | S.null q = []
4236parseQueryString q =
43− let (x, xs) = breakDiscard wand q
37+ let (x, xs) = breakDiscard 38 q -- ampersand
4438 in parsePair x : parseQueryString xs
4539 where
4640 parsePair x =
47− let (k, v) = breakDiscard wequal x
41+ let (k, v) = breakDiscard 61 x -- equal sign
4842 in (decode k, decode v)
49− decode x = fst $ S.unfoldrN (S.length x) go (NoPercent, ([], x))
50− go (state, x) =
51− case (state, uncons x) of
52− (NoPercent, Nothing) -> Nothing
53− (NoChar, Nothing) -> Just (wpercent, (NoPercent, x))
54− (OneChar (w, _), Nothing) ->
55− Just (wpercent, (NoPercent, cons w x))
56− (NoPercent, Just (w, ws)) ->
57− if w == wpercent then go (NoChar, ws)
58− else if w == wplus
59− then Just (wspace, (NoPercent, ws))
60− else Just (w, (NoPercent, ws))
61− (NoChar, Just (w, ws)) ->
62− case hexVal w of
63− Nothing -> Just (wpercent, (NoPercent, x))
64− Just v -> go (OneChar (w, v), ws)
65− (OneChar (w1, v1), Just (w2, ws)) ->
66− case hexVal w2 of
67− Nothing ->
68− Just (wpercent, (NoPercent, w1 `cons` x))
69− Just v2 -> Just (combine v1 v2, (NoPercent, ws))
70− c2w :: Char -> Word8
71− c2w = toEnum . fromEnum
72− wequal = c2w '='
73− wand = c2w '&'
74− wpercent = c2w '%'
75− w0 = c2w '0'
76− w9 = c2w '9'
77− wa = c2w 'a'
78− wf = c2w 'f'
79− wA = c2w 'A'
80− wF = c2w 'F'
81− wspace = c2w ' '
82− wplus = c2w '+'
43+ decode x = fst $ S.unfoldrN (S.length x) go x
44+ go bs =
45+ case uncons bs of
46+ Nothing -> Nothing
47+ Just (43, ws) -> Just (32, ws) -- plus to space
48+ Just (37, ws) -> Just $ fromMaybe (37, ws) $ do -- percent
49+ (x, xs) <- uncons ws
50+ x' <- hexVal x
51+ (y, ys) <- uncons xs
52+ y' <- hexVal y
53+ Just $ (combine x' y', ys)
54+ Just (w, ws) -> Just (w, ws)
8355 hexVal w
84− | w0 <= w && w <= w9 = Just $ w - w0
85− | wa <= w && w <= wf = Just $ w - wa + 10
86− | wA <= w && w <= wF = Just $ w - wA + 10
56+ | 48 <= w && w <= 57 = Just $ w - 48 -- 0 - 9
57+ | 65 <= w && w <= 70 = Just $ w - 55 -- A - F
58+ | 97 <= w && w <= 102 = Just $ w - 87 -- a - f
8759 | otherwise = Nothing
8860 combine :: Word8 -> Word8 -> Word8
8961 combine a b = shiftL a 4 .|. b
90−
91−data DecodeHelper = NoPercent | NoChar | OneChar (Word8, Word8)