uri 0.12.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.document +5 -0
- data/.rdoc_options +4 -0
- data/{LICENSE.txt → BSDL} +3 -3
- data/COPYING +56 -0
- data/README.md +2 -1
- data/docs/kernel.rb +2 -0
- data/lib/uri/common.rb +299 -148
- data/lib/uri/file.rb +3 -3
- data/lib/uri/ftp.rb +1 -1
- data/lib/uri/generic.rb +29 -37
- data/lib/uri/http.rb +2 -2
- data/lib/uri/rfc2396_parser.rb +16 -9
- data/lib/uri/rfc3986_parser.rb +121 -34
- data/lib/uri/version.rb +1 -1
- data/lib/uri.rb +9 -9
- metadata +12 -13
- data/.github/dependabot.yml +0 -6
- data/.github/workflows/test.yml +0 -21
- data/.gitignore +0 -9
- data/Gemfile +0 -10
- data/Rakefile +0 -17
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/uri.gemspec +0 -31
data/lib/uri/common.rb
CHANGED
@@ -13,24 +13,51 @@ require_relative "rfc2396_parser"
|
|
13
13
|
require_relative "rfc3986_parser"
|
14
14
|
|
15
15
|
module URI
|
16
|
-
|
16
|
+
# The default parser instance for RFC 2396.
|
17
|
+
RFC2396_PARSER = RFC2396_Parser.new
|
18
|
+
Ractor.make_shareable(RFC2396_PARSER) if defined?(Ractor)
|
17
19
|
|
18
|
-
|
19
|
-
Parser = RFC2396_Parser
|
20
|
+
# The default parser instance for RFC 3986.
|
20
21
|
RFC3986_PARSER = RFC3986_Parser.new
|
21
22
|
Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor)
|
22
23
|
|
23
|
-
#
|
24
|
-
DEFAULT_PARSER =
|
25
|
-
DEFAULT_PARSER
|
26
|
-
|
27
|
-
|
24
|
+
# The default parser instance.
|
25
|
+
DEFAULT_PARSER = RFC3986_PARSER
|
26
|
+
Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor)
|
27
|
+
|
28
|
+
# Set the default parser instance.
|
29
|
+
def self.parser=(parser = RFC3986_PARSER)
|
30
|
+
remove_const(:Parser) if defined?(::URI::Parser)
|
31
|
+
const_set("Parser", parser.class)
|
32
|
+
|
33
|
+
remove_const(:REGEXP) if defined?(::URI::REGEXP)
|
34
|
+
remove_const(:PATTERN) if defined?(::URI::PATTERN)
|
35
|
+
if Parser == RFC2396_Parser
|
36
|
+
const_set("REGEXP", URI::RFC2396_REGEXP)
|
37
|
+
const_set("PATTERN", URI::RFC2396_REGEXP::PATTERN)
|
38
|
+
end
|
39
|
+
|
40
|
+
Parser.new.regexp.each_pair do |sym, str|
|
41
|
+
remove_const(sym) if const_defined?(sym, false)
|
42
|
+
const_set(sym, str)
|
28
43
|
end
|
29
44
|
end
|
30
|
-
|
31
|
-
|
45
|
+
self.parser = RFC3986_PARSER
|
46
|
+
|
47
|
+
def self.const_missing(const) # :nodoc:
|
48
|
+
if const == :REGEXP
|
49
|
+
warn "URI::REGEXP is obsolete. Use URI::RFC2396_REGEXP explicitly.", uplevel: 1 if $VERBOSE
|
50
|
+
URI::RFC2396_REGEXP
|
51
|
+
elsif value = RFC2396_PARSER.regexp[const]
|
52
|
+
warn "URI::#{const} is obsolete. Use RFC2396_PARSER.regexp[#{const.inspect}] explicitly.", uplevel: 1 if $VERBOSE
|
53
|
+
value
|
54
|
+
elsif value = RFC2396_Parser.const_get(const)
|
55
|
+
warn "URI::#{const} is obsolete. Use RFC2396_Parser::#{const} explicitly.", uplevel: 1 if $VERBOSE
|
56
|
+
value
|
57
|
+
else
|
58
|
+
super
|
59
|
+
end
|
32
60
|
end
|
33
|
-
Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor)
|
34
61
|
|
35
62
|
module Util # :nodoc:
|
36
63
|
def make_components_hash(klass, array_hash)
|
@@ -64,20 +91,36 @@ module URI
|
|
64
91
|
module_function :make_components_hash
|
65
92
|
end
|
66
93
|
|
67
|
-
module Schemes
|
94
|
+
module Schemes # :nodoc:
|
68
95
|
end
|
69
96
|
private_constant :Schemes
|
70
97
|
|
98
|
+
# Registers the given +klass+ as the class to be instantiated
|
99
|
+
# when parsing a \URI with the given +scheme+:
|
71
100
|
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
# can be registered (no -/+/. allowed).
|
101
|
+
# URI.register_scheme('MS_SEARCH', URI::Generic) # => URI::Generic
|
102
|
+
# URI.scheme_list['MS_SEARCH'] # => URI::Generic
|
75
103
|
#
|
104
|
+
# Note that after calling String#upcase on +scheme+, it must be a valid
|
105
|
+
# constant name.
|
76
106
|
def self.register_scheme(scheme, klass)
|
77
107
|
Schemes.const_set(scheme.to_s.upcase, klass)
|
78
108
|
end
|
79
109
|
|
80
|
-
# Returns a
|
110
|
+
# Returns a hash of the defined schemes:
|
111
|
+
#
|
112
|
+
# URI.scheme_list
|
113
|
+
# # =>
|
114
|
+
# {"MAILTO"=>URI::MailTo,
|
115
|
+
# "LDAPS"=>URI::LDAPS,
|
116
|
+
# "WS"=>URI::WS,
|
117
|
+
# "HTTP"=>URI::HTTP,
|
118
|
+
# "HTTPS"=>URI::HTTPS,
|
119
|
+
# "LDAP"=>URI::LDAP,
|
120
|
+
# "FILE"=>URI::File,
|
121
|
+
# "FTP"=>URI::FTP}
|
122
|
+
#
|
123
|
+
# Related: URI.register_scheme.
|
81
124
|
def self.scheme_list
|
82
125
|
Schemes.constants.map { |name|
|
83
126
|
[name.to_s.upcase, Schemes.const_get(name)]
|
@@ -88,9 +131,21 @@ module URI
|
|
88
131
|
private_constant :INITIAL_SCHEMES
|
89
132
|
Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor)
|
90
133
|
|
134
|
+
# Returns a new object constructed from the given +scheme+, +arguments+,
|
135
|
+
# and +default+:
|
136
|
+
#
|
137
|
+
# - The new object is an instance of <tt>URI.scheme_list[scheme.upcase]</tt>.
|
138
|
+
# - The object is initialized by calling the class initializer
|
139
|
+
# using +scheme+ and +arguments+.
|
140
|
+
# See URI::Generic.new.
|
91
141
|
#
|
92
|
-
#
|
93
|
-
#
|
142
|
+
# Examples:
|
143
|
+
#
|
144
|
+
# values = ['john.doe', 'www.example.com', '123', nil, '/forum/questions/', nil, 'tag=networking&order=newest', 'top']
|
145
|
+
# URI.for('https', *values)
|
146
|
+
# # => #<URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
147
|
+
# URI.for('foo', *values, default: URI::HTTP)
|
148
|
+
# # => #<URI::HTTP foo://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
94
149
|
#
|
95
150
|
def self.for(scheme, *arguments, default: Generic)
|
96
151
|
const_name = scheme.to_s.upcase
|
@@ -121,95 +176,49 @@ module URI
|
|
121
176
|
#
|
122
177
|
class BadURIError < Error; end
|
123
178
|
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
# * Port
|
142
|
-
# * Registry
|
143
|
-
# * Path
|
144
|
-
# * Opaque
|
145
|
-
# * Query
|
146
|
-
# * Fragment
|
147
|
-
#
|
148
|
-
# == Usage
|
149
|
-
#
|
150
|
-
# require 'uri'
|
151
|
-
#
|
152
|
-
# URI.split("http://www.ruby-lang.org/")
|
153
|
-
# # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil]
|
179
|
+
# Returns a 9-element array representing the parts of the \URI
|
180
|
+
# formed from the string +uri+;
|
181
|
+
# each array element is a string or +nil+:
|
182
|
+
#
|
183
|
+
# names = %w[scheme userinfo host port registry path opaque query fragment]
|
184
|
+
# values = URI.split('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
|
185
|
+
# names.zip(values)
|
186
|
+
# # =>
|
187
|
+
# [["scheme", "https"],
|
188
|
+
# ["userinfo", "john.doe"],
|
189
|
+
# ["host", "www.example.com"],
|
190
|
+
# ["port", "123"],
|
191
|
+
# ["registry", nil],
|
192
|
+
# ["path", "/forum/questions/"],
|
193
|
+
# ["opaque", nil],
|
194
|
+
# ["query", "tag=networking&order=newest"],
|
195
|
+
# ["fragment", "top"]]
|
154
196
|
#
|
155
197
|
def self.split(uri)
|
156
|
-
|
198
|
+
DEFAULT_PARSER.split(uri)
|
157
199
|
end
|
158
200
|
|
201
|
+
# Returns a new \URI object constructed from the given string +uri+:
|
159
202
|
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
# URI
|
163
|
-
#
|
164
|
-
# == Args
|
165
|
-
#
|
166
|
-
# +uri_str+::
|
167
|
-
# String with URI.
|
168
|
-
#
|
169
|
-
# == Description
|
170
|
-
#
|
171
|
-
# Creates one of the URI's subclasses instance from the string.
|
172
|
-
#
|
173
|
-
# == Raises
|
174
|
-
#
|
175
|
-
# URI::InvalidURIError::
|
176
|
-
# Raised if URI given is not a correct one.
|
177
|
-
#
|
178
|
-
# == Usage
|
179
|
-
#
|
180
|
-
# require 'uri'
|
203
|
+
# URI.parse('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
|
204
|
+
# # => #<URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
205
|
+
# URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
|
206
|
+
# # => #<URI::HTTP http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
181
207
|
#
|
182
|
-
#
|
183
|
-
#
|
184
|
-
# uri.scheme
|
185
|
-
# # => "http"
|
186
|
-
# uri.host
|
187
|
-
# # => "www.ruby-lang.org"
|
188
|
-
#
|
189
|
-
# It's recommended to first ::escape the provided +uri_str+ if there are any
|
190
|
-
# invalid URI characters.
|
208
|
+
# It's recommended to first ::escape string +uri+
|
209
|
+
# if it may contain invalid URI characters.
|
191
210
|
#
|
192
211
|
def self.parse(uri)
|
193
|
-
|
212
|
+
DEFAULT_PARSER.parse(uri)
|
194
213
|
end
|
195
214
|
|
215
|
+
# Merges the given URI strings +str+
|
216
|
+
# per {RFC 2396}[https://www.rfc-editor.org/rfc/rfc2396.html].
|
196
217
|
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
# URI::join(str[, str, ...])
|
200
|
-
#
|
201
|
-
# == Args
|
202
|
-
#
|
203
|
-
# +str+::
|
204
|
-
# String(s) to work with, will be converted to RFC3986 URIs before merging.
|
218
|
+
# Each string in +str+ is converted to an
|
219
|
+
# {RFC3986 URI}[https://www.rfc-editor.org/rfc/rfc3986.html] before being merged.
|
205
220
|
#
|
206
|
-
#
|
207
|
-
#
|
208
|
-
# Joins URIs.
|
209
|
-
#
|
210
|
-
# == Usage
|
211
|
-
#
|
212
|
-
# require 'uri'
|
221
|
+
# Examples:
|
213
222
|
#
|
214
223
|
# URI.join("http://example.com/","main.rbx")
|
215
224
|
# # => #<URI::HTTP http://example.com/main.rbx>
|
@@ -227,7 +236,7 @@ module URI
|
|
227
236
|
# # => #<URI::HTTP http://example.com/foo/bar>
|
228
237
|
#
|
229
238
|
def self.join(*str)
|
230
|
-
|
239
|
+
DEFAULT_PARSER.join(*str)
|
231
240
|
end
|
232
241
|
|
233
242
|
#
|
@@ -254,7 +263,7 @@ module URI
|
|
254
263
|
# URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.")
|
255
264
|
# # => ["http://foo.example.com/bla", "mailto:test@example.com"]
|
256
265
|
#
|
257
|
-
def self.extract(str, schemes = nil, &block)
|
266
|
+
def self.extract(str, schemes = nil, &block) # :nodoc:
|
258
267
|
warn "URI.extract is obsolete", uplevel: 1 if $VERBOSE
|
259
268
|
DEFAULT_PARSER.extract(str, schemes, &block)
|
260
269
|
end
|
@@ -291,7 +300,7 @@ module URI
|
|
291
300
|
# p $&
|
292
301
|
# end
|
293
302
|
#
|
294
|
-
def self.regexp(schemes = nil)
|
303
|
+
def self.regexp(schemes = nil)# :nodoc:
|
295
304
|
warn "URI.regexp is obsolete", uplevel: 1 if $VERBOSE
|
296
305
|
DEFAULT_PARSER.make_regexp(schemes)
|
297
306
|
end
|
@@ -300,7 +309,7 @@ module URI
|
|
300
309
|
256.times do |i|
|
301
310
|
TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i)
|
302
311
|
end
|
303
|
-
TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze
|
312
|
+
TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze # :nodoc:
|
304
313
|
TBLENCWWWCOMP_[' '] = '+'
|
305
314
|
TBLENCWWWCOMP_.freeze
|
306
315
|
TBLDECWWWCOMP_ = {} # :nodoc:
|
@@ -314,40 +323,86 @@ module URI
|
|
314
323
|
TBLDECWWWCOMP_['+'] = ' '
|
315
324
|
TBLDECWWWCOMP_.freeze
|
316
325
|
|
317
|
-
#
|
326
|
+
# Returns a URL-encoded string derived from the given string +str+.
|
318
327
|
#
|
319
|
-
#
|
320
|
-
# (ASCII space) to + and converts others to %XX.
|
328
|
+
# The returned string:
|
321
329
|
#
|
322
|
-
#
|
330
|
+
# - Preserves:
|
323
331
|
#
|
324
|
-
#
|
325
|
-
#
|
332
|
+
# - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>.
|
333
|
+
# - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>,
|
334
|
+
# and <tt>'0'..'9'</tt>.
|
326
335
|
#
|
327
|
-
#
|
336
|
+
# Example:
|
337
|
+
#
|
338
|
+
# URI.encode_www_form_component('*.-_azAZ09')
|
339
|
+
# # => "*.-_azAZ09"
|
340
|
+
#
|
341
|
+
# - Converts:
|
342
|
+
#
|
343
|
+
# - Character <tt>' '</tt> to character <tt>'+'</tt>.
|
344
|
+
# - Any other character to "percent notation";
|
345
|
+
# the percent notation for character <i>c</i> is <tt>'%%%X' % c.ord</tt>.
|
346
|
+
#
|
347
|
+
# Example:
|
348
|
+
#
|
349
|
+
# URI.encode_www_form_component('Here are some punctuation characters: ,;?:')
|
350
|
+
# # => "Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A"
|
351
|
+
#
|
352
|
+
# Encoding:
|
353
|
+
#
|
354
|
+
# - If +str+ has encoding Encoding::ASCII_8BIT, argument +enc+ is ignored.
|
355
|
+
# - Otherwise +str+ is converted first to Encoding::UTF_8
|
356
|
+
# (with suitable character replacements),
|
357
|
+
# and then to encoding +enc+.
|
358
|
+
#
|
359
|
+
# In either case, the returned string has forced encoding Encoding::US_ASCII.
|
360
|
+
#
|
361
|
+
# Related: URI.encode_uri_component (encodes <tt>' '</tt> as <tt>'%20'</tt>).
|
328
362
|
def self.encode_www_form_component(str, enc=nil)
|
329
363
|
_encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc)
|
330
364
|
end
|
331
365
|
|
332
|
-
#
|
366
|
+
# Returns a string decoded from the given \URL-encoded string +str+.
|
367
|
+
#
|
368
|
+
# The given string is first encoded as Encoding::ASCII-8BIT (using String#b),
|
369
|
+
# then decoded (as below), and finally force-encoded to the given encoding +enc+.
|
370
|
+
#
|
371
|
+
# The returned string:
|
372
|
+
#
|
373
|
+
# - Preserves:
|
374
|
+
#
|
375
|
+
# - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>.
|
376
|
+
# - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>,
|
377
|
+
# and <tt>'0'..'9'</tt>.
|
378
|
+
#
|
379
|
+
# Example:
|
333
380
|
#
|
334
|
-
#
|
381
|
+
# URI.decode_www_form_component('*.-_azAZ09')
|
382
|
+
# # => "*.-_azAZ09"
|
335
383
|
#
|
336
|
-
#
|
384
|
+
# - Converts:
|
385
|
+
#
|
386
|
+
# - Character <tt>'+'</tt> to character <tt>' '</tt>.
|
387
|
+
# - Each "percent notation" to an ASCII character.
|
388
|
+
#
|
389
|
+
# Example:
|
390
|
+
#
|
391
|
+
# URI.decode_www_form_component('Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A')
|
392
|
+
# # => "Here are some punctuation characters: ,;?:"
|
393
|
+
#
|
394
|
+
# Related: URI.decode_uri_component (preserves <tt>'+'</tt>).
|
337
395
|
def self.decode_www_form_component(str, enc=Encoding::UTF_8)
|
338
396
|
_decode_uri_component(/\+|%\h\h/, str, enc)
|
339
397
|
end
|
340
398
|
|
341
|
-
#
|
342
|
-
#
|
343
|
-
# This encodes SP to %20 instead of +.
|
399
|
+
# Like URI.encode_www_form_component, except that <tt>' '</tt> (space)
|
400
|
+
# is encoded as <tt>'%20'</tt> (instead of <tt>'+'</tt>).
|
344
401
|
def self.encode_uri_component(str, enc=nil)
|
345
402
|
_encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc)
|
346
403
|
end
|
347
404
|
|
348
|
-
#
|
349
|
-
#
|
350
|
-
# This does not decode + to SP.
|
405
|
+
# Like URI.decode_www_form_component, except that <tt>'+'</tt> is preserved.
|
351
406
|
def self.decode_uri_component(str, enc=Encoding::UTF_8)
|
352
407
|
_decode_uri_component(/%\h\h/, str, enc)
|
353
408
|
end
|
@@ -372,33 +427,104 @@ module URI
|
|
372
427
|
end
|
373
428
|
private_class_method :_decode_uri_component
|
374
429
|
|
375
|
-
#
|
430
|
+
# Returns a URL-encoded string derived from the given
|
431
|
+
# {Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html#module-Enumerable-label-Enumerable+in+Ruby+Classes]
|
432
|
+
# +enum+.
|
433
|
+
#
|
434
|
+
# The result is suitable for use as form data
|
435
|
+
# for an \HTTP request whose <tt>Content-Type</tt> is
|
436
|
+
# <tt>'application/x-www-form-urlencoded'</tt>.
|
437
|
+
#
|
438
|
+
# The returned string consists of the elements of +enum+,
|
439
|
+
# each converted to one or more URL-encoded strings,
|
440
|
+
# and all joined with character <tt>'&'</tt>.
|
441
|
+
#
|
442
|
+
# Simple examples:
|
443
|
+
#
|
444
|
+
# URI.encode_www_form([['foo', 0], ['bar', 1], ['baz', 2]])
|
445
|
+
# # => "foo=0&bar=1&baz=2"
|
446
|
+
# URI.encode_www_form({foo: 0, bar: 1, baz: 2})
|
447
|
+
# # => "foo=0&bar=1&baz=2"
|
448
|
+
#
|
449
|
+
# The returned string is formed using method URI.encode_www_form_component,
|
450
|
+
# which converts certain characters:
|
451
|
+
#
|
452
|
+
# URI.encode_www_form('f#o': '/', 'b-r': '$', 'b z': '@')
|
453
|
+
# # => "f%23o=%2F&b-r=%24&b+z=%40"
|
454
|
+
#
|
455
|
+
# When +enum+ is Array-like, each element +ele+ is converted to a field:
|
376
456
|
#
|
377
|
-
#
|
378
|
-
# from
|
457
|
+
# - If +ele+ is an array of two or more elements,
|
458
|
+
# the field is formed from its first two elements
|
459
|
+
# (and any additional elements are ignored):
|
379
460
|
#
|
380
|
-
#
|
461
|
+
# name = URI.encode_www_form_component(ele[0], enc)
|
462
|
+
# value = URI.encode_www_form_component(ele[1], enc)
|
463
|
+
# "#{name}=#{value}"
|
381
464
|
#
|
382
|
-
#
|
383
|
-
# before calling this method if you want to send data as other than original
|
384
|
-
# encoding or mixed encoding data. (Strings which are encoded in an HTML5
|
385
|
-
# ASCII incompatible encoding are converted to UTF-8.)
|
465
|
+
# Examples:
|
386
466
|
#
|
387
|
-
#
|
388
|
-
#
|
467
|
+
# URI.encode_www_form([%w[foo bar], %w[baz bat bah]])
|
468
|
+
# # => "foo=bar&baz=bat"
|
469
|
+
# URI.encode_www_form([['foo', 0], ['bar', :baz, 'bat']])
|
470
|
+
# # => "foo=0&bar=baz"
|
389
471
|
#
|
390
|
-
#
|
472
|
+
# - If +ele+ is an array of one element,
|
473
|
+
# the field is formed from <tt>ele[0]</tt>:
|
391
474
|
#
|
392
|
-
#
|
393
|
-
#
|
394
|
-
#
|
395
|
-
#
|
396
|
-
#
|
397
|
-
#
|
398
|
-
#
|
399
|
-
#
|
475
|
+
# URI.encode_www_form_component(ele[0])
|
476
|
+
#
|
477
|
+
# Example:
|
478
|
+
#
|
479
|
+
# URI.encode_www_form([['foo'], [:bar], [0]])
|
480
|
+
# # => "foo&bar&0"
|
481
|
+
#
|
482
|
+
# - Otherwise the field is formed from +ele+:
|
483
|
+
#
|
484
|
+
# URI.encode_www_form_component(ele)
|
485
|
+
#
|
486
|
+
# Example:
|
487
|
+
#
|
488
|
+
# URI.encode_www_form(['foo', :bar, 0])
|
489
|
+
# # => "foo&bar&0"
|
490
|
+
#
|
491
|
+
# The elements of an Array-like +enum+ may be mixture:
|
492
|
+
#
|
493
|
+
# URI.encode_www_form([['foo', 0], ['bar', 1, 2], ['baz'], :bat])
|
494
|
+
# # => "foo=0&bar=1&baz&bat"
|
495
|
+
#
|
496
|
+
# When +enum+ is Hash-like,
|
497
|
+
# each +key+/+value+ pair is converted to one or more fields:
|
498
|
+
#
|
499
|
+
# - If +value+ is
|
500
|
+
# {Array-convertible}[https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#label-Array-Convertible+Objects],
|
501
|
+
# each element +ele+ in +value+ is paired with +key+ to form a field:
|
502
|
+
#
|
503
|
+
# name = URI.encode_www_form_component(key, enc)
|
504
|
+
# value = URI.encode_www_form_component(ele, enc)
|
505
|
+
# "#{name}=#{value}"
|
506
|
+
#
|
507
|
+
# Example:
|
508
|
+
#
|
509
|
+
# URI.encode_www_form({foo: [:bar, 1], baz: [:bat, :bam, 2]})
|
510
|
+
# # => "foo=bar&foo=1&baz=bat&baz=bam&baz=2"
|
511
|
+
#
|
512
|
+
# - Otherwise, +key+ and +value+ are paired to form a field:
|
513
|
+
#
|
514
|
+
# name = URI.encode_www_form_component(key, enc)
|
515
|
+
# value = URI.encode_www_form_component(value, enc)
|
516
|
+
# "#{name}=#{value}"
|
517
|
+
#
|
518
|
+
# Example:
|
519
|
+
#
|
520
|
+
# URI.encode_www_form({foo: 0, bar: 1, baz: 2})
|
521
|
+
# # => "foo=0&bar=1&baz=2"
|
522
|
+
#
|
523
|
+
# The elements of a Hash-like +enum+ may be mixture:
|
524
|
+
#
|
525
|
+
# URI.encode_www_form({foo: [0, 1], bar: 2})
|
526
|
+
# # => "foo=0&foo=1&bar=2"
|
400
527
|
#
|
401
|
-
# See URI.encode_www_form_component, URI.decode_www_form.
|
402
528
|
def self.encode_www_form(enum, enc=nil)
|
403
529
|
enum.map do |k,v|
|
404
530
|
if v.nil?
|
@@ -419,22 +545,39 @@ module URI
|
|
419
545
|
end.join('&')
|
420
546
|
end
|
421
547
|
|
422
|
-
#
|
548
|
+
# Returns name/value pairs derived from the given string +str+,
|
549
|
+
# which must be an ASCII string.
|
550
|
+
#
|
551
|
+
# The method may be used to decode the body of Net::HTTPResponse object +res+
|
552
|
+
# for which <tt>res['Content-Type']</tt> is <tt>'application/x-www-form-urlencoded'</tt>.
|
553
|
+
#
|
554
|
+
# The returned data is an array of 2-element subarrays;
|
555
|
+
# each subarray is a name/value pair (both are strings).
|
556
|
+
# Each returned string has encoding +enc+,
|
557
|
+
# and has had invalid characters removed via
|
558
|
+
# {String#scrub}[https://docs.ruby-lang.org/en/master/String.html#method-i-scrub].
|
423
559
|
#
|
424
|
-
#
|
425
|
-
# and returns an array of key-value arrays.
|
560
|
+
# A simple example:
|
426
561
|
#
|
427
|
-
#
|
428
|
-
#
|
562
|
+
# URI.decode_www_form('foo=0&bar=1&baz')
|
563
|
+
# # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
|
429
564
|
#
|
430
|
-
#
|
431
|
-
#
|
432
|
-
#
|
433
|
-
#
|
434
|
-
#
|
435
|
-
#
|
565
|
+
# The returned strings have certain conversions,
|
566
|
+
# similar to those performed in URI.decode_www_form_component:
|
567
|
+
#
|
568
|
+
# URI.decode_www_form('f%23o=%2F&b-r=%24&b+z=%40')
|
569
|
+
# # => [["f#o", "/"], ["b-r", "$"], ["b z", "@"]]
|
570
|
+
#
|
571
|
+
# The given string may contain consecutive separators:
|
572
|
+
#
|
573
|
+
# URI.decode_www_form('foo=0&&bar=1&&baz=2')
|
574
|
+
# # => [["foo", "0"], ["", ""], ["bar", "1"], ["", ""], ["baz", "2"]]
|
575
|
+
#
|
576
|
+
# A different separator may be specified:
|
577
|
+
#
|
578
|
+
# URI.decode_www_form('foo=0--bar=1--baz', separator: '--')
|
579
|
+
# # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
|
436
580
|
#
|
437
|
-
# See URI.decode_www_form_component, URI.encode_www_form.
|
438
581
|
def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false)
|
439
582
|
raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only?
|
440
583
|
ary = []
|
@@ -713,7 +856,15 @@ end # module URI
|
|
713
856
|
module Kernel
|
714
857
|
|
715
858
|
#
|
716
|
-
# Returns
|
859
|
+
# Returns a \URI object derived from the given +uri+,
|
860
|
+
# which may be a \URI string or an existing \URI object:
|
861
|
+
#
|
862
|
+
# # Returns a new URI.
|
863
|
+
# uri = URI('http://github.com/ruby/ruby')
|
864
|
+
# # => #<URI::HTTP http://github.com/ruby/ruby>
|
865
|
+
# # Returns the given URI.
|
866
|
+
# URI(uri)
|
867
|
+
# # => #<URI::HTTP http://github.com/ruby/ruby>
|
717
868
|
#
|
718
869
|
def URI(uri)
|
719
870
|
if uri.is_a?(URI::Generic)
|
data/lib/uri/file.rb
CHANGED
@@ -70,17 +70,17 @@ module URI
|
|
70
70
|
|
71
71
|
# raise InvalidURIError
|
72
72
|
def check_userinfo(user)
|
73
|
-
raise URI::InvalidURIError, "
|
73
|
+
raise URI::InvalidURIError, "cannot set userinfo for file URI"
|
74
74
|
end
|
75
75
|
|
76
76
|
# raise InvalidURIError
|
77
77
|
def check_user(user)
|
78
|
-
raise URI::InvalidURIError, "
|
78
|
+
raise URI::InvalidURIError, "cannot set user for file URI"
|
79
79
|
end
|
80
80
|
|
81
81
|
# raise InvalidURIError
|
82
82
|
def check_password(user)
|
83
|
-
raise URI::InvalidURIError, "
|
83
|
+
raise URI::InvalidURIError, "cannot set password for file URI"
|
84
84
|
end
|
85
85
|
|
86
86
|
# do nothing
|
data/lib/uri/ftp.rb
CHANGED
@@ -17,7 +17,7 @@ module URI
|
|
17
17
|
# This class will be redesigned because of difference of implementations;
|
18
18
|
# the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it
|
19
19
|
# is a good summary about the de facto spec.
|
20
|
-
#
|
20
|
+
# https://datatracker.ietf.org/doc/html/draft-hoffman-ftp-uri-04
|
21
21
|
#
|
22
22
|
class FTP < Generic
|
23
23
|
# A Default port of 21 for URI::FTP.
|