Merge pull request #4764 from tgxworld/nuke_backticks
FIX: Don't use backticks that take in inputs.
This commit is contained in:
commit
f5f54c1b77
|
@ -81,7 +81,8 @@ class UploadsController < ApplicationController
|
||||||
if filename == "image.png" && SiteSetting.convert_pasted_images_to_hq_jpg
|
if filename == "image.png" && SiteSetting.convert_pasted_images_to_hq_jpg
|
||||||
jpeg_path = "#{File.dirname(tempfile.path)}/image.jpg"
|
jpeg_path = "#{File.dirname(tempfile.path)}/image.jpg"
|
||||||
OptimizedImage.ensure_safe_paths!(tempfile.path, jpeg_path)
|
OptimizedImage.ensure_safe_paths!(tempfile.path, jpeg_path)
|
||||||
`convert #{tempfile.path} -quality #{SiteSetting.convert_pasted_images_quality} #{jpeg_path}`
|
|
||||||
|
Discourse::Utils.execute_command('convert', tempfile.path, '-quality', SiteSetting.convert_pasted_images_quality.to_s, jpeg_path)
|
||||||
# only change the format of the image when JPG is at least 5% smaller
|
# only change the format of the image when JPG is at least 5% smaller
|
||||||
if File.size(jpeg_path) < File.size(tempfile.path) * 0.95
|
if File.size(jpeg_path) < File.size(tempfile.path) * 0.95
|
||||||
filename = "image.jpg"
|
filename = "image.jpg"
|
||||||
|
|
|
@ -215,8 +215,7 @@ class OptimizedImage < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.convert_with(instructions, to)
|
def self.convert_with(instructions, to)
|
||||||
`#{instructions.join(" ")} &> /dev/null`
|
return false unless system(instructions.join(" "), '&> /dev/null')
|
||||||
return false if $?.exitstatus != 0
|
|
||||||
|
|
||||||
ImageOptim.new.optimize_image!(to)
|
ImageOptim.new.optimize_image!(to)
|
||||||
true
|
true
|
||||||
|
|
|
@ -253,7 +253,7 @@ class Upload < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.fix_image_orientation(path)
|
def self.fix_image_orientation(path)
|
||||||
`convert #{path} -auto-orient #{path}`
|
Discourse::Utils.execute_command('convert', path, '-auto-orient', path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.migrate_to_new_scheme(limit=nil)
|
def self.migrate_to_new_scheme(limit=nil)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
require "backup_restore/utils"
|
|
||||||
require "backup_restore/backuper"
|
require "backup_restore/backuper"
|
||||||
require "backup_restore/restorer"
|
require "backup_restore/restorer"
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
module BackupRestore
|
module BackupRestore
|
||||||
|
|
||||||
class Backuper
|
class Backuper
|
||||||
include BackupRestore::Utils
|
|
||||||
|
|
||||||
attr_reader :success
|
attr_reader :success
|
||||||
|
|
||||||
def initialize(user_id, opts={})
|
def initialize(user_id, opts={})
|
||||||
|
@ -198,7 +196,7 @@ module BackupRestore
|
||||||
def move_dump_backup
|
def move_dump_backup
|
||||||
log "Finalizing database dump file: #{@backup_filename}"
|
log "Finalizing database dump file: #{@backup_filename}"
|
||||||
|
|
||||||
execute_command(
|
Discourse::Utils.execute_command(
|
||||||
'mv', @dump_filename, File.join(@archive_directory, @backup_filename),
|
'mv', @dump_filename, File.join(@archive_directory, @backup_filename),
|
||||||
failure_message: "Failed to move database dump file."
|
failure_message: "Failed to move database dump file."
|
||||||
)
|
)
|
||||||
|
@ -212,15 +210,15 @@ module BackupRestore
|
||||||
tar_filename = "#{@archive_basename}.tar"
|
tar_filename = "#{@archive_basename}.tar"
|
||||||
|
|
||||||
log "Making sure archive does not already exist..."
|
log "Making sure archive does not already exist..."
|
||||||
execute_command('rm', '-f', tar_filename)
|
Discourse::Utils.execute_command('rm', '-f', tar_filename)
|
||||||
execute_command('rm', '-f', "#{tar_filename}.gz")
|
Discourse::Utils.execute_command('rm', '-f', "#{tar_filename}.gz")
|
||||||
|
|
||||||
log "Creating empty archive..."
|
log "Creating empty archive..."
|
||||||
execute_command('tar', '--create', '--file', tar_filename, '--files-from', '/dev/null')
|
Discourse::Utils.execute_command('tar', '--create', '--file', tar_filename, '--files-from', '/dev/null')
|
||||||
|
|
||||||
log "Archiving data dump..."
|
log "Archiving data dump..."
|
||||||
FileUtils.cd(File.dirname(@dump_filename)) do
|
FileUtils.cd(File.dirname(@dump_filename)) do
|
||||||
execute_command(
|
Discourse::Utils.execute_command(
|
||||||
'tar', '--append', '--dereference', '--file', tar_filename, File.basename(@dump_filename),
|
'tar', '--append', '--dereference', '--file', tar_filename, File.basename(@dump_filename),
|
||||||
failure_message: "Failed to archive data dump."
|
failure_message: "Failed to archive data dump."
|
||||||
)
|
)
|
||||||
|
@ -231,7 +229,7 @@ module BackupRestore
|
||||||
log "Archiving uploads..."
|
log "Archiving uploads..."
|
||||||
FileUtils.cd(File.join(Rails.root, "public")) do
|
FileUtils.cd(File.join(Rails.root, "public")) do
|
||||||
if File.directory?(upload_directory)
|
if File.directory?(upload_directory)
|
||||||
execute_command(
|
Discourse::Utils.execute_command(
|
||||||
'tar', '--append', '--dereference', '--file', tar_filename, upload_directory,
|
'tar', '--append', '--dereference', '--file', tar_filename, upload_directory,
|
||||||
failure_message: "Failed to archive uploads."
|
failure_message: "Failed to archive uploads."
|
||||||
)
|
)
|
||||||
|
@ -243,7 +241,7 @@ module BackupRestore
|
||||||
remove_tmp_directory
|
remove_tmp_directory
|
||||||
|
|
||||||
log "Gzipping archive, this may take a while..."
|
log "Gzipping archive, this may take a while..."
|
||||||
execute_command('gzip', '-5', tar_filename, failure_message: "Failed to gzip archive.")
|
Discourse::Utils.execute_command('gzip', '-5', tar_filename, failure_message: "Failed to gzip archive.")
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_create_hook
|
def after_create_hook
|
||||||
|
@ -259,11 +257,11 @@ module BackupRestore
|
||||||
|
|
||||||
def notify_user
|
def notify_user
|
||||||
log "Notifying '#{@user.username}' of the end of the backup..."
|
log "Notifying '#{@user.username}' of the end of the backup..."
|
||||||
if @success
|
status = @success ? :backup_succeeded : :backup_failed
|
||||||
SystemMessage.create_from_system_user(@user, :backup_succeeded, logs: pretty_logs(@logs))
|
|
||||||
else
|
SystemMessage.create_from_system_user(@user, status,
|
||||||
SystemMessage.create_from_system_user(@user, :backup_failed, logs: pretty_logs(@logs))
|
logs: Discouse::Utils.pretty_logs(@logs)
|
||||||
end
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def clean_up
|
def clean_up
|
||||||
|
|
|
@ -6,8 +6,6 @@ module BackupRestore
|
||||||
class FilenameMissingError < RuntimeError; end
|
class FilenameMissingError < RuntimeError; end
|
||||||
|
|
||||||
class Restorer
|
class Restorer
|
||||||
include BackupRestore::Utils
|
|
||||||
|
|
||||||
attr_reader :success
|
attr_reader :success
|
||||||
|
|
||||||
def initialize(user_id, opts={})
|
def initialize(user_id, opts={})
|
||||||
|
@ -166,7 +164,7 @@ module BackupRestore
|
||||||
|
|
||||||
def copy_archive_to_tmp_directory
|
def copy_archive_to_tmp_directory
|
||||||
log "Copying archive to tmp directory..."
|
log "Copying archive to tmp directory..."
|
||||||
execute_command('cp', @source_filename, @archive_filename, failure_message: "Failed to copy archive to tmp directory.")
|
Discourse::Utils.execute_command('cp', @source_filename, @archive_filename, failure_message: "Failed to copy archive to tmp directory.")
|
||||||
end
|
end
|
||||||
|
|
||||||
def unzip_archive
|
def unzip_archive
|
||||||
|
@ -175,7 +173,7 @@ module BackupRestore
|
||||||
log "Unzipping archive, this may take a while..."
|
log "Unzipping archive, this may take a while..."
|
||||||
|
|
||||||
FileUtils.cd(@tmp_directory) do
|
FileUtils.cd(@tmp_directory) do
|
||||||
execute_command('gzip', '--decompress', @archive_filename, failure_message: "Failed to unzip archive.")
|
Discourse::Utils.execute_command('gzip', '--decompress', @archive_filename, failure_message: "Failed to unzip archive.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -185,7 +183,7 @@ module BackupRestore
|
||||||
@metadata =
|
@metadata =
|
||||||
if system('tar', '--list', '--file', @tar_filename, BackupRestore::METADATA_FILE)
|
if system('tar', '--list', '--file', @tar_filename, BackupRestore::METADATA_FILE)
|
||||||
FileUtils.cd(@tmp_directory) do
|
FileUtils.cd(@tmp_directory) do
|
||||||
execute_command(
|
Discourse::Utils.execute_command(
|
||||||
'tar', '--extract', '--file', @tar_filename, BackupRestore::METADATA_FILE,
|
'tar', '--extract', '--file', @tar_filename, BackupRestore::METADATA_FILE,
|
||||||
failure_message: "Failed to extract metadata file."
|
failure_message: "Failed to extract metadata file."
|
||||||
)
|
)
|
||||||
|
@ -233,7 +231,7 @@ module BackupRestore
|
||||||
log "Extracting dump file..."
|
log "Extracting dump file..."
|
||||||
|
|
||||||
FileUtils.cd(@tmp_directory) do
|
FileUtils.cd(@tmp_directory) do
|
||||||
execute_command(
|
Discourse::Utils.execute_command(
|
||||||
'tar', '--extract', '--file', @tar_filename, File.basename(@dump_filename),
|
'tar', '--extract', '--file', @tar_filename, File.basename(@dump_filename),
|
||||||
failure_message: "Failed to extract dump file."
|
failure_message: "Failed to extract dump file."
|
||||||
)
|
)
|
||||||
|
@ -364,7 +362,7 @@ module BackupRestore
|
||||||
log "Extracting uploads..."
|
log "Extracting uploads..."
|
||||||
|
|
||||||
FileUtils.cd(@tmp_directory) do
|
FileUtils.cd(@tmp_directory) do
|
||||||
execute_command(
|
Discourse::Utils.execute_command(
|
||||||
'tar', '--extract', '--keep-newer-files', '--file', @tar_filename, 'uploads/',
|
'tar', '--extract', '--keep-newer-files', '--file', @tar_filename, 'uploads/',
|
||||||
failure_message: "Failed to extract uploads."
|
failure_message: "Failed to extract uploads."
|
||||||
)
|
)
|
||||||
|
@ -379,7 +377,7 @@ module BackupRestore
|
||||||
previous_db_name = File.basename(tmp_uploads_path)
|
previous_db_name = File.basename(tmp_uploads_path)
|
||||||
current_db_name = RailsMultisite::ConnectionManagement.current_db
|
current_db_name = RailsMultisite::ConnectionManagement.current_db
|
||||||
|
|
||||||
execute_command(
|
Discourse::Utils.execute_command(
|
||||||
'rsync', '-avp', '--safe-links', "#{tmp_uploads_path}/", "uploads/#{current_db_name}/",
|
'rsync', '-avp', '--safe-links', "#{tmp_uploads_path}/", "uploads/#{current_db_name}/",
|
||||||
failure_message: "Failed to restore uploads."
|
failure_message: "Failed to restore uploads."
|
||||||
)
|
)
|
||||||
|
@ -404,11 +402,11 @@ module BackupRestore
|
||||||
def notify_user
|
def notify_user
|
||||||
if user = User.find_by(email: @user_info[:email])
|
if user = User.find_by(email: @user_info[:email])
|
||||||
log "Notifying '#{user.username}' of the end of the restore..."
|
log "Notifying '#{user.username}' of the end of the restore..."
|
||||||
if @success
|
status = @success ? :restore_succeeded : :restore_failed
|
||||||
SystemMessage.create_from_system_user(user, :restore_succeeded, logs: pretty_logs(@logs))
|
|
||||||
else
|
SystemMessage.create_from_system_user(user, status,
|
||||||
SystemMessage.create_from_system_user(user, :restore_failed, logs: pretty_logs(@logs))
|
logs: Discourse::Utils.pretty_logs(@logs)
|
||||||
end
|
)
|
||||||
else
|
else
|
||||||
log "Could not send notification to '#{@user_info[:username]}' (#{@user_info[:email]}), because the user does not exists..."
|
log "Could not send notification to '#{@user_info[:username]}' (#{@user_info[:email]}), because the user does not exists..."
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
require 'open3'
|
|
||||||
|
|
||||||
module BackupRestore
|
|
||||||
module Utils
|
|
||||||
def execute_command(*command, failure_message: "")
|
|
||||||
stdout, stderr, status = Open3.capture3(*command)
|
|
||||||
|
|
||||||
if !status.success?
|
|
||||||
failure_message = "#{failure_message}\n" if !failure_message.blank?
|
|
||||||
raise "#{failure_message}#{stderr}"
|
|
||||||
end
|
|
||||||
|
|
||||||
stdout
|
|
||||||
end
|
|
||||||
|
|
||||||
def pretty_logs(logs)
|
|
||||||
logs.join("\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,4 +1,5 @@
|
||||||
require 'cache'
|
require 'cache'
|
||||||
|
require 'open3'
|
||||||
require_dependency 'plugin/instance'
|
require_dependency 'plugin/instance'
|
||||||
require_dependency 'auth/default_current_user_provider'
|
require_dependency 'auth/default_current_user_provider'
|
||||||
require_dependency 'version'
|
require_dependency 'version'
|
||||||
|
@ -16,6 +17,23 @@ module Discourse
|
||||||
extend Sidekiq::ExceptionHandler
|
extend Sidekiq::ExceptionHandler
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class Utils
|
||||||
|
def self.execute_command(*command, failure_message: "")
|
||||||
|
stdout, stderr, status = Open3.capture3(*command)
|
||||||
|
|
||||||
|
if !status.success?
|
||||||
|
failure_message = "#{failure_message}\n" if !failure_message.blank?
|
||||||
|
raise "#{failure_message}#{stderr}"
|
||||||
|
end
|
||||||
|
|
||||||
|
stdout
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.pretty_logs(logs)
|
||||||
|
logs.join("\n".freeze)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Log an exception.
|
# Log an exception.
|
||||||
#
|
#
|
||||||
# If your code is in a scheduled job, it is recommended to use the
|
# If your code is in a scheduled job, it is recommended to use the
|
||||||
|
|
|
@ -59,7 +59,7 @@ module FileStore
|
||||||
end
|
end
|
||||||
|
|
||||||
def purge_tombstone(grace_period)
|
def purge_tombstone(grace_period)
|
||||||
`find #{tombstone_dir} -mtime +#{grace_period} -type f -delete`
|
Discourse::Utils.execute_command('find', tombstone_dir, '-mtime', "+#{grace_period}", '-type f -delete')
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_path_for(type, upload_id, sha, extension)
|
def get_path_for(type, upload_id, sha, extension)
|
||||||
|
|
|
@ -82,7 +82,7 @@ class LetterAvatar
|
||||||
'#{filename}'
|
'#{filename}'
|
||||||
}
|
}
|
||||||
|
|
||||||
`convert #{instructions.join(" ")}`
|
Discourse::Utils.execute_command('convert', instructions.join(" ".freeze))
|
||||||
|
|
||||||
## do not optimize image, it will end up larger than original
|
## do not optimize image, it will end up larger than original
|
||||||
filename
|
filename
|
||||||
|
|
|
@ -356,11 +356,12 @@ JS
|
||||||
public_data = File.dirname(path) + "/public"
|
public_data = File.dirname(path) + "/public"
|
||||||
if Dir.exists?(public_data)
|
if Dir.exists?(public_data)
|
||||||
target = Rails.root.to_s + "/public/plugins/"
|
target = Rails.root.to_s + "/public/plugins/"
|
||||||
`mkdir -p #{target}`
|
|
||||||
|
Discourse::Utils.execute_command('mkdir', '-p', target)
|
||||||
target << name.gsub(/\s/,"_")
|
target << name.gsub(/\s/,"_")
|
||||||
# TODO a cleaner way of registering and unregistering
|
# TODO a cleaner way of registering and unregistering
|
||||||
`rm -f #{target}`
|
Discourse::Utils.execute_command('rm', '-f', target)
|
||||||
`ln -s #{public_data} #{target}`
|
Discourse::Utils.execute_command('ln', '-s', public_data, target)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue