rubysl-open-uri 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 05f995f524d3e9632f582e2bbd8dcdbf5659e488
4
- data.tar.gz: 458739e0c6c86c472d691d1b01443c76928ed392
3
+ metadata.gz: 127129b8cbce12aae8aff4c5c7e4d7a6d6b69905
4
+ data.tar.gz: ee23740d2028f77cf902ea7d3ec4f4e7c33b78be
5
5
  SHA512:
6
- metadata.gz: d429adfd778c09cf4a20d386a6371d0f3b423041ad1239b4abc6b774f446587ff6081f395e99f50d0dae022ab60df795242336a767a4a636996409da1717db22
7
- data.tar.gz: 357631988ef83b25738f170ce565aa88cf7c69954f6730869a5e5ecf752326528245decff5333c23c98a01e1bb5712f90d1424837f3f05757228c474f3296812
6
+ metadata.gz: 4abdc2787c5f514addfc4ac183e7c51b0f1a89e4b4cb69fdd7fff3f12e5ebda55f02c15ab0322d27852143a92dcadc7b18dec41e7f059cd8538aa8b1f5f759c0
7
+ data.tar.gz: e36dede11c0ec90c2d57a9a0555f18c7f6c7308e2333169a6563e5432120c4fe02e2b4a1bed95c9313d8abe86d6c06603c480b4918a19324b8e83e0c71ba2753
@@ -1,8 +1,7 @@
1
1
  language: ruby
2
- before_install:
3
- - gem update --system
4
- - gem --version
5
- - gem install rubysl-bundler
6
- script: bundle exec mspec spec
2
+ env:
3
+ - RUBYLIB=lib
4
+ script: bundle exec mspec
7
5
  rvm:
8
- - rbx-nightly-18mode
6
+ - 1.9.3
7
+ - rbx-nightly-19mode
@@ -5,22 +5,26 @@ require 'time'
5
5
  module Kernel
6
6
  private
7
7
  alias open_uri_original_open open # :nodoc:
8
+ class << self
9
+ alias open_uri_original_open open # :nodoc:
10
+ end
8
11
 
9
- # makes possible to open various resources including URIs.
10
- # If the first argument respond to `open' method,
11
- # the method is called with the rest arguments.
12
+ # Allows the opening of various resources including URIs.
13
+ #
14
+ # If the first argument responds to the 'open' method, 'open' is called on
15
+ # it with the rest of the arguments.
16
+ #
17
+ # If the first argument is a string that begins with xxx://, it is parsed by
18
+ # URI.parse. If the parsed object responds to the 'open' method,
19
+ # 'open' is called on it with the rest of the arguments.
12
20
  #
13
- # If the first argument is a string which begins with xxx://,
14
- # it is parsed by URI.parse. If the parsed object respond to `open' method,
15
- # the method is called with the rest arguments.
21
+ # Otherwise, the original Kernel#open is called.
16
22
  #
17
- # Otherwise original open is called.
23
+ # OpenURI::OpenRead#open provides URI::HTTP#open, URI::HTTPS#open and
24
+ # URI::FTP#open, Kernel#open.
18
25
  #
19
- # Since open-uri.rb provides URI::HTTP#open, URI::HTTPS#open and
20
- # URI::FTP#open,
21
- # Kernel[#.]open can accepts such URIs and strings which begins with
22
- # http://, https:// and ftp://.
23
- # In these case, the opened file object is extended by OpenURI::Meta.
26
+ # We can accept URIs and strings that begin with http://, https:// and
27
+ # ftp://. In these cases, the opened file object is extended by OpenURI::Meta.
24
28
  def open(name, *rest, &block) # :doc:
25
29
  if name.respond_to?(:open)
26
30
  name.open(*rest, &block)
@@ -35,18 +39,18 @@ module Kernel
35
39
  module_function :open
36
40
  end
37
41
 
38
- # OpenURI is an easy-to-use wrapper for net/http, net/https and net/ftp.
42
+ # OpenURI is an easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP.
39
43
  #
40
- #== Example
44
+ # == Example
41
45
  #
