webricknio 0.6.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.
- data/LICENSE +26 -0
- data/README.md +58 -0
- data/lib/generator/USAGE +8 -0
- data/lib/generator/webricknio.rb +57 -0
- data/lib/generator/webricknio_generator.rb +15 -0
- data/lib/rack/handler/webricknio.rb +88 -0
- data/lib/webricknio.rb +237 -0
- data/lib/webricknio/accesslog.rb +157 -0
- data/lib/webricknio/block.rb +271 -0
- data/lib/webricknio/block.yaml +7 -0
- data/lib/webricknio/config.rb +125 -0
- data/lib/webricknio/httprequest.rb +559 -0
- data/lib/webricknio/httpresponse.rb +469 -0
- data/lib/webricknio/httpserver.rb +499 -0
- data/lib/webricknio/log.rb +30 -0
- data/lib/webricknio/version.rb +14 -0
- data/webricknio.gemspec +15 -0
- metadata +79 -0
@@ -0,0 +1,157 @@
|
|
1
|
+
#--
|
2
|
+
# accesslog.rb -- Access log handling utilities
|
3
|
+
#
|
4
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
5
|
+
# Copyright (c) 2002 keita yamaguchi
|
6
|
+
# Copyright (c) 2002 Internet Programming with Ruby writers
|
7
|
+
# Copyright (c) 2012 Pradeep Singh
|
8
|
+
#
|
9
|
+
# $IPR: accesslog.rb,v 1.1 2002/10/01 17:16:32 gotoyuzo Exp $
|
10
|
+
|
11
|
+
module WEBrickNIO
|
12
|
+
|
13
|
+
##
|
14
|
+
# AccessLog provides logging to various files in various formats.
|
15
|
+
#
|
16
|
+
# Multiple logs may be written to at the same time:
|
17
|
+
#
|
18
|
+
# access_log = [
|
19
|
+
# [$stderr, WEBrick::AccessLog::COMMON_LOG_FORMAT],
|
20
|
+
# [$stderr, WEBrick::AccessLog::REFERER_LOG_FORMAT],
|
21
|
+
# ]
|
22
|
+
#
|
23
|
+
# server = WEBrick::HTTPServer.new :AccessLog => access_log
|
24
|
+
#
|
25
|
+
# Custom log formats may be defined. WEBrick::AccessLog provides a subset
|
26
|
+
# of the formatting from Apache's mod_log_config
|
27
|
+
# http://httpd.apache.org/docs/mod/mod_log_config.html#formats. See
|
28
|
+
# AccessLog::setup_params for a list of supported options
|
29
|
+
#
|
30
|
+
# 99% copy of WEBrick::AccessLog to avoid polluting its namespace
|
31
|
+
# 1% change is in method <code>setup_params</code>
|
32
|
+
|
33
|
+
module AccessLog
|
34
|
+
|
35
|
+
##
|
36
|
+
# Raised if a parameter such as %e, %i, %o or %n is used without fetching
|
37
|
+
# a specific field.
|
38
|
+
|
39
|
+
class AccessLogError < StandardError; end
|
40
|
+
|
41
|
+
##
|
42
|
+
# The Common Log Format's time format
|
43
|
+
|
44
|
+
CLF_TIME_FORMAT = "[%d/%b/%Y:%H:%M:%S %Z]"
|
45
|
+
|
46
|
+
##
|
47
|
+
# Common Log Format
|
48
|
+
|
49
|
+
COMMON_LOG_FORMAT = "%h %l %u %t \"%r\" %s %b"
|
50
|
+
|
51
|
+
##
|
52
|
+
# Short alias for Common Log Format
|
53
|
+
|
54
|
+
CLF = COMMON_LOG_FORMAT
|
55
|
+
|
56
|
+
##
|
57
|
+
# Referer Log Format
|
58
|
+
|
59
|
+
REFERER_LOG_FORMAT = "%{Referer}i -> %U"
|
60
|
+
|
61
|
+
##
|
62
|
+
# User-Agent Log Format
|
63
|
+
|
64
|
+
AGENT_LOG_FORMAT = "%{User-Agent}i"
|
65
|
+
|
66
|
+
##
|
67
|
+
# Combined Log Format
|
68
|
+
|
69
|
+
COMBINED_LOG_FORMAT = "#{CLF} \"%{Referer}i\" \"%{User-agent}i\""
|
70
|
+
|
71
|
+
module_function
|
72
|
+
|
73
|
+
# This format specification is a subset of mod_log_config of Apache:
|
74
|
+
#
|
75
|
+
# %a:: Remote IP address
|
76
|
+
# %b:: Total response size
|
77
|
+
# %e{variable}:: Given variable in ENV
|
78
|
+
# %f:: Response filename
|
79
|
+
# %h:: Remote host name
|
80
|
+
# %{header}i:: Given request header
|
81
|
+
# %l:: Remote logname, always "-"
|
82
|
+
# %m:: Request method
|
83
|
+
# %{attr}n:: Given request attribute from <tt>req.attributes</tt>
|
84
|
+
# %{header}o:: Given response header
|
85
|
+
# %p:: Server's request port
|
86
|
+
# %{format}p:: The canonical port of the server serving the request or the
|
87
|
+
# actual port or the client's actual port. Valid formats are
|
88
|
+
# canonical, local or remote.
|
89
|
+
# %q:: Request query string
|
90
|
+
# %r:: First line of the request
|
91
|
+
# %s:: Request status
|
92
|
+
# %t:: Time the request was recieved
|
93
|
+
# %T:: Time taken to process the request
|
94
|
+
# %u:: Remote user from auth
|
95
|
+
# %U:: Unparsed URI
|
96
|
+
# %%:: Literal %
|
97
|
+
|
98
|
+
def setup_params(config, req, res)
|
99
|
+
params = Hash.new("")
|
100
|
+
#params["a"] = req.peeraddr[3]
|
101
|
+
params["a"] = req.peeraddr.get_address.get_host_address
|
102
|
+
params["b"] = res.sent_size
|
103
|
+
params["e"] = ENV
|
104
|
+
params["f"] = res.filename || ""
|
105
|
+
#params["h"] = req.peeraddr[2]
|
106
|
+
params["h"] = req.peeraddr.get_host_name
|
107
|
+
params["i"] = req
|
108
|
+
params["l"] = "-"
|
109
|
+
params["m"] = req.request_method
|
110
|
+
params["n"] = req.attributes
|
111
|
+
params["o"] = res
|
112
|
+
params["p"] = req.port
|
113
|
+
params["q"] = req.query_string
|
114
|
+
params["r"] = req.request_line.sub(/\x0d?\x0a\z/o, '')
|
115
|
+
params["s"] = res.status # won't support "%>s"
|
116
|
+
params["t"] = req.request_time
|
117
|
+
params["T"] = Time.now - req.request_time
|
118
|
+
params["u"] = req.user || "-"
|
119
|
+
params["U"] = req.unparsed_uri
|
120
|
+
params["v"] = config[:ServerName]
|
121
|
+
params
|
122
|
+
end
|
123
|
+
|
124
|
+
def format(format_string, params)
|
125
|
+
format_string.gsub(/\%(?:\{(.*?)\})?>?([a-zA-Z%])/){
|
126
|
+
param, spec = $1, $2
|
127
|
+
case spec[0]
|
128
|
+
when ?e, ?i, ?n, ?o
|
129
|
+
raise AccessLogError,
|
130
|
+
"parameter is required for \"#{spec}\"" unless param
|
131
|
+
(param = params[spec][param]) ? escape(param) : "-"
|
132
|
+
when ?t
|
133
|
+
params[spec].strftime(param || CLF_TIME_FORMAT)
|
134
|
+
when ?p
|
135
|
+
case param
|
136
|
+
when 'remote'
|
137
|
+
escape(params["i"].peeraddr[1].to_s)
|
138
|
+
else
|
139
|
+
escape(params["p"].to_s)
|
140
|
+
end
|
141
|
+
when ?%
|
142
|
+
"%"
|
143
|
+
else
|
144
|
+
escape(params[spec].to_s)
|
145
|
+
end
|
146
|
+
}
|
147
|
+
end
|
148
|
+
|
149
|
+
def escape(data)
|
150
|
+
if data.tainted?
|
151
|
+
data.gsub(/[[:cntrl:]\\]+/) {$&.dump[1...-1]}.untaint
|
152
|
+
else
|
153
|
+
data
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,271 @@
|
|
1
|
+
#--
|
2
|
+
# block.rb
|
3
|
+
#
|
4
|
+
# Author: Pradeep Singh
|
5
|
+
# Copyright (c) 2012 Pradeep Singh
|
6
|
+
# All rights reserved.
|
7
|
+
|
8
|
+
require 'java'
|
9
|
+
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
module WEBrickNIO
|
13
|
+
|
14
|
+
class BaseBlock
|
15
|
+
def initialize(options = {})
|
16
|
+
@logger = options["logger"] || FakeLogger.new
|
17
|
+
end
|
18
|
+
def valid?(ip)
|
19
|
+
raise "valid? Not implemented"
|
20
|
+
end
|
21
|
+
def add_ip(ip)
|
22
|
+
raise "add_ip Not implemented"
|
23
|
+
end
|
24
|
+
def block_ip?(ip)
|
25
|
+
raise "block_ip? Not implemented"
|
26
|
+
end
|
27
|
+
def self.inherited(subclass)
|
28
|
+
subclass.instance_eval {
|
29
|
+
alias old_new new
|
30
|
+
def new
|
31
|
+
alias_method :matches?, :block_ip?
|
32
|
+
old_new
|
33
|
+
end
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Wrapper that chains other blockers
|
40
|
+
#
|
41
|
+
|
42
|
+
class ChainedBlock < BaseBlock
|
43
|
+
|
44
|
+
def initialize(options = {})
|
45
|
+
begin
|
46
|
+
load
|
47
|
+
rescue Exception => ex
|
48
|
+
puts ex
|
49
|
+
create_default_chain
|
50
|
+
end
|
51
|
+
|
52
|
+
super
|
53
|
+
|
54
|
+
# at_exit do
|
55
|
+
# file = File.new(File.expand_path('block.yaml', File.dirname(__FILE__)), "w")
|
56
|
+
# dump = YAML::dump(@chain)
|
57
|
+
# file.write(dump)
|
58
|
+
# file.close
|
59
|
+
# end
|
60
|
+
end
|
61
|
+
|
62
|
+
def load
|
63
|
+
file = File.new(File.expand_path('block.yaml', File.dirname(__FILE__)), "r")
|
64
|
+
@chain = YAML::load(file)
|
65
|
+
ensure_default_chain @chain
|
66
|
+
puts @chain
|
67
|
+
end
|
68
|
+
|
69
|
+
def reload
|
70
|
+
load
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_ip(ip)
|
74
|
+
@chain.each do |blocker|
|
75
|
+
if blocker.valid? ip
|
76
|
+
blocker.add_ip ip
|
77
|
+
return true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
return false
|
81
|
+
end
|
82
|
+
|
83
|
+
def block_ip?(ip)
|
84
|
+
@chain.each do |blocker|
|
85
|
+
if blocker.block_ip?(ip)
|
86
|
+
return true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
return false
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def create_default_chain
|
95
|
+
@chain = []
|
96
|
+
add_chain_elements @chain
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_chain_elements(arr)
|
100
|
+
arr << PrefixBlock.new
|
101
|
+
arr << ListBlock.new
|
102
|
+
arr
|
103
|
+
end
|
104
|
+
|
105
|
+
def ensure_default_chain(chain)
|
106
|
+
if chain.nil? || !chain.is_a?(Array)
|
107
|
+
create_default_chain
|
108
|
+
elsif chain.length == 0
|
109
|
+
add_chain_elements chain
|
110
|
+
elsif chain.length == 1
|
111
|
+
if chain[0].class.name == "WEBrickNIO::PrefixBlock"
|
112
|
+
chain << ListBlock.new
|
113
|
+
elsif chain[0].class.name == "WEBrickNIO::ListBlock"
|
114
|
+
chain << PrefixBlock.new
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
#
|
123
|
+
# Blocks IPs with given prefix
|
124
|
+
#
|
125
|
+
|
126
|
+
class PrefixBlock < BaseBlock
|
127
|
+
|
128
|
+
def initialize(options = {})
|
129
|
+
@block_list = options["block_list"] || []
|
130
|
+
super
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.from_array(arr)
|
134
|
+
blocker = self.new
|
135
|
+
block_list = []
|
136
|
+
arr.each do |item|
|
137
|
+
blocker.add_ip item.to_s
|
138
|
+
end unless arr.nil?
|
139
|
+
blocker
|
140
|
+
end
|
141
|
+
|
142
|
+
def block_ip?(ip)
|
143
|
+
@block_list.each do |item|
|
144
|
+
if ip.start_with? item
|
145
|
+
@logger.info "ip matches: PrefixBlock - #{ip}"
|
146
|
+
return true
|
147
|
+
end
|
148
|
+
end
|
149
|
+
return false
|
150
|
+
end
|
151
|
+
|
152
|
+
def valid?(ip)
|
153
|
+
ip.split(".").size <= 3
|
154
|
+
end
|
155
|
+
|
156
|
+
def add_ip(ip)
|
157
|
+
return false if ip.nil? || ip.strip.length == 0
|
158
|
+
if valid?(ip) && !@block_list.include?(ip)
|
159
|
+
@block_list << ip
|
160
|
+
true
|
161
|
+
else
|
162
|
+
false
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def to_yaml( opts = {} )
|
167
|
+
YAML.quick_emit( nil, opts ) { |out|
|
168
|
+
out.map("!IPBlockerPrefixBlock,1234/PrefixBlock" ) { |map|
|
169
|
+
map.add("block_list", @block_list)
|
170
|
+
}
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
def to_s
|
175
|
+
"PrefixBlock<#{object_id}>:#{@block_list}"
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
#
|
182
|
+
# Blocks IPs that are exact match
|
183
|
+
#
|
184
|
+
|
185
|
+
class ListBlock < BaseBlock
|
186
|
+
|
187
|
+
def initialize(options = {})
|
188
|
+
@block_list = options["block_list"] || java.util.concurrent.ConcurrentSkipListSet.new
|
189
|
+
super
|
190
|
+
end
|
191
|
+
|
192
|
+
def self.from_array(arr)
|
193
|
+
blocker = self.new
|
194
|
+
arr.each do |item|
|
195
|
+
blocker.add_ip item.to_s
|
196
|
+
end unless arr.nil?
|
197
|
+
blocker
|
198
|
+
end
|
199
|
+
|
200
|
+
def block_ip?(ip)
|
201
|
+
if @block_list.include? ip
|
202
|
+
@logger.info "ip matches: ListBlock - #{ip}"
|
203
|
+
true
|
204
|
+
else
|
205
|
+
false
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def valid?(ip)
|
210
|
+
ip.split(".").size > 3
|
211
|
+
end
|
212
|
+
|
213
|
+
def add_ip(ip)
|
214
|
+
return false if ip.nil? || ip.strip.length == 0
|
215
|
+
if valid? ip
|
216
|
+
@block_list.add ip
|
217
|
+
true
|
218
|
+
else
|
219
|
+
false
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def to_yaml( opts = {} )
|
224
|
+
YAML.quick_emit( nil, opts ) { |out|
|
225
|
+
out.map("!IPBlockerListBlock,1234/ListBlock" ) { |map|
|
226
|
+
map.add("block_list", @block_list.to_a)
|
227
|
+
}
|
228
|
+
}
|
229
|
+
end
|
230
|
+
|
231
|
+
def to_s
|
232
|
+
"ListBlock<#{object_id}>:#{@block_list.to_a}"
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
|
239
|
+
YAML::add_domain_type("IPBlockerListBlock,1234", "ListBlock") do |type, val|
|
240
|
+
ListBlock.from_array(val["block_list"])
|
241
|
+
end
|
242
|
+
|
243
|
+
YAML::add_domain_type("IPBlockerPrefixBlock,1234", "PrefixBlock") do |type, val|
|
244
|
+
PrefixBlock.from_array(val["block_list"])
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
|
249
|
+
class FakeLogger
|
250
|
+
def method_missing(method, *args, &block)
|
251
|
+
puts args
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
#chain = WEBrickNIO::ChainedBlock.new
|
258
|
+
|
259
|
+
#ip ="180.76"
|
260
|
+
#chain.add(ip)
|
261
|
+
|
262
|
+
#ip ="92.240.68.152"
|
263
|
+
#chain.add(ip)
|
264
|
+
#ip ="180.76"
|
265
|
+
#chain.block_ip? ip
|
266
|
+
|
267
|
+
#ip ="92.240.68.152"
|
268
|
+
#chain.matches? ip
|
269
|
+
|
270
|
+
|
271
|
+
|
@@ -0,0 +1,125 @@
|
|
1
|
+
#
|
2
|
+
# config.rb -- Default configurations.
|
3
|
+
#
|
4
|
+
# Author: IPR -- Internet Programming with Ruby -- writers
|
5
|
+
# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
|
6
|
+
# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
|
7
|
+
# reserved.
|
8
|
+
#
|
9
|
+
# $IPR: config.rb,v 1.52 2003/07/22 19:20:42 gotoyuzo Exp $
|
10
|
+
|
11
|
+
require 'webricknio/version'
|
12
|
+
require 'webrick/httpversion'
|
13
|
+
require 'webrick/httputils'
|
14
|
+
require 'webrick/utils'
|
15
|
+
require 'webrick/log'
|
16
|
+
require 'webricknio/log'
|
17
|
+
|
18
|
+
module WEBrickNIO
|
19
|
+
module Config
|
20
|
+
LIBDIR = File::dirname(__FILE__)
|
21
|
+
|
22
|
+
# for GenericServer
|
23
|
+
General = {
|
24
|
+
:ServerName => ::WEBrick::Utils::getservername,
|
25
|
+
:BindAddress => nil, # "0.0.0.0" or "::" or nil
|
26
|
+
:Port => nil, # users MUST specify this!!
|
27
|
+
:ServerType => nil, # default: WEBrick::SimpleServer
|
28
|
+
:Logger => nil, # default: WEBrick::Log.new
|
29
|
+
#:ServerSoftware => "WEBrickNIO/#{WEBrickNIO::VERSION} " +
|
30
|
+
# "(Ruby/#{RUBY_VERSION}/#{RUBY_RELEASE_DATE})",
|
31
|
+
:ServerSoftware => "pks/#{WEBrickNIO::VERSION} ",
|
32
|
+
:TempDir => ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'/tmp',
|
33
|
+
:DoNotListen => false,
|
34
|
+
:StartCallback => nil,
|
35
|
+
:StopCallback => nil,
|
36
|
+
:AcceptCallback => nil,
|
37
|
+
:DoNotReverseLookup => nil,
|
38
|
+
:ShutdownSocketWithoutClose => false,
|
39
|
+
}
|
40
|
+
|
41
|
+
# for HTTPServer, HTTPRequest, HTTPResponse ...
|
42
|
+
HTTP = General.dup.update(
|
43
|
+
:Port => 80,
|
44
|
+
:RequestTimeout => 5,
|
45
|
+
:NumThreads => 20,
|
46
|
+
:HTTPVersion => ::WEBrick::HTTPVersion.new("1.1"),
|
47
|
+
:AccessLog => nil,
|
48
|
+
:LogLocation => nil, #"log/webrick.log"
|
49
|
+
:LogLevel => ::WEBrick::Log::DEBUG,
|
50
|
+
:MimeTypes => ::WEBrick::HTTPUtils::DefaultMimeTypes,
|
51
|
+
:DirectoryIndex => ["index.html","index.htm","index.cgi","index.rhtml"],
|
52
|
+
:DocumentRoot => nil,
|
53
|
+
:DocumentRootOptions => { :FancyIndexing => true },
|
54
|
+
:RequestCallback => nil,
|
55
|
+
:ServerAlias => nil,
|
56
|
+
:InputBufferSize => 65536, # input buffer size in reading request body
|
57
|
+
:OutputBufferSize => 65536, # output buffer size in sending File or IO
|
58
|
+
|
59
|
+
# for HTTPProxyServer
|
60
|
+
:ProxyAuthProc => nil,
|
61
|
+
:ProxyContentHandler => nil,
|
62
|
+
:ProxyVia => true,
|
63
|
+
:ProxyTimeout => true,
|
64
|
+
:ProxyURI => nil,
|
65
|
+
|
66
|
+
:CGIInterpreter => nil,
|
67
|
+
:CGIPathEnv => nil,
|
68
|
+
|
69
|
+
# workaround: if Request-URIs contain 8bit chars,
|
70
|
+
# they should be escaped before calling of URI::parse().
|
71
|
+
:Escape8bitURI => false
|
72
|
+
)
|
73
|
+
|
74
|
+
FileHandler = {
|
75
|
+
:NondisclosureName => [".ht*", "*~"],
|
76
|
+
:FancyIndexing => false,
|
77
|
+
:HandlerTable => {},
|
78
|
+
:HandlerCallback => nil,
|
79
|
+
:DirectoryCallback => nil,
|
80
|
+
:FileCallback => nil,
|
81
|
+
:UserDir => nil, # e.g. "public_html"
|
82
|
+
:AcceptableLanguages => [] # ["en", "ja", ... ]
|
83
|
+
}
|
84
|
+
|
85
|
+
BasicAuth = {
|
86
|
+
:AutoReloadUserDB => true,
|
87
|
+
}
|
88
|
+
|
89
|
+
##
|
90
|
+
# Default configuration for WEBrick::HTTPAuth::DigestAuth.
|
91
|
+
#
|
92
|
+
# :Algorithm:: MD5, MD5-sess (default), SHA1, SHA1-sess
|
93
|
+
# :Domain:: An Array of URIs that define the protected space
|
94
|
+
# :Qop:: 'auth' for authentication, 'auth-int' for integrity protection or
|
95
|
+
# both
|
96
|
+
# :UseOpaque:: Should the server send opaque values to the client? This
|
97
|
+
# helps prevent replay attacks.
|
98
|
+
# :CheckNc:: Should the server check the nonce count? This helps the
|
99
|
+
# server detect replay attacks.
|
100
|
+
# :UseAuthenticationInfoHeader:: Should the server send an
|
101
|
+
# AuthenticationInfo header?
|
102
|
+
# :AutoReloadUserDB:: Reload the user database provided by :UserDB
|
103
|
+
# automatically?
|
104
|
+
# :NonceExpirePeriod:: How long should we store used nonces? Default is
|
105
|
+
# 30 minutes.
|
106
|
+
# :NonceExpireDelta:: How long is a nonce valid? Default is 1 minute
|
107
|
+
# :InternetExplorerHack:: Hack which allows Internet Explorer to work.
|
108
|
+
# :OperaHack:: Hack which allows Opera to work.
|
109
|
+
|
110
|
+
DigestAuth = {
|
111
|
+
:Algorithm => 'MD5-sess', # or 'MD5'
|
112
|
+
:Domain => nil, # an array includes domain names.
|
113
|
+
:Qop => [ 'auth' ], # 'auth' or 'auth-int' or both.
|
114
|
+
:UseOpaque => true,
|
115
|
+
:UseNextNonce => false,
|
116
|
+
:CheckNc => false,
|
117
|
+
:UseAuthenticationInfoHeader => true,
|
118
|
+
:AutoReloadUserDB => true,
|
119
|
+
:NonceExpirePeriod => 30*60,
|
120
|
+
:NonceExpireDelta => 60,
|
121
|
+
:InternetExplorerHack => true,
|
122
|
+
:OperaHack => true,
|
123
|
+
}
|
124
|
+
end
|
125
|
+
end
|