rubysl-open-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.
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