⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 open-uri.rb

📁 Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 经过两年开发后
💻 RB
📖 第 1 页 / 共 2 页
字号:
      if src        obj.status = src.status        obj.base_uri = src.base_uri        src.meta.each {|name, value|          obj.meta_add_field(name, value)        }      end    end    # returns an Array which consists status code and message.    attr_accessor :status    # returns a URI which is base of relative URIs in the data.    # It may differ from the URI supplied by a user because redirection.    attr_accessor :base_uri    # returns a Hash which represents header fields.    # The Hash keys are downcased for canonicalization.    attr_reader :meta    def meta_add_field(name, value) # :nodoc:      @meta[name.downcase] = value    end    # returns a Time which represents Last-Modified field.    def last_modified      if v = @meta['last-modified']        Time.httpdate(v)      else        nil      end    end    RE_LWS = /[\r\n\t ]+/n    RE_TOKEN = %r{[^\x00- ()<>@,;:\\"/\[\]?={}\x7f]+}n    RE_QUOTED_STRING = %r{"(?:[\r\n\t !#-\[\]-~\x80-\xff]|\\[\x00-\x7f])*"}n    RE_PARAMETERS = %r{(?:;#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?=#{RE_LWS}?(?:#{RE_TOKEN}|#{RE_QUOTED_STRING})#{RE_LWS}?)*}n    def content_type_parse # :nodoc:      v = @meta['content-type']      # The last (?:;#{RE_LWS}?)? matches extra ";" which violates RFC2045.      if v && %r{\A#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?/(#{RE_TOKEN})#{RE_LWS}?(#{RE_PARAMETERS})(?:;#{RE_LWS}?)?\z}no =~ v        type = $1.downcase        subtype = $2.downcase        parameters = []        $3.scan(/;#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?=#{RE_LWS}?(?:(#{RE_TOKEN})|(#{RE_QUOTED_STRING}))/no) {|att, val, qval|          val = qval.gsub(/[\r\n\t !#-\[\]-~\x80-\xff]+|(\\[\x00-\x7f])/) { $1 ? $1[1,1] : $& } if qval          parameters << [att.downcase, val]        }        ["#{type}/#{subtype}", *parameters]      else        nil      end    end    # returns "type/subtype" which is MIME Content-Type.    # It is downcased for canonicalization.    # Content-Type parameters are stripped.    def content_type      type, *parameters = content_type_parse      type || 'application/octet-stream'    end    # returns a charset parameter in Content-Type field.    # It is downcased for canonicalization.    #    # If charset parameter is not given but a block is given,    # the block is called and its result is returned.    # It can be used to guess charset.    #    # If charset parameter and block is not given,    # nil is returned except text type in HTTP.    # In that case, "iso-8859-1" is returned as defined by RFC2616 3.7.1.    def charset      type, *parameters = content_type_parse      if pair = parameters.assoc('charset')        pair.last.downcase      elsif block_given?        yield      elsif type && %r{\Atext/} =~ type &&            @base_uri && /\Ahttp\z/i =~ @base_uri.scheme        "iso-8859-1" # RFC2616 3.7.1      else        nil      end    end    # returns a list of encodings in Content-Encoding field    # as an Array of String.    # The encodings are downcased for canonicalization.    def content_encoding      v = @meta['content-encoding']      if v && %r{\A#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?(?:,#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?)*}o =~ v        v.scan(RE_TOKEN).map {|content_coding| content_coding.downcase}      else        []      end    end  end  # Mixin for HTTP and FTP URIs.  module OpenRead    # OpenURI::OpenRead#open provides `open' for URI::HTTP and URI::FTP.    #    # OpenURI::OpenRead#open takes optional 3 arguments as:    # OpenURI::OpenRead#open([mode [, perm]] [, options]) [{|io| ... }]    #    # `mode', `perm' is same as Kernel#open.    #    # However, `mode' must be read mode because OpenURI::OpenRead#open doesn't    # support write mode (yet).    # Also `perm' is just ignored because it is meaningful only for file    # creation.    #    # `options' must be a hash.    #    # Each pairs which key is a string in the hash specify a extra header    # field for HTTP.    # I.e. it is ignored for FTP without HTTP proxy.    #    # The hash may include other options which key is a symbol:    #    # [:proxy]    #  Synopsis:    # :proxy => "http://proxy.foo.com:8000/"    # :proxy => URI.parse("http://proxy.foo.com:8000/")    # :proxy => true    # :proxy => false    # :proxy => nil    #    #    If :proxy option is specified, the value should be String, URI,    #    boolean or nil.    #    When String or URI is given, it is treated as proxy URI.    #    When true is given or the option itself is not specified,    #  environment variable `scheme_proxy' is examined.    #  `scheme' is replaced by `http', `https' or `ftp'.    #    When false or nil is given, the environment variables are ignored and    #    connection will be made to a server directly.    #    # [:proxy_http_basic_authentication]    #  Synopsis:    #    :proxy_http_basic_authentication => ["http://proxy.foo.com:8000/", "proxy-user", "proxy-password"]    #    :proxy_http_basic_authentication => [URI.parse("http://proxy.foo.com:8000/"), "proxy-user", "proxy-password"]    #       #  If :proxy option is specified, the value should be an Array with 3 elements.    #  It should contain a proxy URI, a proxy user name and a proxy password.    #  The proxy URI should be a String, an URI or nil.    #  The proxy user name and password should be a String.    #    #  If nil is given for the proxy URI, this option is just ignored.    #    #  If :proxy and :proxy_http_basic_authentication is specified,     #  ArgumentError is raised.    #    # [:http_basic_authentication]    #  Synopsis:    #    :http_basic_authentication=>[user, password]    #    #  If :http_basic_authentication is specified,    #  the value should be an array which contains 2 strings:    #  username and password.    #  It is used for HTTP Basic authentication defined by RFC 2617.    #    # [:content_length_proc]    #  Synopsis:    # :content_length_proc => lambda {|content_length| ... }    #    #   If :content_length_proc option is specified, the option value procedure    #   is called before actual transfer is started.    #   It takes one argument which is expected content length in bytes.    #    #   If two or more transfer is done by HTTP redirection, the procedure    #   is called only one for a last transfer.    #    #   When expected content length is unknown, the procedure is called with    #   nil.    #   It is happen when HTTP response has no Content-Length header.    #    # [:progress_proc]    #  Synopsis:    # :progress_proc => lambda {|size| ...}    #    #   If :progress_proc option is specified, the proc is called with one    #   argument each time when `open' gets content fragment from network.    #   The argument `size' `size' is a accumulated transfered size in bytes.    #    #   If two or more transfer is done by HTTP redirection, the procedure    #   is called only one for a last transfer.    #    #   :progress_proc and :content_length_proc are intended to be used for    #   progress bar.    #   For example, it can be implemented as follows using Ruby/ProgressBar.    #    #     pbar = nil    #     open("http://...",    #       :content_length_proc => lambda {|t|    #         if t && 0 < t    #           pbar = ProgressBar.new("...", t)    #           pbar.file_transfer_mode    #         end    #       },    #       :progress_proc => lambda {|s|    #         pbar.set s if pbar    #       }) {|f| ... }    #    # [:read_timeout]    #  Synopsis:    #    :read_timeout=>nil     (no timeout)    #    :read_timeout=>10      (10 second)    #    #  :read_timeout option specifies a timeout of read for http connections.    #    # OpenURI::OpenRead#open returns an IO like object if block is not given.    # Otherwise it yields the IO object and return the value of the block.    # The IO object is extended with OpenURI::Meta.    def open(*rest, &block)      OpenURI.open_uri(self, *rest, &block)    end    # OpenURI::OpenRead#read([options]) reads a content referenced by self and    # returns the content as string.    # The string is extended with OpenURI::Meta.    # The argument `options' is same as OpenURI::OpenRead#open.    def read(options={})      self.open(options) {|f|        str = f.read        Meta.init str, f        str      }    end  endendmodule URI  class Generic    # returns a proxy URI.    # The proxy URI is obtained from environment variables such as http_proxy,    # ftp_proxy, no_proxy, etc.    # If there is no proper proxy, nil is returned.    #    # Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.)    # are examined too.    #    # But http_proxy and HTTP_PROXY is treated specially under CGI environment.    # It's because HTTP_PROXY may be set by Proxy: header.    # So HTTP_PROXY is not used.    # http_proxy is not used too if the variable is case insensitive.    # CGI_HTTP_PROXY can be used instead.    def find_proxy      name = self.scheme.downcase + '_proxy'      proxy_uri = nil      if name == 'http_proxy' && ENV.include?('REQUEST_METHOD') # CGI?        # HTTP_PROXY conflicts with *_proxy for proxy settings and        # HTTP_* for header information in CGI.        # So it should be careful to use it.        pairs = ENV.reject {|k, v| /\Ahttp_proxy\z/i !~ k }        case pairs.length        when 0 # no proxy setting anyway.          proxy_uri = nil        when 1          k, v = pairs.shift          if k == 'http_proxy' && ENV[k.upcase] == nil            # http_proxy is safe to use because ENV is case sensitive.            proxy_uri = ENV[name]          else            proxy_uri = nil          end        else # http_proxy is safe to use because ENV is case sensitive.          proxy_uri = ENV[name]        end        if !proxy_uri          # Use CGI_HTTP_PROXY.  cf. libwww-perl.          proxy_uri = ENV["CGI_#{name.upcase}"]        end      elsif name == 'http_proxy'        unless proxy_uri = ENV[name]          if proxy_uri = ENV[name.upcase]            warn 'The environment variable HTTP_PROXY is discouraged.  Use http_proxy.'          end        end      else        proxy_uri = ENV[name] || ENV[name.upcase]      end      if proxy_uri && self.host        require 'socket'        begin          addr = IPSocket.getaddress(self.host)          proxy_uri = nil if /\A127\.|\A::1\z/ =~ addr        rescue SocketError        end      end      if proxy_uri        proxy_uri = URI.parse(proxy_uri)        name = 'no_proxy'        if no_proxy = ENV[name] || ENV[name.upcase]          no_proxy.scan(/([^:,]*)(?::(\d+))?/) {|host, port|            if /(\A|\.)#{Regexp.quote host}\z/i =~ self.host &&               (!port || self.port == port.to_i)              proxy_uri = nil              break            end          }        end        proxy_uri      else        nil      end    end  end  class HTTP    def buffer_open(buf, proxy, options) # :nodoc:      OpenURI.open_http(buf, self, proxy, options)    end    include OpenURI::OpenRead      end  class FTP    def buffer_open(buf, proxy, options) # :nodoc:      if proxy        OpenURI.open_http(buf, self, proxy, options)        return            end      require 'net/ftp'      directories = self.path.split(%r{/}, -1)      directories.shift if directories[0] == '' # strip a field before leading slash      directories.each {|d|        d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }      }      unless filename = directories.pop        raise ArgumentError, "no filename: #{self.inspect}"          end      directories.each {|d|        if /[\r\n]/ =~ d          raise ArgumentError, "invalid directory: #{d.inspect}"            end          }      if /[\r\n]/ =~ filename        raise ArgumentError, "invalid filename: #{filename.inspect}"    end      typecode = self.typecode      if typecode && /\A[aid]\z/ !~ typecode        raise ArgumentError, "invalid typecode: #{typecode.inspect}"  end      # The access sequence is defined by RFC 1738      ftp = Net::FTP.open(self.host)      # todo: extract user/passwd from .netrc.      user = 'anonymous'      passwd = nil      user, passwd = self.userinfo.split(/:/) if self.userinfo      ftp.login(user, passwd)      directories.each {|cwd|        ftp.voidcmd("CWD #{cwd}")      }      if typecode        # xxx: typecode D is not handled.        ftp.voidcmd("TYPE #{typecode.upcase}")      end      if options[:content_length_proc]        options[:content_length_proc].call(ftp.size(filename))      end      ftp.retrbinary("RETR #{filename}", 4096) { |str|        buf << str        options[:progress_proc].call(buf.size) if options[:progress_proc]      }      ftp.close      buf.io.rewind    end    include OpenURI::OpenRead  endend

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -