webrick 1.8.1 → 1.9.1
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 +4 -4
- data/Gemfile +4 -0
- data/README.md +2 -0
- data/Rakefile +0 -7
- data/lib/webrick/cgi.rb +1 -1
- data/lib/webrick/httpauth/authenticator.rb +4 -4
- data/lib/webrick/httpauth/htgroup.rb +1 -1
- data/lib/webrick/httpauth/htpasswd.rb +2 -2
- data/lib/webrick/httpproxy.rb +4 -4
- data/lib/webrick/httprequest.rb +42 -14
- data/lib/webrick/httpresponse.rb +1 -1
- data/lib/webrick/httpserver.rb +2 -2
- data/lib/webrick/httpservlet/abstract.rb +1 -1
- data/lib/webrick/httpservlet/filehandler.rb +6 -6
- data/lib/webrick/httputils.rb +34 -14
- data/lib/webrick/server.rb +1 -1
- data/lib/webrick/version.rb +1 -1
- data/sig/accesslog.rbs +24 -0
- data/sig/cgi.rbs +92 -0
- data/sig/compat.rbs +18 -0
- data/sig/config.rbs +17 -0
- data/sig/cookie.rbs +37 -0
- data/sig/htmlutils.rbs +5 -0
- data/sig/httpauth/authenticator.rbs +55 -0
- data/sig/httpauth/basicauth.rbs +29 -0
- data/sig/httpauth/digestauth.rbs +85 -0
- data/sig/httpauth/htdigest.rbs +31 -0
- data/sig/httpauth/htgroup.rbs +21 -0
- data/sig/httpauth/htpasswd.rbs +31 -0
- data/sig/httpauth/userdb.rbs +13 -0
- data/sig/httpauth.rbs +13 -0
- data/sig/httpproxy.rbs +61 -0
- data/sig/httprequest.rbs +167 -0
- data/sig/httpresponse.rbs +117 -0
- data/sig/https.rbs +49 -0
- data/sig/httpserver.rbs +71 -0
- data/sig/httpservlet/abstract.rbs +36 -0
- data/sig/httpservlet/cgi_runner.rbs +3 -0
- data/sig/httpservlet/cgihandler.rbs +23 -0
- data/sig/httpservlet/erbhandler.rbs +17 -0
- data/sig/httpservlet/filehandler.rbs +76 -0
- data/sig/httpservlet/prochandler.rbs +21 -0
- data/sig/httpservlet.rbs +4 -0
- data/sig/httpstatus.rbs +255 -0
- data/sig/httputils.rbs +116 -0
- data/sig/httpversion.rbs +17 -0
- data/sig/log.rbs +93 -0
- data/sig/manifest.yaml +8 -0
- data/sig/server.rbs +57 -0
- data/sig/ssl.rbs +19 -0
- data/sig/utils.rbs +122 -0
- data/sig/version.rbs +3 -0
- data/webrick.gemspec +35 -0
- metadata +43 -8
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d133a0575bc3ed8393d991def2829498130eac921b9485e47d00a6259ec00fe6
         | 
| 4 | 
            +
              data.tar.gz: 2e8da0c038c346abc67b325c41408199eb6475ee7fad9a155c67330ca15c5aed
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: c5f68a58deca28be7dbde1b557a17a16f9d69c244c567830b89b22c26689db8b28e6a69097e6f47fc3d50d9caea69c691ead0468ef13777081aaf03e0d7c46f2
         | 
| 7 | 
            +
              data.tar.gz: b9c35a51cf9d662d2151dd40d79c2cceebe5404fe5e8464cd666eff3127729a7225b728e78f59bfc08ea545b4de1046dad1c08a65e1e2fd402e91a0c53a264e6
         | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -10,6 +10,8 @@ A WEBrick server can be composed of multiple WEBrick servers or servlets to prov | |
| 10 10 |  | 
| 11 11 | 
             
            WEBrick also includes tools for daemonizing a process and starting a process at a higher privilege level and dropping permissions.
         | 
| 12 12 |  | 
| 13 | 
            +
            WEBrick is suitable for use in testing and for development.  However, while the developers of WEBrick will attempt to fix security issues, they do not encourage the use of WEBrick to serve production web applications that may be subject to hostile input.
         | 
| 14 | 
            +
             | 
| 13 15 | 
             
            ## Installation
         | 
| 14 16 |  | 
| 15 17 | 
             
            Add this line to your application's Gemfile:
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -7,11 +7,4 @@ Rake::TestTask.new(:test) do |t| | |
| 7 7 | 
             
              t.test_files = FileList["test/**/test_*.rb"]
         | 
| 8 8 | 
             
            end
         | 
| 9 9 |  | 
| 10 | 
            -
            task :sync_tool do
         | 
| 11 | 
            -
              require 'fileutils'
         | 
| 12 | 
            -
              FileUtils.cp "../ruby/tool/lib/core_assertions.rb", "./test/lib"
         | 