42
- # It is possible to open http/https/ftp URL as usual like opening a file:
46
+ # It is possible to open an http, https or ftp URL as though it were a file:
43
47
  #
44
48
  # open("http://www.ruby-lang.org/") {|f|
45
49
  # f.each_line {|line| p line}
46
50
  # }
47
51
  #
48
- # The opened file has several methods for meta information as follows since
49
- # it is extended by OpenURI::Meta.
52
+ # The opened file has several getter methods for its meta-information, as
53
+ # follows, since it is extended by OpenURI::Meta.
50
54
  #
51
55
  # open("http://www.ruby-lang.org/en") {|f|
52
56
  # f.each_line {|line| p line}
@@ -67,12 +71,14 @@ end
67
71
  # }
68
72
  #
69
73
  # The environment variables such as http_proxy, https_proxy and ftp_proxy
70
- # are in effect by default. :proxy => nil disables proxy.
74
+ # are in effect by default. Here we disable proxy:
71
75
  #
72
76
  # open("http://www.ruby-lang.org/en/raa.html", :proxy => nil) {|f|
73
77
  # # ...
74
78
  # }
75
79
  #
80
+ # See OpenURI::OpenRead.open and Kernel#open for more on available options.
81
+ #
76
82
  # URI objects can be opened in a similar way.
77
83
  #
78
84
  # uri = URI.parse("http://www.ruby-lang.org/en/")
@@ -91,9 +97,15 @@ end
91
97
  module OpenURI
92
98
  Options = {
93
99
  :proxy => true,
100
+ :proxy_http_basic_authentication => true,
94
101
  :progress_proc => true,
95
102
  :content_length_proc => true,
96
103
  :http_basic_authentication => true,
104
+ :read_timeout => true,
105
+ :ssl_ca_cert => nil,
106
+ :ssl_verify_mode => nil,
107
+ :ftp_active_mode => false,
108
+ :redirect => true,
97
109
  }
98
110
 
99
111
  def OpenURI.check_options(options) # :nodoc:
@@ -117,12 +129,17 @@ module OpenURI
117
129
 
118
130
  def OpenURI.open_uri(name, *rest) # :nodoc:
119
131
  uri = URI::Generic === name ? name : URI.parse(name)
120
- mode, perm, rest = OpenURI.scan_open_optional_arguments(*rest)
132
+ mode, _, rest = OpenURI.scan_open_optional_arguments(*rest)
121
133
  options = rest.shift if !rest.empty? && Hash === rest.first
122
134
  raise ArgumentError.new("extra arguments") if !rest.empty?
123
135
  options ||= {}
124
136
  OpenURI.check_options(options)
125
137
 
138
+ if /\Arb?(?:\Z|:([^:]+))/ =~ mode
139
+ encoding, = $1,Encoding.find($1) if $1
140
+ mode = nil
141
+ end
142
+
126
143
  unless mode == nil ||
127
144
  mode == 'r' || mode == 'rb' ||
128
145
  mode == File::RDONLY
@@ -130,11 +147,16 @@ module OpenURI
130
147
  end
131
148
 
132
149
  io = open_loop(uri, options)
150
+ io.set_encoding(encoding) if encoding
133
151
  if block_given?
134
152
  begin
135
153
  yield io
136
154
  ensure
137
- io.close
155
+ if io.respond_to? :close!
156
+ io.close! # Tempfile
157
+ else
158
+ io.close
159
+ end
138
160
  end
139
161
  else
140
162
  io
@@ -142,16 +164,40 @@ module OpenURI
142
164
  end
143
165
 
144
166
  def OpenURI.open_loop(uri, options) # :nodoc:
