rubysl-uri 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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