| 13 | 
            -
              FileUtils.cp "../ruby/tool/lib/envutil.rb", "./test/lib"
         | 
| 14 | 
            -
              FileUtils.cp "../ruby/tool/lib/find_executable.rb", "./test/lib"
         | 
| 15 | 
            -
            end
         | 
| 16 | 
            -
             | 
| 17 10 | 
             
            task :default => :test
         | 
    
        data/lib/webrick/cgi.rb
    CHANGED
    
    
| @@ -108,10 +108,10 @@ module WEBrick | |
| 108 108 | 
             
                # authentication schemes for proxies.
         | 
| 109 109 |  | 
| 110 110 | 
             
                module ProxyAuthenticator
         | 
| 111 | 
            -
                  RequestField | 
| 112 | 
            -
                  ResponseField | 
| 113 | 
            -
                   | 
| 114 | 
            -
                  AuthException | 
| 111 | 
            +
                  RequestField      = "Proxy-Authorization" # :nodoc:
         | 
| 112 | 
            +
                  ResponseField     = "Proxy-Authenticate" # :nodoc:
         | 
| 113 | 
            +
                  ResponseInfoField = "Proxy-Authentication-Info" # :nodoc:
         | 
| 114 | 
            +
                  AuthException     = HTTPStatus::ProxyAuthenticationRequired # :nodoc:
         | 
| 115 115 | 
             
                end
         | 
| 116 116 | 
             
              end
         | 
| 117 117 | 
             
            end
         | 
| @@ -77,12 +77,12 @@ module WEBrick | |
| 77 77 | 
             
                            if @password_hash == :bcrypt
         | 
| 78 78 | 
             
                              raise StandardError, ".htpasswd file contains crypt password, only bcrypt passwords supported"
         | 
| 79 79 | 
             
                            end
         | 
| 80 | 
            -
                            user, pass = line.split(":")
         | 
| 80 | 
            +
                            user, pass = line.split(":", 2)
         | 
| 81 81 | 
             
                          when %r!\A[^:]+:\$2[aby]\$\d{2}\$.{53}\z!
         | 
| 82 82 | 
             
                            if @password_hash == :crypt
         | 
| 83 83 | 
             
                              raise StandardError, ".htpasswd file contains bcrypt password, only crypt passwords supported"
         | 
| 84 84 | 
             
                            end
         | 
| 85 | 
            -
                            user, pass = line.split(":")
         | 
| 85 | 
            +
                            user, pass = line.split(":", 2)
         | 
| 86 86 | 
             
                          when /:\$/, /:{SHA}/
         | 
| 87 87 | 
             
                            raise NotImplementedError,
         | 
| 88 88 | 
             
                                  'MD5, SHA1 .htpasswd file not supported'
         | 
    
        data/lib/webrick/httpproxy.rb
    CHANGED
    
    | @@ -118,7 +118,7 @@ module WEBrick | |
| 118 118 | 
             
                    public_send("do_#{req.request_method}", req, res)
         | 
| 119 119 | 
             
                  rescue NoMethodError
         | 
| 120 120 | 
             
                    raise HTTPStatus::MethodNotAllowed,
         | 
| 121 | 
            -
                      "unsupported method  | 
| 121 | 
            +
                      "unsupported method '#{req.request_method}'."
         | 
| 122 122 | 
             
                  rescue => err
         | 
| 123 123 | 
             
                    logger.debug("#{err.class}: #{err.message}")
         | 
| 124 124 | 
             
                    raise HTTPStatus::ServiceUnavailable, err.message
         | 
| @@ -149,7 +149,7 @@ module WEBrick | |
| 149 149 | 
             
                  end
         | 
| 150 150 |  | 
| 151 151 | 
             
                  begin
         | 