145
- case opt_proxy = options.fetch(:proxy, true)
167
+ proxy_opts = []
168
+ proxy_opts << :proxy_http_basic_authentication if options.include? :proxy_http_basic_authentication
169
+ proxy_opts << :proxy if options.include? :proxy
170
+ proxy_opts.compact!
171
+ if 1 < proxy_opts.length
172
+ raise ArgumentError, "multiple proxy options specified"
173
+ end
174
+ case proxy_opts.first
175
+ when :proxy_http_basic_authentication
176
+ opt_proxy, proxy_user, proxy_pass = options.fetch(:proxy_http_basic_authentication)
177
+ proxy_user = proxy_user.to_str
178
+ proxy_pass = proxy_pass.to_str
179
+ if opt_proxy == true
180
+ raise ArgumentError.new("Invalid authenticated proxy option: #{options[:proxy_http_basic_authentication].inspect}")
181
+ end
182
+ when :proxy
183
+ opt_proxy = options.fetch(:proxy)
184
+ proxy_user = nil
185
+ proxy_pass = nil
186
+ when nil
187
+ opt_proxy = true
188
+ proxy_user = nil
189
+ proxy_pass = nil
190
+ end
191
+ case opt_proxy
146
192
  when true
147
- find_proxy = lambda {|u| u.find_proxy}
193
+ find_proxy = lambda {|u| pxy = u.find_proxy; pxy ? [pxy, nil, nil] : nil}
148
194
  when nil, false
149
195
  find_proxy = lambda {|u| nil}
150
196
  when String
151
197
  opt_proxy = URI.parse(opt_proxy)
152
- find_proxy = lambda {|u| opt_proxy}
198
+ find_proxy = lambda {|u| [opt_proxy, proxy_user, proxy_pass]}
153
199
  when URI::Generic
154
- find_proxy = lambda {|u| opt_proxy}
200
+ find_proxy = lambda {|u| [opt_proxy, proxy_user, proxy_pass]}
155
201
  else
156
202
  raise ArgumentError.new("Invalid proxy option: #{opt_proxy}")
157
203
  end
@@ -170,6 +216,9 @@ module OpenURI
170
216
  # URI. It is converted to absolute URI using uri as a base URI.
171
217
  redirect = uri + redirect
172
218
  end
219
+ if !options.fetch(:redirect, true)
220
+ raise HTTPRedirect.new(buf.io.status.join(' '), buf.io, redirect)
221
+ end
173
222
  unless OpenURI.redirectable?(uri, redirect)
174
223
  raise "redirection forbidden: #{uri} -> #{redirect}"
175
224
  end
@@ -192,7 +241,10 @@ module OpenURI
192
241
 
193
242
  def OpenURI.redirectable?(uri1, uri2) # :nodoc:
194
243
  # This test is intended to forbid a redirection from http://... to
195
- # file:///etc/passwd.
244
+ # file:///etc/passwd, file:///dev/zero, etc. CVE-2011-1521
245
+ # https to http redirect is also forbidden intentionally.
246
+ # It avoids sending secure cookie or referer by non-secure HTTP protocol.
247
+ # (RFC 2109 4.3.1, RFC 2965 3.3, RFC 2616 15.1.3)
196
248
  # However this is ad hoc. It should be extensible/configurable.
197
249
  uri1.scheme.downcase == uri2.scheme.downcase ||
198
250
  (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp)\z/i =~ uri2.scheme)
@@ -200,7 +252,8 @@ module OpenURI
200
252
 
201
253
  def OpenURI.open_http(buf, target, proxy, options) # :nodoc:
202
254
  if proxy
203
- raise "Non-HTTP proxy URI: #{proxy}" if proxy.class != URI::HTTP
255
+ proxy_uri, proxy_user, proxy_pass = proxy
256
+ raise "Non-HTTP proxy URI: #{proxy_uri}" if proxy_uri.class != URI::HTTP
204
257
  end
205
258
 
206
259
  if target.userinfo && "1.9.0" <= RUBY_VERSION
@@ -208,35 +261,53 @@ module OpenURI
208
261
  raise ArgumentError, "userinfo not supported. [RFC3986]"
209
262
  end
210
263
 
264
+ header = {}
265
+ options.each {|k, v| header[k] = v if String === k }
266
+
211
267
  require 'net/http'
212
268
  klass = Net::HTTP
213
269
  if URI::HTTP === target
214
270
  # HTTP or HTTPS
215
271
  if proxy
