kt-paperclip 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.codeclimate.yml +17 -0
- data/.github/issue_template.md +3 -0
- data/.gitignore +19 -0
- data/.hound.yml +1050 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +47 -0
- data/Appraisals +24 -0
- data/CONTRIBUTING.md +86 -0
- data/Gemfile +18 -0
- data/LICENSE +24 -0
- data/NEWS +515 -0
- data/README.md +1053 -0
- data/RELEASING.md +17 -0
- data/Rakefile +52 -0
- data/UPGRADING +17 -0
- data/features/basic_integration.feature +85 -0
- data/features/migration.feature +29 -0
- data/features/rake_tasks.feature +62 -0
- data/features/step_definitions/attachment_steps.rb +110 -0
- data/features/step_definitions/html_steps.rb +15 -0
- data/features/step_definitions/rails_steps.rb +257 -0
- data/features/step_definitions/s3_steps.rb +14 -0
- data/features/step_definitions/web_steps.rb +106 -0
- data/features/support/env.rb +12 -0
- data/features/support/fakeweb.rb +11 -0
- data/features/support/file_helpers.rb +34 -0
- data/features/support/fixtures/boot_config.txt +15 -0
- data/features/support/fixtures/gemfile.txt +5 -0
- data/features/support/fixtures/preinitializer.txt +20 -0
- data/features/support/paths.rb +28 -0
- data/features/support/rails.rb +39 -0
- data/features/support/selectors.rb +19 -0
- data/gemfiles/4.2.gemfile +20 -0
- data/gemfiles/5.0.gemfile +20 -0
- data/gemfiles/5.1.gemfile +20 -0
- data/gemfiles/5.2.gemfile +20 -0
- data/gemfiles/6.0.gemfile +20 -0
- data/lib/generators/paperclip/USAGE +8 -0
- data/lib/generators/paperclip/paperclip_generator.rb +36 -0
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
- data/lib/paperclip.rb +215 -0
- data/lib/paperclip/attachment.rb +617 -0
- data/lib/paperclip/attachment_registry.rb +60 -0
- data/lib/paperclip/callbacks.rb +42 -0
- data/lib/paperclip/content_type_detector.rb +80 -0
- data/lib/paperclip/errors.rb +34 -0
- data/lib/paperclip/file_command_content_type_detector.rb +28 -0
- data/lib/paperclip/filename_cleaner.rb +15 -0
- data/lib/paperclip/geometry.rb +157 -0
- data/lib/paperclip/geometry_detector_factory.rb +45 -0
- data/lib/paperclip/geometry_parser_factory.rb +31 -0
- data/lib/paperclip/glue.rb +17 -0
- data/lib/paperclip/has_attached_file.rb +116 -0
- data/lib/paperclip/helpers.rb +60 -0
- data/lib/paperclip/interpolations.rb +201 -0
- data/lib/paperclip/interpolations/plural_cache.rb +18 -0
- data/lib/paperclip/io_adapters/abstract_adapter.rb +75 -0
- data/lib/paperclip/io_adapters/attachment_adapter.rb +47 -0
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
- data/lib/paperclip/io_adapters/empty_string_adapter.rb +19 -0
- data/lib/paperclip/io_adapters/file_adapter.rb +26 -0
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
- data/lib/paperclip/io_adapters/identity_adapter.rb +17 -0
- data/lib/paperclip/io_adapters/nil_adapter.rb +37 -0
- data/lib/paperclip/io_adapters/registry.rb +36 -0
- data/lib/paperclip/io_adapters/stringio_adapter.rb +36 -0
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +44 -0
- data/lib/paperclip/io_adapters/uri_adapter.rb +68 -0
- data/lib/paperclip/locales/en.yml +18 -0
- data/lib/paperclip/logger.rb +21 -0
- data/lib/paperclip/matchers.rb +64 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +101 -0
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +97 -0
- data/lib/paperclip/media_type_spoof_detector.rb +90 -0
- data/lib/paperclip/missing_attachment_styles.rb +84 -0
- data/lib/paperclip/processor.rb +56 -0
- data/lib/paperclip/processor_helpers.rb +52 -0
- data/lib/paperclip/rails_environment.rb +21 -0
- data/lib/paperclip/railtie.rb +31 -0
- data/lib/paperclip/schema.rb +81 -0
- data/lib/paperclip/storage.rb +3 -0
- data/lib/paperclip/storage/filesystem.rb +99 -0
- data/lib/paperclip/storage/fog.rb +252 -0
- data/lib/paperclip/storage/s3.rb +461 -0
- data/lib/paperclip/style.rb +106 -0
- data/lib/paperclip/tempfile.rb +42 -0
- data/lib/paperclip/tempfile_factory.rb +22 -0
- data/lib/paperclip/thumbnail.rb +131 -0
- data/lib/paperclip/url_generator.rb +76 -0
- data/lib/paperclip/validators.rb +73 -0
- data/lib/paperclip/validators/attachment_content_type_validator.rb +88 -0
- data/lib/paperclip/validators/attachment_file_name_validator.rb +75 -0
- data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +28 -0
- data/lib/paperclip/validators/attachment_presence_validator.rb +28 -0
- data/lib/paperclip/validators/attachment_size_validator.rb +109 -0
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +29 -0
- data/lib/paperclip/version.rb +3 -0
- data/lib/tasks/paperclip.rake +140 -0
- data/paperclip.gemspec +50 -0
- data/shoulda_macros/paperclip.rb +134 -0
- data/spec/database.yml +4 -0
- data/spec/paperclip/attachment_definitions_spec.rb +13 -0
- data/spec/paperclip/attachment_processing_spec.rb +79 -0
- data/spec/paperclip/attachment_registry_spec.rb +158 -0
- data/spec/paperclip/attachment_spec.rb +1590 -0
- data/spec/paperclip/content_type_detector_spec.rb +47 -0
- data/spec/paperclip/file_command_content_type_detector_spec.rb +40 -0
- data/spec/paperclip/filename_cleaner_spec.rb +13 -0
- data/spec/paperclip/geometry_detector_spec.rb +38 -0
- data/spec/paperclip/geometry_parser_spec.rb +73 -0
- data/spec/paperclip/geometry_spec.rb +255 -0
- data/spec/paperclip/glue_spec.rb +42 -0
- data/spec/paperclip/has_attached_file_spec.rb +78 -0
- data/spec/paperclip/integration_spec.rb +702 -0
- data/spec/paperclip/interpolations_spec.rb +270 -0
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +160 -0
- data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +140 -0
- data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +88 -0
- data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +131 -0
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +137 -0
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
- data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
- data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +221 -0
- data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +108 -0
- data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
- data/spec/paperclip/media_type_spoof_detector_spec.rb +120 -0
- data/spec/paperclip/meta_class_spec.rb +30 -0
- data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +88 -0
- data/spec/paperclip/paperclip_spec.rb +196 -0
- data/spec/paperclip/plural_cache_spec.rb +37 -0
- data/spec/paperclip/processor_helpers_spec.rb +57 -0
- data/spec/paperclip/processor_spec.rb +26 -0
- data/spec/paperclip/rails_environment_spec.rb +30 -0
- data/spec/paperclip/rake_spec.rb +103 -0
- data/spec/paperclip/schema_spec.rb +252 -0
- data/spec/paperclip/storage/filesystem_spec.rb +79 -0
- data/spec/paperclip/storage/fog_spec.rb +560 -0
- data/spec/paperclip/storage/s3_live_spec.rb +188 -0
- data/spec/paperclip/storage/s3_spec.rb +1695 -0
- data/spec/paperclip/style_spec.rb +251 -0
- data/spec/paperclip/tempfile_factory_spec.rb +33 -0
- data/spec/paperclip/tempfile_spec.rb +35 -0
- data/spec/paperclip/thumbnail_spec.rb +504 -0
- data/spec/paperclip/url_generator_spec.rb +221 -0
- data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
- data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +159 -0
- data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +235 -0
- data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +48 -0
- data/spec/paperclip/validators_spec.rb +164 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/support/assertions.rb +84 -0
- data/spec/support/fake_model.rb +24 -0
- data/spec/support/fake_rails.rb +12 -0
- data/spec/support/fixtures/12k.png +0 -0
- data/spec/support/fixtures/50x50.png +0 -0
- data/spec/support/fixtures/5k.png +0 -0
- data/spec/support/fixtures/animated +0 -0
- data/spec/support/fixtures/animated.gif +0 -0
- data/spec/support/fixtures/animated.unknown +0 -0
- data/spec/support/fixtures/bad.png +1 -0
- data/spec/support/fixtures/empty.html +1 -0
- data/spec/support/fixtures/empty.xlsx +0 -0
- data/spec/support/fixtures/fog.yml +8 -0
- data/spec/support/fixtures/rotated.jpg +0 -0
- data/spec/support/fixtures/s3.yml +8 -0
- data/spec/support/fixtures/spaced file.jpg +0 -0
- data/spec/support/fixtures/spaced file.png +0 -0
- data/spec/support/fixtures/text.txt +1 -0
- data/spec/support/fixtures/twopage.pdf +0 -0
- data/spec/support/fixtures/uppercase.PNG +0 -0
- data/spec/support/matchers/accept.rb +5 -0
- data/spec/support/matchers/exist.rb +5 -0
- data/spec/support/matchers/have_column.rb +23 -0
- data/spec/support/mock_attachment.rb +24 -0
- data/spec/support/mock_interpolator.rb +24 -0
- data/spec/support/mock_url_generator_builder.rb +26 -0
- data/spec/support/model_reconstruction.rb +72 -0
- data/spec/support/reporting.rb +11 -0
- data/spec/support/test_data.rb +13 -0
- data/spec/support/version_helper.rb +9 -0
- metadata +586 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
require "active_support/core_ext/module/delegation"
|
2
|
+
|
3
|
+
module Paperclip
|
4
|
+
class AbstractAdapter
|
5
|
+
OS_RESTRICTED_CHARACTERS = %r{[/:]}.freeze
|
6
|
+
|
7
|
+
attr_reader :content_type, :original_filename, :size, :tempfile
|
8
|
+
delegate :binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :readbyte, :rewind, :unlink, to: :@tempfile
|
9
|
+
alias :length :size
|
10
|
+
|
11
|
+
def initialize(target, options = {})
|
12
|
+
@target = target
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def fingerprint
|
17
|
+
@fingerprint ||= begin
|
18
|
+
digest = @options.fetch(:hash_digest).new
|
19
|
+
File.open(path, "rb") do |f|
|
20
|
+
buf = ""
|
21
|
+
digest.update(buf) while f.read(16384, buf)
|
22
|
+
end
|
23
|
+
digest.hexdigest
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def read(length = nil, buffer = nil)
|
28
|
+
@tempfile.read(length, buffer)
|
29
|
+
end
|
30
|
+
|
31
|
+
def inspect
|
32
|
+
"#{self.class}: #{original_filename}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def original_filename=(new_filename)
|
36
|
+
return unless new_filename
|
37
|
+
|
38
|
+
@original_filename = new_filename.gsub(OS_RESTRICTED_CHARACTERS, "_")
|
39
|
+
end
|
40
|
+
|
41
|
+
def nil?
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
def assignment?
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def destination
|
52
|
+
@destination ||= TempfileFactory.new.generate(@original_filename.to_s)
|
53
|
+
end
|
54
|
+
|
55
|
+
def copy_to_tempfile(src)
|
56
|
+
link_or_copy_file(src.path, destination.path)
|
57
|
+
destination
|
58
|
+
end
|
59
|
+
|
60
|
+
def link_or_copy_file(src, dest)
|
61
|
+
begin
|
62
|
+
Paperclip.log("Trying to link #{src} to #{dest}")
|
63
|
+
FileUtils.ln(src, dest, force: true) # overwrite existing
|
64
|
+
rescue Errno::EXDEV, Errno::EPERM, Errno::ENOENT, Errno::EEXIST => e
|
65
|
+
Paperclip.log(
|
66
|
+
"Link failed with #{e.message}; copying link #{src} to #{dest}"
|
67
|
+
)
|
68
|
+
FileUtils.cp(src, dest)
|
69
|
+
end
|
70
|
+
|
71
|
+
@destination.close
|
72
|
+
@destination.open.binmode
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class AttachmentAdapter < AbstractAdapter
|
3
|
+
def self.register
|
4
|
+
Paperclip.io_adapters.register self do |target|
|
5
|
+
Paperclip::Attachment === target || Paperclip::Style === target
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(target, options = {})
|
10
|
+
super
|
11
|
+
@target, @style = case target
|
12
|
+
when Paperclip::Attachment
|
13
|
+
[target, :original]
|
14
|
+
when Paperclip::Style
|
15
|
+
[target.attachment, target.name]
|
16
|
+
end
|
17
|
+
|
18
|
+
cache_current_values
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def cache_current_values
|
24
|
+
self.original_filename = @target.original_filename
|
25
|
+
@content_type = @target.content_type
|
26
|
+
@tempfile = copy_to_tempfile(@target)
|
27
|
+
@size = @tempfile.size || @target.size
|
28
|
+
end
|
29
|
+
|
30
|
+
def copy_to_tempfile(source)
|
31
|
+
if source.staged?
|
32
|
+
link_or_copy_file(source.staged_path(@style), destination.path)
|
33
|
+
else
|
34
|
+
begin
|
35
|
+
source.copy_to_local_file(@style, destination.path)
|
36
|
+
rescue Errno::EACCES
|
37
|
+
# clean up lingering tempfile if we cannot access source file
|
38
|
+
destination.close(true)
|
39
|
+
raise
|
40
|
+
end
|
41
|
+
end
|
42
|
+
destination
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Paperclip::AttachmentAdapter.register
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class DataUriAdapter < StringioAdapter
|
3
|
+
def self.register
|
4
|
+
Paperclip.io_adapters.register self do |target|
|
5
|
+
String === target && target =~ REGEXP
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
REGEXP = /\Adata:([-\w]+\/[-\w\+\.]+)?;base64,(.*)/m.freeze
|
10
|
+
|
11
|
+
def initialize(target_uri, options = {})
|
12
|
+
super(extract_target(target_uri), options)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def extract_target(uri)
|
18
|
+
data_uri_parts = uri.match(REGEXP) || []
|
19
|
+
StringIO.new(Base64.decode64(data_uri_parts[2] || ""))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class EmptyStringAdapter < AbstractAdapter
|
3
|
+
def self.register
|
4
|
+
Paperclip.io_adapters.register self do |target|
|
5
|
+
target.is_a?(String) && target.empty?
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def nil?
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
def assignment?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Paperclip::EmptyStringAdapter.register
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class FileAdapter < AbstractAdapter
|
3
|
+
def self.register
|
4
|
+
Paperclip.io_adapters.register self do |target|
|
5
|
+
File === target || ::Tempfile === target
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(target, options = {})
|
10
|
+
super
|
11
|
+
cache_current_values
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def cache_current_values
|
17
|
+
self.original_filename = @target.original_filename if @target.respond_to?(:original_filename)
|
18
|
+
self.original_filename ||= File.basename(@target.path)
|
19
|
+
@tempfile = copy_to_tempfile(@target)
|
20
|
+
@content_type = ContentTypeDetector.new(@target.path).detect
|
21
|
+
@size = File.size(@target)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Paperclip::FileAdapter.register
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class HttpUrlProxyAdapter < UriAdapter
|
3
|
+
def self.register
|
4
|
+
Paperclip.io_adapters.register self do |target|
|
5
|
+
String === target && target =~ REGEXP
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
REGEXP = /\Ahttps?:\/\//.freeze
|
10
|
+
|
11
|
+
def initialize(target, options = {})
|
12
|
+
escaped = URI.escape(target)
|
13
|
+
super(URI(target == URI.unescape(target) ? escaped : target), options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class IdentityAdapter < AbstractAdapter
|
3
|
+
def self.register
|
4
|
+
Paperclip.io_adapters.register Paperclip::IdentityAdapter.new do |target|
|
5
|
+
Paperclip.io_adapters.registered?(target)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize; end
|
10
|
+
|
11
|
+
def new(target, _)
|
12
|
+
target
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Paperclip::IdentityAdapter.register
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class NilAdapter < AbstractAdapter
|
3
|
+
def self.register
|
4
|
+
Paperclip.io_adapters.register self do |target|
|
5
|
+
target.nil? || ((Paperclip::Attachment === target) && !target.present?)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(_target, _options = {}); end
|
10
|
+
|
11
|
+
def original_filename
|
12
|
+
""
|
13
|
+
end
|
14
|
+
|
15
|
+
def content_type
|
16
|
+
""
|
17
|
+
end
|
18
|
+
|
19
|
+
def size
|
20
|
+
0
|
21
|
+
end
|
22
|
+
|
23
|
+
def nil?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def read(*_args)
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def eof?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Paperclip::NilAdapter.register
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class AdapterRegistry
|
3
|
+
class NoHandlerError < Paperclip::Error; end
|
4
|
+
|
5
|
+
attr_reader :registered_handlers
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@registered_handlers = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def register(handler_class, &block)
|
12
|
+
@registered_handlers << [block, handler_class]
|
13
|
+
end
|
14
|
+
|
15
|
+
def unregister(handler_class)
|
16
|
+
@registered_handlers.reject! { |_, klass| klass == handler_class }
|
17
|
+
end
|
18
|
+
|
19
|
+
def handler_for(target)
|
20
|
+
@registered_handlers.each do |tester, handler|
|
21
|
+
return handler if tester.call(target)
|
22
|
+
end
|
23
|
+
raise NoHandlerError.new("No handler found for #{target.inspect}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def registered?(target)
|
27
|
+
@registered_handlers.any? do |_tester, handler|
|
28
|
+
handler === target
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def for(target, options = {})
|
33
|
+
handler_for(target).new(target, options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class StringioAdapter < AbstractAdapter
|
3
|
+
def self.register
|
4
|
+
Paperclip.io_adapters.register self do |target|
|
5
|
+
StringIO === target
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(target, options = {})
|
10
|
+
super
|
11
|
+
cache_current_values
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_writer :content_type
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def cache_current_values
|
19
|
+
self.original_filename = @target.original_filename if @target.respond_to?(:original_filename)
|
20
|
+
self.original_filename ||= "data"
|
21
|
+
@tempfile = copy_to_tempfile(@target)
|
22
|
+
@content_type = ContentTypeDetector.new(@tempfile.path).detect
|
23
|
+
@size = @target.size
|
24
|
+
end
|
25
|
+
|
26
|
+
def copy_to_tempfile(source)
|
27
|
+
while data = source.read(16 * 1024)
|
28
|
+
destination.write(data)
|
29
|
+
end
|
30
|
+
destination.rewind
|
31
|
+
destination
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Paperclip::StringioAdapter.register
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Paperclip
|
2
|
+
class UploadedFileAdapter < AbstractAdapter
|
3
|
+
def self.register
|
4
|
+
Paperclip.io_adapters.register self do |target|
|
5
|
+
target.class.name.include?("UploadedFile")
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(target, options = {})
|
10
|
+
super
|
11
|
+
cache_current_values
|
12
|
+
|
13
|
+
@tempfile = if @target.respond_to?(:tempfile)
|
14
|
+
copy_to_tempfile(@target.tempfile)
|
15
|
+
else
|
16
|
+
copy_to_tempfile(@target)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
attr_accessor :content_type_detector
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def cache_current_values
|
27
|
+
self.original_filename = @target.original_filename
|
28
|
+
@content_type = determine_content_type
|
29
|
+
@size = File.size(@target.path)
|
30
|
+
end
|
31
|
+
|
32
|
+
def content_type_detector
|
33
|
+
self.class.content_type_detector || Paperclip::ContentTypeDetector
|
34
|
+
end
|
35
|
+
|
36
|
+
def determine_content_type
|
37
|
+
content_type = @target.content_type.to_s.strip
|
38
|
+
content_type = content_type_detector.new(@target.path).detect if content_type_detector
|
39
|
+
content_type
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Paperclip::UploadedFileAdapter.register
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require "open-uri"
|
2
|
+
|
3
|
+
module Paperclip
|
4
|
+
class UriAdapter < AbstractAdapter
|
5
|
+
attr_writer :content_type
|
6
|
+
|
7
|
+
def self.register
|
8
|
+
Paperclip.io_adapters.register self do |target|
|
9
|
+
target.is_a?(URI)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(target, options = {})
|
14
|
+
super
|
15
|
+
@content = download_content
|
16
|
+
cache_current_values
|
17
|
+
@tempfile = copy_to_tempfile(@content)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def cache_current_values
|
23
|
+
self.content_type = content_type_from_content || "text/html"
|
24
|
+
|
25
|
+
self.original_filename = filename_from_content_disposition ||
|
26
|
+
filename_from_path || default_filename
|
27
|
+
@size = @content.size
|
28
|
+
end
|
29
|
+
|
30
|
+
def content_type_from_content
|
31
|
+
@content.meta["content-type"].presence
|
32
|
+
end
|
33
|
+
|
34
|
+
def filename_from_content_disposition
|
35
|
+
if @content.meta.key?("content-disposition") && @content.meta["content-disposition"].match(/filename/i)
|
36
|
+
# can include both filename and filename* values according to RCF6266. filename should come first
|
37
|
+
_, filename = @content.meta["content-disposition"].split(/filename\*?\s*=\s*/i)
|
38
|
+
|
39
|
+
# filename can be enclosed in quotes or not
|
40
|
+
matches = filename.match(/"(.*)"/)
|
41
|
+
matches ? matches[1] : filename.split(";")[0]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def filename_from_path
|
46
|
+
@target.path.split("/").last
|
47
|
+
end
|
48
|
+
|
49
|
+
def default_filename
|
50
|
+
"index.html"
|
51
|
+
end
|
52
|
+
|
53
|
+
def download_content
|
54
|
+
options = { read_timeout: Paperclip.options[:read_timeout] }.compact
|
55
|
+
|
56
|
+
open(@target, **options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def copy_to_tempfile(src)
|
60
|
+
while data = src.read(16 * 1024)
|
61
|
+
destination.write(data)
|
62
|
+
end
|
63
|
+
src.close
|
64
|
+
destination.rewind
|
65
|
+
destination
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|