summaryrefslogtreecommitdiff
path: root/src/server/URLEncoding.hs
diff options
context:
space:
mode:
authorhallgren <hallgren@chalmers.se>2013-06-13 08:23:48 +0000
committerhallgren <hallgren@chalmers.se>2013-06-13 08:23:48 +0000
commitbdfd663e917b0d5ed1a2d987f2f470c682969dd3 (patch)
treeceb77c63bc99dbcb0a1a38322d5ef8a9fbc94486 /src/server/URLEncoding.hs
parent51ece66688cbbb9295126bdc99303b631ef0dacb (diff)
Fix UTF-8 decoding problem in gf -server
The package network-2.4.1.1 thoughlessly introduced a backward incompatible change to the function Network.URI.unEscapeString, see https://github.com/haskell/network/commit/f2168b1f8978b4ad9c504e545755f0795ac869ce This also affects the function Network.Shed.Httpd.queryToArguments, which is used in GFServer.hs. To remain compatible with older and newer versions of the network package, we need to stay clear of queryToArguments and unEscapeString. A replacement function has been added to server/URLEncoding.hs.
Diffstat (limited to 'src/server/URLEncoding.hs')
-rw-r--r--src/server/URLEncoding.hs47
1 files changed, 45 insertions, 2 deletions
diff --git a/src/server/URLEncoding.hs b/src/server/URLEncoding.hs
index ad5fb0dd9..881ca21cd 100644
--- a/src/server/URLEncoding.hs
+++ b/src/server/URLEncoding.hs
@@ -1,9 +1,9 @@
-module URLEncoding where
+module URLEncoding(urlDecodeUnicode,decodeQuery) where
import Data.Bits (shiftL, (.|.))
import Data.Char (chr,digitToInt,isHexDigit)
-
+-- | Decode hexadecimal escapes
urlDecodeUnicode :: String -> String
urlDecodeUnicode [] = ""
urlDecodeUnicode ('%':'u':x1:x2:x3:x4:s)
@@ -16,3 +16,46 @@ urlDecodeUnicode ('%':x1:x2:s) | isHexDigit x1 && isHexDigit x2 =
chr ( digitToInt x1 `shiftL` 4
.|. digitToInt x2) : urlDecodeUnicode s
urlDecodeUnicode (c:s) = c : urlDecodeUnicode s
+
+--------------------------------------------------------------------------------
+
+type Query = [(String,String)]
+
+-- | Decode application/x-www-form-urlencoded
+decodeQuery :: String -> Query
+decodeQuery = map (aboth decode . breakAt '=') . chopList (breakAt '&')
+
+aboth f (x,y) = (f x,f y)
+
+-- | Decode "+" and hexadecimal escapes
+decode [] = []
+decode ('%':'u':d1:d2:d3:d4:cs)
+ | all isHexDigit [d1,d2,d3,d4] = chr(fromhex4 d1 d2 d3 d4):decode cs
+decode ('%':d1:d2:cs)
+ | all isHexDigit [d1,d2] = chr(fromhex2 d1 d2):decode cs
+decode ('+':cs) = ' ':decode cs
+decode (c:cs) = c:decode cs
+
+fromhex4 d1 d2 d3 d4 = 256*fromhex2 d1 d2+fromhex2 d3 d4
+fromhex2 d1 d2 = 16*digitToInt d1+digitToInt d2
+
+
+-- From hbc-library ListUtil ---------------------------------------------------
+
+-- Repeatedly extract (and transform) values until a predicate hold. Return the list of values.
+unfoldr :: (a -> (b, a)) -> (a -> Bool) -> a -> [b]
+unfoldr f p x | p x = []
+ | otherwise = y:unfoldr f p x'
+ where (y, x') = f x
+
+chopList :: ([a] -> (b, [a])) -> [a] -> [b]
+chopList f l = unfoldr f null l
+
+breakAt :: (Eq a) => a -> [a] -> ([a], [a])
+breakAt _ [] = ([], [])
+breakAt x (x':xs) =
+ if x == x' then
+ ([], xs)
+ else
+ let (ys, zs) = breakAt x xs
+ in (x':ys, zs)