This file is indexed.

/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