/usr/lib/ruby/vendor_ruby/mechanize/http/www_authenticate_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 | # coding: BINARY
require 'strscan'
##
# Parses the WWW-Authenticate HTTP header into separate challenges.
class Mechanize::HTTP::WWWAuthenticateParser
attr_accessor :scanner # :nodoc:
##
# Creates a new header parser for WWW-Authenticate headers
def initialize
@scanner = nil
end
##
# Parsers the header. Returns an Array of challenges as strings
def parse www_authenticate
challenges = []
@scanner = StringScanner.new www_authenticate
while true do
break if @scanner.eos?
start = @scanner.pos
challenge = Mechanize::HTTP::AuthChallenge.new
scheme = auth_scheme
if scheme == 'Negotiate'
scan_comma_spaces
end
next unless scheme
challenge.scheme = scheme
space = spaces
if scheme == 'NTLM' then
if space then
challenge.params = @scanner.scan(/.*/)
end
challenge.raw = www_authenticate[start, @scanner.pos]
challenges << challenge
next
else
scheme.capitalize!
end
next unless space
params = {}
while true do
pos = @scanner.pos
name, value = auth_param
name.downcase! if name =~ /^realm$/i
unless name then
challenge.params = params
challenges << challenge
if @scanner.eos? then
challenge.raw = www_authenticate[start, @scanner.pos]
break
end
@scanner.pos = pos # rewind
challenge.raw = www_authenticate[start, @scanner.pos].sub(/(,+)? *$/, '')
challenge = nil # a token should be next, new challenge
break
else
params[name] = value
end
spaces
@scanner.scan(/(, *)+/)
end
end
challenges
end
##
# 1*SP
#
# Parses spaces
def spaces
@scanner.scan(/ +/)
end
##
# scans a comma followed by spaces
# needed for Negotiation, NTLM
#
def scan_comma_spaces
@scanner.scan(/, +/)
end
##
# token = 1*<any CHAR except CTLs or separators>
#
# Parses a token
def token
@scanner.scan(/[^\000-\037\177()<>@,;:\\"\/\[\]?={} ]+/)
end
##
# auth-scheme = token
#
# Parses an auth scheme (a token)
alias auth_scheme token
##
# auth-param = token "=" ( token | quoted-string )
#
# Parses an auth parameter
def auth_param
return nil unless name = token
return nil unless @scanner.scan(/=/)
value = if @scanner.peek(1) == '"' then
quoted_string
else
token
end
return nil unless value
return name, value
end
##
# quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
# qdtext = <any TEXT except <">>
# quoted-pair = "\" CHAR
#
# For TEXT, the rules of RFC 2047 are ignored.
def quoted_string
return nil unless @scanner.scan(/"/)
text = ''
while true do
chunk = @scanner.scan(/[\r\n \t\041\043-\176\200-\377]+/) # not "
if chunk then
text << chunk
text << @scanner.get_byte if
chunk.end_with? '\\' and '"' == @scanner.peek(1)
else
if '"' == @scanner.peek(1) then
@scanner.get_byte
break
else
return nil
end
end
end
text
end
end
|