| 152 | 
            -
                    @logger.debug("CONNECT: upstream proxy is  | 
| 152 | 
            +
                    @logger.debug("CONNECT: upstream proxy is '#{host}:#{port}'.")
         | 
| 153 153 | 
             
                    os = TCPSocket.new(host, port)     # origin server
         | 
| 154 154 |  | 
| 155 155 | 
             
                    if proxy
         | 
| @@ -175,7 +175,7 @@ module WEBrick | |
| 175 175 | 
             
                    @logger.debug("CONNECT #{host}:#{port}: succeeded")
         | 
| 176 176 | 
             
                    res.status = HTTPStatus::RC_OK
         | 
| 177 177 | 
             
                  rescue => ex
         | 
| 178 | 
            -
                    @logger.debug("CONNECT #{host}:#{port}: failed  | 
| 178 | 
            +
                    @logger.debug("CONNECT #{host}:#{port}: failed '#{ex.message}'")
         | 
| 179 179 | 
             
                    res.set_error(ex)
         | 
| 180 180 | 
             
                    raise HTTPStatus::EOFError
         | 
| 181 181 | 
             
                  ensure
         | 
| @@ -241,7 +241,7 @@ module WEBrick | |
| 241 241 | 
             
                    if HopByHop.member?(key)          || # RFC2616: 13.5.1
         | 
| 242 242 | 
             
                       connections.member?(key)       || # RFC2616: 14.10
         | 
| 243 243 | 
             
                       ShouldNotTransfer.member?(key)    # pragmatics
         | 
| 244 | 
            -
                      @logger.debug("choose_header:  | 
| 244 | 
            +
                      @logger.debug("choose_header: '#{key}: #{value}'")
         | 
| 245 245 | 
             
                      next
         | 
| 246 246 | 
             
                    end
         | 
| 247 247 | 
             
                    dst[key] = value
         | 
    
        data/lib/webrick/httprequest.rb
    CHANGED
    
    | @@ -162,7 +162,6 @@ module WEBrick | |
| 162 162 | 
             
                  @script_name = @path_info = nil
         | 
| 163 163 | 
             
                  @query_string = nil
         | 
| 164 164 | 
             
                  @query = nil
         | 
| 165 | 
            -
                  @form_data = nil
         | 
| 166 165 |  | 
| 167 166 | 
             
                  @raw_header = Array.new
         | 
| 168 167 | 
             
                  @header = nil
         | 
| @@ -173,7 +172,8 @@ module WEBrick | |
| 173 172 | 
             
                  @accept_language = []
         | 
| 174 173 | 
             
                  @body = +""
         | 
| 175 174 |  | 
| 176 | 
            -
                  @addr =  | 
| 175 | 
            +
                  @addr = []
         | 
| 176 | 
            +
                  @peeraddr = []
         | 
| 177 177 | 
             
                  @attributes = {}
         | 
| 178 178 | 
             
                  @user = nil
         | 
| 179 179 | 
             
                  @keep_alive = false
         | 
| @@ -224,7 +224,7 @@ module WEBrick | |
| 224 224 | 
             
                    @script_name = ""
         | 
| 225 225 | 
             
                    @path_info = @path.dup
         | 
| 226 226 | 
             
                  rescue
         | 
| 227 | 
            -
                    raise HTTPStatus::BadRequest, "bad URI  | 
| 227 | 
            +
                    raise HTTPStatus::BadRequest, "bad URI '#{@unparsed_uri}'."
         | 
| 228 228 | 
             
                  end
         | 
| 229 229 |  | 
| 230 230 | 
             
                  if /\Aclose\z/io =~ self["connection"]
         | 
| @@ -318,7 +318,7 @@ module WEBrick | |
| 318 318 | 
             
                def [](header_name)
         | 
| 319 319 | 
             
                  if @header
         | 
| 320 320 | 
             
                    value = @header[header_name.downcase]
         | 
| 321 | 
            -
                    value.empty? ? nil : value.join | 
| 321 | 
            +
                    value.empty? ? nil : value.join
         | 
| 322 322 | 
             
                  end
         | 
| 323 323 | 
             
                end
         | 
| 324 324 |  | 
| @@ -329,7 +329,7 @@ module WEBrick | |
| 329 329 | 
             
                  if @header
         | 
| 330 330 | 
             
                    @header.each{|k, v|
         | 
| 331 331 | 
             
                      value = @header[k]
         | 
| 332 | 
            -
                      yield(k, value.empty? ? nil : value.join | 
| 332 | 
            +
                      yield(k, value.empty? ? nil : value.join)
         | 
| 333 333 | 
             
                    }
         | 
| 334 334 | 
             
                  end
         | 
| 335 335 | 
             
                end
         | 
| @@ -402,7 +402,7 @@ module WEBrick | |
| 402 402 | 
             
                # This method provides the metavariables defined by the revision 3
         | 
| 403 403 | 
             
                # of "The WWW Common Gateway Interface Version 1.1"
         | 
| 404 404 | 
             
                # To browse the current document of CGI Version 1.1, see below:
         | 
| 405 | 
            -
                #  | 
| 405 | 
            +
                # https://www.rfc-editor.org/rfc/rfc3875
         | 
| 406 406 |  | 
| 407 407 | 
             
                def meta_vars
         | 
| 408 408 | 
             
                  meta = Hash.new
         | 
| @@ -458,27 +458,46 @@ module WEBrick | |
| 458 458 | 
             
                  end
         | 
| 459 459 |  | 
| 460 460 | 
             
                  @request_time = Time.now
         | 
| 461 | 
            -
                  if /^(\S+) | 
| 461 | 
            +
                  if /^(\S+) (\S++)(?: HTTP\/(\d+\.\d+))?\r\n/mo =~ @request_line
         | 
| 462 462 | 
             
                    @request_method = $1
         | 
| 463 463 | 
             
                    @unparsed_uri   = $2
         | 
| 464 464 | 
             
                    @http_version   = HTTPVersion.new($3 ? $3 : "0.9")
         | 
| 465 465 | 
             
                  else
         | 
| 466 466 | 
             
                    rl = @request_line.sub(/\x0d?\x0a\z/o, '')
         | 
| 467 | 
            -
                    raise HTTPStatus::BadRequest, "bad Request-Line  | 
| 467 | 
            +
                    raise HTTPStatus::BadRequest, "bad Request-Line '#{rl}'."
         | 
| 468 468 | 
             
                  end
         | 
| 469 469 | 
             
                end
         | 
| 470 470 |  | 
| 471 471 | 
             
                def read_header(socket)
         | 
| 472 472 | 
             
                  if socket
         | 
| 473 | 
            +
                    end_of_headers = false
         | 
| 474 | 
            +
             | 
| 473 475 | 
             
                    while line = read_line(socket)
         | 
| 474 | 
            -
                       | 
| 476 | 
            +
                      if line == CRLF
         | 
| 477 | 
            +
                        end_of_headers = true
         | 
| 478 | 
            +
                        break
         | 
| 479 | 
            +
                      end
         | 
| 475 480 | 
             
                      if (@request_bytes += line.bytesize) > MAX_HEADER_LENGTH
         | 
| 476 481 | 
             
                        raise HTTPStatus::RequestEntityTooLarge, 'headers too large'
         | 
| 477 482 | 
             
                      end
         | 
| 483 | 
            +
                      if line.include?("\x00")
         | 
| 484 | 
            +
                        raise HTTPStatus::BadRequest, 'null byte in header'
         | 
| 485 | 
            +
                      end
         | 
| 478 486 | 
             
                      @raw_header << line
         | 
| 479 487 | 
             
                    end
         | 
| 488 | 
            +
             | 
| 489 | 
            +
                    # Allow if @header already set to support chunked trailers
         | 
| 490 | 
            +
                    raise HTTPStatus::EOFError unless end_of_headers || @header
         | 
| 480 491 | 
             
                  end
         | 
| 481 492 | 
             
                  @header = HTTPUtils::parse_header(@raw_header.join)
         | 
| 493 | 
            +
             | 
| 494 | 
            +
                  if (content_length = @header['content-length']) && content_length.length != 0
         | 
| 495 | 
            +
                    if content_length.length > 1
         | 
| 496 | 
            +
                      raise HTTPStatus::BadRequest, "multiple content-length request headers"
         | 
| 497 | 
            +
                    elsif !/\A\d+\z/.match?(content_length[0])
         | 
| 498 | 
            +
                      raise HTTPStatus::BadRequest, "invalid content-length request header"
         | 
| 499 | 
            +
                    end
         | 
| 500 | 
            +
                  end
         | 
| 482 501 | 
             
                end
         | 
| 483 502 |  | 
| 484 503 | 
             
                def parse_uri(str, scheme="http")
         | 
| @@ -503,14 +522,19 @@ module WEBrick | |
| 503 522 | 
             
                  return URI::parse(uri.to_s)
         | 
| 504 523 | 
             
                end
         | 
| 505 524 |  | 
| 525 | 
            +
                host_pattern = URI::RFC2396_Parser.new.pattern.fetch(:HOST)
         | 
| 526 | 
            +
                HOST_PATTERN = /\A(#{host_pattern})(?::(\d+))?\z/n
         | 
| 506 527 | 
             
                def parse_host_request_line(host)
         | 
| 507 | 
            -
                   | 
| 508 | 
            -
                  host.scan(pattern)[0]
         | 
| 528 | 
            +
                  host.scan(HOST_PATTERN)[0]
         | 
| 509 529 | 
             
                end
         | 
| 510 530 |  | 
| 511 531 | 
             
                def read_body(socket, block)
         | 
| 512 532 | 
             
                  return unless socket
         | 
| 513 533 | 
             
                  if tc = self['transfer-encoding']
         | 
| 534 | 
            +
                    if self['content-length']
         | 
| 535 | 
            +
                      raise HTTPStatus::BadRequest, "request with both transfer-encoding and content-length, possible request smuggling"
         | 
| 536 | 
            +
                    end
         | 
| 537 | 
            +
             | 
| 514 538 | 
             
                    case tc
         | 
| 515 539 | 
             
                    when /\Achunked\z/io then read_chunked(socket, block)
         | 
| 516 540 | 
             
                    else raise HTTPStatus::NotImplemented, "Transfer-Encoding: #{tc}."
         | 
| @@ -534,12 +558,12 @@ module WEBrick | |
| 534 558 |  | 
| 535 559 | 
             
                def read_chunk_size(socket)
         | 
| 536 560 | 
             
                  line = read_line(socket)
         | 
| 537 | 
            -
                  if  | 
| 561 | 
            +
                  if /\A([0-9a-fA-F]+)(?:;(\S+(?:=\S+)?))?\r\n\z/ =~ line
         | 
| 538 562 | 
             
                    chunk_size = $1.hex
         | 
| 539 563 | 
             
                    chunk_ext = $2
         | 
| 540 564 | 
             
                    [ chunk_size, chunk_ext ]
         | 
| 541 565 | 
             
                  else
         | 
| 542 | 
            -
                    raise HTTPStatus::BadRequest, "bad chunk  | 
| 566 | 
            +
                    raise HTTPStatus::BadRequest, "bad chunk '#{line}'."
         | 
| 543 567 | 
             
                  end
         | 
| 544 568 | 
             
                end
         | 
| 545 569 |  | 
| @@ -555,7 +579,11 @@ module WEBrick | |
| 555 579 | 
             
                      block.call(data)
         | 
| 556 580 | 
             
                    end while (chunk_size -= sz) > 0
         | 
| 557 581 |  | 
| 558 | 
            -
                    read_line(socket) | 
| 582 | 
            +
                    line = read_line(socket)              # skip CRLF
         | 
| 583 | 
            +
                    unless line == "\r\n"
         | 
| 584 | 
            +
                      raise HTTPStatus::BadRequest, "extra data after chunk '#{line}'."
         | 
| 585 | 
            +
                    end
         | 
| 586 | 
            +
             | 
| 559 587 | 
             
                    chunk_size, = read_chunk_size(socket)
         | 
| 560 588 | 
             
                  end
         | 
| 561 589 | 
             
                  read_header(socket)                    # trailer + CRLF
         | 
    
        data/lib/webrick/httpresponse.rb
    CHANGED
    
    | @@ -453,7 +453,7 @@ module WEBrick | |
| 453 453 | 
             
                  _end_of_html_
         | 
| 454 454 |  | 
| 455 455 | 
             
                  if backtrace && $DEBUG
         | 
| 456 | 
            -
                    @body << "backtrace of  | 
| 456 | 
            +
                    @body << "backtrace of '#{HTMLUtils::escape(ex.class.to_s)}' "
         | 
| 457 457 | 
             
                    @body << "#{HTMLUtils::escape(ex.message)}"
         | 
| 458 458 | 
             
                    @body << "<PRE>"
         | 
| 459 459 | 
             
                    ex.backtrace.each{|line| @body << "\t#{line}\n"}
         | 
    
        data/lib/webrick/httpserver.rb
    CHANGED
    
    | @@ -128,11 +128,11 @@ module WEBrick | |
| 128 128 | 
             
                      do_OPTIONS(req, res)
         | 
| 129 129 | 
             
                      raise HTTPStatus::OK
         | 
| 130 130 | 
             
                    end
         | 
| 131 | 
            -
                    raise HTTPStatus::NotFound, " | 
| 131 | 
            +
                    raise HTTPStatus::NotFound, "'#{req.unparsed_uri}' not found."
         | 
| 132 132 | 
             
                  end
         | 
| 133 133 |  | 
| 134 134 | 
             
                  servlet, options, script_name, path_info = search_servlet(req.path)
         | 
| 135 | 
            -
                  raise HTTPStatus::NotFound, " | 
| 135 | 
            +
                  raise HTTPStatus::NotFound, "'#{req.path}' not found." unless servlet
         | 
| 136 136 | 
             
                  req.script_name = script_name
         | 
| 137 137 | 
             
                  req.path_info = path_info
         | 
| 138 138 | 
             
                  si = servlet.get_instance(self, *options)
         | 
| @@ -250,7 +250,7 @@ module WEBrick | |
| 250 250 |  | 
| 251 251 | 
             
                  def do_POST(req, res)
         | 
| 252 252 | 
             
                    unless exec_handler(req, res)
         | 
| 253 | 
            -
                      raise HTTPStatus::NotFound, " | 
| 253 | 
            +
                      raise HTTPStatus::NotFound, "'#{req.path}' not found."
         | 
| 254 254 | 
             
                    end
         | 
| 255 255 | 
             
                  end
         | 
| 256 256 |  | 
| @@ -307,7 +307,7 @@ module WEBrick | |
| 307 307 | 
             
                  end
         | 
| 308 308 |  | 
| 309 309 | 
             
                  def exec_handler(req, res)
         | 
| 310 | 
            -
                    raise HTTPStatus::NotFound, " | 
| 310 | 
            +
                    raise HTTPStatus::NotFound, "'#{req.path}' not found." unless @root
         | 
| 311 311 | 
             
                    if set_filename(req, res)
         | 
| 312 312 | 
             
                      handler = get_handler(req, res)
         | 
| 313 313 | 
             
                      call_callback(:HandlerCallback, req, res)
         | 
| @@ -359,7 +359,7 @@ module WEBrick | |
| 359 359 | 
             
                        call_callback(:FileCallback, req, res)
         | 
| 360 360 | 
             
                        return true
         | 
| 361 361 | 
             
                      else
         | 
| 362 | 
            -
                        raise HTTPStatus::NotFound, " | 
| 362 | 
            +
                        raise HTTPStatus::NotFound, "'#{req.path}' not found."
         | 
| 363 363 | 
             
                      end
         | 
| 364 364 | 
             
                    end
         | 
| 365 365 |  | 
| @@ -368,8 +368,8 @@ module WEBrick | |
| 368 368 |  | 
| 369 369 | 
             
                  def check_filename(req, res, name)
         | 
| 370 370 | 
             
                    if nondisclosure_name?(name) || windows_ambiguous_name?(name)
         | 
| 371 | 
            -
                      @logger.warn("the request refers nondisclosure name  | 
| 372 | 
            -
                      raise HTTPStatus::NotFound, " | 
| 371 | 
            +
                      @logger.warn("the request refers nondisclosure name '#{name}'.")
         | 
| 372 | 
            +
                      raise HTTPStatus::NotFound, "'#{req.path}' not found."
         | 
| 373 373 | 
             
                    end
         | 
| 374 374 | 
             
                  end
         | 
| 375 375 |  | 
| @@ -437,7 +437,7 @@ module WEBrick | |
| 437 437 | 
             
                  def set_dir_list(req, res)
         | 
| 438 438 | 
             
                    redirect_to_directory_uri(req, res)
         | 
| 439 439 | 
             
                    unless @options[:FancyIndexing]
         | 
| 440 | 
            -
                      raise HTTPStatus::Forbidden, "no access permission to  | 
| 440 | 
            +
                      raise HTTPStatus::Forbidden, "no access permission to '#{req.path}'"
         | 
| 441 441 | 
             
                    end
         | 
| 442 442 | 
             
                    local_path = res.filename
         | 
| 443 443 | 
             
                    list = Dir::entries(local_path).collect{|name|
         | 
    
        data/lib/webrick/httputils.rb
    CHANGED
    
    | @@ -29,14 +29,14 @@ module WEBrick | |
| 29 29 | 
             
                # normalized.
         | 
| 30 30 |  | 
| 31 31 | 
             
                def normalize_path(path)
         | 
| 32 | 
            -
                  raise "abnormal path  | 
| 32 | 
            +
                  raise "abnormal path '#{path}'" if path[0] != ?/
         | 
| 33 33 | 
             
                  ret = path.dup
         | 
| 34 34 |  | 
| 35 35 | 
             
                  ret.gsub!(%r{/+}o, '/')                    # //      => /
         | 
| 36 36 | 
             
                  while ret.sub!(%r'/\.(?:/|\Z)', '/'); end  # /.      => /
         | 
| 37 37 | 
             
                  while ret.sub!(%r'/(?!\.\./)[^/]+/\.\.(?:/|\Z)', '/'); end # /foo/.. => /foo
         | 
| 38 38 |  | 
| 39 | 
            -
                  raise "abnormal path  | 
| 39 | 
            +
                  raise "abnormal path '#{path}'" if %r{/\.\.(/|\Z)} =~ ret
         | 
| 40 40 | 
             
                  ret
         | 
| 41 41 | 
             
                end
         | 
| 42 42 | 
             
                module_function :normalize_path
         | 
| @@ -55,7 +55,6 @@ module WEBrick | |
| 55 55 | 
             
                  "cer"   => "application/pkix-cert",
         | 
| 56 56 | 
             
                  "crl"   => "application/pkix-crl",
         | 
| 57 57 | 
             
                  "crt"   => "application/x-x509-ca-cert",
         | 
| 58 | 
            -
                 #"crl"   => "application/x-pkcs7-crl",
         | 
| 59 58 | 
             
                  "css"   => "text/css",
         | 
| 60 59 | 
             
                  "dms"   => "application/octet-stream",
         | 
| 61 60 | 
             
                  "doc"   => "application/msword",
         | 
| @@ -153,28 +152,49 @@ module WEBrick | |
| 153 152 | 
             
                # Parses an HTTP header +raw+ into a hash of header fields with an Array
         | 
| 154 153 | 
             
                # of values.
         | 
| 155 154 |  | 
| 155 | 
            +
                class SplitHeader < Array
         | 
| 156 | 
            +
                  def join(separator = ", ")
         | 
| 157 | 
            +
                    super
         | 
| 158 | 
            +
                  end
         | 
| 159 | 
            +
                end
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                class CookieHeader < Array
         | 
| 162 | 
            +
                  def join(separator = "; ")
         | 
| 163 | 
            +
                    super
         | 
| 164 | 
            +
                  end
         | 
| 165 | 
            +
                end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                HEADER_CLASSES = Hash.new(SplitHeader).update({
         | 
| 168 | 
            +
                  "cookie" => CookieHeader,
         | 
| 169 | 
            +
                })
         | 
| 170 | 
            +
             | 
| 156 171 | 
             
                def parse_header(raw)
         | 
| 157 172 | 
             
                  header = Hash.new([].freeze)
         | 
| 158 173 | 
             
                  field = nil
         | 
| 159 174 | 
             
                  raw.each_line{|line|
         | 
| 160 175 | 
             
                    case line
         | 
| 161 | 
            -
                    when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+) | 
| 176 | 
            +
                    when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):([^\r\n\0]*?)\r\n\z/om
         | 
| 162 177 | 
             
                      field, value = $1, $2
         | 
| 163 178 | 
             
                      field.downcase!
         | 
| 164 | 
            -
                      header[field] = [] unless header.has_key?(field)
         | 
| 179 | 
            +
                      header[field] = HEADER_CLASSES[field].new unless header.has_key?(field)
         | 
| 165 180 | 
             
                      header[field] << value
         | 
| 166 | 
            -
                    when  | 
| 167 | 
            -
                      value = $1
         | 
| 181 | 
            +
                    when /^[ \t]+([^\r\n\0]*?)\r\n/om
         | 
| 168 182 | 
             
                      unless field
         | 
| 169 183 | 
             
                        raise HTTPStatus::BadRequest, "bad header '#{line}'."
         | 
| 170 184 | 
             
                      end
         | 
| 185 | 
            +
                      value = line
         | 
| 186 | 
            +
                      value.gsub!(/\A[ \t]+/, '')
         | 
| 187 | 
            +
                      value.slice!(-2..-1)
         | 
| 171 188 | 
             
                      header[field][-1] << " " << value
         | 
| 172 189 | 
             
                    else
         | 
| 173 190 | 
             
                      raise HTTPStatus::BadRequest, "bad header '#{line}'."
         | 
| 174 191 | 
             
                    end
         | 
| 175 192 | 
             
                  }
         | 
| 176 193 | 
             
                  header.each{|key, values|
         | 
| 177 | 
            -
                    values.each | 
| 194 | 
            +
                    values.each{|value|
         | 
| 195 | 
            +
                      value.gsub!(/\A[ \t]+/, '')
         | 
| 196 | 
            +
                      value.gsub!(/[ \t]+\z/, '')
         | 
| 197 | 
            +
                    }
         | 
| 178 198 | 
             
                  }
         | 
| 179 199 | 
             
                  header
         | 
| 180 200 | 
             
                end
         | 
| @@ -184,8 +204,8 @@ module WEBrick | |
| 184 204 | 
             
                # Splits a header value +str+ according to HTTP specification.
         | 
| 185 205 |  | 
| 186 206 | 
             
                def split_header_value(str)
         | 
| 187 | 
            -
                  str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",] | 
| 188 | 
            -
                                ( | 
| 207 | 
            +
                  str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]++)+)
         | 
| 208 | 
            +
                                (?:,[ \t]*|\Z)'xn).flatten
         | 
| 189 209 | 
             
                end
         | 
| 190 210 | 
             
                module_function :split_header_value
         | 
| 191 211 |  | 
| @@ -213,9 +233,9 @@ module WEBrick | |
| 213 233 | 
             
                def parse_qvalues(value)
         | 
| 214 234 | 
             
                  tmp = []
         | 
| 215 235 | 
             
                  if value
         | 
| 216 | 
            -
                    parts = value.split( | 
| 236 | 
            +
                    parts = value.split(/,[ \t]*/)
         | 
| 217 237 | 
             
                    parts.each {|part|
         | 
| 218 | 
            -
                      if m = %r{^([ | 
| 238 | 
            +
                      if m = %r{^([^ \t,]+?)(?:;[ \t]*q=(\d+(?:\.\d+)?))?$}.match(part)
         | 
| 219 239 | 
             
                        val = m[1]
         | 
| 220 240 | 
             
                        q = (m[2] or 1).to_f
         | 
| 221 241 | 
             
                        tmp.push([val, q])
         | 
| @@ -314,8 +334,8 @@ module WEBrick | |
| 314 334 | 
             
                    elsif str == CRLF
         | 
| 315 335 | 
             
                      @header = HTTPUtils::parse_header(@raw_header.join)
         | 
| 316 336 | 
             
                      if cd = self['content-disposition']
         | 
| 317 | 
            -
                        if  | 
| 318 | 
            -
                        if  | 
| 337 | 
            +
                        if /[ \t]+name="(.*?)"/ =~ cd then @name = $1 end
         | 
| 338 | 
            +
                        if /[ \t]+filename="(.*?)"/ =~ cd then @filename = $1 end
         | 
| 319 339 | 
             
                      end
         | 
| 320 340 | 
             
                    else
         | 
| 321 341 | 
             
                      @raw_header << str
         | 
    
        data/lib/webrick/server.rb
    CHANGED
    
    | @@ -365,7 +365,7 @@ module WEBrick | |
| 365 365 | 
             
                    begin
         | 
| 366 366 | 
             
                      s.shutdown
         | 
| 367 367 | 
             
                    rescue Errno::ENOTCONN
         | 
| 368 | 
            -
                      # when  | 
| 368 | 
            +
                      # when 'Errno::ENOTCONN: Socket is not connected' on some platforms,
         | 
| 369 369 | 
             
                      # call #close instead of #shutdown.
         | 
| 370 370 | 
             
                      # (ignore @config[:ShutdownSocketWithoutClose])
         | 
| 371 371 | 
             
                      s.close
         | 
    
        data/lib/webrick/version.rb
    CHANGED
    
    
    
        data/sig/accesslog.rbs
    ADDED
    
    | @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            module WEBrick
         | 
| 2 | 
            +
              module AccessLog
         | 
| 3 | 
            +
                class AccessLogError < StandardError
         | 
| 4 | 
            +
                end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                CLF_TIME_FORMAT: String
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                COMMON_LOG_FORMAT: String
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                CLF: String
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                REFERER_LOG_FORMAT: String
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                AGENT_LOG_FORMAT: String
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                COMBINED_LOG_FORMAT: String
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def self?.setup_params: (Hash[Symbol, untyped] config, HTTPRequest req, HTTPResponse res) -> Hash[String, untyped]
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def self?.format: (String format_string, Hash[String, untyped] params) -> String
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def self?.escape: (String data) -> String
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         | 
    
        data/sig/cgi.rbs
    ADDED
    
    | @@ -0,0 +1,92 @@ | |
| 1 | 
            +
            module WEBrick
         | 
| 2 | 
            +
              class CGI
         | 
| 3 | 
            +
                @options: Array[untyped]
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                class CGIError < StandardError
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                attr_reader config: Hash[Symbol, untyped]
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                attr_reader logger: BasicLog
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def initialize: (*untyped args) -> void
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def []: (Symbol key) -> untyped
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                interface _Env
         | 
| 17 | 
            +
                  def []: (String) -> String?
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def start: (?_Env env, ?IO stdin, ?IO stdout) -> void
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def self.setup_header: () -> untyped
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def self.status_line: () -> ""
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def service: (HTTPRequest req, HTTPResponse res) -> void
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                class Socket
         | 
| 29 | 
            +
                  @config: Hash[Symbol, untyped]
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  @env: _Env
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  @header_part: StringIO
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  @body_part: IO
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  @out_port: IO
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                  @server_addr: String
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  @server_name: String?
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  @server_port: String?
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  @remote_addr: String?
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  @remote_host: String?
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  @remote_port: (String | 0)
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  include Enumerable[String]
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  private
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  def initialize: (Hash[Symbol, untyped] config, _Env env, IO stdin, IO stdout) -> void
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  def request_line: () -> String
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  def setup_header: () -> void
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  def add_header: (String hdrname, String value) -> void
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  def input: () -> (IO | StringIO)
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  public
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  def peeraddr: () -> [nil, (String | 0), String?, String?]
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  def addr: () -> [nil, String?, String?, String]
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  def gets: (?String eol, ?Integer? size) -> String?
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  def read: (?Integer? size) -> String?
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  def each: () { (String) -> void } -> void
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  def eof?: () -> bool
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  def <<: (_ToS data) -> IO
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  def write: (_ToS data) -> Integer
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  def cert: () -> OpenSSL::X509::Certificate?
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  def peer_cert: () -> OpenSSL::X509::Certificate?
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  def peer_cert_chain: () -> Array[OpenSSL::X509::Certificate]?
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  def cipher: () -> [String?, String?, String?, String?]?
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
              end
         | 
| 92 | 
            +
            end
         | 
    
        data/sig/compat.rbs
    ADDED
    
    | @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            #
         | 
| 2 | 
            +
            # System call error module used by webrick for cross platform compatibility.
         | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # EPROTO:: protocol error
         | 
| 5 | 
            +
            # ECONNRESET:: remote host reset the connection request
         | 
| 6 | 
            +
            # ECONNABORTED:: Client sent TCP reset (RST) before server has accepted the
         | 
| 7 | 
            +
            #                connection requested by client.
         | 
| 8 | 
            +
            #
         | 
| 9 | 
            +
            module Errno
         | 
| 10 | 
            +
              class EPROTO < SystemCallError
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              class ECONNRESET < SystemCallError
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              class ECONNABORTED < SystemCallError
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
    
        data/sig/config.rbs
    ADDED
    
    | @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            module WEBrick
         | 
| 2 | 
            +
              module Config
         | 
| 3 | 
            +
                LIBDIR: String
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                # for GenericServer
         | 
| 6 | 
            +
                General: Hash[Symbol, untyped]
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                # for HTTPServer, HTTPRequest, HTTPResponse ...
         | 
| 9 | 
            +
                HTTP: Hash[Symbol, untyped]
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                FileHandler: Hash[Symbol, untyped]
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                BasicAuth: Hash[Symbol, untyped]
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                DigestAuth: Hash[Symbol, untyped]
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         |