rubysl-uri 1.0.0 → 2.0.0

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.
@@ -1,9 +1,10 @@
1
- #
2
1
  # = uri/ftp.rb
3
2
  #
4
3
  # Author:: Akira Yamada <akira@ruby-lang.org>
5
4
  # License:: You can redistribute it and/or modify it under the same term as Ruby.
6
- # Revision:: $Id: ftp.rb 16085 2008-04-19 11:56:22Z knu $
5
+ # Revision:: $Id$
6
+ #
7
+ # See URI for general documentation
7
8
  #
8
9
 
9
10
  require 'uri/generic'
@@ -13,26 +14,42 @@ module URI
13
14
  #
14
15
  # FTP URI syntax is defined by RFC1738 section 3.2.
15
16
  #
17
+ # This class will be redesigned because of difference of implementations;
18
+ # the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it
19
+ # is a good summary about the de facto spec.
20
+ # http://tools.ietf.org/html/draft-hoffman-ftp-uri-04
21
+ #
16
22
  class FTP < Generic
23
+ # A Default port of 21 for URI::FTP
17
24
  DEFAULT_PORT = 21
18
25
 
26
+ #
27
+ # An Array of the available components for URI::FTP
28
+ #
19
29
  COMPONENT = [
20
- :scheme,
30
+ :scheme,
21
31
  :userinfo, :host, :port,
22
32
  :path, :typecode
23
33
  ].freeze
34
+
24
35
  #
25
- # Typecode is "a", "i" or "d".
36
+ # Typecode is "a", "i" or "d".
26
37
  #
27
38
  # * "a" indicates a text file (the FTP command was ASCII)
28
39
  # * "i" indicates a binary file (FTP command IMAGE)
29
40
  # * "d" indicates the contents of a directory should be displayed
30
41
  #
31
42
  TYPECODE = ['a', 'i', 'd'].freeze
43
+
44
+ # Typecode prefix
45
+ # ';type='
32
46
  TYPECODE_PREFIX = ';type='.freeze
33
47
 
34
- def self.new2(user, password, host, port, path,
35
- typecode = nil, arg_check = true)
48
+ def self.new2(user, password, host, port, path,
49
+ typecode = nil, arg_check = true) # :nodoc:
50
+ # Do not use this method! Not tested. [Bug #7301]
51
+ # This methods remains just for compatibility,
52
+ # Keep it undocumented until the active maintainer is assigned.
36
53
  typecode = nil if typecode.size == 0
37
54
  if typecode && !TYPECODE.include?(typecode)
38
55
  raise ArgumentError,
@@ -42,22 +59,22 @@ module URI
42
59
  # do escape
43
60
 
44
61
  self.new('ftp',
45
- [user, password],
46
- host, port, nil,
47
- typecode ? path + TYPECODE_PREFIX + typecode : path,
62
+ [user, password],
63
+ host, port, nil,
64
+ typecode ? path + TYPECODE_PREFIX + typecode : path,
48
65
  nil, nil, nil, arg_check)
49
66
  end
50
67
 
51
68
  #
52
69
  # == Description
53
70
  #
54
- # Creates a new URI::FTP object from components, with syntax checking.
71
+ # Creates a new URI::FTP object from components, with syntax checking.
55
72
  #
56
- # The components accepted are +userinfo+, +host+, +port+, +path+ and
73
+ # The components accepted are +userinfo+, +host+, +port+, +path+ and
57
74
  # +typecode+.
58
75
  #
59
- # The components should be provided either as an Array, or as a Hash
60
- # with keys formed by preceding the component names with a colon.
76
+ # The components should be provided either as an Array, or as a Hash
77
+ # with keys formed by preceding the component names with a colon.
61
78
  #
62
79
  # If an Array is used, the components must be passed in the order
63
80
  # [userinfo, host, port, path, typecode]
@@ -67,11 +84,11 @@ module URI
67
84
  #
68
85
  # require 'uri'
69
86
  #
70
- # uri = URI::FTP.build(['user:password', 'ftp.example.com', nil,
87
+ # uri = URI::FTP.build(['user:password', 'ftp.example.com', nil,
71
88
  # '/path/file.> zip', 'i'])
72
89
  # puts uri.to_s -> ftp://user:password@ftp.example.com/%2Fpath/file.zip;type=a
73
90
  #
74
- # uri2 = URI::FTP.build({:host => 'ftp.example.com',
91
+ # uri2 = URI::FTP.build({:host => 'ftp.example.com',
75
92
  # :path => 'ruby/src'})
76
93
  # puts uri2.to_s -> ftp://ftp.example.com/ruby/src
77
94
  #
@@ -92,7 +109,7 @@ module URI
92
109
 
93
110
  if tmp[:typecode]
94
111
  if tmp[:typecode].size == 1
95
- tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode]
112
+ tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode]
96
113
  end
97
114
  tmp[:path] << tmp[:typecode]
98
115
  end
@@ -109,17 +126,19 @@ module URI
109
126
  # Unlike build(), this method does not escape the path component as
110
127
  # required by RFC1738; instead it is treated as per RFC2396.
111
128
  #
112
- # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+,
129
+ # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+,
113
130
  # +opaque+, +query+ and +fragment+, in that order.
114
131
  #
115
132
  def initialize(*arg)
