1
- module Data.URI.UserInfo where
1
+ module Data.URI.UserInfo
2
+ ( UserInfo (..)
3
+ , parser
4
+ , print
5
+ )where
2
6
3
7
import Prelude
4
8
5
9
import Control.Alt ((<|>))
10
+ import Data.Foldable (foldMap )
6
11
import Data.Generic.Rep (class Generic )
7
12
import Data.Generic.Rep.Show (genericShow )
8
13
import Data.Newtype (class Newtype )
9
- import Data.URI.Common (decodePCT , joinWith , parsePCTEncoded , parseSubDelims , parseUnreserved )
10
- import Global (encodeURI )
14
+ import Data.String as Str
15
+ import Data.URI.Common (decodePCTComponent , joinWith , parsePCTEncoded , parseSubDelims , parseUnreserved )
16
+ import Global (encodeURIComponent )
11
17
import Text.Parsing.StringParser (Parser )
12
18
import Text.Parsing.StringParser.Combinators (many1 )
13
19
import Text.Parsing.StringParser.String (string )
@@ -25,9 +31,46 @@ parser ∷ Parser UserInfo
25
31
parser = UserInfo <<< joinWith " " <$> many1 p
26
32
where
27
33
p = parseUnreserved
28
- <|> parsePCTEncoded decodePCT
34
+ <|> parsePCTEncoded decodePCTComponent
29
35
<|> parseSubDelims
30
36
<|> string " :"
31
37
32
38
print ∷ UserInfo → String
33
- print (UserInfo u) = encodeURI u
39
+ print (UserInfo u) = encodeUserPassword u
40
+
41
+
42
+ encodeUserPassword :: String -> String
43
+ encodeUserPassword s = foldMap encodeChar $ Str .toCharArray s
44
+
45
+ shouldNotEscape :: Char -> Boolean
46
+ shouldNotEscape c =
47
+ {-
48
+ https://tools.ietf.org/html/rfc3986#section-3.2.1
49
+ userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
50
+
51
+ https://tools.ietf.org/html/rfc3986#section-2.1
52
+ pct-encoded = "%" HEXDIG HEXDIG
53
+
54
+ https://tools.ietf.org/html/rfc3986#section-2.3
55
+ unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
56
+
57
+ https://tools.ietf.org/html/rfc3986#section-2.1
58
+ sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
59
+ / "*" / "+" / "," / ";" / "="
60
+ -}
61
+ -- unreserved
62
+ (' A' <= c && c <= ' Z' )
63
+ || (' a' <= c && c <= ' z' )
64
+ || (' 0' <= c && c <= ' 9' )
65
+ || c == ' -' || c == ' _' || c == ' .' || c == ' ~'
66
+ -- sub-delims
67
+ || c == ' !' || c == ' $' || c == ' &' || c == ' \' '
68
+ || c == ' (' || c == ' )' || c == ' *' || c == ' +'
69
+ || c == ' ,' || c == ' ;' || c == ' ='
70
+ -- userinfo
71
+ || c == ' :'
72
+
73
+ encodeChar :: Char -> String
74
+ encodeChar c =
75
+ let cStr = Str .singleton c
76
+ in if shouldNotEscape c then cStr else encodeURIComponent cStr
0 commit comments