@@ -145,30 +145,53 @@ defmodule URI do
145
145
encode ( to_string ( k ) ) <> "=" <> encode ( to_string ( v ) )
146
146
end
147
147
148
+ # RFC3986, section 2.2
149
+ @ doc """
150
+ Returns true if the character is a "reserved" character in a URI.
151
+ """
152
+ def char_reserved? ( c ) do
153
+ c in ':/?#[]@!$&\' ()*+,;='
154
+ end
155
+
156
+ # RFC3986, section 2.3
157
+ @ doc """
158
+ Returns true if the character is a "unreserved" character in a URI.
159
+ """
160
+ def char_unreserved? ( c ) do
161
+ c in ?0 .. ?9 or
162
+ c in ?a .. ?z or
163
+ c in ?A .. ?Z or
164
+ c in '~_-.'
165
+ end
166
+
167
+ @ doc """
168
+ Returns true if the character is allowed unescaped in a URI.
169
+ """
170
+ def char_unescaped? ( c ) do
171
+ char_reserved? ( c ) or char_unreserved? ( c )
172
+ end
173
+
148
174
@ doc """
149
175
Percent-escape a URI.
176
+ Accepts `predicate` function as an argument to specify if char can be left as is.
150
177
151
178
## Example
152
179
153
- iex> URI.encode("http ://elixir-lang.org/getting_started/2.html ")
154
- "http%3A%2F%2Felixir-lang.org%2Fgetting_started%2F2.html "
180
+ iex> URI.encode("ftp ://s-ite.tld/?value=put it+й ")
181
+ "ftp://s-ite.tld/?value=put%20it+%D0%B9 "
155
182
156
183
"""
157
- def encode ( s ) , do: for ( << c <- s >> , into: "" , do: percent ( c ) )
158
-
159
- defp percent ( 32 ) , do: << ?+ >>
160
- defp percent ( ?- ) , do: << ?- >>
161
- defp percent ( ?_ ) , do: << ?_ >>
162
- defp percent ( ?. ) , do: << ?. >>
163
-
164
- defp percent ( c )
165
- when c >= ?0 and c <= ?9
166
- when c >= ?a and c <= ?z
167
- when c >= ?A and c <= ?Z do
168
- << c >>
184
+ def encode ( str , predicate \\ & char_unescaped? / 1 ) do
185
+ for << c <- str >> , into: "" , do: percent ( c , predicate )
169
186
end
170
187
171
- defp percent ( c ) , do: "%" <> hex ( bsr ( c , 4 ) ) <> hex ( band ( c , 15 ) )
188
+ defp percent ( c , predicate ) do
189
+ if predicate . ( c ) do
190
+ << c >>
191
+ else
192
+ "%" <> hex ( bsr ( c , 4 ) ) <> hex ( band ( c , 15 ) )
193
+ end
194
+ end
172
195
173
196
defp hex ( n ) when n <= 9 , do: << n + ?0 >>
174
197
defp hex ( n ) , do: << n + ?A - 10 >>
@@ -187,25 +210,22 @@ defmodule URI do
187
210
end
188
211
189
212
def decode ( << ?% , hex1 , hex2 , tail :: binary >> , uri ) do
190
- << bsl ( hex2dec ( hex1 , uri ) , 4 ) + hex2dec ( hex2 , uri ) >> <> decode ( tail , uri )
213
+ << bsl ( hex_to_dec ( hex1 , uri ) , 4 ) + hex_to_dec ( hex2 , uri ) >> <> decode ( tail , uri )
191
214
end
192
215
193
216
def decode ( << head , tail :: binary >> , uri ) do
194
- << check_plus ( head ) >> <> decode ( tail , uri )
217
+ << head >> <> decode ( tail , uri )
195
218
end
196
219
197
220
def decode ( << >> , _uri ) , do: << >>
198
221
199
- defp hex2dec ( n , _uri ) when n in ?A .. ?F , do: n - ?A + 10
200
- defp hex2dec ( n , _uri ) when n in ?a .. ?f , do: n - ?a + 10
201
- defp hex2dec ( n , _uri ) when n in ?0 .. ?9 , do: n - ?0
202
- defp hex2dec ( _n , uri ) do
222
+ defp hex_to_dec ( n , _uri ) when n in ?A .. ?F , do: n - ?A + 10
223
+ defp hex_to_dec ( n , _uri ) when n in ?a .. ?f , do: n - ?a + 10
224
+ defp hex_to_dec ( n , _uri ) when n in ?0 .. ?9 , do: n - ?0
225
+ defp hex_to_dec ( _n , uri ) do
203
226
raise ArgumentError , "malformed URI #{ inspect uri } "
204
227
end
205
228
206
- defp check_plus ( ?+ ) , do: 32
207
- defp check_plus ( c ) , do: c
208
-
209
229
@ doc """
210
230
Parses a URI into components.
211
231
0 commit comments