#!/usr/bin/env ruby require 'webrick' require 'webrick/cgi' begin require 'webrick/httpservlet/webdavhandler' rescue LoadError #:EMBED:webdavhandler.rb end unless WEBrick::HTTPUtils.respond_to? :escape_path # backport patch from webrick/cgi.rb rev 1.4.2.3 module WEBrick; class CGI; class Socket def request_line meth = @env["REQUEST_METHOD"] url = HTTPUtils.escape(@env["SCRIPT_NAME"].dup) if path_info = HTTPUtils.escape(@env["PATH_INFO"]) url << path_info end if query_string = @env["QUERY_STRING"] unless query_string.empty? url << "?" << query_string end end httpv = @config[:HTTPVersion] "#{meth} #{url} HTTP/#{httpv}" end end; end; end end class SaradaCGI < WEBrick::CGI def initialize(useropt={}) super @options = { :Root => Dir.pwd, :NondisclosureName => %w(.ht* sarada.conf nph-sarada.*), } @options.update(useropt) @root = @options[:Root] @options.delete :Root @config[:NPH] = true @logger.level = WEBrick::Log::DEBUG if $DEBUG @logger.debug "#{self.class} initialized. root=#{@root}" end attr_reader :config, :logger def [](key) @config[key] end def start(env=ENV, stdin=$stdin, stdout=$stdout) @env = env super end def self_uri(req) (@env['HTTPS'] ? 'https':'http') + "://" + @env['SERVER_NAME'] + ((!@env['HTTPS'] && @env['SERVER_PORT'] != '80' || @env['HTTPS'] && @env['SERVER_PORT'] != 443) ? ":#{@env['SERVER_PORT']}" : '') + req.path end def dav_handler WEBrick::HTTPServlet::WebDAVHandler.get_instance(self, @root, @options) end def dav_redir(req, res) # FIXME: restruct this method all! for i18n, valid-HTML, user-custom and etc.. case req["User-Agent"] when /Konqueror/ davuri = self_uri(req).sub(/^https?/,'webdav') res.body << " open as folder " when /MSIE/ res.body << "

Open web folder.

Meybe, you need to add following URL as'network place' via 'My Network'.

#{self_uri(req)}/
" else res.body << "

Specify following URL on your WebDAV client.

#{self_uri(req)}/
" end end def service(req, res) if req.path_info.nil? || req.path_info.empty? req.path_info = '/' #elsif %r|^/~([^/]+)| =~ req.path_info # user = $1 # path_info = $'.empty? ? "/" : $' # req.instance_variable_set :@path, req.path_info # req.path_info = path_info end # FIXME: supports keep-alive with apache2. # somehow, we will got "cannot parse chunk" error from client. @config[:HTTPVersion] == "1.1" and res.chunked = true res["Connection"] = "close" if req.path_info[-1..-1] == "/" && req.request_method == "GET" dav_redir(req, res) else dav_handler.service(req, res) end end end if __FILE__ == $0 ## pre-process for apache env = ENV.to_hash # deep clone #if env.has_key?("REDIRECT_URL") && !env["REDIRECT_URL"].empty? # env["PATH_INFO"] = env["REDIRECT_URL"] #end # apache will unescape headers?? maybe mod_encoding's bug??? #env.has_key?("HTTP_DESTINATION") and # env["HTTP_DESTINATION"] = WEBrick::HTTPUtils.escape(env["HTTP_DESTINATION"]) if File.exists? "./saradaconf.yaml" begin require 'yaml' opts = YAML.load(File.read("./saradaconf.yaml")) Hash === opts or raise TypeError.new("non Hash element from yaml") rescue => ex opts = nil $stderr.puts "Error when loading config: #{ex}" end end if $DEBUG $stderr.puts "== headers ==", env.sort.map{|k,v|"\t#{k}= #{v}"} end SaradaCGI.new(*[opts].compact).start(env) end