rubysl-webrick 1.0.0

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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/README.md +29 -0
  7. data/Rakefile +1 -0
  8. data/lib/rubysl/webrick.rb +2 -0
  9. data/lib/rubysl/webrick/version.rb +5 -0
  10. data/lib/rubysl/webrick/webrick.rb +29 -0
  11. data/lib/webrick.rb +1 -0
  12. data/lib/webrick/accesslog.rb +67 -0
  13. data/lib/webrick/cgi.rb +257 -0
  14. data/lib/webrick/compat.rb +15 -0
  15. data/lib/webrick/config.rb +97 -0
  16. data/lib/webrick/cookie.rb +110 -0
  17. data/lib/webrick/htmlutils.rb +25 -0
  18. data/lib/webrick/httpauth.rb +45 -0
  19. data/lib/webrick/httpauth/authenticator.rb +79 -0
  20. data/lib/webrick/httpauth/basicauth.rb +65 -0
  21. data/lib/webrick/httpauth/digestauth.rb +343 -0
  22. data/lib/webrick/httpauth/htdigest.rb +91 -0
  23. data/lib/webrick/httpauth/htgroup.rb +61 -0
  24. data/lib/webrick/httpauth/htpasswd.rb +83 -0
  25. data/lib/webrick/httpauth/userdb.rb +29 -0
  26. data/lib/webrick/httpproxy.rb +254 -0
  27. data/lib/webrick/httprequest.rb +365 -0
  28. data/lib/webrick/httpresponse.rb +327 -0
  29. data/lib/webrick/https.rb +63 -0
  30. data/lib/webrick/httpserver.rb +210 -0
  31. data/lib/webrick/httpservlet.rb +22 -0
  32. data/lib/webrick/httpservlet/abstract.rb +71 -0
  33. data/lib/webrick/httpservlet/cgi_runner.rb +45 -0
  34. data/lib/webrick/httpservlet/cgihandler.rb +104 -0
  35. data/lib/webrick/httpservlet/erbhandler.rb +54 -0
  36. data/lib/webrick/httpservlet/filehandler.rb +398 -0
  37. data/lib/webrick/httpservlet/prochandler.rb +33 -0
  38. data/lib/webrick/httpstatus.rb +126 -0
  39. data/lib/webrick/httputils.rb +391 -0
  40. data/lib/webrick/httpversion.rb +49 -0
  41. data/lib/webrick/log.rb +88 -0
  42. data/lib/webrick/server.rb +200 -0
  43. data/lib/webrick/ssl.rb +126 -0
  44. data/lib/webrick/utils.rb +100 -0
  45. data/lib/webrick/version.rb +13 -0
  46. data/rubysl-webrick.gemspec +23 -0
  47. metadata +145 -0
