Add bin and edit workflow
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 9s

This commit is contained in:
2026-09-16 13:11:16 -06:00
parent c8ac4fcae5
commit 4cee170d66
17576 changed files with 895740 additions and 2 deletions
@@ -0,0 +1,152 @@
# frozen_string_literal: true
#
# httpservlet.rb -- HTTPServlet Module
#
# Author: IPR -- Internet Programming with Ruby -- writers
# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU Yuuzou
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
# reserved.
#
# $IPR: abstract.rb,v 1.24 2003/07/11 11:16:46 gotoyuzo Exp $
require_relative '../htmlutils'
require_relative '../httputils'
require_relative '../httpstatus'
module WEBrick
module HTTPServlet
class HTTPServletError < StandardError; end
##
# AbstractServlet allows HTTP server modules to be reused across multiple
# servers and allows encapsulation of functionality.
#
# By default a servlet will respond to GET, HEAD (through an alias to GET)
# and OPTIONS requests.
#
# By default a new servlet is initialized for every request. A servlet
# instance can be reused by overriding ::get_instance in the
# AbstractServlet subclass.
#
# == A Simple Servlet
#
# class Simple < WEBrick::HTTPServlet::AbstractServlet
# def do_GET request, response
# status, content_type, body = do_stuff_with request
#
# response.status = status
# response['Content-Type'] = content_type
# response.body = body
# end
#
# def do_stuff_with request
# return 200, 'text/plain', 'you got a page'
# end
# end
#
# This servlet can be mounted on a server at a given path:
#
# server.mount '/simple', Simple
#
# == Servlet Configuration
#
# Servlets can be configured via initialize. The first argument is the
# HTTP server the servlet is being initialized for.
#
# class Configurable < Simple
# def initialize server, color, size
# super server
# @color = color
# @size = size
# end
#
# def do_stuff_with request
# content = "<p " \
# %q{style="color: #{@color}; font-size: #{@size}"} \
# ">Hello, World!"
#
# return 200, "text/html", content
# end
# end
#
# This servlet must be provided two arguments at mount time:
#
# server.mount '/configurable', Configurable, 'red', '2em'
class AbstractServlet
##
# Factory for servlet instances that will handle a request from +server+
# using +options+ from the mount point. By default a new servlet
# instance is created for every call.
def self.get_instance(server, *options)
self.new(server, *options)
end
##
# Initializes a new servlet for +server+ using +options+ which are
# stored as-is in +@options+. +@logger+ is also provided.
def initialize(server, *options)
@server = @config = server
@logger = @server[:Logger]
@options = options
end
##
# Dispatches to a +do_+ method based on +req+ if such a method is
# available. (+do_GET+ for a GET request). Raises a MethodNotAllowed
# exception if the method is not implemented.
def service(req, res)
method_name = "do_" + req.request_method.gsub(/-/, "_")
if respond_to?(method_name)
__send__(method_name, req, res)
else
raise HTTPStatus::MethodNotAllowed,
"unsupported method '#{req.request_method}'."
end
end
##
# Raises a NotFound exception
def do_GET(req, res)
raise HTTPStatus::NotFound, "not found."
end
##
# Dispatches to do_GET
def do_HEAD(req, res)
do_GET(req, res)
end
##
# Returns the allowed HTTP request methods
def do_OPTIONS(req, res)
m = self.methods.grep(/\Ado_([A-Z]+)\z/) {$1}
m.sort!
res["allow"] = m.join(",")
end
private
##
# Redirects to a path ending in /
def redirect_to_directory_uri(req, res)
if req.path[-1] != ?/
location = WEBrick::HTTPUtils.escape_path(req.path + "/")
if req.query_string && req.query_string.bytesize > 0
location << "?" << req.query_string
end
res.set_redirect(HTTPStatus::MovedPermanently, location)
end
end
end
end
end
@@ -0,0 +1,47 @@
# frozen_string_literal: true
#
# cgi_runner.rb -- CGI launcher.
#
# Author: IPR -- Internet Programming with Ruby -- writers
# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
# reserved.
#
# $IPR: cgi_runner.rb,v 1.9 2002/09/25 11:33:15 gotoyuzo Exp $
def sysread(io, size)
buf = +""
while size > 0
tmp = io.sysread(size)
buf << tmp
size -= tmp.bytesize
end
return buf
end
STDIN.binmode
len = sysread(STDIN, 8).to_i
out = sysread(STDIN, len)
STDOUT.reopen(File.open(out, "w"))
len = sysread(STDIN, 8).to_i
err = sysread(STDIN, len)
STDERR.reopen(File.open(err, "w"))
len = sysread(STDIN, 8).to_i
dump = sysread(STDIN, len)
hash = Marshal.restore(dump)
ENV.keys.each{|name| ENV.delete(name) }
hash.each{|k, v| ENV[k] = v if v }
dir = File::dirname(ENV["SCRIPT_FILENAME"])
Dir::chdir dir
if ARGV[0]
argv = ARGV.dup
argv << ENV["SCRIPT_FILENAME"]
exec(*argv)
# NOTREACHED
end
exec ENV["SCRIPT_FILENAME"]
@@ -0,0 +1,126 @@
# frozen_string_literal: true
#
# cgihandler.rb -- CGIHandler Class
#
# Author: IPR -- Internet Programming with Ruby -- writers
# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
# reserved.
#
# $IPR: cgihandler.rb,v 1.27 2003/03/21 19:56:01 gotoyuzo Exp $
require 'rbconfig'
require 'tempfile'
require_relative '../config'
require_relative 'abstract'
module WEBrick
module HTTPServlet
##
# Servlet for handling CGI scripts
#
# Example:
#
# server.mount('/cgi/my_script', WEBrick::HTTPServlet::CGIHandler,
# '/path/to/my_script')
class CGIHandler < AbstractServlet
Ruby = RbConfig.ruby # :nodoc:
CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\"" # :nodoc:
CGIRunnerArray = [Ruby, "#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb".freeze].freeze # :nodoc:
##
# Creates a new CGI script servlet for the script at +name+
def initialize(server, name)
super(server, name)
@script_filename = name
@tempdir = server[:TempDir]
interpreter = server[:CGIInterpreter]
if interpreter.is_a?(Array)
@cgicmd = CGIRunnerArray + interpreter
else
@cgicmd = "#{CGIRunner} #{interpreter}"
end
end
# :stopdoc:
def do_GET(req, res)
cgi_in = IO::popen(@cgicmd, "wb")
cgi_out = Tempfile.new("webrick.cgiout.", @tempdir, mode: IO::BINARY)
cgi_out.set_encoding("ASCII-8BIT")
cgi_err = Tempfile.new("webrick.cgierr.", @tempdir, mode: IO::BINARY)
cgi_err.set_encoding("ASCII-8BIT")
begin
cgi_in.sync = true
meta = req.meta_vars
meta["SCRIPT_FILENAME"] = @script_filename
meta["PATH"] = @config[:CGIPathEnv]
meta.delete("HTTP_PROXY")
if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
meta["SystemRoot"] = ENV["SystemRoot"]
end
dump = Marshal.dump(meta)
cgi_in.write("%8d" % cgi_out.path.bytesize)
cgi_in.write(cgi_out.path)
cgi_in.write("%8d" % cgi_err.path.bytesize)
cgi_in.write(cgi_err.path)
cgi_in.write("%8d" % dump.bytesize)
cgi_in.write(dump)
req.body { |chunk| cgi_in.write(chunk) }
ensure
cgi_in.close
status = $?.exitstatus
sleep 0.1 if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
data = cgi_out.read
cgi_out.close(true)
if errmsg = cgi_err.read
if errmsg.bytesize > 0
@logger.error("CGIHandler: #{@script_filename}:\n" + errmsg)
end
end
cgi_err.close(true)
end
if status != 0
@logger.error("CGIHandler: #{@script_filename} exit with #{status}")
end
data = "" unless data
raw_header, body = data.split(/^[\xd\xa]+/, 2)
raise HTTPStatus::InternalServerError,
"Premature end of script headers: #{@script_filename}" if body.nil?
begin
header = HTTPUtils::parse_header(raw_header)
if /^(\d+)/ =~ header['status'][0]
res.status = $1.to_i
header.delete('status')
end
if header.has_key?('location')
# RFC 3875 6.2.3, 6.2.4
res.status = 302 unless (300...400) === res.status
end
if header.has_key?('set-cookie')
header['set-cookie'].each{|k|
res.cookies << Cookie.parse_set_cookie(k)
}
header.delete('set-cookie')
end
header.each{|key, val| res[key] = val.join(", ") }
rescue => ex
raise HTTPStatus::InternalServerError, ex.message
end
res.body = body
end
alias do_POST do_GET
# :startdoc:
end
end
end
@@ -0,0 +1,88 @@
# frozen_string_literal: true
#
# erbhandler.rb -- ERBHandler Class
#
# Author: IPR -- Internet Programming with Ruby -- writers
# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
# reserved.
#
# $IPR: erbhandler.rb,v 1.25 2003/02/24 19:25:31 gotoyuzo Exp $
require_relative 'abstract'
require 'erb'
module WEBrick
module HTTPServlet
##
# ERBHandler evaluates an ERB file and returns the result. This handler
# is automatically used if there are .rhtml files in a directory served by
# the FileHandler.
#
# ERBHandler supports GET and POST methods.
#
# The ERB file is evaluated with the local variables +servlet_request+ and
# +servlet_response+ which are a WEBrick::HTTPRequest and
# WEBrick::HTTPResponse respectively.
#
# Example .rhtml file:
#
# Request to <%= servlet_request.request_uri %>
#
# Query params <%= servlet_request.query.inspect %>
class ERBHandler < AbstractServlet
##
# Creates a new ERBHandler on +server+ that will evaluate and serve the
# ERB file +name+
def initialize(server, name)
super(server, name)
@script_filename = name
end
##
# Handles GET requests
def do_GET(req, res)
unless defined?(ERB)
@logger.warn "#{self.class}: ERB not defined."
raise HTTPStatus::Forbidden, "ERBHandler cannot work."
end
begin
data = File.open(@script_filename, &:read)
res.body = evaluate(ERB.new(data), req, res)
res['content-type'] ||=
HTTPUtils::mime_type(@script_filename, @config[:MimeTypes])
rescue StandardError
raise
rescue Exception => ex
@logger.error(ex)
raise HTTPStatus::InternalServerError, ex.message
end
end
##
# Handles POST requests
alias do_POST do_GET
private
##
# Evaluates +erb+ providing +servlet_request+ and +servlet_response+ as
# local variables.
def evaluate(erb, servlet_request, servlet_response)
Module.new.module_eval{
servlet_request.meta_vars
servlet_request.query
erb.result(binding)
}
end
end
end
end
@@ -0,0 +1,552 @@
# frozen_string_literal: true
#
# filehandler.rb -- FileHandler Module
#
# Author: IPR -- Internet Programming with Ruby -- writers
# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
# reserved.
#
# $IPR: filehandler.rb,v 1.44 2003/06/07 01:34:51 gotoyuzo Exp $
require 'time'
require_relative '../htmlutils'
require_relative '../httputils'
require_relative '../httpstatus'
module WEBrick
module HTTPServlet
##
# Servlet for serving a single file. You probably want to use the
# FileHandler servlet instead as it handles directories and fancy indexes.
#
# Example:
#
# server.mount('/my_page.txt', WEBrick::HTTPServlet::DefaultFileHandler,
# '/path/to/my_page.txt')
#
# This servlet handles If-Modified-Since and Range requests.
class DefaultFileHandler < AbstractServlet
##
# Creates a DefaultFileHandler instance for the file at +local_path+.
def initialize(server, local_path)
super(server, local_path)
@local_path = local_path
end
# :stopdoc:
def do_GET(req, res)
st = File::stat(@local_path)
mtime = st.mtime
res['etag'] = sprintf("%x-%x-%x", st.ino, st.size, st.mtime.to_i)
if not_modified?(req, res, mtime, res['etag'])
res.body = ''
raise HTTPStatus::NotModified
elsif req['range']
make_partial_content(req, res, @local_path, st.size)
raise HTTPStatus::PartialContent
else
mtype = HTTPUtils::mime_type(@local_path, @config[:MimeTypes])
res['content-type'] = mtype
res['content-length'] = st.size.to_s
res['last-modified'] = mtime.httpdate
res.body = File.open(@local_path, "rb")
end
end
def not_modified?(req, res, mtime, etag)
if ir = req['if-range']
begin
if Time.httpdate(ir) >= mtime
return true
end
rescue
if HTTPUtils::split_header_value(ir).member?(res['etag'])
return true
end
end
end
if (ims = req['if-modified-since']) && Time.parse(ims) >= mtime
return true
end
if (inm = req['if-none-match']) &&
HTTPUtils::split_header_value(inm).member?(res['etag'])
return true
end
return false
end
# returns a lambda for webrick/httpresponse.rb send_body_proc
def multipart_body(body, parts, boundary, mtype, filesize)
lambda do |socket|
begin
begin
first = parts.shift
last = parts.shift
socket.write(
"--#{boundary}#{CRLF}" \
"Content-Type: #{mtype}#{CRLF}" \
"Content-Range: bytes #{first}-#{last}/#{filesize}#{CRLF}" \
"#{CRLF}"
)
begin
IO.copy_stream(body, socket, last - first + 1, first)
rescue NotImplementedError
body.seek(first, IO::SEEK_SET)
IO.copy_stream(body, socket, last - first + 1)
end
socket.write(CRLF)
end while parts[0]
socket.write("--#{boundary}--#{CRLF}")
ensure
body.close
end
end
end
def make_partial_content(req, res, filename, filesize)
mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes])
unless ranges = HTTPUtils::parse_range_header(req['range'])
raise HTTPStatus::BadRequest,
"Unrecognized range-spec: \"#{req['range']}\""
end
File.open(filename, "rb"){|io|
if ranges.size > 1
time = Time.now
boundary = "#{time.sec}_#{time.usec}_#{Process::pid}"
parts = []
ranges.each {|range|
prange = prepare_range(range, filesize)
next if prange[0] < 0
parts.concat(prange)
}
raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty?
res["content-type"] = "multipart/byteranges; boundary=#{boundary}"
if req.http_version < '1.1'
res['connection'] = 'close'
else
res.chunked = true
end
res.body = multipart_body(io.dup, parts, boundary, mtype, filesize)
elsif range = ranges[0]
first, last = prepare_range(range, filesize)
raise HTTPStatus::RequestRangeNotSatisfiable if first < 0
res['content-type'] = mtype
res['content-range'] = "bytes #{first}-#{last}/#{filesize}"
res['content-length'] = (last - first + 1).to_s
res.body = io.dup
else
raise HTTPStatus::BadRequest
end
}
end
def prepare_range(range, filesize)
first = range.first < 0 ? filesize + range.first : range.first
return -1, -1 if first < 0 || first >= filesize
last = range.last < 0 ? filesize + range.last : range.last
last = filesize - 1 if last >= filesize
return first, last
end
# :startdoc:
end
##
# Serves a directory including fancy indexing and a variety of other
# options.
#
# Example:
#
# server.mount('/assets', WEBrick::HTTPServlet::FileHandler,
# '/path/to/assets')
class FileHandler < AbstractServlet
HandlerTable = Hash.new # :nodoc:
##
# Allow custom handling of requests for files with +suffix+ by class
# +handler+
def self.add_handler(suffix, handler)
HandlerTable[suffix] = handler
end
##
# Remove custom handling of requests for files with +suffix+
def self.remove_handler(suffix)
HandlerTable.delete(suffix)
end
##
# Creates a FileHandler servlet on +server+ that serves files starting
# at directory +root+
#
# +options+ may be a Hash containing keys from
# WEBrick::Config::FileHandler or +true+ or +false+.
#
# If +options+ is true or false then +:FancyIndexing+ is enabled or
# disabled respectively.
def initialize(server, root, options={}, default=Config::FileHandler)
@config = server.config
@logger = @config[:Logger]
@root = File.expand_path(root)
if options == true || options == false
options = { :FancyIndexing => options }
end
@options = default.dup.update(options)
end
# :stopdoc:
def set_filesystem_encoding(str)
enc = Encoding.find('filesystem')
if enc == Encoding::US_ASCII
str.b
else
str.dup.force_encoding(enc)
end
end
def service(req, res)
# if this class is mounted on "/" and /~username is requested.
# we're going to override path information before invoking service.
if defined?(Etc) && @options[:UserDir] && req.script_name.empty?
if %r|^(/~([^/]+))| =~ req.path_info
script_name, user = $1, $2
path_info = $'
begin
passwd = Etc::getpwnam(user)
@root = File::join(passwd.dir, @options[:UserDir])
req.script_name = script_name
req.path_info = path_info
rescue
@logger.debug "#{self.class}#do_GET: getpwnam(#{user}) failed"
end
end
end
prevent_directory_traversal(req, res)
super(req, res)
end
def do_GET(req, res)
unless exec_handler(req, res)
set_dir_list(req, res)
end
end
def do_POST(req, res)
unless exec_handler(req, res)
raise HTTPStatus::NotFound, "'#{req.path}' not found."
end
end
def do_OPTIONS(req, res)
unless exec_handler(req, res)
super(req, res)
end
end
# ToDo
# RFC2518: HTTP Extensions for Distributed Authoring -- WEBDAV
#
# PROPFIND PROPPATCH MKCOL DELETE PUT COPY MOVE
# LOCK UNLOCK
# RFC3253: Versioning Extensions to WebDAV
# (Web Distributed Authoring and Versioning)
#
# VERSION-CONTROL REPORT CHECKOUT CHECK_IN UNCHECKOUT
# MKWORKSPACE UPDATE LABEL MERGE ACTIVITY
private
def trailing_pathsep?(path)
# check for trailing path separator:
# File.dirname("/aaaa/bbbb/") #=> "/aaaa")
# File.dirname("/aaaa/bbbb/x") #=> "/aaaa/bbbb")
# File.dirname("/aaaa/bbbb") #=> "/aaaa")
# File.dirname("/aaaa/bbbbx") #=> "/aaaa")
return File.dirname(path) != File.dirname(path+"x")
end
def prevent_directory_traversal(req, res)
# Preventing directory traversal on Windows platforms;
# Backslashes (0x5c) in path_info are not interpreted as special
# character in URI notation. So the value of path_info should be
# normalize before accessing to the filesystem.
# dirty hack for filesystem encoding; in nature, File.expand_path
# should not be used for path normalization. [Bug #3345]
path = req.path_info.dup.force_encoding(Encoding.find("filesystem"))
if trailing_pathsep?(req.path_info)
# File.expand_path removes the trailing path separator.
# Adding a character is a workaround to save it.
# File.expand_path("/aaa/") #=> "/aaa"
# File.expand_path("/aaa/" + "x") #=> "/aaa/x"
expanded = File.expand_path(path + "x")
expanded.chop! # remove trailing "x"
else
expanded = File.expand_path(path)
end
expanded.force_encoding(req.path_info.encoding)
req.path_info = expanded
end
def exec_handler(req, res)
raise HTTPStatus::NotFound, "'#{req.path}' not found." unless @root
if set_filename(req, res)
handler = get_handler(req, res)
call_callback(:HandlerCallback, req, res)
h = handler.get_instance(@config, res.filename)
h.service(req, res)
return true
end
call_callback(:HandlerCallback, req, res)
return false
end
def get_handler(req, res)
suffix1 = (/\.(\w+)\z/ =~ res.filename) && $1.downcase
if /\.(\w+)\.([\w\-]+)\z/ =~ res.filename
if @options[:AcceptableLanguages].include?($2.downcase)
suffix2 = $1.downcase
end
end
handler_table = @options[:HandlerTable]
return handler_table[suffix1] || handler_table[suffix2] ||
HandlerTable[suffix1] || HandlerTable[suffix2] ||
DefaultFileHandler
end
def set_filename(req, res)
res.filename = @root
path_info = req.path_info.scan(%r|/[^/]*|)
path_info.unshift("") # dummy for checking @root dir
while base = path_info.first
base = set_filesystem_encoding(base)
break if base == "/"
break unless File.directory?(File.expand_path(res.filename + base))
shift_path_info(req, res, path_info)
call_callback(:DirectoryCallback, req, res)
end
if base = path_info.first
base = set_filesystem_encoding(base)
if base == "/"
if file = search_index_file(req, res)
shift_path_info(req, res, path_info, file)
call_callback(:FileCallback, req, res)
return true
end
shift_path_info(req, res, path_info)
elsif file = search_file(req, res, base)
shift_path_info(req, res, path_info, file)
call_callback(:FileCallback, req, res)
return true
else
raise HTTPStatus::NotFound, "'#{req.path}' not found."
end
end
return false
end
def check_filename(req, res, name)
if nondisclosure_name?(name) || windows_ambiguous_name?(name)
@logger.warn("the request refers nondisclosure name '#{name}'.")
raise HTTPStatus::NotFound, "'#{req.path}' not found."
end
end
def shift_path_info(req, res, path_info, base=nil)
tmp = path_info.shift
base = base || set_filesystem_encoding(tmp)
req.path_info = path_info.join
req.script_name << base
res.filename = File.expand_path(res.filename + base)
check_filename(req, res, File.basename(res.filename))
end
def search_index_file(req, res)
@config[:DirectoryIndex].each{|index|
if file = search_file(req, res, "/"+index)
return file
end
}
return nil
end
def search_file(req, res, basename)
langs = @options[:AcceptableLanguages]
path = res.filename + basename
if File.file?(path)
return basename
elsif langs.size > 0
req.accept_language.each{|lang|
path_with_lang = path + ".#{lang}"
if langs.member?(lang) && File.file?(path_with_lang)
return basename + ".#{lang}"
end
}
(langs - req.accept_language).each{|lang|
path_with_lang = path + ".#{lang}"
if File.file?(path_with_lang)
return basename + ".#{lang}"
end
}
end
return nil
end
def call_callback(callback_name, req, res)
if cb = @options[callback_name]
cb.call(req, res)
end
end
def windows_ambiguous_name?(name)
return true if /[. ]+\z/ =~ name
return true if /::\$DATA\z/ =~ name
return false
end
def nondisclosure_name?(name)
@options[:NondisclosureName].each{|pattern|
if File.fnmatch(pattern, name, File::FNM_CASEFOLD)
return true
end
}
return false
end
def set_dir_list(req, res)
redirect_to_directory_uri(req, res)
unless @options[:FancyIndexing]
raise HTTPStatus::Forbidden, "no access permission to '#{req.path}'"
end
local_path = res.filename
list = Dir::entries(local_path).collect{|name|
next if name == "." || name == ".."
next if nondisclosure_name?(name)
next if windows_ambiguous_name?(name)
st = (File::stat(File.join(local_path, name)) rescue nil)
if st.nil?
[ name, nil, -1 ]
elsif st.directory?
[ name + "/", st.mtime, -1 ]
else
[ name, st.mtime, st.size ]
end
}
list.compact!
query = req.query
d0 = nil
idx = nil
%w[N M S].each_with_index do |q, i|
if d = query.delete(q)
idx ||= i
d0 ||= d
end
end
d0 ||= "A"
idx ||= 0
d1 = (d0 == "A") ? "D" : "A"
if d0 == "A"
list.sort!{|a,b| a[idx] <=> b[idx] }
else
list.sort!{|a,b| b[idx] <=> a[idx] }
end
namewidth = query["NameWidth"]
if namewidth == "*"
namewidth = nil
elsif !namewidth or (namewidth = namewidth.to_i) < 2
namewidth = 25
end
query = query.inject('') {|s, (k, v)| s << '&' << HTMLUtils::escape("#{k}=#{v}")}.dup
type = +"text/html"
case enc = Encoding.find('filesystem')
when Encoding::US_ASCII, Encoding::ASCII_8BIT
else
type << "; charset=\"#{enc.name}\""
end
res['content-type'] = type
title = "Index of #{HTMLUtils::escape(req.path)}"
res.body = +<<-_end_of_html_
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<TITLE>#{title}</TITLE>
<style type="text/css">
<!--
.name, .mtime { text-align: left; }
.size { text-align: right; }
td { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
table { border-collapse: collapse; }
tr th { border-bottom: 2px groove; }
//-->
</style>
</HEAD>
<BODY>
<H1>#{title}</H1>
_end_of_html_
res.body << "<TABLE width=\"100%\"><THEAD><TR>\n"
res.body << "<TH class=\"name\"><A HREF=\"?N=#{d1}#{query}\">Name</A></TH>"
res.body << "<TH class=\"mtime\"><A HREF=\"?M=#{d1}#{query}\">Last modified</A></TH>"
res.body << "<TH class=\"size\"><A HREF=\"?S=#{d1}#{query}\">Size</A></TH>\n"
res.body << "</TR></THEAD>\n"
res.body << "<TBODY>\n"
query.sub!(/\A&/, '?')
list.unshift [ "..", File::mtime(local_path+"/.."), -1 ]
list.each{ |name, time, size|
if name == ".."
dname = "Parent Directory"
elsif namewidth and name.size > namewidth
dname = name[0...(namewidth - 2)] << '..'
else
dname = name
end
s = +"<TR><TD class=\"name\"><A HREF=\"#{HTTPUtils::escape(name)}#{query if name.end_with?('/')}\">#{HTMLUtils::escape(dname)}</A></TD>"
s << "<TD class=\"mtime\">" << (time ? time.strftime("%Y/%m/%d %H:%M") : "") << "</TD>"
s << "<TD class=\"size\">" << (size >= 0 ? size.to_s : "-") << "</TD></TR>\n"
res.body << s
}
res.body << "</TBODY></TABLE>"
res.body << "<HR>"
res.body << <<-_end_of_html_
<ADDRESS>
#{HTMLUtils::escape(@config[:ServerSoftware])}<BR>
at #{req.host}:#{req.port}
</ADDRESS>
</BODY>
</HTML>
_end_of_html_
end
# :startdoc:
end
end
end
@@ -0,0 +1,48 @@
# frozen_string_literal: true
#
# prochandler.rb -- ProcHandler Class
#
# Author: IPR -- Internet Programming with Ruby -- writers
# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
# reserved.
#
# $IPR: prochandler.rb,v 1.7 2002/09/21 12:23:42 gotoyuzo Exp $
require_relative 'abstract'
module WEBrick
module HTTPServlet
##
# Mounts a proc at a path that accepts a request and response.
#
# Instead of mounting this servlet with WEBrick::HTTPServer#mount use
# WEBrick::HTTPServer#mount_proc:
#
# server.mount_proc '/' do |req, res|
# res.body = 'it worked!'
# res.status = 200
# end
class ProcHandler < AbstractServlet
# :stopdoc:
def get_instance(server, *options)
self
end
def initialize(proc)
@proc = proc
end
def do_GET(request, response)
@proc.call(request, response)
end
alias do_POST do_GET
alias do_PUT do_GET
# :startdoc:
end
end
end