0.4.0: Support for blocked extensions and filesize limit
This commit is contained in:
parent
17f1efa214
commit
e096ed5215
3 changed files with 42 additions and 45 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
blocked_extensions:
|
||||||
|
- "exe"
|
|
@ -6,12 +6,16 @@ class Config
|
||||||
property files : String = "./files"
|
property files : String = "./files"
|
||||||
property db : String = "./db.sqlite3"
|
property db : String = "./db.sqlite3"
|
||||||
property filename_lenght : Int8 = 3
|
property filename_lenght : Int8 = 3
|
||||||
|
# In MiB
|
||||||
|
property size_limit : Int16 = 512
|
||||||
property port : UInt16 = 8080
|
property port : UInt16 = 8080
|
||||||
property unix_socket : String?
|
property unix_socket : String?
|
||||||
property delete_files_after : Int32 = 7
|
property delete_files_after : Int32 = 7
|
||||||
# How often should the check of old files be performed? (in seconds)
|
# How often should the check of old files be performed? (in seconds)
|
||||||
property delete_files_after_check_seconds : Int32 = 60
|
property delete_files_after_check_seconds : Int32 = 60
|
||||||
property delete_key_lenght : Int8 = 8
|
property delete_key_lenght : Int8 = 8
|
||||||
|
# Blocked extensions that are not allowed to be uploaded to the server
|
||||||
|
property blocked_extensions : Array(String) = [] of String
|
||||||
|
|
||||||
def self.load
|
def self.load
|
||||||
config_file = "config/config.yml"
|
config_file = "config/config.yml"
|
||||||
|
|
|
@ -1,7 +1,25 @@
|
||||||
module Handling
|
module Handling
|
||||||
extend self
|
extend self
|
||||||
|
|
||||||
|
private macro error403(message)
|
||||||
|
env.response.content_type = "application/json"
|
||||||
|
env.response.status_code = 403
|
||||||
|
error_message = {"error" => {{message}}}.to_json
|
||||||
|
return error_message
|
||||||
|
end
|
||||||
|
|
||||||
|
private macro msg(message)
|
||||||
|
env.response.content_type = "application/json"
|
||||||
|
msg = {"message" => {{message}}}.to_json
|
||||||
|
return msg
|
||||||
|
end
|
||||||
|
|
||||||
def upload(env)
|
def upload(env)
|
||||||
|
env.response.content_type = "application/json"
|
||||||
|
# You can modify this if you want to allow files smaller than 1MiB
|
||||||
|
if env.request.headers["Content-Length"].to_i > 1048576*CONFIG.size_limit
|
||||||
|
error403("File is too big. The maximum size allowed is #{CONFIG.size_limit}MiB")
|
||||||
|
end
|
||||||
filename = ""
|
filename = ""
|
||||||
extension = ""
|
extension = ""
|
||||||
original_filename = ""
|
original_filename = ""
|
||||||
|
@ -13,6 +31,11 @@ module Handling
|
||||||
HTTP::FormData.parse(env.request) do |upload|
|
HTTP::FormData.parse(env.request) do |upload|
|
||||||
next if upload.filename.nil? || upload.filename.to_s.empty?
|
next if upload.filename.nil? || upload.filename.to_s.empty?
|
||||||
extension = File.extname("#{upload.filename}")
|
extension = File.extname("#{upload.filename}")
|
||||||
|
if CONFIG.blocked_extensions.includes?(extension.split(".")[1])
|
||||||
|
error403("Extension '#{extension}' is not allowed")
|
||||||
|
end
|
||||||
|
# TODO: Check if random string is already taken by some file (This will likely
|
||||||
|
# never happen but it is better to design it that way)
|
||||||
filename = Random.base58(CONFIG.filename_lenght)
|
filename = Random.base58(CONFIG.filename_lenght)
|
||||||
if !filename.is_a?(String)
|
if !filename.is_a?(String)
|
||||||
return "This doesn't look like a file"
|
return "This doesn't look like a file"
|
||||||
|
@ -25,12 +48,11 @@ module Handling
|
||||||
original_filename = upload.filename
|
original_filename = upload.filename
|
||||||
uploaded_at = Time.utc
|
uploaded_at = Time.utc
|
||||||
file_hash = Utils.hash_file(file_path)
|
file_hash = Utils.hash_file(file_path)
|
||||||
ip_address = env.request.not_nil!.remote_address.to_s.split(":").first
|
ip_address = env.request.remote_address.to_s.split(":").first
|
||||||
SQL.exec "INSERT INTO FILES VALUES (?, ?, ?, ?, ?, ?, ?)",
|
SQL.exec "INSERT INTO FILES VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||||
original_filename, filename, extension, uploaded_at, file_hash, ip_address, delete_key
|
original_filename, filename, extension, uploaded_at, file_hash, ip_address, delete_key
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
env.response.content_type = "application/json"
|
|
||||||
if !filename.empty?
|
if !filename.empty?
|
||||||
JSON.build do |j|
|
JSON.build do |j|
|
||||||
j.object do
|
j.object do
|
||||||
|
@ -44,57 +66,32 @@ module Handling
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
env.response.content_type = "application/json"
|
error403("No file")
|
||||||
env.response.status_code = 403
|
|
||||||
error_message = {"error" => "No file"}.to_json
|
|
||||||
error_message
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def retrieve_file(env)
|
def retrieve_file(env)
|
||||||
begin
|
filename = SQL.query_one "SELECT filename FROM files WHERE filename = ?", env.params.url["filename"].to_s.split(".").first, as: String
|
||||||
if !File.extname(env.params.url["filename"]).empty?
|
extension = SQL.query_one "SELECT extension FROM files WHERE filename = ?", filename, as: String
|
||||||
send_file env, "#{CONFIG.files}/#{env.params.url["filename"]}"
|
send_file env, "#{CONFIG.files}/#{filename}#{extension}"
|
||||||
# next
|
|
||||||
end
|
|
||||||
dir = Dir.new("#{CONFIG.files}")
|
|
||||||
dir.each do |filename|
|
|
||||||
if filename.starts_with?("#{env.params.url["filename"]}")
|
|
||||||
send_file env, "#{CONFIG.files}/#{env.params.url["filename"]}" + File.extname(filename)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
raise ""
|
|
||||||
rescue
|
|
||||||
env.response.content_type = "text/plain"
|
|
||||||
env.response.status_code = 403
|
|
||||||
return "File does not exist"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def stats(env)
|
def stats(env)
|
||||||
begin
|
env.response.content_type = "application/json"
|
||||||
dir = Dir.new("#{CONFIG.files}")
|
|
||||||
rescue
|
|
||||||
env.response.content_type = "text/plain"
|
|
||||||
env.response.status_code = 403
|
|
||||||
return "Unknown error"
|
|
||||||
end
|
|
||||||
|
|
||||||
json_data = JSON.build do |json|
|
json_data = JSON.build do |json|
|
||||||
json.object do
|
json.object do
|
||||||
json.field "stats" do
|
json.field "stats" do
|
||||||
json.object do
|
json.object do
|
||||||
begin
|
begin
|
||||||
json.field "filesHosted", dir.children.size
|
json.field "filesHosted", SQL.query_one "SELECT COUNT (filename) FROM files", as: Int32
|
||||||
|
json.field "maxUploadSize", CONFIG.size_limit
|
||||||
rescue
|
rescue
|
||||||
json.field "filesHosted", 0
|
json.field "error", "Unknown error"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
dir.close
|
|
||||||
env.response.content_type = "application/json"
|
|
||||||
json_data
|
json_data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -105,18 +102,12 @@ module Handling
|
||||||
file_extension = SQL.query_one "SELECT extension FROM files WHERE delete_key = ?", env.params.query["key"], as: String
|
file_extension = SQL.query_one "SELECT extension FROM files WHERE delete_key = ?", env.params.query["key"], as: String
|
||||||
File.delete("#{CONFIG.files}/#{file_to_delete}#{file_extension}")
|
File.delete("#{CONFIG.files}/#{file_to_delete}#{file_extension}")
|
||||||
SQL.exec "DELETE FROM files WHERE delete_key = ?", env.params.query["key"]
|
SQL.exec "DELETE FROM files WHERE delete_key = ?", env.params.query["key"]
|
||||||
env.response.content_type = "application/json"
|
msg("File deleted successfully")
|
||||||
error_message = {"message" => "File deleted successfully"}.to_json
|
rescue ex
|
||||||
error_message
|
error403("Unknown error: #{ex.message}")
|
||||||
rescue
|
|
||||||
env.response.content_type = "application/json"
|
|
||||||
env.response.status_code = 403
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
env.response.content_type = "application/json"
|
error403("Huh? This delete key doesn't exist")
|
||||||
env.response.status_code = 403
|
|
||||||
error_message = {"error" => "Huh? This delete key doesn't exist"}.to_json
|
|
||||||
error_message
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue