| Class | WEBrick::HTTPServlet::FileHandler |
| In: |
lib/webrick/httpservlet/filehandler.rb
|
| Parent: | AbstractServlet |
| HandlerTable | = | Hash.new |
# File lib/webrick/httpservlet/filehandler.rb, line 131
131: def self.add_handler(suffix, handler)
132: HandlerTable[suffix] = handler
133: end
# File lib/webrick/httpservlet/filehandler.rb, line 139
139: def initialize(server, root, options={}, default=Config::FileHandler)
140: @config = server.config
141: @logger = @config[:Logger]
142: @root = File.expand_path(root)
143: if options == true || options == false
144: options = { :FancyIndexing => options }
145: end
146: @options = default.dup.update(options)
147: end
# File lib/webrick/httpservlet/filehandler.rb, line 135
135: def self.remove_handler(suffix)
136: HandlerTable.delete(suffix)
137: end
# File lib/webrick/httpservlet/filehandler.rb, line 169
169: def do_GET(req, res)
170: unless exec_handler(req, res)
171: set_dir_list(req, res)
172: end
173: end
# File lib/webrick/httpservlet/filehandler.rb, line 181
181: def do_OPTIONS(req, res)
182: unless exec_handler(req, res)
183: super(req, res)
184: end
185: end
# File lib/webrick/httpservlet/filehandler.rb, line 175
175: def do_POST(req, res)
176: unless exec_handler(req, res)
177: raise HTTPStatus::NotFound, "`#{req.path}' not found."
178: end
179: end
# File lib/webrick/httpservlet/filehandler.rb, line 149
149: def service(req, res)
150: # if this class is mounted on "/" and /~username is requested.
151: # we're going to override path informations before invoking service.
152: if defined?(Etc) && @options[:UserDir] && req.script_name.empty?
153: if %r|^(/~([^/]+))| =~ req.path_info
154: script_name, user = $1, $2
155: path_info = $'
156: begin
157: passwd = Etc::getpwnam(user)
158: @root = File::join(passwd.dir, @options[:UserDir])
159: req.script_name = script_name
160: req.path_info = path_info
161: rescue
162: @logger.debug "#{self.class}#do_GET: getpwnam(#{user}) failed"
163: end
164: end
165: end
166: super(req, res)
167: end
# File lib/webrick/httpservlet/filehandler.rb, line 305
305: def call_callback(callback_name, req, res)
306: if cb = @options[callback_name]
307: cb.call(req, res)
308: end
309: end
# File lib/webrick/httpservlet/filehandler.rb, line 257
257: def check_filename(req, res, name)
258: @options[:NondisclosureName].each{|pattern|
259: if File.fnmatch("/#{pattern}", name)
260: @logger.warn("the request refers nondisclosure name `#{name}'.")
261: raise HTTPStatus::NotFound, "`#{req.path}' not found."
262: end
263: }
264: end
RFC3253: Versioning Extensions to WebDAV
(Web Distributed Authoring and Versioning)
VERSION-CONTROL REPORT CHECKOUT CHECK_IN UNCHECKOUT MKWORKSPACE UPDATE LABEL MERGE ACTIVITY
# File lib/webrick/httpservlet/filehandler.rb, line 201
201: def exec_handler(req, res)
202: raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root
203: if set_filename(req, res)
204: handler = get_handler(req)
205: call_callback(:HandlerCallback, req, res)
206: h = handler.get_instance(@config, res.filename)
207: h.service(req, res)
208: return true
209: end
210: call_callback(:HandlerCallback, req, res)
211: return false
212: end
# File lib/webrick/httpservlet/filehandler.rb, line 214
214: def get_handler(req)
215: suffix1 = (/\.(\w+)$/ =~ req.script_name) && $1.downcase
216: suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ req.script_name) && $1.downcase
217: handler_table = @options[:HandlerTable]
218: return handler_table[suffix1] || handler_table[suffix2] ||
219: HandlerTable[suffix1] || HandlerTable[suffix2] ||
220: DefaultFileHandler
221: end
# File lib/webrick/httpservlet/filehandler.rb, line 311
311: def nondisclosure_name?(name)
312: @options[:NondisclosureName].each{|pattern|
313: if File.fnmatch(pattern, name)
314: return true
315: end
316: }
317: return false
318: end
# File lib/webrick/httpservlet/filehandler.rb, line 283
283: def search_file(req, res, basename)
284: langs = @options[:AcceptableLanguages]
285: path = res.filename + basename
286: if File.file?(path)
287: return basename
288: elsif langs.size > 0
289: req.accept_language.each{|lang|
290: path_with_lang = path + ".#{lang}"
291: if langs.member?(lang) && File.file?(path_with_lang)
292: return basename + ".#{lang}"
293: end
294: }
295: (langs - req.accept_language).each{|lang|
296: path_with_lang = path + ".#{lang}"
297: if File.file?(path_with_lang)
298: return basename + ".#{lang}"
299: end
300: }
301: end
302: return nil
303: end
# File lib/webrick/httpservlet/filehandler.rb, line 274
274: def search_index_file(req, res)
275: @config[:DirectoryIndex].each{|index|
276: if file = search_file(req, res, "/"+index)
277: return file
278: end
279: }
280: return nil
281: end
# File lib/webrick/httpservlet/filehandler.rb, line 320
320: def set_dir_list(req, res)
321: redirect_to_directory_uri(req, res)
322: unless @options[:FancyIndexing]
323: raise HTTPStatus::Forbidden, "no access permission to `#{req.path}'"
324: end
325: local_path = res.filename
326: list = Dir::entries(local_path).collect{|name|
327: next if name == "." || name == ".."
328: next if nondisclosure_name?(name)
329: st = (File::stat(local_path + name) rescue nil)
330: if st.nil?
331: [ name, nil, -1 ]
332: elsif st.directory?
333: [ name + "/", st.mtime, -1 ]
334: else
335: [ name, st.mtime, st.size ]
336: end
337: }
338: list.compact!
339:
340: if d0 = req.query["N"]; idx = 0
341: elsif d0 = req.query["M"]; idx = 1
342: elsif d0 = req.query["S"]; idx = 2
343: else d0 = "A" ; idx = 0
344: end
345: d1 = (d0 == "A") ? "D" : "A"
346:
347: if d0 == "A"
348: list.sort!{|a,b| a[idx] <=> b[idx] }
349: else
350: list.sort!{|a,b| b[idx] <=> a[idx] }
351: end
352:
353: res['content-type'] = "text/html"
354:
355: res.body = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n<HTML>\n<HEAD><TITLE>Index of \#{HTMLUtils::escape(req.path)}</TITLE></HEAD>\n<BODY>\n<H1>Index of \#{HTMLUtils::escape(req.path)}</H1>\n"
356:
357: res.body << "<PRE>\n"
358: res.body << " <A HREF=\"?N=#{d1}\">Name</A> "
359: res.body << "<A HREF=\"?M=#{d1}\">Last modified</A> "
360: res.body << "<A HREF=\"?S=#{d1}\">Size</A>\n"
361: res.body << "<HR>\n"
362:
363: list.unshift [ "..", File::mtime(local_path+".."), -1 ]
364: list.each{ |name, time, size|
365: if name == ".."
366: dname = "Parent Directory"
367: elsif name.size > 25
368: dname = name.sub(/^(.{23})(.*)/){ $1 + ".." }
369: else
370: dname = name
371: end
372: s = " <A HREF=\"#{HTTPUtils::escape(name)}\">#{dname}</A>"
373: s << " " * (30 - dname.size)
374: s << (time ? time.strftime("%Y/%m/%d %H:%M ") : " " * 22)
375: s << (size >= 0 ? size.to_s : "-") << "\n"
376: res.body << s
377: }
378: res.body << "</PRE><HR>"
379:
380: res.body << "<ADDRESS>\n\#{HTMLUtils::escape(@config[:ServerSoftware])}<BR>\nat \#{req.host}:\#{req.port}\n</ADDRESS>\n</BODY>\n</HTML>\n"
381: end
# File lib/webrick/httpservlet/filehandler.rb, line 223
223: def set_filename(req, res)
224: res.filename = @root.dup
225: path_info = req.path_info.scan(%r|/[^/]*|)
226:
227: path_info.unshift("") # dummy for checking @root dir
228: while base = path_info.first
229: check_filename(req, res, base)
230: break if base == "/"
231: break unless File.directory?(res.filename + base)
232: shift_path_info(req, res, path_info)
233: call_callback(:DirectoryCallback, req, res)
234: end
235:
236: if base = path_info.first
237: check_filename(req, res, base)
238: if base == "/"
239: if file = search_index_file(req, res)
240: shift_path_info(req, res, path_info, file)
241: call_callback(:FileCallback, req, res)
242: return true
243: end
244: shift_path_info(req, res, path_info)
245: elsif file = search_file(req, res, base)
246: shift_path_info(req, res, path_info, file)
247: call_callback(:FileCallback, req, res)
248: return true
249: else
250: raise HTTPStatus::NotFound, "`#{req.path}' not found."
251: end
252: end
253:
254: return false
255: end