From b51513339c0cbb91b31d50dd13f0cbe3bb239c84 Mon Sep 17 00:00:00 2001 From: Fijxu Date: Mon, 21 Oct 2024 13:54:51 -0300 Subject: [PATCH] 0.9.2: Fix thumbnail folder generation, better chatterino config generation and better error hadling --- src/handling/admin.cr | 14 +++++------ src/handling/handling.cr | 50 +++++++++++++++++++++++++++++----------- src/http-errors.cr | 7 ++++++ src/routing.cr | 11 +++++++++ src/utils.cr | 8 +++---- src/views/chatterino.ecr | 20 ++++++++++++++++ src/views/index.ecr | 2 +- 7 files changed, 86 insertions(+), 26 deletions(-) create mode 100644 src/views/chatterino.ecr diff --git a/src/handling/admin.cr b/src/handling/admin.cr index 7a53526..5d62719 100644 --- a/src/handling/admin.cr +++ b/src/handling/admin.cr @@ -152,13 +152,13 @@ module Handling::Admin # /api/admin/whitelist # curl -X GET -H "X-Api-Key: asd" http://localhost:8080/api/admin/torexitnodes | jq -# def add_ip_to_whitelist(env, nodes) -# json = JSON.build do |j| -# j.object do -# j.field "ips", nodes -# end -# end -# end + # def add_ip_to_whitelist(env, nodes) + # json = JSON.build do |j| + # j.object do + # j.field "ips", nodes + # end + # end + # end # /api/admin/blacklist # curl -X GET -H "X-Api-Key: asd" http://localhost:8080/api/admin/torexitnodes | jq diff --git a/src/handling/handling.cr b/src/handling/handling.cr index 0ddd0ce..6a384f2 100644 --- a/src/handling/handling.cr +++ b/src/handling/handling.cr @@ -1,6 +1,7 @@ require "../http-errors" require "http/client" require "benchmark" +# require "../filters" module Handling extend self @@ -10,6 +11,7 @@ module Handling ip_address = Utils.ip_address(env) protocol = Utils.protocol(env) host = Utils.host(env) + # filter = env.params.query["filter"]? # You can modify this if you want to allow files smaller than 1MiB. # This is generally a good way to check the filesize but there is a better way to do it # which is inspecting the file directly (If I'm not wrong). @@ -46,6 +48,10 @@ module Handling original_filename = upload.filename uploaded_at = Time.utc checksum = Utils.hash_file(file_path) + # TODO: Apply filters + # if filter + # Filters.apply_filter(file_path, filter) + # end end # X-Forwarded-For if behind a reverse proxy and the header is set in the reverse # proxy configuration. @@ -88,13 +94,19 @@ module Handling ip_address = Utils.ip_address(env) protocol = Utils.protocol(env) host = Utils.host(env) - files = env.params.json["files"].as((Array(JSON::Any))) + begin + files = env.params.json["files"].as((Array(JSON::Any))) + rescue ex : JSON::ParseException + LOGGER.error "Body malformed: #{ex.message}" + return error400 "Body malformed: #{ex.message}" + rescue ex + LOGGER.error "Unknown error: #{ex.message}" + return error500 "Unknown error" + end successfull_files = [] of NamedTuple(filename: String, extension: String, original_filename: String, checksum: String, delete_key: String | Nil) failed_files = [] of String # X-Forwarded-For if behind a reverse proxy and the header is set in the reverse # proxy configuration. - if files.empty? - end files.each do |url| url = url.to_s filename = Utils.generate_filename @@ -103,7 +115,9 @@ module Handling checksum = "" uploaded_at = Time.utc extension = File.extname(URI.parse(url).path) - delete_key = nil + if CONFIG.deleteKeyLength > 0 + delete_key = Random.base58(CONFIG.deleteKeyLength) + end file_path = ::File.join ["#{CONFIG.files}", filename + extension] File.open(file_path, "w") do |output| begin @@ -168,7 +182,6 @@ module Handling json end - # TODO: Add delete url, same for upload_url_bulk def upload_url(env) env.response.content_type = "application/json" ip_address = Utils.ip_address(env) @@ -179,31 +192,29 @@ module Handling failed_files = [] of String # X-Forwarded-For if behind a reverse proxy and the header is set in the reverse # proxy configuration. - if url.empty? - end - # files.each do |url| - url = url.to_s filename = Utils.generate_filename original_filename = "" extension = "" checksum = "" uploaded_at = Time.utc extension = File.extname(URI.parse(url).path) - delete_key = nil + if CONFIG.deleteKeyLength > 0 + delete_key = Random.base58(CONFIG.deleteKeyLength) + end file_path = ::File.join ["#{CONFIG.files}", filename + extension] File.open(file_path, "w") do |output| begin + # TODO: Connect timeout to prevent possible Denial of Service to the external website spamming requests + # https://crystal-lang.org/api/1.13.2/HTTP/Client.html#connect_timeout HTTP::Client.get(url) do |res| IO.copy(res.body_io, output) end rescue ex LOGGER.debug "Failed to download file '#{url}': #{ex.message}" - return error403("Failed to download file '#{url}'") + return error403("Failed to download file '#{url}': #{ex.message}") failed_files << url end end - # successfull_files << url - # end if extension.empty? extension = Utils.detect_extension(file_path) File.rename(file_path, file_path + extension) @@ -231,7 +242,6 @@ module Handling LOGGER.error "An error ocurred when trying to insert the data into the DB: #{ex.message}" return error500("An error ocurred when trying to insert the data into the DB") end - # end json = JSON.build do |j| j.array do successfull_files.each do |fileinfo| @@ -383,4 +393,16 @@ module Handling "ErrorMessage": "{json:error}" }) end + + def chatterino_config(env) + host = Utils.host(env) + protocol = Utils.protocol(env) + env.response.content_type = "application/json" + return %({ + "requestUrl": "#{protocol}://#{host}/upload", + "formField": "data", + "imageLink": "{link}", + "deleteLink": "{deleteLink}" + }) + end end diff --git a/src/http-errors.cr b/src/http-errors.cr index 9293971..71619b7 100644 --- a/src/http-errors.cr +++ b/src/http-errors.cr @@ -1,3 +1,10 @@ +macro error400(message) + env.response.content_type = "application/json" + env.response.status_code = 400 + error_message = {"error" => {{message}}}.to_json + error_message + end + macro error401(message) env.response.content_type = "application/json" env.response.status_code = 401 diff --git a/src/routing.cr b/src/routing.cr index b458819..4ddc1a5 100644 --- a/src/routing.cr +++ b/src/routing.cr @@ -50,6 +50,13 @@ module Routing render "src/views/index.ecr" end + get "/chatterino" do |env| + host = Utils.host(env) + protocol = Utils.protocol(env) + files_hosted = SQL.query_one "SELECT COUNT (filename) FROM #{CONFIG.dbTableName}", as: Int32 + render "src/views/chatterino.ecr" + end + post "/upload" do |env| Handling.upload(env) end @@ -82,6 +89,10 @@ module Routing Handling.sharex_config(env) end + get "/chatterinoconfig" do |env| + Handling.chatterino_config(env) + end + if CONFIG.adminEnabled self.register_admin end diff --git a/src/utils.cr b/src/utils.cr index 0c87bf7..0ea423e 100644 --- a/src/utils.cr +++ b/src/utils.cr @@ -30,7 +30,7 @@ module Utils end def create_thumbnails_dir - if !CONFIG.thumbnails + if CONFIG.thumbnails if !Dir.exists?("#{CONFIG.thumbnails}") LOGGER.info "Creating thumbnails folder under '#{CONFIG.thumbnails}'" begin @@ -69,7 +69,7 @@ module Utils dependencies.each do |dep| next if !CONFIG.generateThumbnails if !Process.find_executable(dep) - LOGGER.fatal("'#{dep}' was not found") + LOGGER.fatal("'#{dep}' was not found.") exit(1) end end @@ -113,7 +113,7 @@ module Utils def generate_thumbnail(filename, extension) # Disable generation if false - return if !CONFIG.generateThumbnails + return if !CONFIG.generateThumbnails || !CONFIG.thumbnails LOGGER.debug "Generating thumbnail for #{filename + extension} in background" process = Process.run("ffmpeg", [ @@ -128,7 +128,7 @@ module Utils "-update", "1", "#{CONFIG.thumbnails}/#{filename}.jpg", ]) - if process.normal_exit? + if process.exit_code == 0 LOGGER.debug "Thumbnail for #{filename + extension} generated successfully" SQL.exec "UPDATE #{CONFIG.dbTableName} SET thumbnail = ? WHERE filename = ?", filename + ".jpg", filename else diff --git a/src/views/chatterino.ecr b/src/views/chatterino.ecr new file mode 100644 index 0000000..b8dc463 --- /dev/null +++ b/src/views/chatterino.ecr @@ -0,0 +1,20 @@ + + + + + + <%= host %> + + + + + +
+

Chatterino config

+

Request URL: <%= protocol %>://<%= host %>/upload

+

Form field: data

+

Image link: link

+

Delete link: deleteLink

+
+ + diff --git a/src/views/index.ecr b/src/views/index.ecr index 7d54c47..dd8d711 100644 --- a/src/views/index.ecr +++ b/src/views/index.ecr @@ -22,7 +22,7 @@

- Chatterino Config | + Chatterino Config | ShareX Config | file-uploader-crystal (BETA <%= CURRENT_TAG %> - <%= CURRENT_VERSION %> @ <%= CURRENT_BRANCH %>)