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.

Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +63 -0
  5. data/Rakefile +10 -0
  6. data/bin/console +14 -0
  7. data/bin/setup +8 -0
  8. data/lib/webrick/accesslog.rb +9 -1
  9. data/lib/webrick/cgi.rb +58 -5
  10. data/lib/webrick/compat.rb +2 -1
  11. data/lib/webrick/config.rb +47 -10
  12. data/lib/webrick/cookie.rb +69 -7
  13. data/lib/webrick/htmlutils.rb +4 -2
  14. data/lib/webrick/httpauth/authenticator.rb +13 -8
  15. data/lib/webrick/httpauth/basicauth.rb +16 -8
  16. data/lib/webrick/httpauth/digestauth.rb +35 -32
  17. data/lib/webrick/httpauth/htdigest.rb +12 -8
  18. data/lib/webrick/httpauth/htgroup.rb +10 -6
  19. data/lib/webrick/httpauth/htpasswd.rb +46 -9
  20. data/lib/webrick/httpauth/userdb.rb +1 -0
  21. data/lib/webrick/httpauth.rb +6 -5
  22. data/lib/webrick/httpproxy.rb +93 -48
  23. data/lib/webrick/httprequest.rb +192 -27
  24. data/lib/webrick/httpresponse.rb +221 -70
  25. data/lib/webrick/https.rb +90 -2
  26. data/lib/webrick/httpserver.rb +45 -15
  27. data/lib/webrick/httpservlet/abstract.rb +5 -6
  28. data/lib/webrick/httpservlet/cgi_runner.rb +3 -2
  29. data/lib/webrick/httpservlet/cgihandler.rb +22 -10
  30. data/lib/webrick/httpservlet/erbhandler.rb +4 -3
  31. data/lib/webrick/httpservlet/filehandler.rb +136 -65
  32. data/lib/webrick/httpservlet/prochandler.rb +15 -1
  33. data/lib/webrick/httpservlet.rb +6 -5
  34. data/lib/webrick/httpstatus.rb +24 -14
  35. data/lib/webrick/httputils.rb +133 -13
  36. data/lib/webrick/httpversion.rb +28 -1
  37. data/lib/webrick/log.rb +25 -5
  38. data/lib/webrick/server.rb +234 -74
  39. data/lib/webrick/ssl.rb +100 -12
  40. data/lib/webrick/utils.rb +98 -69
  41. data/lib/webrick/version.rb +6 -1
  42. data/lib/webrick.rb +7 -7
  43. data/webrick.gemspec +76 -0
  44. metadata +70 -69
  45. data/README.txt +0 -21
  46. data/sample/webrick/demo-app.rb +0 -66
  47. data/sample/webrick/demo-multipart.cgi +0 -12
  48. data/sample/webrick/demo-servlet.rb +0 -6
  49. data/sample/webrick/demo-urlencoded.cgi +0 -12
  50. data/sample/webrick/hello.cgi +0 -11
  51. data/sample/webrick/hello.rb +0 -8
  52. data/sample/webrick/httpd.rb +0 -23
  53. data/sample/webrick/httpproxy.rb +0 -25
  54. data/sample/webrick/httpsd.rb +0 -33
  55. data/test/openssl/utils.rb +0 -313
  56. data/test/ruby/envutil.rb +0 -208
  57. data/test/webrick/test_cgi.rb +0 -134
  58. data/test/webrick/test_cookie.rb +0 -131
  59. data/test/webrick/test_filehandler.rb +0 -285
  60. data/test/webrick/test_httpauth.rb +0 -167
  61. data/test/webrick/test_httpproxy.rb +0 -282
  62. data/test/webrick/test_httprequest.rb +0 -411
  63. data/test/webrick/test_httpresponse.rb +0 -49
  64. data/test/webrick/test_httpserver.rb +0 -305
  65. data/test/webrick/test_httputils.rb +0 -96
  66. data/test/webrick/test_httpversion.rb +0 -40
  67. data/test/webrick/test_server.rb +0 -67
  68. data/test/webrick/test_utils.rb +0 -64
  69. data/test/webrick/utils.rb +0 -58
  70. data/test/webrick/webrick.cgi +0 -36
  71. data/test/webrick/webrick_long_filename.cgi +0 -36
@@ -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
- # Load Apache compatible mime.types file.
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
- attr_accessor :name, :filename, :next_data
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) str.gsub(regex){ "%%%02X" % $1.ord } end
356
- def _unescape(str, regex) str.gsub(regex){ $1.hex.chr } end
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
@@ -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
- attr_accessor :major, :minor
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
- # log-level constants
18
- FATAL, ERROR, WARN, INFO, DEBUG = 1, 2, 3, 4, 5
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