webrick 1.3.1 → 1.4.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of webrick might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/lib/webrick.rb +6 -6
- data/lib/webrick/accesslog.rb +9 -1
- data/lib/webrick/cgi.rb +51 -2
- data/lib/webrick/compat.rb +2 -1
- data/lib/webrick/config.rb +42 -5
- data/lib/webrick/cookie.rb +68 -6
- data/lib/webrick/htmlutils.rb +4 -2
- data/lib/webrick/httpauth.rb +1 -0
- data/lib/webrick/httpauth/authenticator.rb +13 -8
- data/lib/webrick/httpauth/basicauth.rb +3 -3
- data/lib/webrick/httpauth/digestauth.rb +25 -9
- data/lib/webrick/httpauth/htdigest.rb +8 -4
- data/lib/webrick/httpauth/htgroup.rb +1 -0
- data/lib/webrick/httpauth/htpasswd.rb +7 -3
- data/lib/webrick/httpauth/userdb.rb +1 -0
- data/lib/webrick/httpproxy.rb +47 -14
- data/lib/webrick/httprequest.rb +142 -16
- data/lib/webrick/httpresponse.rb +96 -24
- data/lib/webrick/https.rb +24 -1
- data/lib/webrick/httpserver.rb +20 -4
- data/lib/webrick/httpservlet.rb +1 -0
- data/lib/webrick/httpservlet/abstract.rb +2 -1
- data/lib/webrick/httpservlet/cgi_runner.rb +1 -0
- data/lib/webrick/httpservlet/cgihandler.rb +19 -5
- data/lib/webrick/httpservlet/erbhandler.rb +2 -1
- data/lib/webrick/httpservlet/filehandler.rb +87 -34
- data/lib/webrick/httpservlet/prochandler.rb +14 -0
- data/lib/webrick/httpstatus.rb +24 -10
- data/lib/webrick/httputils.rb +129 -13
- data/lib/webrick/httpversion.rb +28 -1
- data/lib/webrick/log.rb +22 -2
- data/lib/webrick/server.rb +203 -60
- data/lib/webrick/ssl.rb +80 -5
- data/lib/webrick/utils.rb +97 -67
- data/lib/webrick/version.rb +6 -1
- metadata +59 -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/httpresponse.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# httpresponse.rb -- HTTPResponse Class
|
3
4
|
#
|
@@ -16,25 +17,81 @@ require 'webrick/httpstatus'
|
|
16
17
|
|
17
18
|
module WEBrick
|
18
19
|
##
|
19
|
-
# An HTTP response.
|
20
|
+
# An HTTP response. This is filled in by the service or do_* methods of a
|
21
|
+
# WEBrick HTTP Servlet.
|
20
22
|
|
21
23
|
class HTTPResponse
|
22
|
-
|
24
|
+
|
25
|
+
##
|
26
|
+
# HTTP Response version
|
27
|
+
|
28
|
+
attr_reader :http_version
|
29
|
+
|
30
|
+
##
|
31
|
+
# Response status code (200)
|
32
|
+
|
33
|
+
attr_reader :status
|
34
|
+
|
35
|
+
##
|
36
|
+
# Response header
|
37
|
+
|
38
|
+
attr_reader :header
|
39
|
+
|
40
|
+
##
|
41
|
+
# Response cookies
|
42
|
+
|
23
43
|
attr_reader :cookies
|
44
|
+
|
45
|
+
##
|
46
|
+
# Response reason phrase ("OK")
|
47
|
+
|
24
48
|
attr_accessor :reason_phrase
|
25
49
|
|
26
50
|
##
|
27
|
-
# Body may be a String or IO
|
51
|
+
# Body may be a String or IO-like object that responds to #read and
|
52
|
+
# #readpartial.
|
28
53
|
|
29
54
|
attr_accessor :body
|
30
55
|
|
31
|
-
|
56
|
+
##
|
57
|
+
# Request method for this response
|
58
|
+
|
59
|
+
attr_accessor :request_method
|
60
|
+
|
61
|
+
##
|
62
|
+
# Request URI for this response
|
63
|
+
|
64
|
+
attr_accessor :request_uri
|
65
|
+
|
66
|
+
##
|
67
|
+
# Request HTTP version for this response
|
68
|
+
|
69
|
+
attr_accessor :request_http_version
|
70
|
+
|
71
|
+
##
|
72
|
+
# Filename of the static file in this response. Only used by the
|
73
|
+
# FileHandler servlet.
|
74
|
+
|
32
75
|
attr_accessor :filename
|
76
|
+
|
77
|
+
##
|
78
|
+
# Is this a keep-alive response?
|
79
|
+
|
33
80
|
attr_accessor :keep_alive
|
34
|
-
attr_reader :config, :sent_size
|
35
81
|
|
36
82
|
##
|
37
|
-
#
|
83
|
+
# Configuration for this response
|
84
|
+
|
85
|
+
attr_reader :config
|
86
|
+
|
87
|
+
##
|
88
|
+
# Bytes sent in this response
|
89
|
+
|
90
|
+
attr_reader :sent_size
|
91
|
+
|
92
|
+
##
|
93
|
+
# Creates a new HTTP response object. WEBrick::Config::HTTP is the
|
94
|
+
# default configuration.
|
38
95
|
|
39
96
|
def initialize(config)
|
40
97
|
@config = config
|
@@ -115,7 +172,7 @@ module WEBrick
|
|
115
172
|
end
|
116
173
|
|
117
174
|
##
|
118
|
-
# Iterates over each header in the
|
175
|
+
# Iterates over each header in the response
|
119
176
|
|
120
177
|
def each
|
121
178
|
@header.each{|field, value| yield(field, value) }
|
@@ -145,7 +202,7 @@ module WEBrick
|
|
145
202
|
##
|
146
203
|
# Sends the response on +socket+
|
147
204
|
|
148
|
-
def send_response(socket)
|
205
|
+
def send_response(socket) # :nodoc:
|
149
206
|
begin
|
150
207
|
setup_header()
|
151
208
|
send_header(socket)
|
@@ -162,7 +219,7 @@ module WEBrick
|
|
162
219
|
##
|
163
220
|
# Sets up the headers for sending
|
164
221
|
|
165
|
-
def setup_header()
|
222
|
+
def setup_header() # :nodoc:
|
166
223
|
@reason_phrase ||= HTTPStatus::reason_phrase(@status)
|
167
224
|
@header['server'] ||= @config[:ServerSoftware]
|
168
225
|
@header['date'] ||= Time.now.httpdate
|
@@ -225,7 +282,7 @@ module WEBrick
|
|
225
282
|
##
|
226
283
|
# Sends the headers on +socket+
|
227
284
|
|
228
|
-
def send_header(socket)
|
285
|
+
def send_header(socket) # :nodoc:
|
229
286
|
if @http_version.major > 0
|
230
287
|
data = status_line()
|
231
288
|
@header.each{|key, value|
|
@@ -243,10 +300,11 @@ module WEBrick
|
|
243
300
|
##
|
244
301
|
# Sends the body on +socket+
|
245
302
|
|
246
|
-
def send_body(socket)
|
247
|
-
|
248
|
-
|
249
|
-
else
|
303
|
+
def send_body(socket) # :nodoc:
|
304
|
+
if @body.respond_to? :readpartial then
|
305
|
+
send_body_io(socket)
|
306
|
+
else
|
307
|
+
send_body_string(socket)
|
250
308
|
end
|
251
309
|
end
|
252
310
|
|
@@ -264,7 +322,7 @@ module WEBrick
|
|
264
322
|
# res.set_redirect WEBrick::HTTPStatus::TemporaryRedirect
|
265
323
|
|
266
324
|
def set_redirect(status, url)
|
267
|
-
@body = "<HTML><A HREF=\"#{url
|
325
|
+
@body = "<HTML><A HREF=\"#{url}\">#{url}</A>.</HTML>\n"
|
268
326
|
@header['location'] = url.to_s
|
269
327
|
raise status
|
270
328
|
end
|
@@ -294,6 +352,14 @@ module WEBrick
|
|
294
352
|
host, port = @config[:ServerName], @config[:Port]
|
295
353
|
end
|
296
354
|
|
355
|
+
error_body(backtrace, ex, host, port)
|
356
|
+
end
|
357
|
+
|
358
|
+
private
|
359
|
+
|
360
|
+
# :stopdoc:
|
361
|
+
|
362
|
+
def error_body(backtrace, ex, host, port)
|
297
363
|
@body = ''
|
298
364
|
@body << <<-_end_of_html_
|
299
365
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
|
@@ -323,20 +389,23 @@ module WEBrick
|
|
323
389
|
_end_of_html_
|
324
390
|
end
|
325
391
|
|
326
|
-
private
|
327
|
-
|
328
392
|
def send_body_io(socket)
|
329
393
|
begin
|
330
394
|
if @request_method == "HEAD"
|
331
395
|
# do nothing
|
332
396
|
elsif chunked?
|
333
|
-
|
334
|
-
|
335
|
-
data =
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
397
|
+
begin
|
398
|
+
buf = ''
|
399
|
+
data = ''
|
400
|
+
while true
|
401
|
+
@body.readpartial( @buffer_size, buf ) # there is no need to clear buf?
|
402
|
+
data << format("%x", buf.bytesize) << CRLF
|
403
|
+
data << buf << CRLF
|
404
|
+
_write_data(socket, data)
|
405
|
+
data.clear
|
406
|
+
@sent_size += buf.bytesize
|
407
|
+
end
|
408
|
+
rescue EOFError # do nothing
|
340
409
|
end
|
341
410
|
_write_data(socket, "0#{CRLF}#{CRLF}")
|
342
411
|
else
|
@@ -395,5 +464,8 @@ module WEBrick
|
|
395
464
|
def _write_data(socket, data)
|
396
465
|
socket << data
|
397
466
|
end
|
467
|
+
|
468
|
+
# :startdoc:
|
398
469
|
end
|
470
|
+
|
399
471
|
end
|
data/lib/webrick/https.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# https.rb -- SSL/TLS enhancement for HTTPServer
|
3
4
|
#
|
@@ -15,8 +16,28 @@ module WEBrick
|
|
15
16
|
HTTP.update(SSL)
|
16
17
|
end
|
17
18
|
|
19
|
+
##
|
20
|
+
#--
|
21
|
+
# Adds SSL functionality to WEBrick::HTTPRequest
|
22
|
+
|
18
23
|
class HTTPRequest
|
19
|
-
|
24
|
+
|
25
|
+
##
|
26
|
+
# HTTP request SSL cipher
|
27
|
+
|
28
|
+
attr_reader :cipher
|
29
|
+
|
30
|
+
##
|
31
|
+
# HTTP request server certificate
|
32
|
+
|
33
|
+
attr_reader :server_cert
|
34
|
+
|
35
|
+
##
|
36
|
+
# HTTP request client certificate
|
37
|
+
|
38
|
+
attr_reader :client_cert
|
39
|
+
|
40
|
+
# :stopdoc:
|
20
41
|
|
21
42
|
alias orig_parse parse
|
22
43
|
|
@@ -60,5 +81,7 @@ module WEBrick
|
|
60
81
|
end
|
61
82
|
meta
|
62
83
|
end
|
84
|
+
|
85
|
+
# :startdoc:
|
63
86
|
end
|
64
87
|
end
|
data/lib/webrick/httpserver.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# httpserver.rb -- HTTPServer Class
|
3
4
|
#
|
@@ -8,6 +9,7 @@
|
|
8
9
|
#
|
9
10
|
# $IPR: httpserver.rb,v 1.63 2002/10/01 17:16:32 gotoyuzo Exp $
|
10
11
|
|
12
|
+
require 'io/wait'
|
11
13
|
require 'webrick/server'
|
12
14
|
require 'webrick/httputils'
|
13
15
|
require 'webrick/httpstatus'
|
@@ -72,11 +74,11 @@ module WEBrick
|
|
72
74
|
begin
|
73
75
|
timeout = @config[:RequestTimeout]
|
74
76
|
while timeout > 0
|
75
|
-
break if
|
76
|
-
|
77
|
+
break if sock.to_io.wait_readable(0.5)
|
78
|
+
break if @status != :Running
|
77
79
|
timeout -= 0.5
|
78
80
|
end
|
79
|
-
raise HTTPStatus::EOFError if timeout <= 0
|
81
|
+
raise HTTPStatus::EOFError if timeout <= 0 || @status != :Running
|
80
82
|
raise HTTPStatus::EOFError if sock.eof?
|
81
83
|
req.parse(sock)
|
82
84
|
res.request_method = req.request_method
|
@@ -138,6 +140,10 @@ module WEBrick
|
|
138
140
|
si.service(req, res)
|
139
141
|
end
|
140
142
|
|
143
|
+
##
|
144
|
+
# The default OPTIONS request handler says GET, HEAD, POST and OPTIONS
|
145
|
+
# requests are allowed.
|
146
|
+
|
141
147
|
def do_OPTIONS(req, res)
|
142
148
|
res["allow"] = "GET,HEAD,POST,OPTIONS"
|
143
149
|
end
|
@@ -207,6 +213,10 @@ module WEBrick
|
|
207
213
|
}
|
208
214
|
end
|
209
215
|
|
216
|
+
##
|
217
|
+
# Logs +req+ and +res+ in the access logs. +config+ is used for the
|
218
|
+
# server name.
|
219
|
+
|
210
220
|
def access_log(config, req, res)
|
211
221
|
param = AccessLog::setup_params(config, req, res)
|
212
222
|
@config[:AccessLog].each{|logger, fmt|
|
@@ -214,7 +224,13 @@ module WEBrick
|
|
214
224
|
}
|
215
225
|
end
|
216
226
|
|
217
|
-
|
227
|
+
##
|
228
|
+
# Mount table for the path a servlet is mounted on in the directory space
|
229
|
+
# of the server. Users of WEBrick can only access this indirectly via
|
230
|
+
# WEBrick::HTTPServer#mount, WEBrick::HTTPServer#unmount and
|
231
|
+
# WEBrick::HTTPServer#search_servlet
|
232
|
+
|
233
|
+
class MountTable # :nodoc:
|
218
234
|
def initialize
|
219
235
|
@tab = Hash.new
|
220
236
|
compile
|
data/lib/webrick/httpservlet.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# httpservlet.rb -- HTTPServlet Module
|
3
4
|
#
|
@@ -54,7 +55,7 @@ module WEBrick
|
|
54
55
|
# Servlets can be configured via initialize. The first argument is the
|
55
56
|
# HTTP server the servlet is being initialized for.
|
56
57
|
#
|
57
|
-
# class
|
58
|
+
# class Configurable < Simple
|
58
59
|
# def initialize server, color, size
|
59
60
|
# super server
|
60
61
|
# @color = color
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# cgihandler.rb -- CGIHandler Class
|
3
4
|
#
|
@@ -16,9 +17,20 @@ require 'webrick/httpservlet/abstract'
|
|
16
17
|
module WEBrick
|
17
18
|
module HTTPServlet
|
18
19
|
|
20
|
+
##
|
21
|
+
# Servlet for handling CGI scripts
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
#
|
25
|
+
# server.mount('/cgi/my_script', WEBrick::HTTPServlet::CGIHandler,
|
26
|
+
# '/path/to/my_script')
|
27
|
+
|
19
28
|
class CGIHandler < AbstractServlet
|
20
|
-
Ruby = RbConfig.ruby
|
21
|
-
CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\""
|
29
|
+
Ruby = RbConfig.ruby # :nodoc:
|
30
|
+
CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\"" # :nodoc:
|
31
|
+
|
32
|
+
##
|
33
|
+
# Creates a new CGI script servlet for the script at +name+
|
22
34
|
|
23
35
|
def initialize(server, name)
|
24
36
|
super(server, name)
|
@@ -27,10 +39,9 @@ module WEBrick
|
|
27
39
|
@cgicmd = "#{CGIRunner} #{server[:CGIInterpreter]}"
|
28
40
|
end
|
29
41
|
|
30
|
-
|
31
|
-
data = nil
|
32
|
-
status = -1
|
42
|
+
# :stopdoc:
|
33
43
|
|
44
|
+
def do_GET(req, res)
|
34
45
|
cgi_in = IO::popen(@cgicmd, "wb")
|
35
46
|
cgi_out = Tempfile.new("webrick.cgiout.", @tempdir, mode: IO::BINARY)
|
36
47
|
cgi_out.set_encoding("ASCII-8BIT")
|
@@ -41,6 +52,7 @@ module WEBrick
|
|
41
52
|
meta = req.meta_vars
|
42
53
|
meta["SCRIPT_FILENAME"] = @script_filename
|
43
54
|
meta["PATH"] = @config[:CGIPathEnv]
|
55
|
+
meta.delete("HTTP_PROXY")
|
44
56
|
if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
|
45
57
|
meta["SystemRoot"] = ENV["SystemRoot"]
|
46
58
|
end
|
@@ -102,6 +114,8 @@ module WEBrick
|
|
102
114
|
res.body = body
|
103
115
|
end
|
104
116
|
alias do_POST do_GET
|
117
|
+
|
118
|
+
# :startdoc:
|
105
119
|
end
|
106
120
|
|
107
121
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# erbhandler.rb -- ERBHandler Class
|
3
4
|
#
|
@@ -56,7 +57,7 @@ module WEBrick
|
|
56
57
|
res.body = evaluate(ERB.new(data), req, res)
|
57
58
|
res['content-type'] ||=
|
58
59
|
HTTPUtils::mime_type(@script_filename, @config[:MimeTypes])
|
59
|
-
rescue StandardError
|
60
|
+
rescue StandardError
|
60
61
|
raise
|
61
62
|
rescue Exception => ex
|
62
63
|
@logger.error(ex)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: false
|
1
2
|
#
|
2
3
|
# filehandler.rb -- FileHandler Module
|
3
4
|
#
|
@@ -18,12 +19,29 @@ require 'webrick/httpstatus'
|
|
18
19
|
module WEBrick
|
19
20
|
module HTTPServlet
|
20
21
|
|
22
|
+
##
|
23
|
+
# Servlet for serving a single file. You probably want to use the
|
24
|
+
# FileHandler servlet instead as it handles directories and fancy indexes.
|
25
|
+
#
|
26
|
+
# Example:
|
27
|
+
#
|
28
|
+
# server.mount('/my_page.txt', WEBrick::HTTPServlet::DefaultFileHandler,
|
29
|
+
# '/path/to/my_page.txt')
|
30
|
+
#
|
31
|
+
# This servlet handles If-Modified-Since and Range requests.
|
32
|
+
|
21
33
|
class DefaultFileHandler < AbstractServlet
|
34
|
+
|
35
|
+
##
|
36
|
+
# Creates a DefaultFileHandler instance for the file at +local_path+.
|
37
|
+
|
22
38
|
def initialize(server, local_path)
|
23
39
|
super(server, local_path)
|
24
40
|
@local_path = local_path
|
25
41
|
end
|
26
42
|
|
43
|
+
# :stopdoc:
|
44
|
+
|
27
45
|
def do_GET(req, res)
|
28
46
|
st = File::stat(@local_path)
|
29
47
|
mtime = st.mtime
|
@@ -123,13 +141,21 @@ module WEBrick
|
|
123
141
|
last = filesize - 1 if last >= filesize
|
124
142
|
return first, last
|
125
143
|
end
|
144
|
+
|
145
|
+
# :startdoc:
|
126
146
|
end
|
127
147
|
|
128
148
|
##
|
129
|
-
# Serves
|
149
|
+
# Serves a directory including fancy indexing and a variety of other
|
150
|
+
# options.
|
151
|
+
#
|
152
|
+
# Example:
|
153
|
+
#
|
154
|
+
# server.mount('/assets', WEBrick::HTTPServlet::FileHandler,
|
155
|
+
# '/path/to/assets')
|
130
156
|
|
131
157
|
class FileHandler < AbstractServlet
|
132
|
-
HandlerTable = Hash.new
|
158
|
+
HandlerTable = Hash.new # :nodoc:
|
133
159
|
|
134
160
|
##
|
135
161
|
# Allow custom handling of requests for files with +suffix+ by class
|
@@ -150,19 +176,8 @@ module WEBrick
|
|
150
176
|
# Creates a FileHandler servlet on +server+ that serves files starting
|
151
177
|
# at directory +root+
|
152
178
|
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
# :AcceptableLanguages:: Array of languages allowed for accept-language
|
156
|
-
# :DirectoryCallback:: Allows preprocessing of directory requests
|
157
|
-
# :FancyIndexing:: If true, show an index for directories
|
158
|
-
# :FileCallback:: Allows preprocessing of file requests
|
159
|
-
# :HandlerCallback:: Allows preprocessing of requests
|
160
|
-
# :HandlerTable:: Maps file suffixes to file handlers.
|
161
|
-
# DefaultFileHandler is used by default but any servlet
|
162
|
-
# can be used.
|
163
|
-
# :NondisclosureName:: Do not show files matching this array of globs
|
164
|
-
# :UserDir:: Directory inside ~user to serve content from for /~user
|
165
|
-
# requests. Only works if mounted on /
|
179
|
+
# +options+ may be a Hash containing keys from
|
180
|
+
# WEBrick::Config::FileHandler or +true+ or +false+.
|
166
181
|
#
|
167
182
|
# If +options+ is true or false then +:FancyIndexing+ is enabled or
|
168
183
|
# disabled respectively.
|
@@ -177,6 +192,8 @@ module WEBrick
|
|
177
192
|
@options = default.dup.update(options)
|
178
193
|
end
|
179
194
|
|
195
|
+
# :stopdoc:
|
196
|
+
|
180
197
|
def service(req, res)
|
181
198
|
# if this class is mounted on "/" and /~username is requested.
|
182
199
|
# we're going to override path informations before invoking service.
|
@@ -409,11 +426,18 @@ module WEBrick
|
|
409
426
|
}
|
410
427
|
list.compact!
|
411
428
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
429
|
+
query = req.query
|
430
|
+
|
431
|
+
d0 = nil
|
432
|
+
idx = nil
|
433
|
+
%w[N M S].each_with_index do |q, i|
|
434
|
+
if d = query.delete(q)
|
435
|
+
idx ||= i
|
436
|
+
d0 ||= d
|
437
|
+
end
|
416
438
|
end
|
439
|
+
d0 ||= "A"
|
440
|
+
idx ||= 0
|
417
441
|
d1 = (d0 == "A") ? "D" : "A"
|
418
442
|
|
419
443
|
if d0 == "A"
|
@@ -422,38 +446,66 @@ module WEBrick
|
|
422
446
|
list.sort!{|a,b| b[idx] <=> a[idx] }
|
423
447
|
end
|
424
448
|
|
425
|
-
|
449
|
+
namewidth = query["NameWidth"]
|
450
|
+
if namewidth == "*"
|
451
|
+
namewidth = nil
|
452
|
+
elsif !namewidth or (namewidth = namewidth.to_i) < 2
|
453
|
+
namewidth = 25
|
454
|
+
end
|
455
|
+
query = query.inject('') {|s, (k, v)| s << '&' << HTMLUtils::escape("#{k}=#{v}")}
|
456
|
+
|
457
|
+
type = "text/html"
|
458
|
+
case enc = Encoding.find('filesystem')
|
459
|
+
when Encoding::US_ASCII, Encoding::ASCII_8BIT
|
460
|
+
else
|
461
|
+
type << "; charset=\"#{enc.name}\""
|
462
|
+
end
|
463
|
+
res['content-type'] = type
|
426
464
|
|
465
|
+
title = "Index of #{HTMLUtils::escape(req.path)}"
|
427
466
|
res.body = <<-_end_of_html_
|
428
467
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
429
468
|
<HTML>
|
430
|
-
<HEAD
|
469
|
+
<HEAD>
|
470
|
+
<TITLE>#{title}</TITLE>
|
471
|
+
<style type="text/css">
|
472
|
+
<!--
|
473
|
+
.name, .mtime { text-align: left; }
|
474
|
+
.size { text-align: right; }
|
475
|
+
td { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
|
476
|
+
table { border-collapse: collapse; }
|
477
|
+
tr th { border-bottom: 2px groove; }
|
478
|
+
//-->
|
479
|
+
</style>
|
480
|
+
</HEAD>
|
431
481
|
<BODY>
|
432
|
-
<H1
|
482
|
+
<H1>#{title}</H1>
|
433
483
|
_end_of_html_
|
434
484
|
|
435
|
-
res.body << "<
|
436
|
-
res.body << "
|
437
|
-
res.body << "<A HREF=\"?M=#{d1}\">Last modified</A>
|
438
|
-
res.body << "<A HREF=\"?S=#{d1}\">Size</A>\n"
|
439
|
-
res.body << "
|
485
|
+
res.body << "<TABLE width=\"100%\"><THEAD><TR>\n"
|
486
|
+
res.body << "<TH class=\"name\"><A HREF=\"?N=#{d1}#{query}\">Name</A></TH>"
|
487
|
+
res.body << "<TH class=\"mtime\"><A HREF=\"?M=#{d1}#{query}\">Last modified</A></TH>"
|
488
|
+
res.body << "<TH class=\"size\"><A HREF=\"?S=#{d1}#{query}\">Size</A></TH>\n"
|
489
|
+
res.body << "</TR></THEAD>\n"
|
490
|
+
res.body << "<TBODY>\n"
|
440
491
|
|
492
|
+
query.sub!(/\A&/, '?')
|
441
493
|
list.unshift [ "..", File::mtime(local_path+"/.."), -1 ]
|
442
494
|
list.each{ |name, time, size|
|
443
495
|
if name == ".."
|
444
496
|
dname = "Parent Directory"
|
445
|
-
elsif name.
|
446
|
-
dname = name
|
497
|
+
elsif namewidth and name.size > namewidth
|
498
|
+
dname = name[0...(namewidth - 2)] << '..'
|
447
499
|
else
|
448
500
|
dname = name
|
449
501
|
end
|
450
|
-
s = "
|
451
|
-
s << " "
|
452
|
-
s << (
|
453
|
-
s << (size >= 0 ? size.to_s : "-") << "\n"
|
502
|
+
s = "<TR><TD class=\"name\"><A HREF=\"#{HTTPUtils::escape(name)}#{query if name.end_with?('/')}\">#{HTMLUtils::escape(dname)}</A></TD>"
|
503
|
+
s << "<TD class=\"mtime\">" << (time ? time.strftime("%Y/%m/%d %H:%M") : "") << "</TD>"
|
504
|
+
s << "<TD class=\"size\">" << (size >= 0 ? size.to_s : "-") << "</TD></TR>\n"
|
454
505
|
res.body << s
|
455
506
|
}
|
456
|
-
res.body << "</
|
507
|
+
res.body << "</TBODY></TABLE>"
|
508
|
+
res.body << "<HR>"
|
457
509
|
|
458
510
|
res.body << <<-_end_of_html_
|
459
511
|
<ADDRESS>
|
@@ -465,6 +517,7 @@ module WEBrick
|
|
465
517
|
_end_of_html_
|
466
518
|
end
|
467
519
|
|
520
|
+
# :startdoc:
|
468
521
|
end
|
469
522
|
end
|
470
523
|
end
|