216
- klass = Net::HTTP::Proxy(proxy.host, proxy.port)
272
+ if proxy_user && proxy_pass
273
+ klass = Net::HTTP::Proxy(proxy_uri.hostname, proxy_uri.port, proxy_user, proxy_pass)
274
+ else
275
+ klass = Net::HTTP::Proxy(proxy_uri.hostname, proxy_uri.port)
276
+ end
217
277
  end
218
- target_host = target.host
278
+ target_host = target.hostname
219
279
  target_port = target.port
220
280
  request_uri = target.request_uri
221
281
  else
222
282
  # FTP over HTTP proxy
223
- target_host = proxy.host
224
- target_port = proxy.port
283
+ target_host = proxy_uri.hostname
284
+ target_port = proxy_uri.port
225
285
  request_uri = target.to_s
286
+ if proxy_user && proxy_pass
287
+ header["Proxy-Authorization"] = 'Basic ' + ["#{proxy_user}:#{proxy_pass}"].pack('m').delete("\r\n")
288
+ end
226
289
  end
227
290
 
228
291
  http = klass.new(target_host, target_port)
229
292
  if target.class == URI::HTTPS
230
293
  require 'net/https'
231
294
  http.use_ssl = true
232
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
295
+ http.verify_mode = options[:ssl_verify_mode] || OpenSSL::SSL::VERIFY_PEER
233
296
  store = OpenSSL::X509::Store.new
234
- store.set_default_paths
297
+ if options[:ssl_ca_cert]
298
+ if File.directory? options[:ssl_ca_cert]
299
+ store.add_path options[:ssl_ca_cert]
300
+ else
301
+ store.add_file options[:ssl_ca_cert]
302
+ end
303
+ else
304
+ store.set_default_paths
305
+ end
235
306
  http.cert_store = store
236
307
  end
237
-
238
- header = {}
239
- options.each {|k, v| header[k] = v if String === k }
308
+ if options.include? :read_timeout
309
+ http.read_timeout = options[:read_timeout]
310
+ end
240
311
 
241
312
  resp = nil
