1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* lib/net/http/header.rb (Net::HTTPHeader#range): fix broken parser of

HTTP Range request. Old one can't parse invalid specs and multiple
  specs correctly.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35764 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2012-05-23 13:09:26 +00:00
parent b0dd250dc9
commit 3ba0abdb15
3 changed files with 61 additions and 12 deletions

View file

@ -1,3 +1,9 @@
Wed May 23 22:06:14 2012 NARUSE, Yui <naruse@ruby-lang.org>
* lib/net/http/header.rb (Net::HTTPHeader#range): fix broken parser of
HTTP Range request. Old one can't parse invalid specs and multiple
specs correctly.
Wed May 23 10:18:54 2012 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (finish_overlapped_socket, overlapped_socket_io):

View file

@ -177,18 +177,44 @@ module Net::HTTPHeader
# HTTP header field, or +nil+ if there is no such header.
def range
return nil unless @header['range']
self['Range'].split(/,/).map {|spec|
m = /bytes\s*=\s*(\d+)?\s*-\s*(\d+)?/i.match(spec) or
raise HTTPHeaderSyntaxError, "wrong Range: #{spec}"
value = self['Range']
# byte-range-set = *( "," OWS ) ( byte-range-spec / suffix-byte-range-spec )
# *( OWS "," [ OWS ( byte-range-spec / suffix-byte-range-spec ) ] )
# corrected collected ABNF
# http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-19#section-5.4.1
# http://tools.ietf.org/html/draft-ietf-httpbis-p5-range-19#appendix-C
# http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-19#section-3.2.5
unless /\Abytes=((?:,[ \t]*)*(?:\d+-\d*|-\d+)(?:[ \t]*,(?:[ \t]*\d+-\d*|-\d+)?)*)\z/ =~ value
raise Net::HTTPHeaderSyntaxError, "invalid syntax for byte-ranges-specifier: '#{value}'"
end
byte_range_set = $1
result = byte_range_set.split(/,/).map {|spec|
m = /(\d+)?\s*-\s*(\d+)?/i.match(spec) or
raise Net::HTTPHeaderSyntaxError, "invalid byte-range-spec: '#{spec}'"
d1 = m[1].to_i
d2 = m[2].to_i
if m[1] and m[2] then d1..d2
elsif m[1] then d1..-1
elsif m[2] then -d2..-1
if m[1] and m[2]
if d1 > d2
raise Net::HTTPHeaderSyntaxError, "last-byte-pos MUST greater than or equal to first-byte-pos but '#{spec}'"
end
d1..d2
elsif m[1]
d1..-1
elsif m[2]
-d2..-1
else
raise HTTPHeaderSyntaxError, 'range is not specified'
raise Net::HTTPHeaderSyntaxError, 'range is not specified'
end
}
# if result.empty?
# byte-range-set must include at least one byte-range-spec or suffix-byte-range-spec
# but above regexp already denies it.
if result.size == 1 && result[0].begin == 0 && result[0].end == -1
raise Net::HTTPHeaderSyntaxError, 'only one suffix-byte-range-spec with zero suffix-length'
end
result
end
# Sets the HTTP Range: header.

View file

@ -156,15 +156,32 @@ class HTTPHeaderTest < Test::Unit::TestCase
end
def test_range
try_range(1..5, '1-5')
try_range(234..567, '234-567')
try_range(-5..-1, '-5')
try_range(1..-1, '1-')
try_range([1..5], '1-5')
try_invalid_range('5-1')
try_range([234..567], '234-567')
try_range([-5..-1], '-5')
try_invalid_range('-0')
try_range([1..-1], '1-')
try_range([0..0,-1..-1], '0-0,-1')
try_range([1..2, 3..4], '1-2,3-4')
try_range([1..2, 3..4], '1-2 , 3-4')
try_range([1..2, 1..4], '1-2,1-4')
try_invalid_range('invalid')
try_invalid_range(' 12-')
try_invalid_range('12- ')
try_invalid_range('123-abc')
try_invalid_range('abc-123')
end
def try_range(r, s)
@c['range'] = "bytes=#{s}"
assert_equal r, Array(@c.range)[0]
assert_equal r, @c.range
end
def try_invalid_range(s)
@c['range'] = "bytes=#{s}"
assert_raise(Net::HTTPHeaderSyntaxError, s){ @c.range }
end
def test_range=