module URLencode(Query,encodeQuery,encode, -- ** Helper functions hex4,hex ) where import Data.Char(chr,ord) import Data.List(intercalate) --import Utils2(mix,chr,ord) import URLQuery {- $doc Spaces, and other special characters, are not allowed in URLs, so there is an escape mechanism to represent them. -} -- | The function 'encode' converts a string by escaping special characters, -- returning a string suitable for use in a URL. -- The function 'URLdecode.decode' undoes the effect of 'encode'. encode :: String -> String encode = concatMap enc where unreserved c = 'a'<=c && c<= 'z' || 'A'<=c && c<='Z' || '0'<=c && c<='9' special c = c<' ' || c>'~' || c `elem` "\"<>&=%/?#+:()[]{}~" -- more? enc ' ' = "+" enc c | unreserved c || not (special c) = [c] -- speedup | otherwise = '%':hex4 (ord c) {- | When the contents of a form (here referred to as a /query/) is submitted to a web server, it is encoded as a sequence of pairs of field names and values in the following way: @ field_1=value_1&...&field_n=value_n @ Special characters, like @=@, @&@ and spaces, occuring in the field names and values, are escaped, as with the function 'encode'. The functions 'encodeQuery' and 'URLdecode.decodeQuery' convert to and from the above form, applying 'encode' and 'decode', respectively, to the parts of the query. Examples > encode "Sixth Sense, The (1999)" = "Sixth+Sense%2C+The+%281999%29" > deocdeQuery "year=1999&actor=Willis%2C+Bruce" = > [("year","1999"),("actor","Willis, Bruce")] -} encodeQuery :: Query -> String encodeQuery values = intercalate "&" (map urlEnc values) where urlEnc (name,value) = encode name ++ "=" ++ encode value -- ** Helper functions -- | Generates @uXXXX@ (a backwards compatible non-standard extension) -- for characters codes 256-65535, @XX@ for 0..255. hex4 n = if n<256 then hex n else 'u':hex (n `div` 256)++hex (n `rem` 256) -- | Generates @XX@ (two hexadecimal digits) representing character -- codes 0..255. hex n = [hexdigit (n `div` 16),hexdigit (n `rem` 16)] where hexdigit n = if n<10 then chr(n+ord '0') else chr(n+(ord 'A'-10))