athlite_open-uri 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
File without changes
@@ -0,0 +1,3 @@
1
+ === 0.0.1 2011-11-08
2
+
3
+ * Ripped from standard lib, and added the possibility to add option :ssl_verify
@@ -0,0 +1,7 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/open-uri.rb
6
+ test/test_helper.rb
7
+ test/test_open-uri.rb
@@ -0,0 +1,13 @@
1
+ = open-uri
2
+
3
+ * http://github.com/athlite/open-uri
4
+
5
+ == DESCRIPTION:
6
+
7
+ OpenURI ripped from 1.8.7's standard lib. Added option, :ssl_verify, which makes it possible to skip certificate verification.
8
+
9
+ == SYNOPSIS:
10
+
11
+ open(url, :ssl_verify => false|true)
12
+
13
+
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/open-uri'
6
+
7
+ Hoe.plugin :newgem
8
+
9
+ $hoe = Hoe.spec 'athlite_open-uri' do
10
+ self.version = "0.0.1"
11
+ self.developer 'Thomas Tinnesand Eng', 'thomas.tinnesand.eng@gmail.com'
12
+ self.rubyforge_name = self.name
13
+ end
14
+
15
+ require 'newgem/tasks'
16
+ Dir['tasks/**/*.rake'].each { |t| load t }
@@ -0,0 +1,686 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'uri'
5
+ require 'stringio'
6
+ require 'time'
7
+
8
+ module Kernel
9
+ private
10
+ alias open_uri_original_open open # :nodoc:
11
+
12
+ # makes possible to open various resources including URIs.
13
+ # If the first argument respond to `open' method,
14
+ # the method is called with the rest arguments.
15
+ #
16
+ # If the first argument is a string which begins with xxx://,
17
+ # it is parsed by URI.parse. If the parsed object respond to `open' method,
18
+ # the method is called with the rest arguments.
19
+ #
20
+ # Otherwise original open is called.
21
+ #
22
+ # Since open-uri.rb provides URI::HTTP#open, URI::HTTPS#open and
23
+ # URI::FTP#open,
24
+ # Kernel[#.]open can accepts such URIs and strings which begins with
25
+ # http://, https:// and ftp://.
26
+ # In these case, the opened file object is extended by OpenURI::Meta.
27
+ def open(name, *rest, &block) # :doc:
28
+ if name.respond_to?(:open)
29
+ name.open(*rest, &block)
30
+ elsif name.respond_to?(:to_str) &&
31
+ %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ name &&
32
+ (uri = URI.parse(name)).respond_to?(:open)
33
+ uri.open(*rest, &block)
34
+ else
35
+ open_uri_original_open(name, *rest, &block)
36
+ end
37
+ end
38
+ module_function :open
39
+ end
40
+
41
+ # OpenURI is an easy-to-use wrapper for net/http, net/https and net/ftp.
42
+ #
43
+ #== Example
44
+ #
45
+ # It is possible to open http/https/ftp URL as usual like opening a file:
46
+ #
47
+ # open("http://www.ruby-lang.org/") {|f|
48
+ # f.each_line {|line| p line}
49
+ # }
50
+ #
51
+ # The opened file has several methods for meta information as follows since
52
+ # it is extended by OpenURI::Meta.
53
+ #
54
+ # open("http://www.ruby-lang.org/en") {|f|
55
+ # f.each_line {|line| p line}
56
+ # p f.base_uri # <URI::HTTP:0x40e6ef2 URL:http://www.ruby-lang.org/en/>
57
+ # p f.content_type # "text/html"
58
+ # p f.charset # "iso-8859-1"
59
+ # p f.content_encoding # []
60
+ # p f.last_modified # Thu Dec 05 02:45:02 UTC 2002
61
+ # }
62
+ #
63
+ # Additional header fields can be specified by an optional hash argument.
64
+ #
65
+ # open("http://www.ruby-lang.org/en/",
66
+ # "User-Agent" => "Ruby/#{RUBY_VERSION}",
67
+ # "From" => "foo@bar.invalid",
68
+ # "Referer" => "http://www.ruby-lang.org/") {|f|
69
+ # # ...
70
+ # }
71
+ #
72
+ # The environment variables such as http_proxy, https_proxy and ftp_proxy
73
+ # are in effect by default. :proxy => nil disables proxy.
74
+ #
75
+ # open("http://www.ruby-lang.org/en/raa.html", :proxy => nil) {|f|
76
+ # # ...
77
+ # }
78
+ #
79
+ # URI objects can be opened in a similar way.
80
+ #
81
+ # uri = URI.parse("http://www.ruby-lang.org/en/")
82
+ # uri.open {|f|
83
+ # # ...
84
+ # }
85
+ #
86
+ # URI objects can be read directly. The returned string is also extended by
87
+ # OpenURI::Meta.
88
+ #
89
+ # str = uri.read
90
+ # p str.base_uri
91
+ #
92
+ # Author:: Tanaka Akira <akr@m17n.org>
93
+
94
+ module OpenURI
95
+ Options = {
96
+ :proxy => true,
97
+ :progress_proc => true,
98
+ :content_length_proc => true,
99
+ :http_basic_authentication => true,
100
+ :ssl_verify => true
101
+ }
102
+
103
+ def OpenURI.check_options(options) # :nodoc:
104
+ options.each {|k, v|
105
+ next unless Symbol === k
106
+ unless Options.include? k
107
+ raise ArgumentError, "unrecognized option: #{k}"
108
+ end
109
+ }
110
+ end
111
+
112
+ def OpenURI.scan_open_optional_arguments(*rest) # :nodoc:
113
+ if !rest.empty? && (String === rest.first || Integer === rest.first)
114
+ mode = rest.shift
115
+ if !rest.empty? && Integer === rest.first
116
+ perm = rest.shift
117
+ end
118
+ end
119
+ return mode, perm, rest
120
+ end
121
+
122
+ def OpenURI.open_uri(name, *rest) # :nodoc:
123
+ uri = URI::Generic === name ? name : URI.parse(name)
124
+ mode, perm, rest = OpenURI.scan_open_optional_arguments(*rest)
125
+ options = rest.shift if !rest.empty? && Hash === rest.first
126
+ raise ArgumentError.new("extra arguments") if !rest.empty?
127
+ options ||= {}
128
+ OpenURI.check_options(options)
129
+
130
+ unless mode == nil ||
131
+ mode == 'r' || mode == 'rb' ||
132
+ mode == File::RDONLY
133
+ raise ArgumentError.new("invalid access mode #{mode} (#{uri.class} resource is read only.)")
134
+ end
135
+
136
+ io = open_loop(uri, options)
137
+ if block_given?
138
+ begin
139
+ yield io
140
+ ensure
141
+ io.close
142
+ end
143
+ else
144
+ io
145
+ end
146
+ end
147
+
148
+ def OpenURI.open_loop(uri, options) # :nodoc:
149
+ case opt_proxy = options.fetch(:proxy, true)
150
+ when true
151
+ find_proxy = lambda {|u| u.find_proxy}
152
+ when nil, false
153
+ find_proxy = lambda {|u| nil}
154
+ when String
155
+ opt_proxy = URI.parse(opt_proxy)
156
+ find_proxy = lambda {|u| opt_proxy}
157
+ when URI::Generic
158
+ find_proxy = lambda {|u| opt_proxy}
159
+ else
160
+ raise ArgumentError.new("Invalid proxy option: #{opt_proxy}")
161
+ end
162
+
163
+ uri_set = {}
164
+ buf = nil
165
+ while true
166
+ redirect = catch(:open_uri_redirect) {
167
+ buf = Buffer.new
168
+ uri.buffer_open(buf, find_proxy.call(uri), options)
169
+ nil
170
+ }
171
+ if redirect
172
+ if redirect.relative?
173
+ # Although it violates RFC2616, Location: field may have relative
174
+ # URI. It is converted to absolute URI using uri as a base URI.
175
+ redirect = uri + redirect
176
+ end
177
+ unless OpenURI.redirectable?(uri, redirect)
178
+ raise "redirection forbidden: #{uri} -> #{redirect}"
179
+ end
180
+ if options.include? :http_basic_authentication
181
+ # send authentication only for the URI directly specified.
182
+ options = options.dup
183
+ options.delete :http_basic_authentication
184
+ end
185
+ uri = redirect
186
+ raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s
187
+ uri_set[uri.to_s] = true
188
+ else
189
+ break
190
+ end
191
+ end
192
+ io = buf.io
193
+ io.base_uri = uri
194
+ io
195
+ end
196
+
197
+ def OpenURI.redirectable?(uri1, uri2) # :nodoc:
198
+ # This test is intended to forbid a redirection from http://... to
199
+ # file:///etc/passwd.
200
+ # However this is ad hoc. It should be extensible/configurable.
201
+ uri1.scheme.downcase == uri2.scheme.downcase ||
202
+ (/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp)\z/i =~ uri2.scheme)
203
+ end
204
+
205
+ def OpenURI.open_http(buf, target, proxy, options) # :nodoc:
206
+ if proxy
207
+ raise "Non-HTTP proxy URI: #{proxy}" if proxy.class != URI::HTTP
208
+ end
209
+
210
+ if target.userinfo && "1.9.0" <= RUBY_VERSION
211
+ # don't raise for 1.8 because compatibility.
212
+ raise ArgumentError, "userinfo not supported. [RFC3986]"
213
+ end
214
+
215
+ require 'net/http'
216
+ klass = Net::HTTP
217
+ if URI::HTTP === target
218
+ # HTTP or HTTPS
219
+ if proxy
220
+ klass = Net::HTTP::Proxy(proxy.host, proxy.port)
221
+ end
222
+ target_host = target.host
223
+ target_port = target.port
224
+ request_uri = target.request_uri
225
+ else
226
+ # FTP over HTTP proxy
227
+ target_host = proxy.host
228
+ target_port = proxy.port
229
+ request_uri = target.to_s
230
+ end
231
+
232
+ http = klass.new(target_host, target_port)
233
+ if target.class == URI::HTTPS
234
+ require 'net/https'
235
+ http.use_ssl = true
236
+ if options[:ssl_verify]
237
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
238
+ else
239
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
240
+ end
241
+ store = OpenSSL::X509::Store.new
242
+ store.set_default_paths
243
+ http.cert_store = store
244
+ end
245
+
246
+ header = {}
247
+ options.each {|k, v| header[k] = v if String === k }
248
+
249
+ resp = nil
250
+ http.start {
251
+ req = Net::HTTP::Get.new(request_uri, header)
252
+ if options.include? :http_basic_authentication
253
+ user, pass = options[:http_basic_authentication]
254
+ req.basic_auth user, pass
255
+ end
256
+ http.request(req) {|response|
257
+ resp = response
258
+ if options[:content_length_proc] && Net::HTTPSuccess === resp
259
+ if resp.key?('Content-Length')
260
+ options[:content_length_proc].call(resp['Content-Length'].to_i)
261
+ else
262
+ options[:content_length_proc].call(nil)
263
+ end
264
+ end
265
+ resp.read_body {|str|
266
+ buf << str
267
+ if options[:progress_proc] && Net::HTTPSuccess === resp
268
+ options[:progress_proc].call(buf.size)
269
+ end
270
+ }
271
+ }
272
+ }
273
+ io = buf.io
274
+ io.rewind
275
+ io.status = [resp.code, resp.message]
276
+ resp.each {|name,value| buf.io.meta_add_field name, value }
277
+ case resp
278
+ when Net::HTTPSuccess
279
+ when Net::HTTPMovedPermanently, # 301
280
+ Net::HTTPFound, # 302
281
+ Net::HTTPSeeOther, # 303
282
+ Net::HTTPTemporaryRedirect # 307
283
+ throw :open_uri_redirect, URI.parse(resp['location'])
284
+ else
285
+ raise OpenURI::HTTPError.new(io.status.join(' '), io)
286
+ end
287
+ end
288
+
289
+ class HTTPError < StandardError
290
+ def initialize(message, io)
291
+ super(message)
292
+ @io = io
293
+ end
294
+ attr_reader :io
295
+ end
296
+
297
+ class Buffer # :nodoc:
298
+ def initialize
299
+ @io = StringIO.new
300
+ @size = 0
301
+ end
302
+ attr_reader :size
303
+
304
+ StringMax = 10240
305
+ def <<(str)
306
+ @io << str
307
+ @size += str.length
308
+ if StringIO === @io && StringMax < @size
309
+ require 'tempfile'
310
+ io = Tempfile.new('open-uri')
311
+ io.binmode
312
+ Meta.init io, @io if @io.respond_to? :meta
313
+ io << @io.string
314
+ @io = io
315
+ end
316
+ end
317
+
318
+ def io
319
+ Meta.init @io unless @io.respond_to? :meta
320
+ @io
321
+ end
322
+ end
323
+
324
+ # Mixin for holding meta-information.
325
+ module Meta
326
+ def Meta.init(obj, src=nil) # :nodoc:
327
+ obj.extend Meta
328
+ obj.instance_eval {
329
+ @base_uri = nil
330
+ @meta = {}
331
+ }
332
+ if src
333
+ obj.status = src.status
334
+ obj.base_uri = src.base_uri
335
+ src.meta.each {|name, value|
336
+ obj.meta_add_field(name, value)
337
+ }
338
+ end
339
+ end
340
+
341
+ # returns an Array which consists status code and message.
342
+ attr_accessor :status
343
+
344
+ # returns a URI which is base of relative URIs in the data.
345
+ # It may differ from the URI supplied by a user because redirection.
346
+ attr_accessor :base_uri
347
+
348
+ # returns a Hash which represents header fields.
349
+ # The Hash keys are downcased for canonicalization.
350
+ attr_reader :meta
351
+
352
+ def meta_add_field(name, value) # :nodoc:
353
+ @meta[name.downcase] = value
354
+ end
355
+
356
+ # returns a Time which represents Last-Modified field.
357
+ def last_modified
358
+ if v = @meta['last-modified']
359
+ Time.httpdate(v)
360
+ else
361
+ nil
362
+ end
363
+ end
364
+
365
+ RE_LWS = /[\r\n\t ]+/n
366
+ RE_TOKEN = %r{[^\x00- ()<>@,;:\\"/\[\]?={}\x7f]+}n
367
+ RE_QUOTED_STRING = %r{"(?:[\r\n\t !#-\[\]-~\x80-\xff]|\\[\x00-\x7f])*"}n
368
+ RE_PARAMETERS = %r{(?:;#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?=#{RE_LWS}?(?:#{RE_TOKEN}|#{RE_QUOTED_STRING})#{RE_LWS}?)*}n
369
+
370
+ def content_type_parse # :nodoc:
371
+ v = @meta['content-type']
372
+ # The last (?:;#{RE_LWS}?)? matches extra ";" which violates RFC2045.
373
+ if v && %r{\A#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?/(#{RE_TOKEN})#{RE_LWS}?(#{RE_PARAMETERS})(?:;#{RE_LWS}?)?\z}no =~ v
374
+ type = $1.downcase
375
+ subtype = $2.downcase
376
+ parameters = []
377
+ $3.scan(/;#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?=#{RE_LWS}?(?:(#{RE_TOKEN})|(#{RE_QUOTED_STRING}))/no) {|att, val, qval|
378
+ val = qval.gsub(/[\r\n\t !#-\[\]-~\x80-\xff]+|(\\[\x00-\x7f])/) { $1 ? $1[1,1] : $& } if qval
379
+ parameters << [att.downcase, val]
380
+ }
381
+ ["#{type}/#{subtype}", *parameters]
382
+ else
383
+ nil
384
+ end
385
+ end
386
+
387
+ # returns "type/subtype" which is MIME Content-Type.
388
+ # It is downcased for canonicalization.
389
+ # Content-Type parameters are stripped.
390
+ def content_type
391
+ type, *parameters = content_type_parse
392
+ type || 'application/octet-stream'
393
+ end
394
+
395
+ # returns a charset parameter in Content-Type field.
396
+ # It is downcased for canonicalization.
397
+ #
398
+ # If charset parameter is not given but a block is given,
399
+ # the block is called and its result is returned.
400
+ # It can be used to guess charset.
401
+ #
402
+ # If charset parameter and block is not given,
403
+ # nil is returned except text type in HTTP.
404
+ # In that case, "iso-8859-1" is returned as defined by RFC2616 3.7.1.
405
+ def charset
406
+ type, *parameters = content_type_parse
407
+ if pair = parameters.assoc('charset')
408
+ pair.last.downcase
409
+ elsif block_given?
410
+ yield
411
+ elsif type && %r{\Atext/} =~ type &&
412
+ @base_uri && /\Ahttp\z/i =~ @base_uri.scheme
413
+ "iso-8859-1" # RFC2616 3.7.1
414
+ else
415
+ nil
416
+ end
417
+ end
418
+
419
+ # returns a list of encodings in Content-Encoding field
420
+ # as an Array of String.
421
+ # The encodings are downcased for canonicalization.
422
+ def content_encoding
423
+ v = @meta['content-encoding']
424
+ if v && %r{\A#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?(?:,#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?)*}o =~ v
425
+ v.scan(RE_TOKEN).map {|content_coding| content_coding.downcase}
426
+ else
427
+ []
428
+ end
429
+ end
430
+ end
431
+
432
+ # Mixin for HTTP and FTP URIs.
433
+ module OpenRead
434
+ # OpenURI::OpenRead#open provides `open' for URI::HTTP and URI::FTP.
435
+ #
436
+ # OpenURI::OpenRead#open takes optional 3 arguments as:
437
+ # OpenURI::OpenRead#open([mode [, perm]] [, options]) [{|io| ... }]
438
+ #
439
+ # `mode', `perm' is same as Kernel#open.
440
+ #
441
+ # However, `mode' must be read mode because OpenURI::OpenRead#open doesn't
442
+ # support write mode (yet).
443
+ # Also `perm' is just ignored because it is meaningful only for file
444
+ # creation.
445
+ #
446
+ # `options' must be a hash.
447
+ #
448
+ # Each pairs which key is a string in the hash specify a extra header
449
+ # field for HTTP.
450
+ # I.e. it is ignored for FTP without HTTP proxy.
451
+ #
452
+ # The hash may include other options which key is a symbol:
453
+ #
454
+ # [:proxy]
455
+ # Synopsis:
456
+ # :proxy => "http://proxy.foo.com:8000/"
457
+ # :proxy => URI.parse("http://proxy.foo.com:8000/")
458
+ # :proxy => true
459
+ # :proxy => false
460
+ # :proxy => nil
461
+ #
462
+ # If :proxy option is specified, the value should be String, URI,
463
+ # boolean or nil.
464
+ # When String or URI is given, it is treated as proxy URI.
465
+ # When true is given or the option itself is not specified,
466
+ # environment variable `scheme_proxy' is examined.
467
+ # `scheme' is replaced by `http', `https' or `ftp'.
468
+ # When false or nil is given, the environment variables are ignored and
469
+ # connection will be made to a server directly.
470
+ #
471
+ # [:http_basic_authentication]
472
+ # Synopsis:
473
+ # :http_basic_authentication=>[user, password]
474
+ #
475
+ # If :http_basic_authentication is specified,
476
+ # the value should be an array which contains 2 strings:
477
+ # username and password.
478
+ # It is used for HTTP Basic authentication defined by RFC 2617.
479
+ #
480
+ # [:content_length_proc]
481
+ # Synopsis:
482
+ # :content_length_proc => lambda {|content_length| ... }
483
+ #
484
+ # If :content_length_proc option is specified, the option value procedure
485
+ # is called before actual transfer is started.
486
+ # It takes one argument which is expected content length in bytes.
487
+ #
488
+ # If two or more transfer is done by HTTP redirection, the procedure
489
+ # is called only one for a last transfer.
490
+ #
491
+ # When expected content length is unknown, the procedure is called with
492
+ # nil.
493
+ # It is happen when HTTP response has no Content-Length header.
494
+ #
495
+ # [:progress_proc]
496
+ # Synopsis:
497
+ # :progress_proc => lambda {|size| ...}
498
+ #
499
+ # If :progress_proc option is specified, the proc is called with one
500
+ # argument each time when `open' gets content fragment from network.
501
+ # The argument `size' `size' is a accumulated transfered size in bytes.
502
+ #
503
+ # If two or more transfer is done by HTTP redirection, the procedure
504
+ # is called only one for a last transfer.
505
+ #
506
+ # :progress_proc and :content_length_proc are intended to be used for
507
+ # progress bar.
508
+ # For example, it can be implemented as follows using Ruby/ProgressBar.
509
+ #
510
+ # pbar = nil
511
+ # open("http://...",
512
+ # :content_length_proc => lambda {|t|
513
+ # if t && 0 < t
514
+ # pbar = ProgressBar.new("...", t)
515
+ # pbar.file_transfer_mode
516
+ # end
517
+ # },
518
+ # :progress_proc => lambda {|s|
519
+ # pbar.set s if pbar
520
+ # }) {|f| ... }
521
+ #
522
+ # OpenURI::OpenRead#open returns an IO like object if block is not given.
523
+ # Otherwise it yields the IO object and return the value of the block.
524
+ # The IO object is extended with OpenURI::Meta.
525
+ def open(*rest, &block)
526
+ OpenURI.open_uri(self, *rest, &block)
527
+ end
528
+
529
+ # OpenURI::OpenRead#read([options]) reads a content referenced by self and
530
+ # returns the content as string.
531
+ # The string is extended with OpenURI::Meta.
532
+ # The argument `options' is same as OpenURI::OpenRead#open.
533
+ def read(options={})
534
+ self.open(options) {|f|
535
+ str = f.read
536
+ Meta.init str, f
537
+ str
538
+ }
539
+ end
540
+ end
541
+ end
542
+
543
+ module URI
544
+ class Generic
545
+ # returns a proxy URI.
546
+ # The proxy URI is obtained from environment variables such as http_proxy,
547
+ # ftp_proxy, no_proxy, etc.
548
+ # If there is no proper proxy, nil is returned.
549
+ #
550
+ # Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.)
551
+ # are examined too.
552
+ #
553
+ # But http_proxy and HTTP_PROXY is treated specially under CGI environment.
554
+ # It's because HTTP_PROXY may be set by Proxy: header.
555
+ # So HTTP_PROXY is not used.
556
+ # http_proxy is not used too if the variable is case insensitive.
557
+ # CGI_HTTP_PROXY can be used instead.
558
+ def find_proxy
559
+ name = self.scheme.downcase + '_proxy'
560
+ proxy_uri = nil
561
+ if name == 'http_proxy' && ENV.include?('REQUEST_METHOD') # CGI?
562
+ # HTTP_PROXY conflicts with *_proxy for proxy settings and
563
+ # HTTP_* for header information in CGI.
564
+ # So it should be careful to use it.
565
+ pairs = ENV.reject {|k, v| /\Ahttp_proxy\z/i !~ k }
566
+ case pairs.length
567
+ when 0 # no proxy setting anyway.
568
+ proxy_uri = nil
569
+ when 1
570
+ k, v = pairs.shift
571
+ if k == 'http_proxy' && ENV[k.upcase] == nil
572
+ # http_proxy is safe to use because ENV is case sensitive.
573
+ proxy_uri = ENV[name]
574
+ else
575
+ proxy_uri = nil
576
+ end
577
+ else # http_proxy is safe to use because ENV is case sensitive.
578
+ proxy_uri = ENV.to_hash[name]
579
+ end
580
+ if !proxy_uri
581
+ # Use CGI_HTTP_PROXY. cf. libwww-perl.
582
+ proxy_uri = ENV["CGI_#{name.upcase}"]
583
+ end
584
+ elsif name == 'http_proxy'
585
+ unless proxy_uri = ENV[name]
586
+ if proxy_uri = ENV[name.upcase]
587
+ warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.'
588
+ end
589
+ end
590
+ else
591
+ proxy_uri = ENV[name] || ENV[name.upcase]
592
+ end
593
+
594
+ if proxy_uri && self.host
595
+ require 'socket'
596
+ begin
597
+ addr = IPSocket.getaddress(self.host)
598
+ proxy_uri = nil if /\A127\.|\A::1\z/ =~ addr
599
+ rescue SocketError
600
+ end
601
+ end
602
+
603
+ if proxy_uri
604
+ proxy_uri = URI.parse(proxy_uri)
605
+ name = 'no_proxy'
606
+ if no_proxy = ENV[name] || ENV[name.upcase]
607
+ no_proxy.scan(/([^:,]*)(?::(\d+))?/) {|host, port|
608
+ if /(\A|\.)#{Regexp.quote host}\z/i =~ self.host &&
609
+ (!port || self.port == port.to_i)
610
+ proxy_uri = nil
611
+ break
612
+ end
613
+ }
614
+ end
615
+ proxy_uri
616
+ else
617
+ nil
618
+ end
619
+ end
620
+ end
621
+
622
+ class HTTP
623
+ def buffer_open(buf, proxy, options) # :nodoc:
624
+ OpenURI.open_http(buf, self, proxy, options)
625
+ end
626
+
627
+ include OpenURI::OpenRead
628
+ end
629
+
630
+ class FTP
631
+ def buffer_open(buf, proxy, options) # :nodoc:
632
+ if proxy
633
+ OpenURI.open_http(buf, self, proxy, options)
634
+ return
635
+ end
636
+ require 'net/ftp'
637
+
638
+ directories = self.path.split(%r{/}, -1)
639
+ directories.shift if directories[0] == '' # strip a field before leading slash
640
+ directories.each {|d|
641
+ d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }
642
+ }
643
+ unless filename = directories.pop
644
+ raise ArgumentError, "no filename: #{self.inspect}"
645
+ end
646
+ directories.each {|d|
647
+ if /[\r\n]/ =~ d
648
+ raise ArgumentError, "invalid directory: #{d.inspect}"
649
+ end
650
+ }
651
+ if /[\r\n]/ =~ filename
652
+ raise ArgumentError, "invalid filename: #{filename.inspect}"
653
+ end
654
+ typecode = self.typecode
655
+ if typecode && /\A[aid]\z/ !~ typecode
656
+ raise ArgumentError, "invalid typecode: #{typecode.inspect}"
657
+ end
658
+
659
+ # The access sequence is defined by RFC 1738
660
+ ftp = Net::FTP.open(self.host)
661
+ # todo: extract user/passwd from .netrc.
662
+ user = 'anonymous'
663
+ passwd = nil
664
+ user, passwd = self.userinfo.split(/:/) if self.userinfo
665
+ ftp.login(user, passwd)
666
+ directories.each {|cwd|
667
+ ftp.voidcmd("CWD #{cwd}")
668
+ }
669
+ if typecode
670
+ # xxx: typecode D is not handled.
671
+ ftp.voidcmd("TYPE #{typecode.upcase}")
672
+ end
673
+ if options[:content_length_proc]
674
+ options[:content_length_proc].call(ftp.size(filename))
675
+ end
676
+ ftp.retrbinary("RETR #{filename}", 4096) { |str|
677
+ buf << str
678
+ options[:progress_proc].call(buf.size) if options[:progress_proc]
679
+ }
680
+ ftp.close
681
+ buf.io.rewind
682
+ end
683
+
684
+ include OpenURI::OpenRead
685
+ end
686
+ end
@@ -0,0 +1,3 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../lib/open-uri'
@@ -0,0 +1,14 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestOpenUri < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ url = "https://assl.site.com"
10
+ file = open(url,:ssl_verify => false)
11
+ content = file.read
12
+ assert content.length > 0
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: athlite_open-uri
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Thomas Tinnesand Eng
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-11-08 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: hoe
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 27
30
+ segments:
31
+ - 2
32
+ - 12
33
+ version: "2.12"
34
+ type: :development
35
+ version_requirements: *id001
36
+ description: OpenURI ripped from 1.8.7's standard lib. Added option, :ssl_verify, which makes it possible to skip certificate verification.
37
+ email:
38
+ - thomas.tinnesand.eng@gmail.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files:
44
+ - History.txt
45
+ - Manifest.txt
46
+ files:
47
+ - History.txt
48
+ - Manifest.txt
49
+ - README.rdoc
50
+ - Rakefile
51
+ - lib/open-uri.rb
52
+ - test/test_helper.rb
53
+ - test/test_open-uri.rb
54
+ - .gemtest
55
+ has_rdoc: true
56
+ homepage: http://github.com/athlite/open-uri
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --main
62
+ - README.rdoc
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 3
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project: athlite_open-uri
86
+ rubygems_version: 1.6.2
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: OpenURI ripped from 1.8.7's standard lib
90
+ test_files:
91
+ - test/test_helper.rb
92
+ - test/test_open-uri.rb