rubysl-webrick 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|