@@ -0,0 +1,49 @@
1
+ #
2
+ # HTTPVersion.rb -- presentation of HTTP version
3
+ #
4
+ # Author: IPR -- Internet Programming with Ruby -- writers
5
+ # Copyright (c) 2002 Internet Programming with Ruby writers. All rights
6
+ # reserved.
7
+ #
8
+ # $IPR: httpversion.rb,v 1.5 2002/09/21 12:23:37 gotoyuzo Exp $
9
+
10
+ module WEBrick
11
+ class HTTPVersion
12
+ include Comparable
13
+
14
+ attr_accessor :major, :minor
15
+
16
+ def self.convert(version)
17
+ version.is_a?(self) ? version : new(version)
18
+ end
19
+
20
+ def initialize(version)
21
+ case version
22
+ when HTTPVersion
23
+ @major, @minor = version.major, version.minor
24
+ when String
25
+ if /^(\d+)\.(\d+)$/ =~ version
26
+ @major, @minor = $1.to_i, $2.to_i
27
+ end
28
+ end
29
+ if @major.nil? || @minor.nil?
30
+ raise ArgumentError,
31
+ format("cannot convert %s into %s", version.class, self.class)
32
+ end
33
+ end
34
+
35
+ def <=>(other)
36
+ unless other.is_a?(self.class)
37
+ other = self.class.new(other)
38
+ end
39
+ if (ret = @major <=> other.major) == 0
40
+ return @minor <=> other.minor
41
+ end
42
+ return ret
43
+ end
44
+
45
+ def to_s
46
+ format("%d.%d", @major, @minor)
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,88 @@
1
+ #
2
+ # log.rb -- Log Class
3
+ #
4
+ # Author: IPR -- Internet Programming with Ruby -- writers
5
+ # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
6
+ # Copyright (c) 2002 Internet Programming with Ruby writers. All rights
7
+ # reserved.
8
+ #
9
+ # $IPR: log.rb,v 1.26 2002/10/06 17:06:10 gotoyuzo Exp $
10
+
11
+ module WEBrick
12
+ class BasicLog
13
+ # log-level constant
14
+ FATAL, ERROR, WARN, INFO, DEBUG = 1, 2, 3, 4, 5
15
+
16
+ attr_accessor :level
17
+
18
+ def initialize(log_file=nil, level=nil)
19
+ @level = level || INFO
20
+ case log_file
21
+ when String
22
+ @log = open(log_file, "a+")
23
+ @log.sync = true
24
+ @opened = true
25
+ when NilClass
26
+ @log = $stderr
27
+ else
28
+ @log = log_file # requires "<<". (see BasicLog#log)
29
+ end
30
+ end
31
+
32
+ def close
33
+ @log.close if @opened
34
+ @log = nil
35
+ end
36
+
37
+ def log(level, data)
38
+ if @log && level <= @level
39
+ data += "\n" if /\n\Z/ !~ data
40
+ @log << data
41
+ end
42
+ end
43
+
44
+ def <<(obj)
45
+ log(INFO, obj.to_s)
46
+ end
47
+
48
+ def fatal(msg) log(FATAL, "FATAL " << format(msg)); end
49
+ def error(msg) log(ERROR, "ERROR " << format(msg)); end
50
+ def warn(msg) log(WARN, "WARN " << format(msg)); end
51
+ def info(msg) log(INFO, "INFO " << format(msg)); end
52
+ def debug(msg) log(DEBUG, "DEBUG " << format(msg)); end
53
+
54
+ def fatal?; @level >= FATAL; end
55
+ def error?; @level >= ERROR; end
56
+ def warn?; @level >= WARN; end
57
+ def info?; @level >= INFO; end
58
+ def debug?; @level >= DEBUG; end
59
+
60
+ private
61
+
62
+ def format(arg)
63
+ str = if arg.is_a?(Exception)
64
+ "#{arg.class}: #{arg.message}\n\t" <<
65
+ arg.backtrace.join("\n\t") << "\n"
66
+ elsif arg.respond_to?(:to_str)
67
+ arg.to_str
68
+ else
69
+ arg.inspect
70
+ end
71
+ end
72
+ end
73
+
74
+ class Log < BasicLog
75
+ attr_accessor :time_format
76
+
77
+ def initialize(log_file=nil, level=nil)
78
+ super(log_file, level)
79
+ @time_format = "[%Y-%m-%d %H:%M:%S]"
80
+ end
81
+
82
+ def log(level, data)
83
+ tmp = Time.now.strftime(@time_format)
84
+ tmp << " " << data
85
+ super(level, tmp)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,200 @@
1
+ #
2
+ # server.rb -- GenericServer Class
3
+ #
4
+ # Author: IPR -- Internet Programming with Ruby -- writers
5
+ # Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
6
+ # Copyright (c) 2002 Internet Programming with Ruby writers. All rights
7
+ # reserved.
8
+ #
9
+ # $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $
10
+
11
+ require 'thread'
12
+ require 'socket'
13
+ require 'timeout'
14
+ require 'webrick/config'
15
+ require 'webrick/log'
16
+
17
+ module WEBrick
18
+
19
+ class ServerError < StandardError; end
20
+
21
+ class SimpleServer
22
+ def SimpleServer.start
23
+ yield
24
+ end
25
+ end
26
+
27
+ class Daemon
28
+ def Daemon.start
29
+ exit!(0) if fork
30
+ Process::setsid
31
+ exit!(0) if fork
32
+ Dir::chdir("/")
33
+ File::umask(0)
34
+ STDIN.reopen("/dev/null")
35
+ STDOUT.reopen("/dev/null", "w")
36
+ STDERR.reopen("/dev/null", "w")
37
+ yield if block_given?
38
+ end
39
+ end
40
+
41
+ class GenericServer
42
+ attr_reader :status, :config, :logger, :tokens, :listeners
43
+
44
+ def initialize(config={}, default=Config::General)
45
+ @config = default.dup.update(config)
46
+ @status = :Stop
47
+ @config[:Logger] ||= Log::new
48
+ @logger = @config[:Logger]
49
+
50
+ @tokens = SizedQueue.new(@config[:MaxClients])
51
+ @config[:MaxClients].times{ @tokens.push(nil) }
52
+
53
+ webrickv = WEBrick::VERSION
54
+ rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
55
+ @logger.info("WEBrick #{webrickv}")
56
+ @logger.info("ruby #{rubyv}")
57
+
58
+ @listeners = []
59
+ unless @config[:DoNotListen]
60
+ if @config[:Listen]
61
+ warn(":Listen option is deprecated; use GenericServer#listen")
62
+ end
63
+ listen(@config[:BindAddress], @config[:Port])
64
+ if @config[:Port] == 0
65
+ @config[:Port] = @listeners[0].addr[1]
66
+ end
67
+ end
68
+ end
69
+
70
+ def [](key)
71
+ @config[key]
72
+ end
73
+
74
+ def listen(address, port)
75
+ @listeners += Utils::create_listeners(address, port, @logger)
76
+ end
77
+
78
+ def start(&block)
79
+ raise ServerError, "already started." if @status != :Stop
80
+ server_type = @config[:ServerType] || SimpleServer
81
+
82
+ server_type.start{
83
+ @logger.info \
84
+ "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
85
+ call_callback(:StartCallback)
86
+
87
+ thgroup = ThreadGroup.new
88
+ @status = :Running
89
+ while @status == :Running
90
+ begin
91
+ if svrs = IO.select(@listeners, nil, nil, 2.0)
92
+ svrs[0].each{|svr|
93
+ @tokens.pop # blocks while no token is there.
94
+ if sock = accept_client(svr)
95
+ th = start_thread(sock, &block)
96
+ th[:WEBrickThread] = true
97
+ thgroup.add(th)
98
+ else
99
+ @tokens.push(nil)
100
+ end
101
+ }
102
+ end
103
+ rescue Errno::EBADF, IOError => ex
104
+ # if the listening socket was closed in GenericServer#shutdown,
105
+ # IO::select raise it.
106
+ rescue Exception => ex
107
+ msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
108
+ @logger.error msg
109
+ end
110
+ end
111
+
112
+ @logger.info "going to shutdown ..."
113
+ thgroup.list.each{|th| th.join if th[:WEBrickThread] }
114
+ call_callback(:StopCallback)
115
+ @logger.info "#{self.class}#start done."
116
+ @status = :Stop
117
+ }
118
+ end
119
+
120
+ def stop
121
+ if @status == :Running
122
+ @status = :Shutdown
123
+ end
124
+ end
125
+
126
+ def shutdown
127
+ stop
128
+ @listeners.each{|s|
129
+ if @logger.debug?
130
+ addr = s.addr
131
+ @logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
132
+ end
133
+ s.close
134
+ }
135
+ @listeners.clear
136
+ end
137
+
138
+ def run(sock)
139
+ @logger.fatal "run() must be provided by user."
140
+ end
141
+
142
+ private
143
+
144
+ def accept_client(svr)
145
+ sock = nil
146
+ begin
147
+ sock = svr.accept
148
+ sock.sync = true
149
+ Utils::set_non_blocking(sock)
150
+ Utils::set_close_on_exec(sock)
151
+ rescue Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPROTO => ex
152
+ # TCP connection was established but RST segment was sent
153
+ # from peer before calling TCPServer#accept.
154
+ rescue Exception => ex
155
+ msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
156
+ @logger.error msg
157
+ end
158
+ return sock
159
+ end
160
+
161
+ def start_thread(sock, &block)
162
+ Thread.start{
163
+ begin
164
+ Thread.current[:WEBrickSocket] = sock
165
+ begin
166
+ addr = sock.peeraddr
167
+ @logger.debug "accept: #{addr[3]}:#{addr[1]}"
168
+ rescue SocketError
169
+ @logger.debug "accept: <address unknown>"
170
+ raise
171
+ end
172
+ call_callback(:AcceptCallback, sock)
173
+ block ? block.call(sock) : run(sock)
174
+ rescue Errno::ENOTCONN
175
+ @logger.debug "Errno::ENOTCONN raised"
176
+ rescue ServerError => ex
177
+ msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
178
+ @logger.error msg
179
+ rescue Exception => ex
180
+ @logger.error ex
181
+ ensure
182
+ @tokens.push(nil)
183
+ Thread.current[:WEBrickSocket] = nil
184
+ if addr
185
+ @logger.debug "close: #{addr[3]}:#{addr[1]}"
186
+ else
187
+ @logger.debug "close: <address unknown>"
188
+ end
189
+ sock.close
190
+ end
191
+ }
192
+ end
193
+
194
+ def call_callback(callback_name, *args)
195
+ if cb = @config[callback_name]
196
+ cb.call(*args)
197
+ end
198
+ end
199
+ end # end of GenericServer
200
+ end
@@ -0,0 +1,126 @@
1
+ #
2
+ # ssl.rb -- SSL/TLS enhancement for GenericServer
3
+ #
4
+ # Copyright (c) 2003 GOTOU Yuuzou All rights reserved.
5
+ #
6
+ # $Id: ssl.rb 11708 2007-02-12 23:01:19Z shyouhei $
7
+
8
+ require 'webrick'
9
+ require 'openssl'
10
+
11
+ module WEBrick
12
+ module Config
13
+ svrsoft = General[:ServerSoftware]
14
+ osslv = ::OpenSSL::OPENSSL_VERSION.split[1]
15
+ SSL = {
16
+ :ServerSoftware => "#{svrsoft} OpenSSL/#{osslv}",
17
+ :SSLEnable => false,
18
+ :SSLCertificate => nil,
19
+ :SSLPrivateKey => nil,
20
+ :SSLClientCA => nil,
21
+ :SSLExtraChainCert => nil,
22
+ :SSLCACertificateFile => nil,
23
+ :SSLCACertificatePath => nil,
24
+ :SSLCertificateStore => nil,
25
+ :SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
26
+ :SSLVerifyDepth => nil,
27
+ :SSLVerifyCallback => nil, # custom verification
28
+ :SSLTimeout => nil,
29
+ :SSLOptions => nil,
30
+ :SSLStartImmediately => true,
31
+ # Must specify if you use auto generated certificate.
32
+ :SSLCertName => nil,
33
+ :SSLCertComment => "Generated by Ruby/OpenSSL"
34
+ }
35
+ General.update(SSL)
36
+ end
37
+
38
+ module Utils
39
+ def create_self_signed_cert(bits, cn, comment)
40
+ rsa = OpenSSL::PKey::RSA.new(bits){|p, n|
41
+ case p
42
+ when 0; $stderr.putc "." # BN_generate_prime
43
+ when 1; $stderr.putc "+" # BN_generate_prime
44
+ when 2; $stderr.putc "*" # searching good prime,
45
+ # n = #of try,
46
+ # but also data from BN_generate_prime
47
+ when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
48
+ # but also data from BN_generate_prime
49
+ else; $stderr.putc "*" # BN_generate_prime
50
+ end
51
+ }
52
+ cert = OpenSSL::X509::Certificate.new
53
+ cert.version = 3
54
+ cert.serial = 0
55
+ name = OpenSSL::X509::Name.new(cn)
56
+ cert.subject = name
57
+ cert.issuer = name
58
+ cert.not_before = Time.now
59
+ cert.not_after = Time.now + (365*24*60*60)
60
+ cert.public_key = rsa.public_key
61
+
62
+ ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
63
+ ef.issuer_certificate = cert
64
+ cert.extensions = [
65
+ ef.create_extension("basicConstraints","CA:FALSE"),
66
+ ef.create_extension("keyUsage", "keyEncipherment"),
67
+ ef.create_extension("subjectKeyIdentifier", "hash"),
68
+ ef.create_extension("extendedKeyUsage", "serverAuth"),
69
+ ef.create_extension("nsComment", comment),
70
+ ]
71
+ aki = ef.create_extension("authorityKeyIdentifier",
72
+ "keyid:always,issuer:always")
73
+ cert.add_extension(aki)
74
+ cert.sign(rsa, OpenSSL::Digest::SHA1.new)
75
+
76
+ return [ cert, rsa ]
77
+ end
78
+ module_function :create_self_signed_cert
79
+ end
80
+
81
+ class GenericServer
82
+ def ssl_context
83
+ @ssl_context ||= nil
84
+ end
85
+
86
+ def listen(address, port)
87
+ listeners = Utils::create_listeners(address, port, @logger)
88
+ if @config[:SSLEnable]
89
+ unless ssl_context
90
+ @ssl_context = setup_ssl_context(@config)
91
+ @logger.info("\n" + @config[:SSLCertificate].to_text)
92
+ end
93
+ listeners.collect!{|svr|
94
+ ssvr = ::OpenSSL::SSL::SSLServer.new(svr, ssl_context)
95
+ ssvr.start_immediately = @config[:SSLStartImmediately]
96
+ ssvr
97
+ }
98
+ end
99
+ @listeners += listeners
100
+ end
101
+
102
+ def setup_ssl_context(config)
103
+ unless config[:SSLCertificate]
104
+ cn = config[:SSLCertName]
105
+ comment = config[:SSLCertComment]
106
+ cert, key = Utils::create_self_signed_cert(1024, cn, comment)
107
+ config[:SSLCertificate] = cert
108
+ config[:SSLPrivateKey] = key
109
+ end
110
+ ctx = OpenSSL::SSL::SSLContext.new
111
+ ctx.key = config[:SSLPrivateKey]
112
+ ctx.cert = config[:SSLCertificate]
113
+ ctx.client_ca = config[:SSLClientCA]
114
+ ctx.extra_chain_cert = config[:SSLExtraChainCert]
115
+ ctx.ca_file = config[:SSLCACertificateFile]
116
+ ctx.ca_path = config[:SSLCACertificatePath]
117
+ ctx.cert_store = config[:SSLCertificateStore]
118
+ ctx.verify_mode = config[:SSLVerifyClient]
119
+ ctx.verify_depth = config[:SSLVerifyDepth]
120
+ ctx.verify_callback = config[:SSLVerifyCallback]
121
+ ctx.timeout = config[:SSLTimeout]
122
+ ctx.options = config[:SSLOptions]
123
+ ctx
124
+ end
125
+ end
126
+ end