summaryrefslogtreecommitdiffstats
path: root/app.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app.rb')
-rw-r--r--app.rb72
1 files changed, 71 insertions, 1 deletions
diff --git a/app.rb b/app.rb
index ff7740c..6b11d5d 100644
--- a/app.rb
+++ b/app.rb
@@ -37,6 +37,7 @@ configure do
set :bind, '127.0.0.1'
set :port, 4567
set :logging, true
+ Rack::Utils.multipart_part_limit = 2000 # default 128; allow bulk photo uploads
end
configure :production do
@@ -478,9 +479,13 @@ end
post '/admin/update' do
require_admin!
rel = params[:rel].to_s.chomp('/')
+ force = params[:force].to_s == '1'
job_id = SecureRandom.hex(8)
script = File.join(__dir__, 'scripts', 'update.rb')
- cmd = rel.empty? ? ['ruby', script] : ['ruby', script, rel]
+ args = []
+ args << '--force' if force
+ args << rel unless rel.empty?
+ cmd = ['ruby', script, *args]
UPDATE_JOBS_MUTEX.synchronize do
UPDATE_JOBS[job_id] = { status: :running, lines: [] }
@@ -515,6 +520,71 @@ get '/admin/update/:id' do
{ status: job[:status], lines: job[:lines] }.to_json
end
+post '/admin/upload' do
+ require_admin!
+
+ rel = params['rel'].to_s.chomp('/')
+
+ sub_name = params['new_album_name'].to_s.strip
+ sub_name = '' if sub_name.match?(%r{[/\x00]}) || %w[. ..].include?(sub_name)
+
+ target_rel = if !sub_name.empty?
+ rel.empty? ? sub_name : "#{rel}/#{sub_name}"
+ else
+ rel
+ end
+
+ target_dir = if target_rel.empty?
+ MEDIA_ROOT
+ else
+ full = File.expand_path(target_rel, MEDIA_ROOT)
+ halt 400, 'Invalid path' unless full.start_with?("#{MEDIA_ROOT}/")
+ full
+ end
+
+ FileUtils.mkdir_p(target_dir)
+
+ files = params['files[]'] || params['files']
+ files = [files] unless files.is_a?(Array)
+ files = files.compact
+
+ saved = 0
+ files.each do |f|
+ next unless f.is_a?(Hash) && f[:filename].to_s.strip != ''
+ name = File.basename(f[:filename].to_s.encode('UTF-8', invalid: :replace, undef: :replace).gsub("\x00", ''))
+ next if name.empty?
+ ext = File.extname(name).downcase.delete_prefix('.')
+ next unless MEDIA_EXTS.include?(ext)
+ dest = File.join(target_dir, name)
+ FileUtils.cp(f[:tempfile].path, dest)
+ saved += 1
+ end
+
+ job_id = SecureRandom.hex(8)
+ script = File.join(__dir__, 'scripts', 'update.rb')
+ cmd = target_rel.empty? ? ['ruby', script] : ['ruby', script, target_rel]
+
+ UPDATE_JOBS_MUTEX.synchronize { UPDATE_JOBS[job_id] = { status: :running, lines: [] } }
+
+ Thread.new do
+ begin
+ IO.popen(cmd, err: [:child, :out]) do |io|
+ io.each_line { |line| UPDATE_JOBS_MUTEX.synchronize { UPDATE_JOBS[job_id][:lines] << line.chomp } }
+ end
+ code = $?.exitstatus
+ UPDATE_JOBS_MUTEX.synchronize { UPDATE_JOBS[job_id][:status] = code.zero? ? :done : :error }
+ rescue => e
+ UPDATE_JOBS_MUTEX.synchronize do
+ UPDATE_JOBS[job_id][:status] = :error
+ UPDATE_JOBS[job_id][:lines] << "Error: #{e.message}"
+ end
+ end
+ end
+
+ content_type :json
+ { job_id: job_id, saved: saved, album_rel: target_rel }.to_json
+end
+
# ── Thumbnail generation ───────────────────────────────────────────────────────
def generate_thumb(source, dest, ext)