#!/usr/bin/env ruby # Copyright 2004 Leslie A. Hensley # hensleyl@papermountain.org # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA require 'etc' require 'webrick' require 'cgi' include WEBrick STORAGE_DIR = "files" RANDOM_LENGTH = 4 MAX_ACCESS = 50 #override the default mimetype module WEBrick module HTTPUtils def mime_type(filename, mime_tab) if suffix = (/\.(\w+)$/ =~ filename && $1) mtype = mime_tab[suffix.downcase] end mtype || "text/plain" end module_function :mime_type end end def randomString size pool = ('a'..'z').to_a + ((0..9).to_a) Array.new(size).collect{pool[rand(pool.size)]}.join end class URLEncodedFileHandler < HTTPServlet::FileHandler @@accessCount = Hash.new {0} def set_filename(req, res) if req.path == "/" res.set_redirect(HTTPStatus::MovedPermanently, "/site/") return true end req.path_info.gsub!(/[^\/%+]*$/){|match| CGI.escape(match)} begin found = super(req, res) rescue HTTPStatus::NotFound res.set_redirect(HTTPStatus::MovedPermanently, "/site" + req.path) return true end if found @@accessCount[res.filename] += 1 if @@accessCount[res.filename] > MAX_ACCESS raise HTTPStatus::Forbidden, "`#{req.path}' limit exceeded" end end found end end server = HTTPServer.new( :Port => 80, :Logger => WEBrick::Log::new("dropoff_error.log", WEBrick::Log::DEBUG), :AccessLog => [[WEBrick::BasicLog::new("dropoff_access.log"), WEBrick::AccessLog::COMBINED_LOG_FORMAT]], :MimeTypes => HTTPUtils::load_mime_types("/etc/mime.types")) if(Process.uid == 0) nobody = Etc.getpwnam("nobody") Dir.chdir("dropoff_home") Dir.chroot("dropoff_home") Process.egid = Process.gid = nobody.gid Process.euid = Process.uid = nobody.uid end HTTPServlet::FileHandler.remove_handler("cgi") HTTPServlet::FileHandler.remove_handler("rhtml") server.mount("/", URLEncodedFileHandler, STORAGE_DIR) server.mount("/site", HTTPServlet::FileHandler, "site") server.mount_proc('/store') do |request, response| baseName = CGI.escape(request.query['name'] && request.query['name'].size > 0 ? request.query['name'][0..150] : 'dropoff.txt') directoryName = randomString RANDOM_LENGTH while(FileTest.exists? directoryName) do directoryName = randomString RANDOM_LENGTH end Dir.mkdir "#{STORAGE_DIR}/#{directoryName}" File.open("#{STORAGE_DIR}/#{directoryName}/#{baseName}", 'w') do |file| file.print request.query['data'][0..20*1024] end response.body = "#{ARGV[0]}/#{directoryName}/#{baseName}" response['Content-Type'] = 'text/plain' end trap('INT'){ server.shutdown } server.start