133
+ raise InvalidURIError unless arg[5]
134
+ arg[5] = arg[5].sub(/^\//,'').sub(/^%2F/,'/')
116
135
  super(*arg)
117
136
  @typecode = nil
118
137
  tmp = @path.index(TYPECODE_PREFIX)
119
138
  if tmp
120
139
  typecode = @path[tmp + TYPECODE_PREFIX.size..-1]
121
- self.set_path(@path[0..tmp - 1])
122
-
140
+ @path = @path[0..tmp - 1]
141
+
123
142
  if arg[-1]
124
143
  self.typecode = typecode
125
144
  else
@@ -127,8 +146,15 @@ module URI
127
146
  end
128
147
  end
129
148
  end
149
+
150
+ # typecode accessor
151
+ #
152
+ # see URI::FTP::COMPONENT
130
153
  attr_reader :typecode
131
154
 
155
+ # validates typecode +v+,
156
+ # returns a +true+ or +false+ boolean
157
+ #
132
158
  def check_typecode(v)
133
159
  if TYPECODE.include?(v)
134
160
  return true
@@ -139,11 +165,39 @@ module URI
139
165
  end
140
166
  private :check_typecode
141
167
 
168
+ # private setter for the typecode +v+
169
+ #
170
+ # see also URI::FTP.typecode=
171
+ #
142
172
  def set_typecode(v)
143
173
  @typecode = v
144
174
  end
145
175
  protected :set_typecode
146
176
 
177
+ #
178
+ # == Args
179
+ #
180
+ # +v+::
181
+ # String
182
+ #
183
+ # == Description
184
+ #
185
+ # public setter for the typecode +v+.
186
+ # (with validation)
187
+ #
188
+ # see also URI::FTP.check_typecode
189
+ #
190
+ # == Usage
191
+ #
192
+ # require 'uri'
193
+ #
194
+ # uri = URI.parse("ftp://john@ftp.example.com/my_file.img")
195
+ # #=> #<URI::FTP:0x00000000923650 URL:ftp://john@ftp.example.com/my_file.img>
196
+ # uri.typecode = "i"
197
+ # # => "i"
198
+ # uri
199
+ # #=> #<URI::FTP:0x00000000923650 URL:ftp://john@ftp.example.com/my_file.img;type=i>
200
+ #
147
201
  def typecode=(typecode)
148
202
  check_typecode(typecode)
149
203
  set_typecode(typecode)
@@ -164,9 +218,9 @@ module URI
164
218
  # RFC 1738 specifically states that the path for an FTP URI does not
165
219
  # include the / which separates the URI path from the URI host. Example:
166
220
  #
167
- # ftp://ftp.example.com/pub/ruby
221
+ # ftp://ftp.example.com/pub/ruby
168
222
  #
169
- # The above URI indicates that the client should connect to
223
+ # The above URI indicates that the client should connect to
170
224
  # ftp.example.com then cd pub/ruby from the initial login directory.
171
225
  #
172
226
  # If you want to cd to an absolute directory, you must include an
@@ -177,8 +231,13 @@ module URI
177
231
  # This method will then return "/pub/ruby"
178
232
  #
179
233
  def path
180
- return @path.sub(/^\//,'').sub(/^%2F/i,'/')
234
+ return @path.sub(/^\//,'').sub(/^%2F/,'/')
235
+ end
236
+
237
+ def set_path(v)
238
+ super("/" + v.sub(/^\//, "%2F"))
181
239
  end
240
+ protected :set_path
182
241
 
183
242
  def to_s
184
243
  save_path = nil
@@ -1,23 +1,26 @@
1
- #
2
1
  # = uri/generic.rb
3
2
  #
4
3
  # Author:: Akira Yamada <akira@ruby-lang.org>
5
4
  # License:: You can redistribute it and/or modify it under the same term as Ruby.
6
- # Revision:: $Id: generic.rb 16085 2008-04-19 11:56:22Z knu $
5
+ # Revision:: $Id$
6
+ #
7
+ # See URI for general documentation
7
8
  #
8
9
 
9
10
  require 'uri/common'
10
11
 
11
12
  module URI
12
-
13
+
13
14
  #
14
15
  # Base class for all URI classes.
15
16
  # Implements generic URI syntax as per RFC 2396.
16
17
  #
17
18
  class Generic
18
19
  include URI
19
- include REGEXP
20
20
 
21
+ #
22
+ # A Default port of nil for URI::Generic
23
+ #
21
24
  DEFAULT_PORT = nil
22
25
 
23
26
  #
@@ -27,15 +30,21 @@ module URI
27
30
  self::DEFAULT_PORT
28
31
  end
29
32
 
33
+ #
34
+ # Returns default port
35
+ #
30
36
  def default_port
31
37
  self.class.default_port
32
38
  end
33
39
 
40
+ #
41
+ # An Array of the available components for URI::Generic
42
+ #
34
43
  COMPONENT = [
35
- :scheme,
36
- :userinfo, :host, :port, :registry,
37
- :path, :opaque,
38
- :query,
44
+ :scheme,
45
+ :userinfo, :host, :port, :registry,
46
+ :path, :opaque,
47
+ :query,
39
48
  :fragment
40
49
  ].freeze
41
50
 
@@ -46,10 +55,14 @@ module URI
46
55
  self::COMPONENT
47
56
  end
48
57
 
58
+ #
59
+ # Default to not use the registry for a URI::Generic
60
+ #
49
61
  USE_REGISTRY = false
50
62
 
51
63
  #
52
- # DOC: FIXME!
64
+ # Returns whether a registry of naming
65
+ # authorities are being used.
53
66
  #
54
67
  def self.use_registry
55
68
  self::USE_REGISTRY
@@ -63,7 +76,7 @@ module URI
63
76
  # == Description
64
77
  #
65
78
  # At first, tries to create a new URI::Generic instance using
66
- # URI::Generic::build. But, if exception URI::InvalidComponentError is raised,
79
+ # URI::Generic::build. But, if exception URI::InvalidComponentError is raised,
67
80
  # then it URI::Escape.escape all URI components and tries again.
68
81
  #
69
82
  #
@@ -72,9 +85,9 @@ module URI
72
85
  return self.build(args)
73
86
  rescue InvalidComponentError
74
87
  if args.kind_of?(Array)
75
- return self.build(args.collect{|x|
76
- if x
77
- URI.escape(x)
88
+ return self.build(args.collect{|x|
89
+ if x.is_a?(String)
90
+ DEFAULT_PARSER.escape(x)
78
91
  else
79
92
  x
80
93
  end
@@ -83,7 +96,7 @@ module URI
83
96
  tmp = {}
84
97
  args.each do |key, value|
85
98
  tmp[key] = if value
86
- URI.escape(value)
99
+ DEFAULT_PARSER.escape(value)
87
100
  else
88
101
  value
89
102
  end
@@ -108,7 +121,7 @@ module URI
108
121
  def self.build(args)
109
122
  if args.kind_of?(Array) &&
110
123
  args.size == ::URI::Generic::COMPONENT.size
111
- tmp = args
124
+ tmp = args.dup
112
125
  elsif args.kind_of?(Hash)
113
126
  tmp = ::URI::Generic::COMPONENT.collect do |c|
114
127
  if args.include?(c)
@@ -118,10 +131,12 @@ module URI
118
131
  end
119
132
  end
120
133
  else
121
- raise ArgumentError,
122
- "expected Array of or Hash of components of #{self.class} (#{self.class.component.join(', ')})"
134
+ component = self.class.component rescue ::URI::Generic::COMPONENT
135
+ raise ArgumentError,
136
+ "expected Array of or Hash of components of #{self.class} (#{component.join(', ')})"
123
137
  end
124
138
 
139
+ tmp << nil
125
140
  tmp << true
126
141
  return self.new(*tmp)
127
142
  end
@@ -137,15 +152,17 @@ module URI
137
152
  # +port+::
138
153
  # Server port
139
154
  # +registry+::
140
- # DOC: FIXME!
155
+ # Registry of naming authorities.
141
156
  # +path+::
142
157
  # Path on server
143
158
  # +opaque+::
144
- # DOC: FIXME!
159
+ # Opaque part
145
160
  # +query+::
146
161
  # Query data
147
162
  # +fragment+::
148
163
  # A part of URI after '#' sign
164
+ # +parser+::
165
+ # Parser for internal use [URI::DEFAULT_PARSER by default]
149
166
  # +arg_check+::
150
167
  # Check arguments [false by default]
151
168
  #
@@ -153,11 +170,12 @@ module URI
153
170
  #
154
171
  # Creates a new URI::Generic instance from ``generic'' components without check.
155
172
  #
156
- def initialize(scheme,
157
- userinfo, host, port, registry,
158
- path, opaque,
159
- query,
173
+ def initialize(scheme,
174
+ userinfo, host, port, registry,
175
+ path, opaque,
176
+ query,
160
177
  fragment,
178
+ parser = DEFAULT_PARSER,
161
179
  arg_check = false)
162
180
  @scheme = nil
163
181
  @user = nil
@@ -169,6 +187,7 @@ module URI
169
187
  @opaque = nil
170
188
  @registry = nil
171
189
  @fragment = nil
190
+ @parser = parser == DEFAULT_PARSER ? nil : parser
172
191
 
173
192
  if arg_check
174
193
  self.scheme = scheme
@@ -192,23 +211,98 @@ module URI
192
211
  self.set_fragment(fragment)
193
212
  end
194
213
  if @registry && !self.class.use_registry
195
- raise InvalidURIError,
214
+ raise InvalidURIError,
196
215
  "the scheme #{@scheme} does not accept registry part: #{@registry} (or bad hostname?)"
197
216
  end
198
-
217
+
199
218
  @scheme.freeze if @scheme
200
219
  self.set_path('') if !@path && !@opaque # (see RFC2396 Section 5.2)
201
220
  self.set_port(self.default_port) if self.default_port && !@port
202
221
  end
222
+
223
+ #
224
+ # returns the scheme component of the URI.
225
+ #
226
+ # URI("http://foo/bar/baz").scheme #=> "http"
227
+ #
203
228
  attr_reader :scheme
229
+
230
+ # returns the host component of the URI.
231
+ #
232
+ # URI("http://foo/bar/baz").host #=> "foo"
233
+ #
234
+ # It returns nil if no host component.
235
+ #
236
+ # URI("mailto:foo@example.org").host #=> nil
237
+ #
238
+ # The component doesn't contains the port number.
239
+ #
240
+ # URI("http://foo:8080/bar/baz").host #=> "foo"
241
+ #
242
+ # Since IPv6 addresses are wrapped by brackets in URIs,
243
+ # this method returns IPv6 addresses wrapped by brackets.
244
+ # This form is not appropriate to pass socket methods such as TCPSocket.open.
245
+ # If unwrapped host names are required, use "hostname" method.
246
+ #
247
+ # URI("http://[::1]/bar/baz").host #=> "[::1]"
248
+ # URI("http://[::1]/bar/baz").hostname #=> "::1"
249
+ #
204
250
  attr_reader :host
251
+
252
+ # returns the port component of the URI.
253
+ #
254
+ # URI("http://foo/bar/baz").port #=> "80"
255
+ #
256
+ # URI("http://foo:8080/bar/baz").port #=> "8080"
257
+ #
205
258
  attr_reader :port
259
+
260
+ # returns the registry component of the URI.
261
+ #
262
+ # (see RFC2396 Section 3.2)
263
+ #
206
264
  attr_reader :registry
265
+
266
+ # returns the path component of the URI.
267
+ #
268
+ # URI("http://foo/bar/baz").path #=> "/bar/baz"
269
+ #
207
270
  attr_reader :path
271
+
272
+ # returns the query component of the URI.
273
+ #
274
+ # URI("http://foo/bar/baz?search=FooBar").query #=> "search=FooBar"
275
+ #
208
276
  attr_reader :query
277
+
278
+ # returns the opaque part of the URI.
279
+ #
280
+ # URI("mailto:foo@example.org").opaque #=> "foo@example.org"
281
+ #
282
+ # Portion of the path that does make use of the slash '/'.
283
+ # The path typically refers to the absolute path and the opaque part.
284
+ # (see RFC2396 Section 3 and 5.2)
285
+ #
209
286
  attr_reader :opaque
287
+
288
+ # returns the fragment component of the URI.
289
+ #
290
+ # URI("http://foo/bar/baz?search=FooBar#ponies").fragment #=> "ponies"
291
+ #
210
292
  attr_reader :fragment
211
293
 
294
+ # returns the parser to be used.
295
+ #
296
+ # Unless a URI::Parser is defined, then DEFAULT_PARSER is used.
297
+ #
298
+ def parser
299
+ if !defined?(@parser) || !@parser
300
+ DEFAULT_PARSER
301
+ else
302
+ @parser || DEFAULT_PARSER
303
+ end
304
+ end
305
+
212
306
  # replace self by other URI object
213
307
  def replace!(oth)
214
308
  if self.class != oth.class
@@ -221,12 +315,18 @@ module URI
221
315
  end
222
316
  private :replace!
223
317
 
318
+ #
319
+ # Components of the URI in the order.
320
+ #
224
321
  def component
225
322
  self.class.component
226
323
  end
227
324
 
325
+ #
326
+ # check the scheme +v+ component against the URI::Parser Regexp for :SCHEME
327
+ #
228
328
  def check_scheme(v)
229
- if v && SCHEME !~ v
329
+ if v && parser.regexp[:SCHEME] !~ v
230
330
  raise InvalidComponentError,
231
331
  "bad component(expected scheme component): #{v}"
232
332
  end
@@ -235,17 +335,53 @@ module URI
235
335
  end
236
336
  private :check_scheme
237
337
 
338
+ # protected setter for the scheme component +v+
339
+ #
340
+ # see also URI::Generic.scheme=
341
+ #
238
342
  def set_scheme(v)
239
- @scheme = v
343
+ @scheme = v ? v.downcase : v
240
344
  end
241
345
  protected :set_scheme
242
346
 
347
+ #
348
+ # == Args
349
+ #
350
+ # +v+::
351
+ # String
352
+ #
353
+ # == Description
354
+ #
355
+ # public setter for the scheme component +v+.
356
+ # (with validation)
357
+ #
358
+ # see also URI::Generic.check_scheme
359
+ #
360
+ # == Usage
361
+ #
362
+ # require 'uri'
363
+ #
364
+ # uri = URI.parse("http://my.example.com")
365
+ # uri.scheme = "https"
366
+ # # => "https"
367
+ # uri
368
+ # #=> #<URI::HTTP:0x000000008e89e8 URL:https://my.example.com>
369
+ #
243
370
  def scheme=(v)
244
371
  check_scheme(v)
245
372
  set_scheme(v)
246
373
  v
247
374
  end
248
375
 
376
+ #
377
+ # check the +user+ and +password+.
378
+ #
379
+ # If +password+ is not provided, then +user+ is
380
+ # split, using URI::Generic.split_userinfo, to
381
+ # pull +user+ and +password.
382
+ #
383
+ # see also URI::Generic.check_user, URI::Generic.check_password
384
+ #
249
385
  def check_userinfo(user, password = nil)
250
386
  if !password
251
387
  user, password = split_userinfo(user)
@@ -257,15 +393,22 @@ module URI
257
393
  end
258
394
  private :check_userinfo
259
395
 
396
+ #
397
+ # check the user +v+ component for RFC2396 compliance
398
+ # and against the URI::Parser Regexp for :USERINFO
399
+ #
400
+ # Can not have a registry or opaque component defined,
401
+ # with a user component defined.
402
+ #
260
403
  def check_user(v)
261
404
  if @registry || @opaque
262
- raise InvalidURIError,
405
+ raise InvalidURIError,
263
406
  "can not set user with registry or opaque"
264
407
  end
265
408
 
266
409
  return v unless v
267
410
 
268
- if USERINFO !~ v
411
+ if parser.regexp[:USERINFO] !~ v
269
412
  raise InvalidComponentError,
270
413
  "bad component(expected userinfo component or user component): #{v}"
271
414
  end
@@ -274,9 +417,16 @@ module URI
274
417
  end
275
418
  private :check_user
276
419
 
420
+ #
421
+ # check the password +v+ component for RFC2396 compliance
422
+ # and against the URI::Parser Regexp for :USERINFO
423
+ #
424
+ # Can not have a registry or opaque component defined,
425
+ # with a user component defined.
426
+ #
277
427
  def check_password(v, user = @user)
278
428
  if @registry || @opaque
279
- raise InvalidURIError,
429
+ raise InvalidURIError,
280
430
  "can not set password with registry or opaque"
281
431
  end
282
432
  return v unless v
@@ -286,7 +436,7 @@ module URI
286
436
  "password component depends user component"
287
437
  end
288
438
 
289
- if USERINFO !~ v
439
+ if parser.regexp[:USERINFO] !~ v
290
440
  raise InvalidComponentError,
291
441
  "bad component(expected user component): #{v}"
292
442
  end
@@ -307,20 +457,71 @@ module URI
307
457
  # returns userinfo
308
458
  end
309
459
 
460
+ #
461
+ # == Args
462
+ #
463
+ # +v+::
464
+ # String
465
+ #
466
+ # == Description
467
+ #
468
+ # public setter for the +user+ component.
469
+ # (with validation)
470
+ #
471
+ # see also URI::Generic.check_user
472
+ #
473
+ # == Usage
474
+ #
475
+ # require 'uri'
476
+ #
477
+ # uri = URI.parse("http://john:S3nsit1ve@my.example.com")
478
+ # uri.user = "sam"
479
+ # # => "sam"
480
+ # uri
481
+ # #=> #<URI::HTTP:0x00000000881d90 URL:http://sam:V3ry_S3nsit1ve@my.example.com>
482
+ #
310
483
  def user=(user)
311
484
  check_user(user)
312
485
  set_user(user)
313
486
  # returns user
314
487
  end
315
-
488
+
489
+ #
490
+ # == Args
491
+ #
492
+ # +v+::
493
+ # String
494
+ #
495
+ # == Description
496
+ #
497
+ # public setter for the +password+ component.
498
+ # (with validation)
499
+ #
500
+ # see also URI::Generic.check_password
501
+ #
502
+ # == Usage
503
+ #
504
+ # require 'uri'
505
+ #
506
+ # uri = URI.parse("http://john:S3nsit1ve@my.example.com")
507
+ # uri.password = "V3ry_S3nsit1ve"
508
+ # # => "V3ry_S3nsit1ve"
509
+ # uri
510
+ # #=> #<URI::HTTP:0x00000000881d90 URL:http://john:V3ry_S3nsit1ve@my.example.com>
511
+ #
316
512
  def password=(password)
317
513
  check_password(password)
318
514
  set_password(password)
319
515
  # returns password
320
516
  end
321
517
 
518
+ # protect setter for the +user+ component, and +password+ if available.
519
+ # (with validation)
520
+ #
521
+ # see also URI::Generic.userinfo=
522
+ #
322
523
  def set_userinfo(user, password = nil)
323
- unless password
524
+ unless password
324
525
  user, password = split_userinfo(user)
325
526
  end
326
527
  @user = user
@@ -330,18 +531,28 @@ module URI
330
531
  end
331
532
  protected :set_userinfo
332
533
 
534
+ # protected setter for the user component +v+
535
+ #
536
+ # see also URI::Generic.user=
537
+ #
333
538
  def set_user(v)
334
539
  set_userinfo(v, @password)
335
540
  v
336
541
  end
337
542
  protected :set_user
338
543
 
544
+ # protected setter for the password component +v+
545
+ #
546
+ # see also URI::Generic.password=
547
+ #
339
548
  def set_password(v)
340
549
  @password = v
341
550
  # returns v
342
551
  end
343
552
  protected :set_password
344
553
 
554
+ # returns the userinfo +ui+ as user, password
555
+ # if properly formated as 'user:password'
345
556
  def split_userinfo(ui)
346
557
  return nil, nil unless ui
347
558
  user, password = ui.split(/:/, 2)
@@ -350,11 +561,13 @@ module URI
350
561
  end
351
562
  private :split_userinfo
352
563
 
564
+ # escapes 'user:password' +v+ based on RFC 1738 section 3.1
353
565
  def escape_userpass(v)
354
- v = URI.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/
566
+ v = parser.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/
355
567
  end
356
568
  private :escape_userpass
357
569
 
570
+ # returns the userinfo, either as 'user' or 'user:password'
358
571
  def userinfo
359
572
  if @user.nil?
360
573
  nil
@@ -365,21 +578,30 @@ module URI
365
578
  end
366
579
  end
367
580
 
581
+ # returns the user component
368
582
  def user
369
583
  @user
370
584
  end
371
585
 
586
+ # returns the password component
372
587
  def password
373
588
  @password
374
589
  end
375
590
 
591
+ #
592
+ # check the host +v+ component for RFC2396 compliance
593
+ # and against the URI::Parser Regexp for :HOST
594
+ #
595
+ # Can not have a registry or opaque component defined,
596
+ # with a host component defined.
597
+ #
376
598
  def check_host(v)
377
599
  return v unless v
378
600
 
379
601
  if @registry || @opaque
380
- raise InvalidURIError,
602
+ raise InvalidURIError,
381
603
  "can not set host with registry or opaque"
382
- elsif HOST !~ v
604
+ elsif parser.regexp[:HOST] !~ v
383
605
  raise InvalidComponentError,
384
606
  "bad component(expected host component): #{v}"
385
607
  end
@@ -388,24 +610,90 @@ module URI
388
610
  end
389
611
  private :check_host
390
612
 
613
+ # protected setter for the host component +v+
614
+ #
615
+ # see also URI::Generic.host=
616
+ #
391
617
  def set_host(v)
392
618
  @host = v
393
619
  end
394
620
  protected :set_host
395
621
 
622
+ #
623
+ # == Args
624
+ #
625
+ # +v+::
626
+ # String
627
+ #
628
+ # == Description
629
+ #
630
+ # public setter for the host component +v+.
631
+ # (with validation)
632
+ #
633
+ # see also URI::Generic.check_host
634
+ #
635
+ # == Usage
636
+ #
637
+ # require 'uri'
638
+ #
639
+ # uri = URI.parse("http://my.example.com")
640
+ # uri.host = "foo.com"
641
+ # # => "foo.com"
642
+ # uri
643
+ # #=> #<URI::HTTP:0x000000008e89e8 URL:http://foo.com>
644
+ #
396
645
  def host=(v)
397
646
  check_host(v)
398
647
  set_host(v)
399
648
  v
400
649
  end
401
650
 
651
+ # extract the host part of the URI and unwrap brackets for IPv6 addresses.
652
+ #
653
+ # This method is same as URI::Generic#host except
654
+ # brackets for IPv6 (andn future IP) addresses are removed.
655
+ #
656
+ # u = URI("http://[::1]/bar")
657
+ # p u.hostname #=> "::1"
658
+ # p u.host #=> "[::1]"
659
+ #
660
+ def hostname
661
+ v = self.host
662
+ /\A\[(.*)\]\z/ =~ v ? $1 : v
663
+ end
664
+
665
+ # set the host part of the URI as the argument with brackets for IPv6 addresses.
666
+ #
667
+ # This method is same as URI::Generic#host= except
668
+ # the argument can be bare IPv6 address.
669
+ #
670
+ # u = URI("http://foo/bar")
671
+ # p u.to_s #=> "http://foo/bar"
672
+ # u.hostname = "::1"
673
+ # p u.to_s #=> "http://[::1]/bar"
674
+ #
675
+ # If the arugument seems IPv6 address,
676
+ # it is wrapped by brackets.
677
+ #
678
+ def hostname=(v)
679
+ v = "[#{v}]" if /\A\[.*\]\z/ !~ v && /:/ =~ v
680
+ self.host = v
681
+ end
682
+
683
+ #
684
+ # check the port +v+ component for RFC2396 compliance
685
+ # and against the URI::Parser Regexp for :PORT
686
+ #
687
+ # Can not have a registry or opaque component defined,
688
+ # with a port component defined.
689
+ #
402
690
  def check_port(v)
403
691
  return v unless v
404
692
 
405
693
  if @registry || @opaque
406
- raise InvalidURIError,
694
+ raise InvalidURIError,
407
695
  "can not set port with registry or opaque"
408
- elsif !v.kind_of?(Fixnum) && PORT !~ v
696
+ elsif !v.kind_of?(Fixnum) && parser.regexp[:PORT] !~ v
409
697
  raise InvalidComponentError,
410
698
  "bad component(expected port component): #{v}"
411
699
  end
@@ -414,6 +702,10 @@ module URI
414
702
  end
415
703
  private :check_port
416
704
 
705
+ # protected setter for the port component +v+
706
+ #
707
+ # see also URI::Generic.port=
708
+ #
417
709
  def set_port(v)
418
710
  unless !v || v.kind_of?(Fixnum)
419
711
  if v.empty?
@@ -426,12 +718,42 @@ module URI
426
718
  end
427
719
  protected :set_port
428
720
 
721
+ #
722
+ # == Args
723
+ #
724
+ # +v+::
725
+ # String
726
+ #
727
+ # == Description
728
+ #
729
+ # public setter for the port component +v+.
730
+ # (with validation)
731
+ #
732
+ # see also URI::Generic.check_port
733
+ #
734
+ # == Usage
735
+ #
736
+ # require 'uri'
737
+ #
738
+ # uri = URI.parse("http://my.example.com")
739
+ # uri.port = 8080
740
+ # # => 8080
741
+ # uri
742
+ # #=> #<URI::HTTP:0x000000008e89e8 URL:http://my.example.com:8080>
743
+ #
429
744
  def port=(v)
430
745
  check_port(v)
431
746
  set_port(v)
432
747
  port
433
748
  end
434
749
 
750
+ #
751
+ # check the registry +v+ component for RFC2396 compliance
752
+ # and against the URI::Parser Regexp for :REGISTRY
753
+ #
754
+ # Can not have a host, port or user component defined,
755
+ # with a registry component defined.
756
+ #
435
757
  def check_registry(v)
436
758
  return v unless v
437
759
 
@@ -439,9 +761,9 @@ module URI
439
761
  # authority = server | reg_name
440
762
  # server = [ [ userinfo "@" ] hostport ]
441
763
  if @host || @port || @user # userinfo = @user + ':' + @password
442
- raise InvalidURIError,
764
+ raise InvalidURIError,
443
765
  "can not set registry with host, port, or userinfo"
444
- elsif v && REGISTRY !~ v
766
+ elsif v && parser.regexp[:REGISTRY] !~ v
445
767
  raise InvalidComponentError,
446
768
  "bad component(expected registry component): #{v}"
447
769
  end
@@ -450,34 +772,61 @@ module URI
450
772
  end
451
773
  private :check_registry
452
774
 
775
+ # protected setter for the registry component +v+
776
+ #
777
+ # see also URI::Generic.registry=
778
+ #
453
779
  def set_registry(v)
454
780
  @registry = v
455
781
  end
456
782
  protected :set_registry
457
783
 
784
+ #
785
+ # == Args
786
+ #
787
+ # +v+::
788
+ # String
789
+ #
790
+ # == Description
791
+ #
792
+ # public setter for the registry component +v+.
793
+ # (with validation)
794
+ #
795
+ # see also URI::Generic.check_registry
796
+ #
458
797
  def registry=(v)
459
798
  check_registry(v)
460
799
  set_registry(v)
461
800
  v
462
801
  end
463
802
 
803
+ #
804
+ # check the path +v+ component for RFC2396 compliance
805
+ # and against the URI::Parser Regexp
806
+ # for :ABS_PATH and :REL_PATH
807
+ #
808
+ # Can not have a opaque component defined,
809
+ # with a path component defined.
810
+ #
464
811
  def check_path(v)
465
812
  # raise if both hier and opaque are not nil, because:
466
813
  # absoluteURI = scheme ":" ( hier_part | opaque_part )
467
814
  # hier_part = ( net_path | abs_path ) [ "?" query ]
468
815
  if v && @opaque
469
- raise InvalidURIError,
816
+ raise InvalidURIError,
470
817
  "path conflicts with opaque"
471
818
  end
472
819
 
473
- if @scheme
474
- if v && v != '' && ABS_PATH !~ v
475
- raise InvalidComponentError,
820
+ # If scheme is ftp, path may be relative.
821
+ # See RFC 1738 section 3.2.2, and RFC 2396.
822
+ if @scheme && @scheme != "ftp"
823
+ if v && v != '' && parser.regexp[:ABS_PATH] !~ v
824
+ raise InvalidComponentError,
476
825
  "bad component(expected absolute path component): #{v}"
477
826
  end
478
827
  else
479
- if v && v != '' && ABS_PATH !~ v && REL_PATH !~ v
480
- raise InvalidComponentError,
828
+ if v && v != '' && parser.regexp[:ABS_PATH] !~ v && parser.regexp[:REL_PATH] !~ v
829
+ raise InvalidComponentError,
481
830
  "bad component(expected relative path component): #{v}"
482
831
  end
483
832
  end
@@ -486,17 +835,51 @@ module URI
486
835
  end
487
836
  private :check_path
488
837
 
838
+ # protected setter for the path component +v+
839
+ #
840
+ # see also URI::Generic.path=
841
+ #
489
842
  def set_path(v)
490
843
  @path = v
491
844
  end
492
845
  protected :set_path
493
846
 
847
+ #
848
+ # == Args
849
+ #
850
+ # +v+::
851
+ # String
852
+ #
853
+ # == Description
854
+ #
855
+ # public setter for the path component +v+.
856
+ # (with validation)
857
+ #
858
+ # see also URI::Generic.check_path
859
+ #
860
+ # == Usage
861
+ #
862
+ # require 'uri'
863
+ #
864
+ # uri = URI.parse("http://my.example.com/pub/files")
865
+ # uri.path = "/faq/"
866
+ # # => "/faq/"
867
+ # uri
868
+ # #=> #<URI::HTTP:0x000000008e89e8 URL:http://my.example.com/faq/>
869
+ #
494
870
  def path=(v)
495
871
  check_path(v)
496
872
  set_path(v)
497
873
  v
498
874
  end
499
875
 
876
+ #
877
+ # check the query +v+ component for RFC2396 compliance
878
+ # and against the URI::Parser Regexp for :QUERY
879
+ #
880
+ # Can not have a opaque component defined,
881
+ # with a query component defined.
882
+ #
500
883
  def check_query(v)
501
884
  return v unless v
502
885
 
@@ -504,30 +887,64 @@ module URI
504
887
  # absoluteURI = scheme ":" ( hier_part | opaque_part )
505
888
  # hier_part = ( net_path | abs_path ) [ "?" query ]
506
889
  if @opaque
507
- raise InvalidURIError,
890
+ raise InvalidURIError,
508
891
  "query conflicts with opaque"
509
892
  end
510
893
 
511
- if v && v != '' && QUERY !~ v
512
- raise InvalidComponentError,
894
+ if v && v != '' && parser.regexp[:QUERY] !~ v
895
+ raise InvalidComponentError,
513
896
  "bad component(expected query component): #{v}"
514
- end
897
+ end
515
898
 
516
899
  return true
517
900
  end
518
901
  private :check_query
519
902
 
903
+ # protected setter for the query component +v+
904
+ #
905
+ # see also URI::Generic.query=
906
+ #
520
907
  def set_query(v)
521
908
  @query = v
522
909
  end
523
910
  protected :set_query
524
911
 
912
+ #
913
+ # == Args
914
+ #
915
+ # +v+::
916
+ # String
917
+ #
918
+ # == Description
919
+ #
920
+ # public setter for the query component +v+.
921
+ # (with validation)
922
+ #
923
+ # see also URI::Generic.check_query
924
+ #
925
+ # == Usage
926
+ #
927
+ # require 'uri'
928
+ #
929
+ # uri = URI.parse("http://my.example.com/?id=25")
930
+ # uri.query = "id=1"
931
+ # # => "id=1"
932
+ # uri
933
+ # #=> #<URI::HTTP:0x000000008e89e8 URL:http://my.example.com/?id=1>
934
+ #
525
935
  def query=(v)
526
936
  check_query(v)
527
937
  set_query(v)
528
938
  v
529
939
  end
530
940
 
941
+ #
942
+ # check the opaque +v+ component for RFC2396 compliance and
943
+ # against the URI::Parser Regexp for :OPAQUE
944
+ #
945
+ # Can not have a host, port, user or path component defined,
946
+ # with an opaque component defined.
947
+ #
531
948
  def check_opaque(v)
532
949
  return v unless v
533
950
 
@@ -535,9 +952,9 @@ module URI
535
952
  # absoluteURI = scheme ":" ( hier_part | opaque_part )
536
953
  # hier_part = ( net_path | abs_path ) [ "?" query ]
537
954
  if @host || @port || @user || @path # userinfo = @user + ':' + @password
538
- raise InvalidURIError,
955
+ raise InvalidURIError,
539
956
  "can not set opaque with host, port, userinfo or path"
540
- elsif v && OPAQUE !~ v
957
+ elsif v && parser.regexp[:OPAQUE] !~ v
541
958
  raise InvalidComponentError,
542
959
  "bad component(expected opaque component): #{v}"
543
960
  end
@@ -546,22 +963,42 @@ module URI
546
963
  end
547
964
  private :check_opaque
548
965
 
966
+ # protected setter for the opaque component +v+
967
+ #
968
+ # see also URI::Generic.opaque=
969
+ #
549
970
  def set_opaque(v)
550
971
  @opaque = v
551
972
  end
552
973
  protected :set_opaque
553
974
 
975
+ #
976
+ # == Args
977
+ #
978
+ # +v+::
979
+ # String
980
+ #
981
+ # == Description
982
+ #
983
+ # public setter for the opaque component +v+.
984
+ # (with validation)
985
+ #
986
+ # see also URI::Generic.check_opaque
987
+ #
554
988
  def opaque=(v)
555
989
  check_opaque(v)
556
990
  set_opaque(v)
557
991
  v
558
992
  end
559
993
 
994
+ #
995
+ # check the fragment +v+ component against the URI::Parser Regexp for :FRAGMENT
996
+ #
560
997
  def check_fragment(v)
561
998
  return v unless v
562
999
 
563
- if v && v != '' && FRAGMENT !~ v
564
- raise InvalidComponentError,
1000
+ if v && v != '' && parser.regexp[:FRAGMENT] !~ v
1001
+ raise InvalidComponentError,
565
1002
  "bad component(expected fragment component): #{v}"
566
1003
  end
567
1004
 
@@ -569,11 +1006,38 @@ module URI
569
1006
  end
570
1007
  private :check_fragment
571
1008
 
1009
+ # protected setter for the fragment component +v+
1010
+ #
1011
+ # see also URI::Generic.fragment=
1012
+ #
572
1013
  def set_fragment(v)
573
1014
  @fragment = v
574
1015
  end
575
1016
  protected :set_fragment
576
1017
 
1018
+ #
1019
+ # == Args
1020
+ #
1021
+ # +v+::
1022
+ # String
1023
+ #
1024
+ # == Description
1025
+ #
1026
+ # public setter for the fragment component +v+.
1027
+ # (with validation)
1028
+ #
1029
+ # see also URI::Generic.check_fragment
1030
+ #
1031
+ # == Usage
1032
+ #
1033
+ # require 'uri'
1034
+ #
1035
+ # uri = URI.parse("http://my.example.com/?id=25#time=1305212049")
1036
+ # uri.fragment = "time=1305212086"
1037
+ # # => "time=1305212086"
1038
+ # uri
1039
+ # #=> #<URI::HTTP:0x000000007a81f8 URL:http://my.example.com/?id=25#time=1305212086>
1040
+ #
577
1041
  def fragment=(v)
578
1042
  check_fragment(v)
579
1043
  set_fragment(v)
@@ -610,11 +1074,18 @@ module URI
610
1074
  !absolute?
611
1075
  end
612
1076
 
1077
+ #
1078
+ # returns an Array of the path split on '/'
1079
+ #
613
1080
  def split_path(path)
614
1081
  path.split(%r{/+}, -1)
615
1082
  end
616
1083
  private :split_path
617
1084
 
1085
+ #
1086
+ # Merges a base path +base+, with relative path +rel+,
1087
+ # returns a modified base path.
1088
+ #
618
1089
  def merge_path(base, rel)
619
1090
 
620
1091
  # RFC2396, Section 5.2, 5)
@@ -769,22 +1240,15 @@ module URI
769
1240
  # return base and rel.
770
1241
  # you can modify `base', but can not `rel'.
771
1242
  def merge0(oth)
772
- case oth
773
- when Generic
774
- when String
775
- oth = URI.parse(oth)
776
- else
777
- raise ArgumentError,
778
- "bad argument(expected URI object or URI string)"
779
- end
1243
+ oth = parser.send(:convert_to_uri, oth)
780
1244
 
781
1245
  if self.relative? && oth.relative?
782
- raise BadURIError,
1246
+ raise BadURIError,
783
1247
  "both URI are relative"
784
1248
  end
785
1249
 
786
1250
  if self.absolute? && oth.absolute?
787
- #raise BadURIError,
1251
+ #raise BadURIError,
788
1252
  # "both URI are absolute"
789
1253
  # hmm... should return oth for usability?
790
1254
  return oth, oth
@@ -798,31 +1262,28 @@ module URI
798
1262
  end
799
1263
  private :merge0
800
1264
 
1265
+ # :stopdoc:
801
1266
  def route_from_path(src, dst)
802
- # RFC2396, Section 4.2
803
- return '' if src == dst
804
-
805
- src_path = split_path(src)
806
- dst_path = split_path(dst)
807
-
808
- # hmm... dst has abnormal absolute path,
809
- # like "/./", "/../", "/x/../", ...
810
- if dst_path.include?('..') ||
811
- dst_path.include?('.')
1267
+ case dst
1268
+ when src
1269
+ # RFC2396, Section 4.2
1270
+ return ''
1271
+ when %r{(?:\A|/)\.\.?(?:/|\z)}
1272
+ # dst has abnormal absolute path,
1273
+ # like "/./", "/../", "/x/../", ...
812
1274
  return dst.dup
813
1275
  end
814
1276
 
815
- src_path.pop
1277
+ src_path = src.scan(%r{(?:\A|[^/]+)/})
1278
+ dst_path = dst.scan(%r{(?:\A|[^/]+)/?})
816
1279
 
817
1280
  # discard same parts
818
- while dst_path.first == src_path.first
819
- break if dst_path.empty?
820
-
1281
+ while !dst_path.empty? && dst_path.first == src_path.first
821
1282
  src_path.shift
822
1283
  dst_path.shift
823
1284
  end
824
1285
 
825
- tmp = dst_path.join('/')
1286
+ tmp = dst_path.join
826
1287
 
827
1288
  # calculate
828
1289
  if src_path.empty?
@@ -838,23 +1299,17 @@ module URI
838
1299
  return '../' * src_path.size + tmp
839
1300
  end
840
1301
  private :route_from_path
1302
+ # :startdoc:
841
1303
 
1304
+ # :stopdoc:
842
1305
  def route_from0(oth)
843
- case oth
844
- when Generic
845
- when String
846
- oth = URI.parse(oth)
847
- else
848
- raise ArgumentError,
849
- "bad argument(expected URI object or URI string)"
850
- end
851
-
1306
+ oth = parser.send(:convert_to_uri, oth)
852
1307
  if self.relative?
853
- raise BadURIError,
1308
+ raise BadURIError,
854
1309
  "relative URI: #{self}"
855
1310
  end
856
1311
  if oth.relative?
857
- raise BadURIError,
1312
+ raise BadURIError,
858
1313
  "relative URI: #{oth}"
859
1314
  end
860
1315
 
@@ -862,16 +1317,18 @@ module URI
862
1317
  return self, self.dup
863
1318
  end
864
1319
  rel = URI::Generic.new(nil, # it is relative URI
865
- self.userinfo, self.host, self.port,
1320
+ self.userinfo, self.host, self.port,
866
1321
  self.registry, self.path, self.opaque,
867
- self.query, self.fragment)
1322
+ self.query, self.fragment, parser)
868
1323
 
869
1324
  if rel.userinfo != oth.userinfo ||
870
1325
  rel.host.to_s.downcase != oth.host.to_s.downcase ||
871
1326
  rel.port != oth.port
872
- if self.userinfo.nil? && self.host.nil?
873
- return self, self.dup
874
- end
1327
+
1328
+ if self.userinfo.nil? && self.host.nil?
1329
+ return self, self.dup
1330
+ end
1331
+
875
1332
  rel.set_port(nil) if rel.port == oth.default_port
876
1333
  return rel, rel
877
1334
  end
@@ -893,6 +1350,8 @@ module URI
893
1350
  return oth, rel
894
1351
  end
895
1352
  private :route_from0
1353
+ # :startdoc:
1354
+
896
1355
  #
897
1356
  # == Args
898
1357
  #
@@ -950,23 +1409,14 @@ module URI
950
1409
  # uri = URI.parse('http://my.example.com')
951
1410
  # p uri.route_to('http://my.example.com/main.rbx?page=1')
952
1411
  # #=> #<URI::Generic:0x2020c2f6 URL:/main.rbx?page=1>
953
- #
1412
+ #
954
1413
  def route_to(oth)
955
- case oth
956
- when Generic
957
- when String
958
- oth = URI.parse(oth)
959
- else
960
- raise ArgumentError,
961
- "bad argument(expected URI object or URI string)"
962
- end
963
-
964
- oth.route_from(self)
1414
+ parser.send(:convert_to_uri, oth).route_from(self)
965
1415
  end
966
1416
 
967
1417
  #
968
1418
  # Returns normalized URI
969
- #
1419
+ #
970
1420
  def normalize
971
1421
  uri = dup
972
1422
  uri.normalize!
@@ -980,15 +1430,15 @@ module URI
980
1430
  if path && path == ''
981
1431
  set_path('/')
982
1432
  end
983
- if host && host != host.downcase
984
- set_host(self.host.downcase)
985
- end
986
-
987
1433
  if scheme && scheme != scheme.downcase
988
1434
  set_scheme(self.scheme.downcase)
989
1435
  end
1436
+ if host && host != host.downcase
1437
+ set_host(self.host.downcase)
1438
+ end
990
1439
  end
991
1440
 
1441
+ # returns the assemble String with path and query components
992
1442
  def path_query
993
1443
  str = @path
994
1444
  if @query
@@ -1000,7 +1450,7 @@ module URI
1000
1450
 
1001
1451
  #
1002
1452
  # Constructs String from URI
1003
- #
1453
+ #
1004
1454
  def to_s
1005
1455
  str = ''
1006
1456
  if @scheme
@@ -1058,7 +1508,9 @@ module URI
1058
1508
  end
1059
1509
 
1060
1510
  def eql?(oth)
1061
- oth.is_a?(URI) && self.component_ary.eql?(oth.component_ary)
1511
+ self.class == oth.class &&
1512
+ parser == oth.parser &&
1513
+ self.component_ary.eql?(oth.component_ary)
1062
1514
  end
1063
1515
 
1064
1516
  =begin
@@ -1072,6 +1524,9 @@ module URI
1072
1524
 
1073
1525
  =begin
1074
1526
  =end
1527
+
1528
+
1529
+ # returns an Array of the components defined from the COMPONENT Array
1075
1530
  def component_ary
1076
1531
  component.collect do |x|
1077
1532
  self.send(x)
@@ -1101,7 +1556,7 @@ module URI
1101
1556
  if component.include?(c)
1102
1557
  self.send(c)
1103
1558
  else
1104
- raise ArgumentError,
1559
+ raise ArgumentError,
1105
1560
  "expected of components of #{self.class} (#{self.class.component.join(', ')})"
1106
1561
  end
1107
1562
  end
@@ -1112,15 +1567,110 @@ module URI
1112
1567
  @@to_s.bind(self).call.sub!(/>\z/) {" URL:#{self}>"}
1113
1568
  end
1114
1569
 
1570
+ #
1571
+ # == Args
1572
+ #
1573
+ # +v+::
1574
+ # URI or String
1575
+ #
1576
+ # == Description
1577
+ #
1578
+ # attempt to parse other URI +oth+
1579
+ # return [parsed_oth, self]
1580
+ #
1581
+ # == Usage
1582
+ #
1583
+ # require 'uri'
1584
+ #
1585
+ # uri = URI.parse("http://my.example.com")
1586
+ # uri.coerce("http://foo.com")
1587
+ # #=> [#<URI::HTTP:0x00000000bcb028 URL:http://foo.com/>, #<URI::HTTP:0x00000000d92178 URL:http://my.example.com>]
1588
+ #
1115
1589
  def coerce(oth)
1116
1590
  case oth
1117
1591
  when String
1118
- oth = URI.parse(oth)
1592
+ oth = parser.parse(oth)
1119
1593
  else
1120
1594
  super
1121
1595
  end
1122
1596
 
1123
1597
  return oth, self
1124
1598
  end
1599
+
1600
+ # returns a proxy URI.
1601
+ # The proxy URI is obtained from environment variables such as http_proxy,
1602
+ # ftp_proxy, no_proxy, etc.
1603
+ # If there is no proper proxy, nil is returned.
1604
+ #
1605
+ # Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.)
1606
+ # are examined too.
1607
+ #
1608
+ # But http_proxy and HTTP_PROXY is treated specially under CGI environment.
1609
+ # It's because HTTP_PROXY may be set by Proxy: header.
1610
+ # So HTTP_PROXY is not used.
1611
+ # http_proxy is not used too if the variable is case insensitive.
1612
+ # CGI_HTTP_PROXY can be used instead.
1613
+ def find_proxy
1614
+ name = self.scheme.downcase + '_proxy'
1615
+ proxy_uri = nil
1616
+ if name == 'http_proxy' && ENV.include?('REQUEST_METHOD') # CGI?
1617
+ # HTTP_PROXY conflicts with *_proxy for proxy settings and
1618
+ # HTTP_* for header information in CGI.
1619
+ # So it should be careful to use it.
1620
+ pairs = ENV.reject {|k, v| /\Ahttp_proxy\z/i !~ k }
1621
+ case pairs.length
1622
+ when 0 # no proxy setting anyway.
1623
+ proxy_uri = nil
1624
+ when 1
1625
+ k, _ = pairs.shift
1626
+ if k == 'http_proxy' && ENV[k.upcase] == nil
1627
+ # http_proxy is safe to use because ENV is case sensitive.
1628
+ proxy_uri = ENV[name]
1629
+ else
1630
+ proxy_uri = nil
1631
+ end
1632
+ else # http_proxy is safe to use because ENV is case sensitive.
1633
+ proxy_uri = ENV.to_hash[name]
1634
+ end
1635
+ if !proxy_uri
1636
+ # Use CGI_HTTP_PROXY. cf. libwww-perl.
1637
+ proxy_uri = ENV["CGI_#{name.upcase}"]
1638
+ end
1639
+ elsif name == 'http_proxy'
1640
+ unless proxy_uri = ENV[name]
1641
+ if proxy_uri = ENV[name.upcase]
1642
+ warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.'
1643
+ end
1644
+ end
1645
+ else
1646
+ proxy_uri = ENV[name] || ENV[name.upcase]
1647
+ end
1648
+
1649
+ if proxy_uri && self.hostname
1650
+ require 'socket'
1651
+ begin
1652
+ addr = IPSocket.getaddress(self.hostname)
1653
+ proxy_uri = nil if /\A127\.|\A::1\z/ =~ addr
1654
+ rescue SocketError
1655
+ end
1656
+ end
1657
+
1658
+ if proxy_uri
1659
+ proxy_uri = URI.parse(proxy_uri)
1660
+ name = 'no_proxy'
1661
+ if no_proxy = ENV[name] || ENV[name.upcase]
1662
+ no_proxy.scan(/([^:,]*)(?::(\d+))?/) {|host, port|
1663
+ if /(\A|\.)#{Regexp.quote host}\z/i =~ self.host &&
1664
+ (!port || self.port == port.to_i)
1665
+ proxy_uri = nil
1666
+ break
1667
+ end
1668
+ }
1669
+ end
1670
+ proxy_uri
1671
+ else
1672
+ nil
1673
+ end
1674
+ end
1125
1675
  end
1126
1676
  end