rubysl-webrick 1.0.0 → 2.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.
- checksums.yaml +14 -6
- data/.travis.yml +5 -6
- data/lib/rubysl/webrick/version.rb +1 -1
- data/lib/rubysl/webrick/webrick.rb +199 -2
- data/lib/webrick/accesslog.rb +96 -5
- data/lib/webrick/cgi.rb +80 -29
- data/lib/webrick/compat.rb +20 -0
- data/lib/webrick/config.rb +59 -5
- data/lib/webrick/cookie.rb +66 -5
- data/lib/webrick/htmlutils.rb +4 -1
- data/lib/webrick/httpauth.rb +53 -3
- data/lib/webrick/httpauth/authenticator.rb +53 -16
- data/lib/webrick/httpauth/basicauth.rb +45 -2
- data/lib/webrick/httpauth/digestauth.rb +82 -17
- data/lib/webrick/httpauth/htdigest.rb +38 -1
- data/lib/webrick/httpauth/htgroup.rb +32 -0
- data/lib/webrick/httpauth/htpasswd.rb +40 -2
- data/lib/webrick/httpauth/userdb.rb +27 -4
- data/lib/webrick/httpproxy.rb +197 -112
- data/lib/webrick/httprequest.rb +268 -50
- data/lib/webrick/httpresponse.rb +170 -33
- data/lib/webrick/https.rb +26 -3
- data/lib/webrick/httpserver.rb +75 -7
- data/lib/webrick/httpservlet/abstract.rb +88 -6
- data/lib/webrick/httpservlet/cgi_runner.rb +5 -4
- data/lib/webrick/httpservlet/cgihandler.rb +37 -18
- data/lib/webrick/httpservlet/erbhandler.rb +40 -7
- data/lib/webrick/httpservlet/filehandler.rb +116 -28
- data/lib/webrick/httpservlet/prochandler.rb +17 -4
- data/lib/webrick/httpstatus.rb +86 -18
- data/lib/webrick/httputils.rb +131 -23
- data/lib/webrick/httpversion.rb +28 -2
- data/lib/webrick/log.rb +72 -5
- data/lib/webrick/server.rb +158 -33
- data/lib/webrick/ssl.rb +78 -9
- data/lib/webrick/utils.rb +151 -5
- data/lib/webrick/version.rb +5 -1
- data/rubysl-webrick.gemspec +0 -1
- metadata +12 -24
@@ -1,11 +1,11 @@
|
|
1
|
-
#
|
1
|
+
#
|
2
2
|
# prochandler.rb -- ProcHandler Class
|
3
|
-
#
|
3
|
+
#
|
4
4
|
# Author: IPR -- Internet Programming with Ruby -- writers
|
5
5
|
# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
|
6
6
|
# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
|
7
7
|
# reserved.
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# $IPR: prochandler.rb,v 1.7 2002/09/21 12:23:42 gotoyuzo Exp $
|
10
10
|
|
11
11
|
require 'webrick/httpservlet/abstract.rb'
|
@@ -13,10 +13,22 @@ require 'webrick/httpservlet/abstract.rb'
|
|
13
13
|
module WEBrick
|
14
14
|
module HTTPServlet
|
15
15
|
|
16
|
+
##
|
17
|
+
# Mounts a proc at a path that accepts a request and response.
|
18
|
+
#
|
19
|
+
# Instead of mounting this servlet with WEBrick::HTTPServer#mount use
|
20
|
+
# WEBrick::HTTPServer#mount_proc:
|
21
|
+
#
|
22
|
+
# server.mount_proc '/' do |req, res|
|
23
|
+
# res.body = 'it worked!'
|
24
|
+
# res.status = 200
|
25
|
+
# end
|
26
|
+
|
16
27
|
class ProcHandler < AbstractServlet
|
28
|
+
# :stopdoc:
|
17
29
|
def get_instance(server, *options)
|
18
30
|
self
|
19
|
-
end
|
31
|
+
end
|
20
32
|
|
21
33
|
def initialize(proc)
|
22
34
|
@proc = proc
|
@@ -27,6 +39,7 @@ module WEBrick
|
|
27
39
|
end
|
28
40
|
|
29
41
|
alias do_POST do_GET
|
42
|
+
# :startdoc:
|
30
43
|
end
|
31
44
|
|
32
45
|
end
|
data/lib/webrick/httpstatus.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
#--
|
2
2
|
# httpstatus.rb -- HTTPStatus Class
|
3
3
|
#
|
4
4
|
# Author: IPR -- Internet Programming with Ruby -- writers
|
@@ -10,19 +10,50 @@
|
|
10
10
|
|
11
11
|
module WEBrick
|
12
12
|
|
13
|
+
##
|
14
|
+
# This module is used to manager HTTP status codes.
|
15
|
+
#
|
16
|
+
# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html for more
|
17
|
+
# information.
|
13
18
|
module HTTPStatus
|
14
19
|
|
15
|
-
|
20
|
+
##
|
21
|
+
# Root of the HTTP status class hierarchy
|
22
|
+
class Status < StandardError
|
23
|
+
def initialize(*args) # :nodoc:
|
24
|
+
args[0] = AccessLog.escape(args[0]) unless args.empty?
|
25
|
+
super(*args)
|
26
|
+
end
|
27
|
+
class << self
|
28
|
+
attr_reader :code, :reason_phrase # :nodoc:
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the HTTP status code
|
32
|
+
def code() self::class::code end
|
33
|
+
|
34
|
+
# Returns the HTTP status description
|
35
|
+
def reason_phrase() self::class::reason_phrase end
|
36
|
+
|
37
|
+
alias to_i code # :nodoc:
|
38
|
+
end
|
39
|
+
|
40
|
+
# Root of the HTTP info statuses
|
16
41
|
class Info < Status; end
|
42
|
+
# Root of the HTTP sucess statuses
|
17
43
|
class Success < Status; end
|
44
|
+
# Root of the HTTP redirect statuses
|
18
45
|
class Redirect < Status; end
|
46
|
+
# Root of the HTTP error statuses
|
19
47
|
class Error < Status; end
|
48
|
+
# Root of the HTTP client error statuses
|
20
49
|
class ClientError < Error; end
|
50
|
+
# Root of the HTTP server error statuses
|
21
51
|
class ServerError < Error; end
|
22
|
-
|
52
|
+
|
23
53
|
class EOFError < StandardError; end
|
24
54
|
|
25
|
-
|
55
|
+
# HTTP status codes and descriptions
|
56
|
+
StatusMessage = { # :nodoc:
|
26
57
|
100 => 'Continue',
|
27
58
|
101 => 'Switching Protocols',
|
28
59
|
200 => 'OK',
|
@@ -32,6 +63,7 @@ module WEBrick
|
|
32
63
|
204 => 'No Content',
|
33
64
|
205 => 'Reset Content',
|
34
65
|
206 => 'Partial Content',
|
66
|
+
207 => 'Multi-Status',
|
35
67
|
300 => 'Multiple Choices',
|
36
68
|
301 => 'Moved Permanently',
|
37
69
|
302 => 'Found',
|
@@ -57,17 +89,30 @@ module WEBrick
|
|
57
89
|
415 => 'Unsupported Media Type',
|
58
90
|
416 => 'Request Range Not Satisfiable',
|
59
91
|
417 => 'Expectation Failed',
|
92
|
+
422 => 'Unprocessable Entity',
|
93
|
+
423 => 'Locked',
|
94
|
+
424 => 'Failed Dependency',
|
95
|
+
426 => 'Upgrade Required',
|
96
|
+
428 => 'Precondition Required',
|
97
|
+
429 => 'Too Many Requests',
|
98
|
+
431 => 'Request Header Fields Too Large',
|
60
99
|
500 => 'Internal Server Error',
|
61
100
|
501 => 'Not Implemented',
|
62
101
|
502 => 'Bad Gateway',
|
63
102
|
503 => 'Service Unavailable',
|
64
103
|
504 => 'Gateway Timeout',
|
65
|
-
505 => 'HTTP Version Not Supported'
|
104
|
+
505 => 'HTTP Version Not Supported',
|
105
|
+
507 => 'Insufficient Storage',
|
106
|
+
511 => 'Network Authentication Required',
|
66
107
|
}
|
67
108
|
|
68
|
-
|
109
|
+
# Maps a status code to the corresponding Status class
|
110
|
+
CodeToError = {} # :nodoc:
|
69
111
|
|
112
|
+
# Creates a status or error class for each status code and
|
113
|
+
# populates the CodeToError map.
|
70
114
|
StatusMessage.each{|code, message|
|
115
|
+
message.freeze
|
71
116
|
var_name = message.gsub(/[ \-]/,'_').upcase
|
72
117
|
err_name = message.gsub(/[ \-]/,'')
|
73
118
|
|
@@ -79,42 +124,65 @@ module WEBrick
|
|
79
124
|
when 500...600; parent = ServerError
|
80
125
|
end
|
81
126
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
def reason_phrase() self::class::reason_phrase end
|
89
|
-
alias to_i code
|
90
|
-
end
|
91
|
-
-
|
92
|
-
|
93
|
-
CodeToError[code] = const_get(err_name)
|
127
|
+
const_set("RC_#{var_name}", code)
|
128
|
+
err_class = Class.new(parent)
|
129
|
+
err_class.instance_variable_set(:@code, code)
|
130
|
+
err_class.instance_variable_set(:@reason_phrase, message)
|
131
|
+
const_set(err_name, err_class)
|
132
|
+
CodeToError[code] = err_class
|
94
133
|
}
|
95
134
|
|
135
|
+
##
|
136
|
+
# Returns the description corresponding to the HTTP status +code+
|
137
|
+
#
|
138
|
+
# WEBrick::HTTPStatus.reason_phrase 404
|
139
|
+
# => "Not Found"
|
96
140
|
def reason_phrase(code)
|
97
141
|
StatusMessage[code.to_i]
|
98
142
|
end
|
143
|
+
|
144
|
+
##
|
145
|
+
# Is +code+ an informational status?
|
99
146
|
def info?(code)
|
100
147
|
code.to_i >= 100 and code.to_i < 200
|
101
148
|
end
|
149
|
+
|
150
|
+
##
|
151
|
+
# Is +code+ a successful status?
|
102
152
|
def success?(code)
|
103
153
|
code.to_i >= 200 and code.to_i < 300
|
104
154
|
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# Is +code+ a redirection status?
|
105
158
|
def redirect?(code)
|
106
159
|
code.to_i >= 300 and code.to_i < 400
|
107
160
|
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Is +code+ an error status?
|
108
164
|
def error?(code)
|
109
165
|
code.to_i >= 400 and code.to_i < 600
|
110
166
|
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# Is +code+ a client error status?
|
111
170
|
def client_error?(code)
|
112
171
|
code.to_i >= 400 and code.to_i < 500
|
113
172
|
end
|
173
|
+
|
174
|
+
##
|
175
|
+
# Is +code+ a server error status?
|
114
176
|
def server_error?(code)
|
115
177
|
code.to_i >= 500 and code.to_i < 600
|
116
178
|
end
|
117
179
|
|
180
|
+
##
|
181
|
+
# Returns the status class corresponding to +code+
|
182
|
+
#
|
183
|
+
# WEBrick::HTTPStatus[302]
|
184
|
+
# => WEBrick::HTTPStatus::NotFound
|
185
|
+
#
|
118
186
|
def self.[](code)
|
119
187
|
CodeToError[code]
|
120
188
|
end
|
data/lib/webrick/httputils.rb
CHANGED
@@ -12,12 +12,21 @@ require 'socket'
|
|
12
12
|
require 'tempfile'
|
13
13
|
|
14
14
|
module WEBrick
|
15
|
-
CR = "\x0d"
|
16
|
-
LF = "\x0a"
|
17
|
-
CRLF = "\x0d\x0a"
|
15
|
+
CR = "\x0d" # :nodoc:
|
16
|
+
LF = "\x0a" # :nodoc:
|
17
|
+
CRLF = "\x0d\x0a" # :nodoc:
|
18
|
+
|
19
|
+
##
|
20
|
+
# HTTPUtils provides utility methods for working with the HTTP protocol.
|
21
|
+
#
|
22
|
+
# This module is generally used internally by WEBrick
|
18
23
|
|
19
24
|
module HTTPUtils
|
20
25
|
|
26
|
+
##
|
27
|
+
# Normalizes a request path. Raises an exception if the path cannot be
|
28
|
+
# normalized.
|
29
|
+
|
21
30
|
def normalize_path(path)
|
22
31
|
raise "abnormal path `#{path}'" if path[0] != ?/
|
23
32
|
ret = path.dup
|
@@ -31,7 +40,8 @@ module WEBrick
|
|
31
40
|
end
|
32
41
|
module_function :normalize_path
|
33
42
|
|
34
|
-
|
43
|
+
##
|
44
|
+
# Default mime types
|
35
45
|
|
36
46
|
DefaultMimeTypes = {
|
37
47
|
"ai" => "application/postscript",
|
@@ -57,6 +67,7 @@ module WEBrick
|
|
57
67
|
"jpe" => "image/jpeg",
|
58
68
|
"jpeg" => "image/jpeg",
|
59
69
|
"jpg" => "image/jpeg",
|
70
|
+
"js" => "application/javascript",
|
60
71
|
"lha" => "application/octet-stream",
|
61
72
|
"lzh" => "application/octet-stream",
|
62
73
|
"mov" => "video/quicktime",
|
@@ -78,10 +89,12 @@ module WEBrick
|
|
78
89
|
"rtf" => "application/rtf",
|
79
90
|
"sgm" => "text/sgml",
|
80
91
|
"sgml" => "text/sgml",
|
92
|
+
"svg" => "image/svg+xml",
|
81
93
|
"tif" => "image/tiff",
|
82
94
|
"tiff" => "image/tiff",
|
83
95
|
"txt" => "text/plain",
|
84
96
|
"xbm" => "image/x-xbitmap",
|
97
|
+
"xhtml" => "text/html",
|
85
98
|
"xls" => "application/vnd.ms-excel",
|
86
99
|
"xml" => "text/xml",
|
87
100
|
"xpm" => "image/x-xpixmap",
|
@@ -89,7 +102,9 @@ module WEBrick
|
|
89
102
|
"zip" => "application/zip",
|
90
103
|
}
|
91
104
|
|
92
|
-
|
105
|
+
##
|
106
|
+
# Loads Apache-compatible mime.types in +file+.
|
107
|
+
|
93
108
|
def load_mime_types(file)
|
94
109
|
open(file){ |io|
|
95
110
|
hash = Hash.new
|
@@ -97,7 +112,7 @@ module WEBrick
|
|
97
112
|
next if /^#/ =~ line
|
98
113
|
line.chomp!
|
99
114
|
mimetype, ext0 = line.split(/\s+/, 2)
|
100
|
-
next unless ext0
|
115
|
+
next unless ext0
|
101
116
|
next if ext0.empty?
|
102
117
|
ext0.split(/\s+/).each{ |ext| hash[ext] = mimetype }
|
103
118
|
}
|
@@ -106,6 +121,10 @@ module WEBrick
|
|
106
121
|
end
|
107
122
|
module_function :load_mime_types
|
108
123
|
|
124
|
+
##
|
125
|
+
# Returns the mime type of +filename+ from the list in +mime_tab+. If no
|
126
|
+
# mime type was found application/octet-stream is returned.
|
127
|
+
|
109
128
|
def mime_type(filename, mime_tab)
|
110
129
|
suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
|
111
130
|
suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase)
|
@@ -113,12 +132,14 @@ module WEBrick
|
|
113
132
|
end
|
114
133
|
module_function :mime_type
|
115
134
|
|
116
|
-
|
135
|
+
##
|
136
|
+
# Parses an HTTP header +raw+ into a hash of header fields with an Array
|
137
|
+
# of values.
|
117
138
|
|
118
139
|
def parse_header(raw)
|
119
140
|
header = Hash.new([].freeze)
|
120
141
|
field = nil
|
121
|
-
raw.
|
142
|
+
raw.each_line{|line|
|
122
143
|
case line
|
123
144
|
when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):\s*(.*?)\s*\z/om
|
124
145
|
field, value = $1, $2
|
@@ -128,11 +149,11 @@ module WEBrick
|
|
128
149
|
when /^\s+(.*?)\s*\z/om
|
129
150
|
value = $1
|
130
151
|
unless field
|
131
|
-
raise "bad header '#{line
|
152
|
+
raise HTTPStatus::BadRequest, "bad header '#{line}'."
|
132
153
|
end
|
133
154
|
header[field][-1] << " " << value
|
134
155
|
else
|
135
|
-
raise "bad header '#{line
|
156
|
+
raise HTTPStatus::BadRequest, "bad header '#{line}'."
|
136
157
|
end
|
137
158
|
}
|
138
159
|
header.each{|key, values|
|
@@ -145,12 +166,18 @@ module WEBrick
|
|
145
166
|
end
|
146
167
|
module_function :parse_header
|
147
168
|
|
169
|
+
##
|
170
|
+
# Splits a header value +str+ according to HTTP specification.
|
171
|
+
|
148
172
|
def split_header_value(str)
|
149
173
|
str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+)
|
150
174
|
(?:,\s*|\Z)'xn).flatten
|
151
175
|
end
|
152
176
|
module_function :split_header_value
|
153
177
|
|
178
|
+
##
|
179
|
+
# Parses a Range header value +ranges_specifier+
|
180
|
+
|
154
181
|
def parse_range_header(ranges_specifier)
|
155
182
|
if /^bytes=(.*)/ =~ ranges_specifier
|
156
183
|
byte_range_set = split_header_value($1)
|
@@ -166,6 +193,9 @@ module WEBrick
|
|
166
193
|
end
|
167
194
|
module_function :parse_range_header
|
168
195
|
|
196
|
+
##
|
197
|
+
# Parses q values in +value+ as used in Accept headers.
|
198
|
+
|
169
199
|
def parse_qvalues(value)
|
170
200
|
tmp = []
|
171
201
|
if value
|
@@ -184,7 +214,8 @@ module WEBrick
|
|
184
214
|
end
|
185
215
|
module_function :parse_qvalues
|
186
216
|
|
187
|
-
|
217
|
+
##
|
218
|
+
# Removes quotes and escapes from +str+
|
188
219
|
|
189
220
|
def dequote(str)
|
190
221
|
ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
|
@@ -193,20 +224,43 @@ module WEBrick
|
|
193
224
|
end
|
194
225
|
module_function :dequote
|
195
226
|
|
227
|
+
##
|
228
|
+
# Quotes and escapes quotes in +str+
|
229
|
+
|
196
230
|
def quote(str)
|
197
231
|
'"' << str.gsub(/[\\\"]/o, "\\\1") << '"'
|
198
232
|
end
|
199
233
|
module_function :quote
|
200
234
|
|
201
|
-
|
235
|
+
##
|
236
|
+
# Stores multipart form data. FormData objects are created when
|
237
|
+
# WEBrick::HTTPUtils.parse_form_data is called.
|
202
238
|
|
203
239
|
class FormData < String
|
204
|
-
EmptyRawHeader = [].freeze
|
205
|
-
EmptyHeader = {}.freeze
|
240
|
+
EmptyRawHeader = [].freeze # :nodoc:
|
241
|
+
EmptyHeader = {}.freeze # :nodoc:
|
242
|
+
|
243
|
+
##
|
244
|
+
# The name of the form data part
|
206
245
|
|
207
|
-
attr_accessor :name
|
246
|
+
attr_accessor :name
|
247
|
+
|
248
|
+
##
|
249
|
+
# The filename of the form data part
|
250
|
+
|
251
|
+
attr_accessor :filename
|
252
|
+
|
253
|
+
attr_accessor :next_data # :nodoc:
|
208
254
|
protected :next_data
|
209
255
|
|
256
|
+
##
|
257
|
+
# Creates a new FormData object.
|
258
|
+
#
|
259
|
+
# +args+ is an Array of form data entries. One FormData will be created
|
260
|
+
# for each entry.
|
261
|
+
#
|
262
|
+
# This is called by WEBrick::HTTPUtils.parse_form_data for you
|
263
|
+
|
210
264
|
def initialize(*args)
|
211
265
|
@name = @filename = @next_data = nil
|
212
266
|
if args.empty?
|
@@ -215,7 +269,7 @@ module WEBrick
|
|
215
269
|
super("")
|
216
270
|
else
|
217
271
|
@raw_header = EmptyRawHeader
|
218
|
-
@header = EmptyHeader
|
272
|
+
@header = EmptyHeader
|
219
273
|
super(args.shift)
|
220
274
|
unless args.empty?
|
221
275
|
@next_data = self.class.new(*args)
|
@@ -223,6 +277,9 @@ module WEBrick
|
|
223
277
|
end
|
224
278
|
end
|
225
279
|
|
280
|
+
##
|
281
|
+
# Retrieves the header at the first entry in +key+
|
282
|
+
|
226
283
|
def [](*key)
|
227
284
|
begin
|
228
285
|
@header[key[0].downcase].join(", ")
|
@@ -231,11 +288,17 @@ module WEBrick
|
|
231
288
|
end
|
232
289
|
end
|
233
290
|
|
291
|
+
##
|
292
|
+
# Adds +str+ to this FormData which may be the body, a header or a
|
293
|
+
# header entry.
|
294
|
+
#
|
295
|
+
# This is called by WEBrick::HTTPUtils.parse_form_data for you
|
296
|
+
|
234
297
|
def <<(str)
|
235
298
|
if @header
|
236
299
|
super
|
237
300
|
elsif str == CRLF
|
238
|
-
@header = HTTPUtils::parse_header(@raw_header)
|
301
|
+
@header = HTTPUtils::parse_header(@raw_header.join)
|
239
302
|
if cd = self['content-disposition']
|
240
303
|
if /\s+name="(.*?)"/ =~ cd then @name = $1 end
|
241
304
|
if /\s+filename="(.*?)"/ =~ cd then @filename = $1 end
|
@@ -246,10 +309,15 @@ module WEBrick
|
|
246
309
|
self
|
247
310
|
end
|
248
311
|
|
312
|
+
##
|
313
|
+
# Adds +data+ at the end of the chain of entries
|
314
|
+
#
|
315
|
+
# This is called by WEBrick::HTTPUtils.parse_form_data for you.
|
316
|
+
|
249
317
|
def append_data(data)
|
250
318
|
tmp = self
|
251
319
|
while tmp
|
252
|
-
unless tmp.next_data
|
320
|
+
unless tmp.next_data
|
253
321
|
tmp.next_data = data
|
254
322
|
break
|
255
323
|
end
|
@@ -258,6 +326,9 @@ module WEBrick
|
|
258
326
|
self
|
259
327
|
end
|
260
328
|
|
329
|
+
##
|
330
|
+
# Yields each entry in this FormData
|
331
|
+
|
261
332
|
def each_data
|
262
333
|
tmp = self
|
263
334
|
while tmp
|
@@ -267,6 +338,9 @@ module WEBrick
|
|
267
338
|
end
|
268
339
|
end
|
269
340
|
|
341
|
+
##
|
342
|
+
# Returns all the FormData as an Array
|
343
|
+
|
270
344
|
def list
|
271
345
|
ret = []
|
272
346
|
each_data{|data|
|
@@ -275,18 +349,27 @@ module WEBrick
|
|
275
349
|
ret
|
276
350
|
end
|
277
351
|
|
352
|
+
##
|
353
|
+
# A FormData will behave like an Array
|
354
|
+
|
278
355
|
alias :to_ary :list
|
279
356
|
|
357
|
+
##
|
358
|
+
# This FormData's body
|
359
|
+
|
280
360
|
def to_s
|
281
361
|
String.new(self)
|
282
362
|
end
|
283
363
|
end
|
284
364
|
|
365
|
+
##
|
366
|
+
# Parses the query component of a URI in +str+
|
367
|
+
|
285
368
|
def parse_query(str)
|
286
369
|
query = Hash.new
|
287
370
|
if str
|
288
371
|
str.split(/[&;]/).each{|x|
|
289
|
-
next if x.empty?
|
372
|
+
next if x.empty?
|
290
373
|
key, val = x.split(/=/,2)
|
291
374
|
key = unescape_form(key)
|
292
375
|
val = unescape_form(val.to_s)
|
@@ -303,12 +386,15 @@ module WEBrick
|
|
303
386
|
end
|
304
387
|
module_function :parse_query
|
305
388
|
|
389
|
+
##
|
390
|
+
# Parses form data in +io+ with the given +boundary+
|
391
|
+
|
306
392
|
def parse_form_data(io, boundary)
|
307
|
-
boundary_regexp = /\A--#{boundary}(--)?#{CRLF}\z/
|
393
|
+
boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/
|
308
394
|
form_data = Hash.new
|
309
395
|
return form_data unless io
|
310
396
|
data = nil
|
311
|
-
io.
|
397
|
+
io.each_line{|line|
|
312
398
|
if boundary_regexp =~ line
|
313
399
|
if data
|
314
400
|
data.chop!
|
@@ -316,7 +402,7 @@ module WEBrick
|
|
316
402
|
if form_data.has_key?(key)
|
317
403
|
form_data[key].append_data(data)
|
318
404
|
else
|
319
|
-
form_data[key] = data
|
405
|
+
form_data[key] = data
|
320
406
|
end
|
321
407
|
end
|
322
408
|
data = FormData.new
|
@@ -347,9 +433,11 @@ module WEBrick
|
|
347
433
|
|
348
434
|
module_function
|
349
435
|
|
436
|
+
# :stopdoc:
|
437
|
+
|
350
438
|
def _make_regex(str) /([#{Regexp.escape(str)}])/n end
|
351
439
|
def _make_regex!(str) /([^#{Regexp.escape(str)}])/n end
|
352
|
-
def _escape(str, regex) str.gsub(regex){ "%%%02X" % $1
|
440
|
+
def _escape(str, regex) str.gsub(regex){ "%%%02X" % $1.ord } end
|
353
441
|
def _unescape(str, regex) str.gsub(regex){ $1.hex.chr } end
|
354
442
|
|
355
443
|
UNESCAPED = _make_regex(control+space+delims+unwise+nonascii)
|
@@ -358,24 +446,41 @@ module WEBrick
|
|
358
446
|
ESCAPED = /%([0-9a-fA-F]{2})/
|
359
447
|
UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,")
|
360
448
|
|
449
|
+
# :startdoc:
|
450
|
+
|
451
|
+
##
|
452
|
+
# Escapes HTTP reserved and unwise characters in +str+
|
453
|
+
|
361
454
|
def escape(str)
|
362
455
|
_escape(str, UNESCAPED)
|
363
456
|
end
|
364
457
|
|
458
|
+
##
|
459
|
+
# Unescapes HTTP reserved and unwise characters in +str+
|
460
|
+
|
365
461
|
def unescape(str)
|
366
462
|
_unescape(str, ESCAPED)
|
367
463
|
end
|
368
464
|
|
465
|
+
##
|
466
|
+
# Escapes form reserved characters in +str+
|
467
|
+
|
369
468
|
def escape_form(str)
|
370
469
|
ret = _escape(str, UNESCAPED_FORM)
|
371
470
|
ret.gsub!(/ /, "+")
|
372
471
|
ret
|
373
472
|
end
|
374
473
|
|
474
|
+
##
|
475
|
+
# Unescapes form reserved characters in +str+
|
476
|
+
|
375
477
|
def unescape_form(str)
|
376
478
|
_unescape(str.gsub(/\+/, " "), ESCAPED)
|
377
479
|
end
|
378
480
|
|
481
|
+
##
|
482
|
+
# Escapes path +str+
|
483
|
+
|
379
484
|
def escape_path(str)
|
380
485
|
result = ""
|
381
486
|
str.scan(%r{/([^/]*)}).each{|i|
|
@@ -384,6 +489,9 @@ module WEBrick
|
|
384
489
|
return result
|
385
490
|
end
|
386
491
|
|
492
|
+
##
|
493
|
+
# Escapes 8 bit characters in +str+
|
494
|
+
|
387
495
|
def escape8bit(str)
|
388
496
|
_escape(str, NONASCII)
|
389
497
|
end
|