webrick 1.3.1 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of webrick might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +63 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/webrick/accesslog.rb +9 -1
- data/lib/webrick/cgi.rb +58 -5
- data/lib/webrick/compat.rb +2 -1
- data/lib/webrick/config.rb +47 -10
- data/lib/webrick/cookie.rb +69 -7
- data/lib/webrick/htmlutils.rb +4 -2
- data/lib/webrick/httpauth/authenticator.rb +13 -8
- data/lib/webrick/httpauth/basicauth.rb +16 -8
- data/lib/webrick/httpauth/digestauth.rb +35 -32
- data/lib/webrick/httpauth/htdigest.rb +12 -8
- data/lib/webrick/httpauth/htgroup.rb +10 -6
- data/lib/webrick/httpauth/htpasswd.rb +46 -9
- data/lib/webrick/httpauth/userdb.rb +1 -0
- data/lib/webrick/httpauth.rb +6 -5
- data/lib/webrick/httpproxy.rb +93 -48
- data/lib/webrick/httprequest.rb +192 -27
- data/lib/webrick/httpresponse.rb +221 -70
- data/lib/webrick/https.rb +90 -2
- data/lib/webrick/httpserver.rb +45 -15
- data/lib/webrick/httpservlet/abstract.rb +5 -6
- data/lib/webrick/httpservlet/cgi_runner.rb +3 -2
- data/lib/webrick/httpservlet/cgihandler.rb +22 -10
- data/lib/webrick/httpservlet/erbhandler.rb +4 -3
- data/lib/webrick/httpservlet/filehandler.rb +136 -65
- data/lib/webrick/httpservlet/prochandler.rb +15 -1
- data/lib/webrick/httpservlet.rb +6 -5
- data/lib/webrick/httpstatus.rb +24 -14
- data/lib/webrick/httputils.rb +133 -13
- data/lib/webrick/httpversion.rb +28 -1
- data/lib/webrick/log.rb +25 -5
- data/lib/webrick/server.rb +234 -74
- data/lib/webrick/ssl.rb +100 -12
- data/lib/webrick/utils.rb +98 -69
- data/lib/webrick/version.rb +6 -1
- data/lib/webrick.rb +7 -7
- data/webrick.gemspec +76 -0
- metadata +70 -69
- data/README.txt +0 -21
- data/sample/webrick/demo-app.rb +0 -66
- data/sample/webrick/demo-multipart.cgi +0 -12
- data/sample/webrick/demo-servlet.rb +0 -6
- data/sample/webrick/demo-urlencoded.cgi +0 -12
- data/sample/webrick/hello.cgi +0 -11
- data/sample/webrick/hello.rb +0 -8
- data/sample/webrick/httpd.rb +0 -23
- data/sample/webrick/httpproxy.rb +0 -25
- data/sample/webrick/httpsd.rb +0 -33
- data/test/openssl/utils.rb +0 -313
- data/test/ruby/envutil.rb +0 -208
- data/test/webrick/test_cgi.rb +0 -134
- data/test/webrick/test_cookie.rb +0 -131
- data/test/webrick/test_filehandler.rb +0 -285
- data/test/webrick/test_httpauth.rb +0 -167
- data/test/webrick/test_httpproxy.rb +0 -282
- data/test/webrick/test_httprequest.rb +0 -411
- data/test/webrick/test_httpresponse.rb +0 -49
- data/test/webrick/test_httpserver.rb +0 -305
- data/test/webrick/test_httputils.rb +0 -96
- data/test/webrick/test_httpversion.rb +0 -40
- data/test/webrick/test_server.rb +0 -67
- data/test/webrick/test_utils.rb +0 -64
- data/test/webrick/utils.rb +0 -58
- data/test/webrick/webrick.cgi +0 -36
- data/test/webrick/webrick_long_filename.cgi +0 -36
data/lib/webrick/httputils.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# httputils.rb -- HTTPUtils Module
|
3
4
|
#
|
@@ -12,12 +13,21 @@ require 'socket'
|
|
12
13
|
require 'tempfile'
|
13
14
|
|
14
15
|
module WEBrick
|
15
|
-
CR = "\x0d"
|
16
|
-
LF = "\x0a"
|
17
|
-
CRLF = "\x0d\x0a"
|
16
|
+
CR = "\x0d" # :nodoc:
|
17
|
+
LF = "\x0a" # :nodoc:
|
18
|
+
CRLF = "\x0d\x0a" # :nodoc:
|
19
|
+
|
20
|
+
##
|
21
|
+
# HTTPUtils provides utility methods for working with the HTTP protocol.
|
22
|
+
#
|
23
|
+
# This module is generally used internally by WEBrick
|
18
24
|
|
19
25
|
module HTTPUtils
|
20
26
|
|
27
|
+
##
|
28
|
+
# Normalizes a request path. Raises an exception if the path cannot be
|
29
|
+
# normalized.
|
30
|
+
|
21
31
|
def normalize_path(path)
|
22
32
|
raise "abnormal path `#{path}'" if path[0] != ?/
|
23
33
|
ret = path.dup
|
@@ -31,7 +41,8 @@ module WEBrick
|
|
31
41
|
end
|
32
42
|
module_function :normalize_path
|
33
43
|
|
34
|
-
|
44
|
+
##
|
45
|
+
# Default mime types
|
35
46
|
|
36
47
|
DefaultMimeTypes = {
|
37
48
|
"ai" => "application/postscript",
|
@@ -58,6 +69,7 @@ module WEBrick
|
|
58
69
|
"jpeg" => "image/jpeg",
|
59
70
|
"jpg" => "image/jpeg",
|
60
71
|
"js" => "application/javascript",
|
72
|
+
"json" => "application/json",
|
61
73
|
"lha" => "application/octet-stream",
|
62
74
|
"lzh" => "application/octet-stream",
|
63
75
|
"mov" => "video/quicktime",
|
@@ -83,6 +95,7 @@ module WEBrick
|
|
83
95
|
"tif" => "image/tiff",
|
84
96
|
"tiff" => "image/tiff",
|
85
97
|
"txt" => "text/plain",
|
98
|
+
"wasm" => "application/wasm",
|
86
99
|
"xbm" => "image/x-xbitmap",
|
87
100
|
"xhtml" => "text/html",
|
88
101
|
"xls" => "application/vnd.ms-excel",
|
@@ -92,8 +105,12 @@ module WEBrick
|
|
92
105
|
"zip" => "application/zip",
|
93
106
|
}
|
94
107
|
|
95
|
-
|
108
|
+
##
|
109
|
+
# Loads Apache-compatible mime.types in +file+.
|
110
|
+
|
96
111
|
def load_mime_types(file)
|
112
|
+
# note: +file+ may be a "| command" for now; some people may
|
113
|
+
# rely on this, but currently we do not use this method by default.
|
97
114
|
open(file){ |io|
|
98
115
|
hash = Hash.new
|
99
116
|
io.each{ |line|
|
@@ -109,6 +126,10 @@ module WEBrick
|
|
109
126
|
end
|
110
127
|
module_function :load_mime_types
|
111
128
|
|
129
|
+
##
|
130
|
+
# Returns the mime type of +filename+ from the list in +mime_tab+. If no
|
131
|
+
# mime type was found application/octet-stream is returned.
|
132
|
+
|
112
133
|
def mime_type(filename, mime_tab)
|
113
134
|
suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
|
114
135
|
suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase)
|
@@ -116,7 +137,9 @@ module WEBrick
|
|
116
137
|
end
|
117
138
|
module_function :mime_type
|
118
139
|
|
119
|
-
|
140
|
+
##
|
141
|
+
# Parses an HTTP header +raw+ into a hash of header fields with an Array
|
142
|
+
# of values.
|
120
143
|
|
121
144
|
def parse_header(raw)
|
122
145
|
header = Hash.new([].freeze)
|
@@ -148,12 +171,18 @@ module WEBrick
|
|
148
171
|
end
|
149
172
|
module_function :parse_header
|
150
173
|
|
174
|
+
##
|
175
|
+
# Splits a header value +str+ according to HTTP specification.
|
176
|
+
|
151
177
|
def split_header_value(str)
|
152
178
|
str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+)
|
153
179
|
(?:,\s*|\Z)'xn).flatten
|
154
180
|
end
|
155
181
|
module_function :split_header_value
|
156
182
|
|
183
|
+
##
|
184
|
+
# Parses a Range header value +ranges_specifier+
|
185
|
+
|
157
186
|
def parse_range_header(ranges_specifier)
|
158
187
|
if /^bytes=(.*)/ =~ ranges_specifier
|
159
188
|
byte_range_set = split_header_value($1)
|
@@ -169,6 +198,9 @@ module WEBrick
|
|
169
198
|
end
|
170
199
|
module_function :parse_range_header
|
171
200
|
|
201
|
+
##
|
202
|
+
# Parses q values in +value+ as used in Accept headers.
|
203
|
+
|
172
204
|
def parse_qvalues(value)
|
173
205
|
tmp = []
|
174
206
|
if value
|
@@ -187,7 +219,8 @@ module WEBrick
|
|
187
219
|
end
|
188
220
|
module_function :parse_qvalues
|
189
221
|
|
190
|
-
|
222
|
+
##
|
223
|
+
# Removes quotes and escapes from +str+
|
191
224
|
|
192
225
|
def dequote(str)
|
193
226
|
ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
|
@@ -196,20 +229,43 @@ module WEBrick
|
|
196
229
|
end
|
197
230
|
module_function :dequote
|
198
231
|
|
232
|
+
##
|
233
|
+
# Quotes and escapes quotes in +str+
|
234
|
+
|
199
235
|
def quote(str)
|
200
236
|
'"' << str.gsub(/[\\\"]/o, "\\\1") << '"'
|
201
237
|
end
|
202
238
|
module_function :quote
|
203
239
|
|
204
|
-
|
240
|
+
##
|
241
|
+
# Stores multipart form data. FormData objects are created when
|
242
|
+
# WEBrick::HTTPUtils.parse_form_data is called.
|
205
243
|
|
206
244
|
class FormData < String
|
207
|
-
EmptyRawHeader = [].freeze
|
208
|
-
EmptyHeader = {}.freeze
|
245
|
+
EmptyRawHeader = [].freeze # :nodoc:
|
246
|
+
EmptyHeader = {}.freeze # :nodoc:
|
247
|
+
|
248
|
+
##
|
249
|
+
# The name of the form data part
|
250
|
+
|
251
|
+
attr_accessor :name
|
209
252
|
|
210
|
-
|
253
|
+
##
|
254
|
+
# The filename of the form data part
|
255
|
+
|
256
|
+
attr_accessor :filename
|
257
|
+
|
258
|
+
attr_accessor :next_data # :nodoc:
|
211
259
|
protected :next_data
|
212
260
|
|
261
|
+
##
|
262
|
+
# Creates a new FormData object.
|
263
|
+
#
|
264
|
+
# +args+ is an Array of form data entries. One FormData will be created
|
265
|
+
# for each entry.
|
266
|
+
#
|
267
|
+
# This is called by WEBrick::HTTPUtils.parse_form_data for you
|
268
|
+
|
213
269
|
def initialize(*args)
|
214
270
|
@name = @filename = @next_data = nil
|
215
271
|
if args.empty?
|
@@ -226,6 +282,9 @@ module WEBrick
|
|
226
282
|
end
|
227
283
|
end
|
228
284
|
|
285
|
+
##
|
286
|
+
# Retrieves the header at the first entry in +key+
|
287
|
+
|
229
288
|
def [](*key)
|
230
289
|
begin
|
231
290
|
@header[key[0].downcase].join(", ")
|
@@ -234,6 +293,12 @@ module WEBrick
|
|
234
293
|
end
|
235
294
|
end
|
236
295
|
|
296
|
+
##
|
297
|
+
# Adds +str+ to this FormData which may be the body, a header or a
|
298
|
+
# header entry.
|
299
|
+
#
|
300
|
+
# This is called by WEBrick::HTTPUtils.parse_form_data for you
|
301
|
+
|
237
302
|
def <<(str)
|
238
303
|
if @header
|
239
304
|
super
|
@@ -249,6 +314,11 @@ module WEBrick
|
|
249
314
|
self
|
250
315
|
end
|
251
316
|
|
317
|
+
##
|
318
|
+
# Adds +data+ at the end of the chain of entries
|
319
|
+
#
|
320
|
+
# This is called by WEBrick::HTTPUtils.parse_form_data for you.
|
321
|
+
|
252
322
|
def append_data(data)
|
253
323
|
tmp = self
|
254
324
|
while tmp
|
@@ -261,6 +331,9 @@ module WEBrick
|
|
261
331
|
self
|
262
332
|
end
|
263
333
|
|
334
|
+
##
|
335
|
+
# Yields each entry in this FormData
|
336
|
+
|
264
337
|
def each_data
|
265
338
|
tmp = self
|
266
339
|
while tmp
|
@@ -270,6 +343,9 @@ module WEBrick
|
|
270
343
|
end
|
271
344
|
end
|
272
345
|
|
346
|
+
##
|
347
|
+
# Returns all the FormData as an Array
|
348
|
+
|
273
349
|
def list
|
274
350
|
ret = []
|
275
351
|
each_data{|data|
|
@@ -278,13 +354,22 @@ module WEBrick
|
|
278
354
|
ret
|
279
355
|
end
|
280
356
|
|
357
|
+
##
|
358
|
+
# A FormData will behave like an Array
|
359
|
+
|
281
360
|
alias :to_ary :list
|
282
361
|
|
362
|
+
##
|
363
|
+
# This FormData's body
|
364
|
+
|
283
365
|
def to_s
|
284
366
|
String.new(self)
|
285
367
|
end
|
286
368
|
end
|
287
369
|
|
370
|
+
##
|
371
|
+
# Parses the query component of a URI in +str+
|
372
|
+
|
288
373
|
def parse_query(str)
|
289
374
|
query = Hash.new
|
290
375
|
if str
|
@@ -306,6 +391,9 @@ module WEBrick
|
|
306
391
|
end
|
307
392
|
module_function :parse_query
|
308
393
|
|
394
|
+
##
|
395
|
+
# Parses form data in +io+ with the given +boundary+
|
396
|
+
|
309
397
|
def parse_form_data(io, boundary)
|
310
398
|
boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/
|
311
399
|
form_data = Hash.new
|
@@ -350,10 +438,22 @@ module WEBrick
|
|
350
438
|
|
351
439
|
module_function
|
352
440
|
|
441
|
+
# :stopdoc:
|
442
|
+
|
353
443
|
def _make_regex(str) /([#{Regexp.escape(str)}])/n end
|
354
444
|
def _make_regex!(str) /([^#{Regexp.escape(str)}])/n end
|
355
|
-
def _escape(str, regex)
|
356
|
-
|
445
|
+
def _escape(str, regex)
|
446
|
+
str = str.b
|
447
|
+
str.gsub!(regex) {"%%%02X" % $1.ord}
|
448
|
+
# %-escaped string should contain US-ASCII only
|
449
|
+
str.force_encoding(Encoding::US_ASCII)
|
450
|
+
end
|
451
|
+
def _unescape(str, regex)
|
452
|
+
str = str.b
|
453
|
+
str.gsub!(regex) {$1.hex.chr}
|
454
|
+
# encoding of %-unescaped string is unknown
|
455
|
+
str
|
456
|
+
end
|
357
457
|
|
358
458
|
UNESCAPED = _make_regex(control+space+delims+unwise+nonascii)
|
359
459
|
UNESCAPED_FORM = _make_regex(reserved+control+delims+unwise+nonascii)
|
@@ -361,24 +461,41 @@ module WEBrick
|
|
361
461
|
ESCAPED = /%([0-9a-fA-F]{2})/
|
362
462
|
UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,")
|
363
463
|
|
464
|
+
# :startdoc:
|
465
|
+
|
466
|
+
##
|
467
|
+
# Escapes HTTP reserved and unwise characters in +str+
|
468
|
+
|
364
469
|
def escape(str)
|
365
470
|
_escape(str, UNESCAPED)
|
366
471
|
end
|
367
472
|
|
473
|
+
##
|
474
|
+
# Unescapes HTTP reserved and unwise characters in +str+
|
475
|
+
|
368
476
|
def unescape(str)
|
369
477
|
_unescape(str, ESCAPED)
|
370
478
|
end
|
371
479
|
|
480
|
+
##
|
481
|
+
# Escapes form reserved characters in +str+
|
482
|
+
|
372
483
|
def escape_form(str)
|
373
484
|
ret = _escape(str, UNESCAPED_FORM)
|
374
485
|
ret.gsub!(/ /, "+")
|
375
486
|
ret
|
376
487
|
end
|
377
488
|
|
489
|
+
##
|
490
|
+
# Unescapes form reserved characters in +str+
|
491
|
+
|
378
492
|
def unescape_form(str)
|
379
493
|
_unescape(str.gsub(/\+/, " "), ESCAPED)
|
380
494
|
end
|
381
495
|
|
496
|
+
##
|
497
|
+
# Escapes path +str+
|
498
|
+
|
382
499
|
def escape_path(str)
|
383
500
|
result = ""
|
384
501
|
str.scan(%r{/([^/]*)}).each{|i|
|
@@ -387,6 +504,9 @@ module WEBrick
|
|
387
504
|
return result
|
388
505
|
end
|
389
506
|
|
507
|
+
##
|
508
|
+
# Escapes 8 bit characters in +str+
|
509
|
+
|
390
510
|
def escape8bit(str)
|
391
511
|
_escape(str, NONASCII)
|
392
512
|
end
|
data/lib/webrick/httpversion.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#--
|
2
3
|
# HTTPVersion.rb -- presentation of HTTP version
|
3
4
|
#
|
@@ -8,15 +9,33 @@
|
|
8
9
|
# $IPR: httpversion.rb,v 1.5 2002/09/21 12:23:37 gotoyuzo Exp $
|
9
10
|
|
10
11
|
module WEBrick
|
12
|
+
|
13
|
+
##
|
14
|
+
# Represents an HTTP protocol version
|
15
|
+
|
11
16
|
class HTTPVersion
|
12
17
|
include Comparable
|
13
18
|
|
14
|
-
|
19
|
+
##
|
20
|
+
# The major protocol version number
|
21
|
+
|
22
|
+
attr_accessor :major
|
23
|
+
|
24
|
+
##
|
25
|
+
# The minor protocol version number
|
26
|
+
|
27
|
+
attr_accessor :minor
|
28
|
+
|
29
|
+
##
|
30
|
+
# Converts +version+ into an HTTPVersion
|
15
31
|
|
16
32
|
def self.convert(version)
|
17
33
|
version.is_a?(self) ? version : new(version)
|
18
34
|
end
|
19
35
|
|
36
|
+
##
|
37
|
+
# Creates a new HTTPVersion from +version+.
|
38
|
+
|
20
39
|
def initialize(version)
|
21
40
|
case version
|
22
41
|
when HTTPVersion
|
@@ -32,6 +51,10 @@ module WEBrick
|
|
32
51
|
end
|
33
52
|
end
|
34
53
|
|
54
|
+
##
|
55
|
+
# Compares this version with +other+ according to the HTTP specification
|
56
|
+
# rules.
|
57
|
+
|
35
58
|
def <=>(other)
|
36
59
|
unless other.is_a?(self.class)
|
37
60
|
other = self.class.new(other)
|
@@ -42,6 +65,10 @@ module WEBrick
|
|
42
65
|
return ret
|
43
66
|
end
|
44
67
|
|
68
|
+
##
|
69
|
+
# The HTTP version as show in the HTTP request and response. For example,
|
70
|
+
# "1.1"
|
71
|
+
|
45
72
|
def to_s
|
46
73
|
format("%d.%d", @major, @minor)
|
47
74
|
end
|
data/lib/webrick/log.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#--
|
2
3
|
# log.rb -- Log Class
|
3
4
|
#
|
@@ -14,8 +15,27 @@ module WEBrick
|
|
14
15
|
# A generic logging class
|
15
16
|
|
16
17
|
class BasicLog
|
17
|
-
|
18
|
-
|
18
|
+
|
19
|
+
# Fatal log level which indicates a server crash
|
20
|
+
|
21
|
+
FATAL = 1
|
22
|
+
|
23
|
+
# Error log level which indicates a recoverable error
|
24
|
+
|
25
|
+
ERROR = 2
|
26
|
+
|
27
|
+
# Warning log level which indicates a possible problem
|
28
|
+
|
29
|
+
WARN = 3
|
30
|
+
|
31
|
+
# Information log level which indicates possibly useful information
|
32
|
+
|
33
|
+
INFO = 4
|
34
|
+
|
35
|
+
# Debugging error level for messages used in server development or
|
36
|
+
# debugging
|
37
|
+
|
38
|
+
DEBUG = 5
|
19
39
|
|
20
40
|
# log-level, messages above this level will be logged
|
21
41
|
attr_accessor :level
|
@@ -31,7 +51,7 @@ module WEBrick
|
|
31
51
|
@level = level || INFO
|
32
52
|
case log_file
|
33
53
|
when String
|
34
|
-
@log = open(log_file, "a+")
|
54
|
+
@log = File.open(log_file, "a+")
|
35
55
|
@log.sync = true
|
36
56
|
@opened = true
|
37
57
|
when NilClass
|
@@ -98,10 +118,10 @@ module WEBrick
|
|
98
118
|
# * Otherwise it will return +arg+.inspect.
|
99
119
|
def format(arg)
|
100
120
|
if arg.is_a?(Exception)
|
101
|
-
"#{arg.class}: #{arg.message}\n\t" <<
|
121
|
+
"#{arg.class}: #{AccessLog.escape(arg.message)}\n\t" <<
|
102
122
|
arg.backtrace.join("\n\t") << "\n"
|
103
123
|
elsif arg.respond_to?(:to_str)
|
104
|
-
arg.to_str
|
124
|
+
AccessLog.escape(arg.to_str)
|
105
125
|
else
|
106
126
|
arg.inspect
|
107
127
|
end
|