summaryrefslogtreecommitdiff
path: root/lib/uploaded_file.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/uploaded_file.rb')
-rw-r--r--lib/uploaded_file.rb40
1 files changed, 37 insertions, 3 deletions
diff --git a/lib/uploaded_file.rb b/lib/uploaded_file.rb
index 4a3c40f88eb..5dc85b2baea 100644
--- a/lib/uploaded_file.rb
+++ b/lib/uploaded_file.rb
@@ -1,8 +1,10 @@
require "tempfile"
+require "tmpdir"
require "fileutils"
-# Taken from: Rack::Test::UploadedFile
class UploadedFile
+ InvalidPathError = Class.new(StandardError)
+
# The filename, *not* including the path, of the "uploaded" file
attr_reader :original_filename
@@ -12,14 +14,46 @@ class UploadedFile
# The content type of the "uploaded" file
attr_accessor :content_type
- def initialize(path, filename, content_type = "text/plain")
- raise "#{path} file does not exist" unless ::File.exist?(path)
+ attr_reader :remote_id
+ attr_reader :sha256
+
+ def initialize(path, filename: nil, content_type: "application/octet-stream", sha256: nil, remote_id: nil)
+ raise InvalidPathError, "#{path} file does not exist" unless ::File.exist?(path)
@content_type = content_type
@original_filename = filename || ::File.basename(path)
+ @content_type = content_type
+ @sha256 = sha256
+ @remote_id = remote_id
@tempfile = File.new(path, 'rb')
end
+ def self.from_params(params, field, upload_path)
+ unless params["#{field}.path"]
+ raise InvalidPathError, "file is invalid" if params["#{field}.remote_id"]
+
+ return
+ end
+
+ file_path = File.realpath(params["#{field}.path"])
+
+ unless self.allowed_path?(file_path, [upload_path, Dir.tmpdir].compact)
+ raise InvalidPathError, "insecure path used '#{file_path}'"
+ end
+
+ UploadedFile.new(file_path,
+ filename: params["#{field}.name"],
+ content_type: params["#{field}.type"] || 'application/octet-stream',
+ sha256: params["#{field}.sha256"],
+ remote_id: params["#{field}.remote_id"])
+ end
+
+ def self.allowed_path?(file_path, paths)
+ paths.any? do |path|
+ File.exist?(path) && file_path.start_with?(File.realpath(path))
+ end
+ end
+
def path
@tempfile.path
end