242
313
  http.start {
@@ -272,7 +343,12 @@ module OpenURI
272
343
  Net::HTTPFound, # 302
273
344
  Net::HTTPSeeOther, # 303
274
345
  Net::HTTPTemporaryRedirect # 307
275
- throw :open_uri_redirect, URI.parse(resp['location'])
346
+ begin
347
+ loc_uri = URI.parse(resp['location'])
348
+ rescue URI::InvalidURIError
349
+ raise OpenURI::HTTPError.new(io.status.join(' ') + ' (Invalid Location URI)', io)
350
+ end
351
+ throw :open_uri_redirect, loc_uri
276
352
  else
277
353
  raise OpenURI::HTTPError.new(io.status.join(' '), io)
278
354
  end
@@ -286,7 +362,17 @@ module OpenURI
286
362
  attr_reader :io
287
363
  end
288
364
 
289
- class Buffer # :nodoc:
365
+ # Raised on redirection,
366
+ # only occurs when +redirect+ option for HTTP is +false+.
367
+ class HTTPRedirect < HTTPError
368
+ def initialize(message, io, uri)
369
+ super(message, io)
370
+ @uri = uri
371
+ end
372
+ attr_reader :uri
373
+ end
374
+
375
+ class Buffer # :nodoc: all
290
376
  def initialize
291
377
  @io = StringIO.new
292
378
  @size = 0
@@ -301,14 +387,14 @@ module OpenURI
301
387
  require 'tempfile'
302
388
  io = Tempfile.new('open-uri')
303
389
  io.binmode
304
- Meta.init io, @io if @io.respond_to? :meta
390
+ Meta.init io, @io if Meta === @io
305
391
  io << @io.string
306
392
  @io = io
307
393
  end
308
394
  end
309
395
 
310
396
  def io
311
- Meta.init @io unless @io.respond_to? :meta
397
+ Meta.init @io unless Meta === @io
312
398
  @io
313
399
  end
314
400
  end
@@ -330,22 +416,43 @@ module OpenURI
330
416
  end
331
417
  end
332
418
 
333
- # returns an Array which consists status code and message.
419
+ # returns an Array that consists of status code and message.
334
420
  attr_accessor :status
335
421
 
336
- # returns a URI which is base of relative URIs in the data.
337
- # It may differ from the URI supplied by a user because redirection.
422
+ # returns a URI that is the base of relative URIs in the data.
423
+ # It may differ from the URI supplied by a user due to redirection.
338
424
  attr_accessor :base_uri
339
425
 
340
- # returns a Hash which represents header fields.
426
+ # returns a Hash that represents header fields.
341
427
  # The Hash keys are downcased for canonicalization.
342
428
  attr_reader :meta
343
429
 
430
+ def meta_setup_encoding # :nodoc:
431
+ charset = self.charset
432
+ enc = nil
433
+ if charset
434
+ begin
435
+ enc = Encoding.find(charset)
436
+ rescue ArgumentError
437
+ end
438
+ end
439
+ enc = Encoding::ASCII_8BIT unless enc
440
+ if self.respond_to? :force_encoding
441
+ self.force_encoding(enc)
442
+ elsif self.respond_to? :string
443
+ self.string.force_encoding(enc)
444
+ else # Tempfile
445
+ self.set_encoding enc
446
+ end
447
+ end
448
+
344
449
  def meta_add_field(name, value) # :nodoc:
345
- @meta[name.downcase] = value
450
+ name = name.downcase
451
+ @meta[name] = value
452
+ meta_setup_encoding if name == 'content-type'
346
453
  end
347
454
 
348
- # returns a Time which represents Last-Modified field.
455
+ # returns a Time that represents the Last-Modified field.
349
456
  def last_modified
350
457
  if v = @meta['last-modified']
351
458
  Time.httpdate(v)
@@ -354,10 +461,12 @@ module OpenURI
354
461
  end
355
462
  end
356
463
 
464
+ # :stopdoc:
357
465
  RE_LWS = /[\r\n\t ]+/n
358
466
  RE_TOKEN = %r{[^\x00- ()<>@,;:\\"/\[\]?={}\x7f]+}n
359
467
  RE_QUOTED_STRING = %r{"(?:[\r\n\t !#-\[\]-~\x80-\xff]|\\[\x00-\x7f])*"}n
360
468
  RE_PARAMETERS = %r{(?:;#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?=#{RE_LWS}?(?:#{RE_TOKEN}|#{RE_QUOTED_STRING})#{RE_LWS}?)*}n
469
+ # :startdoc:
361
470
 
362
471
  def content_type_parse # :nodoc:
363
472
  v = @meta['content-type']
@@ -367,7 +476,9 @@ module OpenURI
367
476
  subtype = $2.downcase
368
477
  parameters = []
369
478
  $3.scan(/;#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?=#{RE_LWS}?(?:(#{RE_TOKEN})|(#{RE_QUOTED_STRING}))/no) {|att, val, qval|
370
- val = qval.gsub(/[\r\n\t !#-\[\]-~\x80-\xff]+|(\\[\x00-\x7f])/) { $1 ? $1[1,1] : $& } if qval
479
+ if qval
480
+ val = qval[1...-1].gsub(/[\r\n\t !#-\[\]-~\x80-\xff]+|(\\[\x00-\x7f])/n) { $1 ? $1[1,1] : $& }
481
+ end
371
482
  parameters << [att.downcase, val]
372
483
  }
373
484
  ["#{type}/#{subtype}", *parameters]
@@ -380,7 +491,7 @@ module OpenURI
380
491
  # It is downcased for canonicalization.
381
492
  # Content-Type parameters are stripped.
382
493
  def content_type
383
- type, *parameters = content_type_parse
494
+ type, *_ = content_type_parse
384
495
  type || 'application/octet-stream'
385
496
  end
386
497
 
@@ -426,22 +537,25 @@ module OpenURI
426
537
  # OpenURI::OpenRead#open provides `open' for URI::HTTP and URI::FTP.
427
538
  #
428
539
  # OpenURI::OpenRead#open takes optional 3 arguments as:
429
- # OpenURI::OpenRead#open([mode [, perm]] [, options]) [{|io| ... }]
430
540
  #
431
- # `mode', `perm' is same as Kernel#open.
541
+ # OpenURI::OpenRead#open([mode [, perm]] [, options]) [{|io| ... }]
542
+ #
543
+ # OpenURI::OpenRead#open returns an IO-like object if block is not given.
544
+ # Otherwise it yields the IO object and return the value of the block.
545
+ # The IO object is extended with OpenURI::Meta.
546
+ #
547
+ # +mode+ and +perm+ are the same as Kernel#open.
432
548
  #
433
- # However, `mode' must be read mode because OpenURI::OpenRead#open doesn't
549
+ # However, +mode+ must be read mode because OpenURI::OpenRead#open doesn't
434
550
  # support write mode (yet).
435
- # Also `perm' is just ignored because it is meaningful only for file
436
- # creation.
551
+ # Also +perm+ is ignored because it is meaningful only for file creation.
437
552
  #
438
- # `options' must be a hash.
553
+ # +options+ must be a hash.
439
554
  #
440
- # Each pairs which key is a string in the hash specify a extra header
441
- # field for HTTP.
442
- # I.e. it is ignored for FTP without HTTP proxy.
555
+ # Each option with a string key specifies an extra header field for HTTP.
556
+ # I.e., it is ignored for FTP without HTTP proxy.
443
557
  #
444
- # The hash may include other options which key is a symbol:
558
+ # The hash may include other options, where keys are symbols:
445
559
  #
446
560
  # [:proxy]
447
561
  # Synopsis:
@@ -450,16 +564,37 @@ module OpenURI
450
564
  # :proxy => true
451
565
  # :proxy => false
452
566
  # :proxy => nil
453
- #
567
+ #
454
568
  # If :proxy option is specified, the value should be String, URI,
455
569
  # boolean or nil.
570
+ #
456
571
  # When String or URI is given, it is treated as proxy URI.
572
+ #
457
573
  # When true is given or the option itself is not specified,
458
574
  # environment variable `scheme_proxy' is examined.
459
575
  # `scheme' is replaced by `http', `https' or `ftp'.
576
+ #
460
577
  # When false or nil is given, the environment variables are ignored and
461
578
  # connection will be made to a server directly.
462
579
  #
580
+ # [:proxy_http_basic_authentication]
581
+ # Synopsis:
582
+ # :proxy_http_basic_authentication =>
583
+ # ["http://proxy.foo.com:8000/", "proxy-user", "proxy-password"]
584
+ # :proxy_http_basic_authentication =>
585
+ # [URI.parse("http://proxy.foo.com:8000/"),
586
+ # "proxy-user", "proxy-password"]
587
+ #
588
+ # If :proxy option is specified, the value should be an Array with 3
589
+ # elements. It should contain a proxy URI, a proxy user name and a proxy
590
+ # password. The proxy URI should be a String, an URI or nil. The proxy
591
+ # user name and password should be a String.
592
+ #
593
+ # If nil is given for the proxy URI, this option is just ignored.
594
+ #
595
+ # If :proxy and :proxy_http_basic_authentication is specified,
596
+ # ArgumentError is raised.
597
+ #
463
598
  # [:http_basic_authentication]
464
599
  # Synopsis:
465
600
  # :http_basic_authentication=>[user, password]
@@ -472,17 +607,16 @@ module OpenURI
472
607
  # [:content_length_proc]
473
608
  # Synopsis:
474
609
  # :content_length_proc => lambda {|content_length| ... }
475
- #
610
+ #
476
611
  # If :content_length_proc option is specified, the option value procedure
477
612
  # is called before actual transfer is started.
478
- # It takes one argument which is expected content length in bytes.
479
- #
613
+ # It takes one argument, which is expected content length in bytes.
614
+ #
480
615
  # If two or more transfer is done by HTTP redirection, the procedure
481
616
  # is called only one for a last transfer.
482
- #
617
+ #
483
618
  # When expected content length is unknown, the procedure is called with
484
- # nil.
485
- # It is happen when HTTP response has no Content-Length header.
619
+ # nil. This happens when the HTTP response has no Content-Length header.
486
620
  #
487
621
  # [:progress_proc]
488
622
  # Synopsis:
@@ -490,7 +624,7 @@ module OpenURI
490
624
  #
491
625
  # If :progress_proc option is specified, the proc is called with one
492
626
  # argument each time when `open' gets content fragment from network.
493
- # The argument `size' `size' is a accumulated transfered size in bytes.
627
+ # The argument +size+ is the accumulated transferred size in bytes.
494
628
  #
495
629
  # If two or more transfer is done by HTTP redirection, the procedure
496
630
  # is called only one for a last transfer.
@@ -511,9 +645,45 @@ module OpenURI
511
645
  # pbar.set s if pbar
512
646
  # }) {|f| ... }
513
647
  #
514
- # OpenURI::OpenRead#open returns an IO like object if block is not given.
515
- # Otherwise it yields the IO object and return the value of the block.
516
- # The IO object is extended with OpenURI::Meta.
648
+ # [:read_timeout]
649
+ # Synopsis:
650
+ # :read_timeout=>nil (no timeout)
651
+ # :read_timeout=>10 (10 second)
652
+ #
653
+ # :read_timeout option specifies a timeout of read for http connections.
654
+ #
655
+ # [:ssl_ca_cert]
656
+ # Synopsis:
657
+ # :ssl_ca_cert=>filename
658
+ #
659
+ # :ssl_ca_cert is used to specify CA certificate for SSL.
660
+ # If it is given, default certificates are not used.
661
+ #
662
+ # [:ssl_verify_mode]
663
+ # Synopsis:
664
+ # :ssl_verify_mode=>mode
665
+ #
666
+ # :ssl_verify_mode is used to specify openssl verify mode.
667
+ #
668
+ # [:ftp_active_mode]
669
+ # Synopsis:
670
+ # :ftp_active_mode=>bool
671
+ #
672
+ # <tt>:ftp_active_mode => true</tt> is used to make ftp active mode.
673
+ # Ruby 1.9 uses passive mode by default.
674
+ # Note that the active mode is default in Ruby 1.8 or prior.
675
+ #
676
+ # [:redirect]
677
+ # Synopsis:
678
+ # :redirect=>bool
679
+ #
680
+ # +:redirect+ is true by default. <tt>:redirect => false</tt> is used to
681
+ # disable all HTTP redirects.
682
+ #
683
+ # OpenURI::HTTPRedirect exception raised on redirection.
684
+ # Using +true+ also means that redirections between http and ftp are
685
+ # permitted.
686
+ #
517
687
  def open(*rest, &block)
518
688
  OpenURI.open_uri(self, *rest, &block)
519
689
  end
@@ -521,7 +691,7 @@ module OpenURI
521
691
  # OpenURI::OpenRead#read([options]) reads a content referenced by self and
522
692
  # returns the content as string.
523
693
  # The string is extended with OpenURI::Meta.
524
- # The argument `options' is same as OpenURI::OpenRead#open.
694
+ # The argument +options+ is same as OpenURI::OpenRead#open.
525
695
  def read(options={})
526
696
  self.open(options) {|f|
527
697
  str = f.read
@@ -533,84 +703,6 @@ module OpenURI
533
703
  end
534
704
 
535
705
  module URI
536
- class Generic
537
- # returns a proxy URI.
538
- # The proxy URI is obtained from environment variables such as http_proxy,
539
- # ftp_proxy, no_proxy, etc.
540
- # If there is no proper proxy, nil is returned.
541
- #
542
- # Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.)
543
- # are examined too.
544
- #
545
- # But http_proxy and HTTP_PROXY is treated specially under CGI environment.
546
- # It's because HTTP_PROXY may be set by Proxy: header.
547
- # So HTTP_PROXY is not used.
548
- # http_proxy is not used too if the variable is case insensitive.
549
- # CGI_HTTP_PROXY can be used instead.
550
- def find_proxy
551
- name = self.scheme.downcase + '_proxy'
552
- proxy_uri = nil
553
- if name == 'http_proxy' && ENV.include?('REQUEST_METHOD') # CGI?
554
- # HTTP_PROXY conflicts with *_proxy for proxy settings and
555
- # HTTP_* for header information in CGI.
556
- # So it should be careful to use it.
557
- pairs = ENV.reject {|k, v| /\Ahttp_proxy\z/i !~ k }
558
- case pairs.length
559
- when 0 # no proxy setting anyway.
560
- proxy_uri = nil
561
- when 1
562
- k, v = pairs.shift
563
- if k == 'http_proxy' && ENV[k.upcase] == nil
564
- # http_proxy is safe to use because ENV is case sensitive.
565
- proxy_uri = ENV[name]
566
- else
567
- proxy_uri = nil
568
- end
569
- else # http_proxy is safe to use because ENV is case sensitive.
570
- proxy_uri = ENV.to_hash[name]
571
- end
572
- if !proxy_uri
573
- # Use CGI_HTTP_PROXY. cf. libwww-perl.
574
- proxy_uri = ENV["CGI_#{name.upcase}"]
575
- end
576
- elsif name == 'http_proxy'
577
- unless proxy_uri = ENV[name]
578
- if proxy_uri = ENV[name.upcase]
579
- warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.'
580
- end
581
- end
582
- else
583
- proxy_uri = ENV[name] || ENV[name.upcase]
584
- end
585
-
586
- if proxy_uri && self.host
587
- require 'socket'
588
- begin
589
- addr = IPSocket.getaddress(self.host)
590
- proxy_uri = nil if /\A127\.|\A::1\z/ =~ addr
591
- rescue SocketError
592
- end
593
- end
594
-
595
- if proxy_uri
596
- proxy_uri = URI.parse(proxy_uri)
597
- name = 'no_proxy'
598
- if no_proxy = ENV[name] || ENV[name.upcase]
599
- no_proxy.scan(/([^:,]*)(?::(\d+))?/) {|host, port|
600
- if /(\A|\.)#{Regexp.quote host}\z/i =~ self.host &&
601
- (!port || self.port == port.to_i)
602
- proxy_uri = nil
603
- break
604
- end
605
- }
606
- end
607
- proxy_uri
608
- else
609
- nil
610
- end
611
- end
612
- end
613
-
614
706
  class HTTP
615
707
  def buffer_open(buf, proxy, options) # :nodoc:
616
708
  OpenURI.open_http(buf, self, proxy, options)
@@ -627,8 +719,9 @@ module URI
627
719
  end
628
720
  require 'net/ftp'
629
721
 
630
- directories = self.path.split(%r{/}, -1)
631
- directories.shift if directories[0] == '' # strip a field before leading slash
722
+ path = self.path
723
+ path = path.sub(%r{\A/}, '%2F') # re-encode the beginning slash because uri library decodes it.
724
+ directories = path.split(%r{/}, -1)
632
725
  directories.each {|d|
633
726
  d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }
634
727
  }
@@ -649,7 +742,9 @@ module URI
649
742
  end
650
743
 
651
744
  # The access sequence is defined by RFC 1738
652
- ftp = Net::FTP.open(self.host)
745
+ ftp = Net::FTP.new
746
+ ftp.connect(self.hostname, self.port)
747
+ ftp.passive = true if !options[:ftp_active_mode]
653
748
  # todo: extract user/passwd from .netrc.
654
749
  user = 'anonymous'
655
750
  passwd = nil
@@ -1,5 +1,5 @@
1
1
  module RubySL
2
2
  module OpenURI
3
- VERSION = "1.0.0"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
@@ -19,5 +19,4 @@ Gem::Specification.new do |spec|
19
19
  spec.add_development_dependency "bundler", "~> 1.3"
20
20
  spec.add_development_dependency "rake", "~> 10.0"
21
21
  spec.add_development_dependency "mspec", "~> 1.5"
22
- spec.add_development_dependency "rubysl-prettyprint", "~> 1.0"
23
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubysl-open-uri
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Shirai
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-25 00:00:00.000000000 Z
11
+ date: 2013-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.5'
55
- - !ruby/object:Gem::Dependency
56
- name: rubysl-prettyprint
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '1.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ~>
67
- - !ruby/object:Gem::Version
68
- version: '1.0'
69
55
  description: Ruby standard library uri.
70
56
  email:
71
57
  - brixen@gmail.com