diff options
author | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-05-23 13:09:26 +0000 |
---|---|---|
committer | naruse <naruse@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-05-23 13:09:26 +0000 |
commit | 3ba0abdb157b490644264c3bc45cb8fbc1e1f46b (patch) | |
tree | 80bce60b70dc3152f5697701a90d6cf690e0b004 /lib/net | |
parent | b0dd250dc95ea0fae89c3201967039d582fbf156 (diff) | |
download | ruby-3ba0abdb157b490644264c3bc45cb8fbc1e1f46b.tar.gz |
* 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
Diffstat (limited to 'lib/net')
-rw-r--r-- | lib/net/http/header.rb | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb index ec77c8c958..7e46e04395 100644 --- a/lib/net/http/header.rb +++ b/lib/net/http/header.rb @@ -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. |