Class WEBrick::HTTPServlet::FileHandler
In: lib/webrick/httpservlet/filehandler.rb
Parent: AbstractServlet

Methods

Constants

HandlerTable = Hash.new

Public Class methods

[Source]

     # File lib/webrick/httpservlet/filehandler.rb, line 131
131:       def self.add_handler(suffix, handler)
132:         HandlerTable[suffix] = handler
133:       end

[Source]

     # 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

[Source]

     # File lib/webrick/httpservlet/filehandler.rb, line 135
135:       def self.remove_handler(suffix)
136:         HandlerTable.delete(suffix)
137:       end

Public Instance methods

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

Private Instance methods

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # 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

[Source]

     # File lib/webrick/httpservlet/filehandler.rb, line 266
266:       def shift_path_info(req, res, path_info, base=nil)
267:         tmp = path_info.shift
268:         base = base || tmp
269:         req.path_info = path_info.join
270:         req.script_name << base
271:         res.filename << base
272:       end

[Validate]