126 lines
3.3 KiB
Ruby
126 lines
3.3 KiB
Ruby
#!/usr/bin/env ruby
|
|
|
|
## TODO: Can we somehow make this dynamic?
|
|
CONF_PATH = "/etc/aperture.conf"
|
|
USER_PREFIX = "~"
|
|
|
|
require 'cgi'
|
|
require 'yaml'
|
|
require_relative 'libmagic'
|
|
|
|
$cgi = CGI.new
|
|
|
|
# convenience function to print an error to CGI log and quit
|
|
def die(status, error)
|
|
$cgi.print $cgi.http_header(
|
|
"type" => "text/plain",
|
|
"status" => status
|
|
)
|
|
if status == "SERVER_ERROR"
|
|
$stderr.puts "[aperture:fatal] " + error
|
|
$cgi.print "Something went wrong! Ask the server admin to check the logs for more info."
|
|
else
|
|
$cgi.print error
|
|
end
|
|
exit
|
|
end
|
|
|
|
def get_yaml(path)
|
|
if not File.file? path
|
|
die("SERVER_ERROR", "Application not configured")
|
|
end
|
|
|
|
begin
|
|
cfg = YAML.load(
|
|
File.open(path).read
|
|
)
|
|
return cfg
|
|
rescue
|
|
die("SERVER_ERROR", "Config file broken ;_;")
|
|
end
|
|
# should be unreachable
|
|
die("SERVER_ERROR", "get_yaml broken ;_;")
|
|
end
|
|
|
|
# sanitizes string so all that's left is alphanumerics and .
|
|
def sanitize(str)
|
|
return str.gsub(/(^\.|[^0-9a-zA-Z\.])/i, '_')
|
|
end
|
|
|
|
# main function
|
|
def main()
|
|
# consistency checks for request
|
|
# if not authenticated, ignore
|
|
if $cgi.remote_user.nil? || $cgi.remote_user.empty?
|
|
die("FORBIDDEN", "")
|
|
end
|
|
|
|
# even though remote_user comes from the upstream, don't trust it
|
|
clean_name = sanitize $cgi.remote_user
|
|
|
|
# Only POST supported for this API
|
|
if $cgi.request_method != "POST"
|
|
die("METHOD_NOT_ALLOWED", "Method not allowed")
|
|
end
|
|
|
|
if !$cgi.content_type.start_with?("multipart/form-data")
|
|
die("NOT_ACCEPTABLE", "Please use multipart/form-data, you're using " + $cgi.content_type)
|
|
end
|
|
|
|
cfg = get_yaml CONF_PATH
|
|
|
|
# make sure expected config entries are there
|
|
if cfg['save_path'].nil? or cfg['save_path'].empty?
|
|
die "SERVER_ERROR", "config: save_path not set!"
|
|
end
|
|
|
|
if cfg['root_url'].nil? or cfg['root_url'].empty?
|
|
die "SERVER_ERROR", "config: root_url not set!"
|
|
end
|
|
|
|
# XXX: configurable prefix?
|
|
user_dir = cfg['save_path'] + "/" + USER_PREFIX + clean_name
|
|
|
|
if not File.directory? user_dir
|
|
die("SERVER_ERROR", "User directory " + user_dir + " doesn't exist!")
|
|
end
|
|
|
|
# get file data
|
|
if $cgi.params['sendfile'].nil? || $cgi.params['sendfile'].empty?
|
|
die("NOT_ACCEPTABLE", "Missing sendfile?")
|
|
end
|
|
|
|
upfile = $cgi.params['sendfile'][0]
|
|
|
|
# get the mime type from the file contents, not HTTP
|
|
lm = LibMagic::Magic.new(cfg['magic_path'])
|
|
ftype = lm.get_mime_type(upfile)
|
|
if ftype.match(/^(image|text|audio|video)\/[a-zA-Z0-9\-\.]+$/).nil?
|
|
die("NOT_ACCEPTABLE", "MIME type " + ftype + " not supported here")
|
|
end
|
|
lm.close
|
|
|
|
clean_file = sanitize upfile.original_filename
|
|
full_path = user_dir + "/" + clean_file
|
|
|
|
# don't overwrite an existing file unless they asked for it
|
|
if $cgi.params['overwrite'] != "true" and File.exists? full_path
|
|
die("NOT_ACCEPTABLE" "File " + clean_file + " already exists!")
|
|
end
|
|
|
|
# finally, store the file
|
|
File.open(full_path, "w") do |new_file|
|
|
new_file.write(upfile.read)
|
|
end
|
|
|
|
# print OK and send URL
|
|
|
|
$cgi.print $cgi.http_header("status" => "OK",
|
|
"type" => "text/plain")
|
|
|
|
$cgi.print cfg['root_url'] + USER_PREFIX + clean_name + "/" + clean_file
|
|
end
|
|
|
|
main
|
|
exit 0
|
|
|