/usr/lib/ruby/vendor_ruby/mechanize/http/content_disposition_parser.rb is in ruby-mechanize 2.7.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | # coding: BINARY
require 'strscan'
require 'time'
class Mechanize::HTTP
ContentDisposition = Struct.new :type, :filename, :creation_date,
:modification_date, :read_date, :size, :parameters
end
##
# Parser Content-Disposition headers that loosely follows RFC 2183.
#
# Beyond RFC 2183, this parser allows:
#
# * Missing disposition-type
# * Multiple semicolons
# * Whitespace around semicolons
class Mechanize::HTTP::ContentDispositionParser
attr_accessor :scanner # :nodoc:
@parser = nil
##
# Parses the disposition type and params in the +content_disposition+
# string. The "Content-Disposition:" must be removed.
def self.parse content_disposition
@parser ||= self.new
@parser.parse content_disposition
end
##
# Creates a new parser Content-Disposition headers
def initialize
@scanner = nil
end
##
# Parses the +content_disposition+ header. If +header+ is set to true the
# "Content-Disposition:" portion will be parsed
def parse content_disposition, header = false
return nil if content_disposition.empty?
@scanner = StringScanner.new content_disposition
if header then
return nil unless @scanner.scan(/Content-Disposition/i)
return nil unless @scanner.scan(/:/)
spaces
end
type = rfc_2045_token
@scanner.scan(/;+/)
if @scanner.peek(1) == '=' then
@scanner.pos = 0
type = nil
end
disposition = Mechanize::HTTP::ContentDisposition.new type
spaces
return nil unless parameters = parse_parameters
disposition.filename = parameters.delete 'filename'
disposition.creation_date = parameters.delete 'creation-date'
disposition.modification_date = parameters.delete 'modification-date'
disposition.read_date = parameters.delete 'read-date'
disposition.size = parameters.delete 'size'
disposition.parameters = parameters
disposition
end
##
# Extracts disposition-parm and returns a Hash.
def parse_parameters
parameters = {}
while true do
return nil unless param = rfc_2045_token
param.downcase!
return nil unless @scanner.scan(/=/)
value = case param
when /^filename$/ then
rfc_2045_value
when /^(creation|modification|read)-date$/ then
Time.rfc822 rfc_2045_quoted_string
when /^size$/ then
rfc_2045_value.to_i(10)
else
rfc_2045_value
end
return nil unless value
parameters[param] = value
spaces
break if @scanner.eos? or not @scanner.scan(/;+/)
spaces
end
parameters
end
##
# quoted-string = <"> *(qtext/quoted-pair) <">
# qtext = <any CHAR excepting <">, "\" & CR,
# and including linear-white-space
# quoted-pair = "\" CHAR
#
# Parses an RFC 2045 quoted-string
def rfc_2045_quoted_string
return nil unless @scanner.scan(/"/)
text = ''
while true do
chunk = @scanner.scan(/[\000-\014\016-\041\043-\133\135-\177]+/) # not \r "
if chunk then
text << chunk
if @scanner.peek(1) == '\\' then
@scanner.get_byte
return nil if @scanner.eos?
text << @scanner.get_byte
elsif @scanner.scan(/\r\n[\t ]+/) then
text << " "
end
else
if '"' == @scanner.peek(1) then
@scanner.get_byte
break
else
return nil
end
end
end
text
end
##
# token := 1*<any (US-ASCII) CHAR except SPACE, CTLs, or tspecials>
#
# Parses an RFC 2045 token
def rfc_2045_token
@scanner.scan(/[^\000-\037\177()<>@,;:\\"\/\[\]?= ]+/)
end
##
# value := token / quoted-string
#
# Parses an RFC 2045 value
def rfc_2045_value
if @scanner.peek(1) == '"' then
rfc_2045_quoted_string
else
rfc_2045_token
end
end
##
# 1*SP
#
# Parses spaces
def spaces
@scanner.scan(/ +/)
end
end
|