dragonfly 0.9.15 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of dragonfly might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/.gitignore +1 -8
- data/.travis.yml +11 -0
- data/Gemfile +1 -0
- data/History.md +52 -2
- data/LICENSE +1 -1
- data/README.md +38 -95
- data/dev/grid.jpg +0 -0
- data/dev/irbrc.rb +27 -0
- data/dev/rails_template.rb +38 -0
- data/dev/test.ru +56 -0
- data/dev/test_rails +19 -0
- data/dragonfly.gemspec +3 -21
- data/lib/dragonfly.rb +45 -44
- data/lib/dragonfly/app.rb +175 -96
- data/lib/dragonfly/configurable.rb +71 -170
- data/lib/dragonfly/content.rb +211 -0
- data/lib/dragonfly/core_ext/object.rb +1 -6
- data/lib/dragonfly/file_data_store.rb +197 -0
- data/lib/dragonfly/image_magick/analysers/image_properties.rb +23 -0
- data/lib/dragonfly/image_magick/generators/convert.rb +19 -0
- data/lib/dragonfly/image_magick/generators/plain.rb +26 -0
- data/lib/dragonfly/image_magick/generators/plasma.rb +25 -0
- data/lib/dragonfly/image_magick/generators/text.rb +127 -0
- data/lib/dragonfly/image_magick/plugin.rb +83 -0
- data/lib/dragonfly/image_magick/processors/convert.rb +29 -0
- data/lib/dragonfly/image_magick/processors/encode.rb +18 -0
- data/lib/dragonfly/image_magick/processors/thumb.rb +76 -0
- data/lib/dragonfly/job.rb +118 -134
- data/lib/dragonfly/job_endpoint.rb +2 -0
- data/lib/dragonfly/memory_data_store.rb +34 -0
- data/lib/dragonfly/middleware.rb +5 -3
- data/lib/dragonfly/{active_model_extensions.rb → model.rb} +5 -3
- data/lib/dragonfly/{active_model_extensions → model}/attachment.rb +40 -35
- data/lib/dragonfly/{active_model_extensions → model}/attachment_class_methods.rb +36 -40
- data/lib/dragonfly/model/class_methods.rb +109 -0
- data/lib/dragonfly/{active_model_extensions → model}/instance_methods.rb +2 -2
- data/lib/dragonfly/{active_model_extensions → model}/validations.rb +17 -12
- data/lib/dragonfly/railtie.rb +8 -6
- data/lib/dragonfly/register.rb +27 -0
- data/lib/dragonfly/response.rb +47 -52
- data/lib/dragonfly/routed_endpoint.rb +4 -0
- data/lib/dragonfly/serializer.rb +15 -5
- data/lib/dragonfly/server.rb +56 -29
- data/lib/dragonfly/shell.rb +12 -23
- data/lib/dragonfly/spec/data_store_examples.rb +64 -0
- data/lib/dragonfly/temp_object.rb +32 -47
- data/lib/dragonfly/url_attributes.rb +19 -22
- data/lib/dragonfly/url_mapper.rb +3 -0
- data/lib/dragonfly/utils.rb +12 -0
- data/lib/dragonfly/version.rb +1 -1
- data/lib/dragonfly/whitelist.rb +19 -0
- data/lib/rails/generators/dragonfly/USAGE +8 -0
- data/lib/rails/generators/dragonfly/dragonfly_generator.rb +24 -0
- data/lib/rails/generators/dragonfly/templates/initializer.rb.erb +27 -0
- data/samples/gif.gif +0 -0
- data/spec/dragonfly/app_spec.rb +270 -64
- data/spec/dragonfly/configurable_spec.rb +142 -418
- data/spec/dragonfly/content_spec.rb +353 -0
- data/spec/dragonfly/cookie_monster_spec.rb +2 -1
- data/spec/dragonfly/file_data_store_spec.rb +301 -0
- data/spec/dragonfly/image_magick/analysers/image_properties_spec.rb +20 -0
- data/spec/dragonfly/image_magick/generators/convert_spec.rb +19 -0
- data/spec/dragonfly/image_magick/generators/plain_spec.rb +50 -0
- data/spec/dragonfly/image_magick/generators/plasma_spec.rb +32 -0
- data/spec/dragonfly/image_magick/generators/text_spec.rb +77 -0
- data/spec/dragonfly/image_magick/plugin_spec.rb +131 -0
- data/spec/dragonfly/image_magick/processors/convert_spec.rb +56 -0
- data/spec/dragonfly/image_magick/processors/thumb_spec.rb +173 -0
- data/spec/dragonfly/job_endpoint_spec.rb +30 -73
- data/spec/dragonfly/job_spec.rb +280 -608
- data/spec/dragonfly/memory_data_store_spec.rb +20 -0
- data/spec/dragonfly/middleware_spec.rb +47 -27
- data/spec/dragonfly/{active_model_extensions → model}/model_spec.rb +331 -555
- data/spec/dragonfly/model/validations_spec.rb +196 -0
- data/spec/dragonfly/register_spec.rb +35 -0
- data/spec/dragonfly/routed_endpoint_spec.rb +6 -6
- data/spec/dragonfly/serializer_spec.rb +13 -15
- data/spec/dragonfly/server_spec.rb +122 -46
- data/spec/dragonfly/shell_spec.rb +43 -24
- data/spec/dragonfly/temp_object_spec.rb +69 -94
- data/spec/dragonfly/url_attributes_spec.rb +49 -0
- data/spec/dragonfly/utils_spec.rb +32 -0
- data/spec/dragonfly/whitelist_spec.rb +30 -0
- data/spec/dragonfly_spec.rb +43 -0
- data/spec/fixtures/deprecated_stored_content/eggs.bonus +1 -0
- data/spec/fixtures/deprecated_stored_content/eggs.bonus.meta +1 -0
- data/spec/functional/configuration_spec.rb +19 -0
- data/spec/functional/model_urls_spec.rb +43 -41
- data/spec/functional/remote_on_the_fly_spec.rb +14 -16
- data/spec/functional/shell_commands_spec.rb +24 -14
- data/spec/functional/to_response_spec.rb +10 -10
- data/spec/functional/urls_spec.rb +5 -3
- data/spec/spec_helper.rb +23 -28
- data/spec/support/argument_matchers.rb +7 -8
- data/spec/support/image_matchers.rb +14 -36
- data/spec/support/model_helpers.rb +97 -0
- data/spec/support/simple_matchers.rb +12 -0
- metadata +92 -393
- data/.yardopts +0 -29
- data/Rakefile +0 -36
- data/config.ru +0 -14
- data/docs.watchr +0 -1
- data/extra_docs/Analysers.md +0 -68
- data/extra_docs/Caching.md +0 -23
- data/extra_docs/Configuration.md +0 -149
- data/extra_docs/Couch.md +0 -49
- data/extra_docs/DataStorage.md +0 -226
- data/extra_docs/Encoding.md +0 -67
- data/extra_docs/ExampleUseCases.md +0 -116
- data/extra_docs/GeneralUsage.md +0 -105
- data/extra_docs/Generators.md +0 -68
- data/extra_docs/Heroku.md +0 -50
- data/extra_docs/ImageMagick.md +0 -136
- data/extra_docs/Index.md +0 -33
- data/extra_docs/MimeTypes.md +0 -40
- data/extra_docs/Models.md +0 -441
- data/extra_docs/Mongo.md +0 -42
- data/extra_docs/Processing.md +0 -77
- data/extra_docs/Rack.md +0 -52
- data/extra_docs/Rails2.md +0 -57
- data/extra_docs/Rails3.md +0 -56
- data/extra_docs/ServingRemotely.md +0 -104
- data/extra_docs/Sinatra.md +0 -25
- data/extra_docs/URLs.md +0 -203
- data/features/images.feature +0 -47
- data/features/no_processing.feature +0 -14
- data/features/rails.feature +0 -8
- data/features/steps/common_steps.rb +0 -8
- data/features/steps/dragonfly_steps.rb +0 -66
- data/features/steps/rails_steps.rb +0 -40
- data/features/support/env.rb +0 -13
- data/features/support/setup.rb +0 -41
- data/fixtures/rails/files/app/models/album.rb +0 -6
- data/fixtures/rails/files/app/views/albums/new.html.erb +0 -7
- data/fixtures/rails/files/app/views/albums/show.html.erb +0 -6
- data/fixtures/rails/files/config/initializers/dragonfly.rb +0 -4
- data/fixtures/rails/files/features/manage_album_images.feature +0 -38
- data/fixtures/rails/files/features/step_definitions/helper_steps.rb +0 -7
- data/fixtures/rails/files/features/step_definitions/image_steps.rb +0 -25
- data/fixtures/rails/files/features/step_definitions/web_steps.rb +0 -189
- data/fixtures/rails/files/features/support/paths.rb +0 -17
- data/fixtures/rails/files/features/text_images.feature +0 -7
- data/fixtures/rails/template.rb +0 -20
- data/irbrc.rb +0 -19
- data/lib/dragonfly/active_model_extensions/class_methods.rb +0 -98
- data/lib/dragonfly/analyser.rb +0 -58
- data/lib/dragonfly/analysis/file_command_analyser.rb +0 -33
- data/lib/dragonfly/analysis/image_magick_analyser.rb +0 -6
- data/lib/dragonfly/config/heroku.rb +0 -26
- data/lib/dragonfly/config/image_magick.rb +0 -6
- data/lib/dragonfly/config/rails.rb +0 -20
- data/lib/dragonfly/data_storage.rb +0 -11
- data/lib/dragonfly/data_storage/couch_data_store.rb +0 -83
- data/lib/dragonfly/data_storage/file_data_store.rb +0 -144
- data/lib/dragonfly/data_storage/mongo_data_store.rb +0 -96
- data/lib/dragonfly/data_storage/s3data_store.rb +0 -168
- data/lib/dragonfly/encoder.rb +0 -13
- data/lib/dragonfly/encoding/image_magick_encoder.rb +0 -6
- data/lib/dragonfly/function_manager.rb +0 -67
- data/lib/dragonfly/generation/image_magick_generator.rb +0 -6
- data/lib/dragonfly/generator.rb +0 -9
- data/lib/dragonfly/image_magick/analyser.rb +0 -53
- data/lib/dragonfly/image_magick/config.rb +0 -44
- data/lib/dragonfly/image_magick/encoder.rb +0 -57
- data/lib/dragonfly/image_magick/generator.rb +0 -147
- data/lib/dragonfly/image_magick/processor.rb +0 -114
- data/lib/dragonfly/image_magick/utils.rb +0 -46
- data/lib/dragonfly/image_magick_utils.rb +0 -4
- data/lib/dragonfly/job_builder.rb +0 -39
- data/lib/dragonfly/job_definitions.rb +0 -30
- data/lib/dragonfly/loggable.rb +0 -28
- data/lib/dragonfly/processing/image_magick_processor.rb +0 -6
- data/lib/dragonfly/processor.rb +0 -9
- data/lib/dragonfly/rails/images.rb +0 -32
- data/lib/dragonfly/simple_cache.rb +0 -23
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +0 -95
- data/spec/dragonfly/analyser_spec.rb +0 -123
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +0 -49
- data/spec/dragonfly/data_storage/couch_data_store_spec.rb +0 -84
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +0 -308
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +0 -81
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +0 -277
- data/spec/dragonfly/data_storage/shared_data_store_examples.rb +0 -77
- data/spec/dragonfly/function_manager_spec.rb +0 -154
- data/spec/dragonfly/image_magick/analyser_spec.rb +0 -73
- data/spec/dragonfly/image_magick/encoder_spec.rb +0 -46
- data/spec/dragonfly/image_magick/generator_spec.rb +0 -178
- data/spec/dragonfly/image_magick/processor_spec.rb +0 -293
- data/spec/dragonfly/job_builder_spec.rb +0 -37
- data/spec/dragonfly/job_definitions_spec.rb +0 -57
- data/spec/dragonfly/loggable_spec.rb +0 -80
- data/spec/dragonfly/simple_cache_spec.rb +0 -27
- data/spec/dragonfly/url_attributes.rb +0 -47
- data/spec/functional/deprecations_spec.rb +0 -51
- data/spec/functional/image_magick_app_spec.rb +0 -27
- data/spec/test_imagemagick.ru +0 -49
- data/yard/handlers/configurable_attr_handler.rb +0 -38
- data/yard/setup.rb +0 -15
- data/yard/templates/default/fulldoc/html/css/common.css +0 -109
- data/yard/templates/default/layout/html/layout.erb +0 -93
- data/yard/templates/default/module/html/configuration_summary.erb +0 -31
- data/yard/templates/default/module/setup.rb +0 -17
@@ -0,0 +1,29 @@
|
|
1
|
+
module Dragonfly
|
2
|
+
module ImageMagick
|
3
|
+
module Processors
|
4
|
+
class Convert
|
5
|
+
|
6
|
+
def call(content, args='', opts={})
|
7
|
+
convert_command = content.env[:convert_command] || 'convert'
|
8
|
+
format = opts['format']
|
9
|
+
|
10
|
+
frame_string = "[#{opts['frame']}]" if opts['frame']
|
11
|
+
content.shell_update :ext => format do |old_path, new_path|
|
12
|
+
"#{convert_command} #{old_path}#{frame_string} #{args} #{new_path}"
|
13
|
+
end
|
14
|
+
|
15
|
+
if format
|
16
|
+
content.meta['format'] = format.to_s
|
17
|
+
content.ext = format
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def update_url(attrs, args='', opts={})
|
22
|
+
format = opts['format']
|
23
|
+
attrs.ext = format if format
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Dragonfly
|
2
|
+
module ImageMagick
|
3
|
+
module Processors
|
4
|
+
class Encode
|
5
|
+
|
6
|
+
def update_url(attrs, format, args="")
|
7
|
+
attrs.ext = format.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(content, format, args="")
|
11
|
+
content.process!(:convert, args, 'format' => format)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Dragonfly
|
2
|
+
module ImageMagick
|
3
|
+
module Processors
|
4
|
+
class Thumb
|
5
|
+
|
6
|
+
GRAVITIES = {
|
7
|
+
'nw' => 'NorthWest',
|
8
|
+
'n' => 'North',
|
9
|
+
'ne' => 'NorthEast',
|
10
|
+
'w' => 'West',
|
11
|
+
'c' => 'Center',
|
12
|
+
'e' => 'East',
|
13
|
+
'sw' => 'SouthWest',
|
14
|
+
's' => 'South',
|
15
|
+
'se' => 'SouthEast'
|
16
|
+
}
|
17
|
+
|
18
|
+
# Geometry string patterns
|
19
|
+
RESIZE_GEOMETRY = /^\d*x\d*[><%^!]?$|^\d+@$/ # e.g. '300x200!'
|
20
|
+
CROPPED_RESIZE_GEOMETRY = /^(\d+)x(\d+)#(\w{1,2})?$/ # e.g. '20x50#ne'
|
21
|
+
CROP_GEOMETRY = /^(\d+)x(\d+)([+-]\d+)?([+-]\d+)?(\w{1,2})?$/ # e.g. '30x30+10+10'
|
22
|
+
|
23
|
+
def update_url(url_attributes, geometry, opts={})
|
24
|
+
format = opts['format']
|
25
|
+
url_attributes.ext = format if format
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(content, geometry, opts={})
|
29
|
+
args = case geometry
|
30
|
+
when RESIZE_GEOMETRY
|
31
|
+
resize_args(geometry)
|
32
|
+
when CROPPED_RESIZE_GEOMETRY
|
33
|
+
resize_and_crop_args($1, $2, $3)
|
34
|
+
when CROP_GEOMETRY
|
35
|
+
crop_args(
|
36
|
+
'width' => $1,
|
37
|
+
'height' => $2,
|
38
|
+
'x' => $3,
|
39
|
+
'y' => $4,
|
40
|
+
'gravity' => $5
|
41
|
+
)
|
42
|
+
else raise ArgumentError, "Didn't recognise the geometry string #{geometry}"
|
43
|
+
end
|
44
|
+
content.process!(:convert, args, opts)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def resize_args(geometry)
|
50
|
+
"-resize #{geometry}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def crop_args(opts)
|
54
|
+
raise ArgumentError, "you can't give a crop offset and gravity at the same time" if opts['x'] && opts['gravity']
|
55
|
+
|
56
|
+
width = opts['width']
|
57
|
+
height = opts['height']
|
58
|
+
gravity = GRAVITIES[opts['gravity']]
|
59
|
+
x = "#{opts['x'] || 0}"
|
60
|
+
x = '+' + x unless x[/^[+-]/]
|
61
|
+
y = "#{opts['y'] || 0}"
|
62
|
+
y = '+' + y unless y[/^[+-]/]
|
63
|
+
|
64
|
+
"#{"-gravity #{gravity} " if gravity}-crop #{width}x#{height}#{x}#{y} +repage"
|
65
|
+
end
|
66
|
+
|
67
|
+
def resize_and_crop_args(width, height, gravity)
|
68
|
+
gravity = GRAVITIES[gravity || 'c']
|
69
|
+
"-resize #{width}x#{height}^^ -gravity #{gravity} -crop #{width}x#{height}+0+0 +repage"
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
data/lib/dragonfly/job.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
require 'digest/sha1'
|
3
|
-
require '
|
3
|
+
require 'uri'
|
4
4
|
require 'open-uri'
|
5
5
|
require 'pathname'
|
6
|
+
require 'base64'
|
7
|
+
require 'dragonfly/serializer'
|
8
|
+
require 'dragonfly/content'
|
9
|
+
require 'dragonfly/url_attributes'
|
10
|
+
require 'dragonfly/job_endpoint'
|
6
11
|
|
7
12
|
module Dragonfly
|
8
13
|
class Job
|
@@ -10,9 +15,7 @@ module Dragonfly
|
|
10
15
|
# Exceptions
|
11
16
|
class AppDoesNotMatch < StandardError; end
|
12
17
|
class JobAlreadyApplied < StandardError; end
|
13
|
-
class NoContent < StandardError; end
|
14
18
|
class NothingToProcess < StandardError; end
|
15
|
-
class NothingToEncode < StandardError; end
|
16
19
|
class InvalidArray < StandardError; end
|
17
20
|
class NoSHAGiven < StandardError; end
|
18
21
|
class IncorrectSHA < StandardError; end
|
@@ -20,9 +23,9 @@ module Dragonfly
|
|
20
23
|
extend Forwardable
|
21
24
|
def_delegators :result,
|
22
25
|
:data, :file, :tempfile, :path, :to_file, :size, :each,
|
23
|
-
:meta, :meta=, :name, :name=, :basename, :basename=, :ext, :ext
|
24
|
-
|
25
|
-
|
26
|
+
:meta, :meta=, :add_meta, :name, :name=, :basename, :basename=, :ext, :ext=, :mime_type,
|
27
|
+
:analyse, :shell_eval, :store,
|
28
|
+
:b64_data
|
26
29
|
|
27
30
|
class Step
|
28
31
|
|
@@ -51,6 +54,14 @@ module Dragonfly
|
|
51
54
|
|
52
55
|
attr_reader :job, :args
|
53
56
|
|
57
|
+
def app
|
58
|
+
job.app
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_a
|
62
|
+
[self.class.abbreviation, *args]
|
63
|
+
end
|
64
|
+
|
54
65
|
def inspect
|
55
66
|
"#{self.class.step_name}(#{args.map{|a| a.inspect }.join(', ')})"
|
56
67
|
end
|
@@ -58,90 +69,135 @@ module Dragonfly
|
|
58
69
|
end
|
59
70
|
|
60
71
|
class Fetch < Step
|
72
|
+
class NotFound < RuntimeError; end
|
73
|
+
|
61
74
|
def uid
|
62
75
|
args.first
|
63
76
|
end
|
77
|
+
|
64
78
|
def apply
|
65
|
-
content, meta =
|
66
|
-
|
79
|
+
content, meta = app.datastore.read(uid)
|
80
|
+
raise NotFound, "uid #{uid} not found" if content.nil?
|
81
|
+
job.content.update(content, meta)
|
67
82
|
end
|
68
83
|
end
|
69
84
|
|
70
85
|
class Process < Step
|
86
|
+
def init
|
87
|
+
processor.update_url(job.url_attributes, *arguments) if processor.respond_to?(:update_url)
|
88
|
+
end
|
89
|
+
|
71
90
|
def name
|
72
91
|
args.first.to_sym
|
73
92
|
end
|
93
|
+
|
74
94
|
def arguments
|
75
95
|
args[1..-1]
|
76
96
|
end
|
77
|
-
def apply
|
78
|
-
raise NothingToProcess, "Can't process because temp object has not been initialized. Need to fetch first?" unless job.temp_object
|
79
|
-
content, meta = job.app.processor.process(job.temp_object, name, *arguments)
|
80
|
-
job.update(content, meta)
|
81
|
-
end
|
82
|
-
end
|
83
97
|
|
84
|
-
|
85
|
-
|
86
|
-
job.url_attrs[:format] = format
|
87
|
-
end
|
88
|
-
def format
|
89
|
-
args.first.to_sym
|
90
|
-
end
|
91
|
-
def arguments
|
92
|
-
args[1..-1]
|
98
|
+
def processor
|
99
|
+
@processor ||= app.get_processor(name)
|
93
100
|
end
|
101
|
+
|
94
102
|
def apply
|
95
|
-
|
96
|
-
content, meta = job.app.encoder.encode(job.temp_object, format, *arguments)
|
97
|
-
job.update(content, (meta || {}).merge(:format => format))
|
103
|
+
processor.call(job.content, *arguments)
|
98
104
|
end
|
99
105
|
end
|
100
106
|
|
101
107
|
class Generate < Step
|
108
|
+
def init
|
109
|
+
generator.update_url(job.url_attributes, *arguments) if generator.respond_to?(:update_url)
|
110
|
+
end
|
111
|
+
|
102
112
|
def name
|
103
|
-
args.first
|
113
|
+
args.first
|
104
114
|
end
|
115
|
+
|
116
|
+
def generator
|
117
|
+
@generator ||= app.get_generator(name)
|
118
|
+
end
|
119
|
+
|
105
120
|
def arguments
|
106
121
|
args[1..-1]
|
107
122
|
end
|
123
|
+
|
108
124
|
def apply
|
109
|
-
|
110
|
-
job.update(content, meta)
|
125
|
+
generator.call(job.content, *arguments)
|
111
126
|
end
|
112
127
|
end
|
113
128
|
|
114
129
|
class FetchFile < Step
|
130
|
+
def initialize(job, path)
|
131
|
+
super(job, path.to_s)
|
132
|
+
end
|
115
133
|
def init
|
116
|
-
job.
|
134
|
+
job.url_attributes.name = filename
|
117
135
|
end
|
136
|
+
|
118
137
|
def path
|
119
138
|
@path ||= File.expand_path(args.first)
|
120
139
|
end
|
140
|
+
|
121
141
|
def filename
|
122
142
|
@filename ||= File.basename(path)
|
123
143
|
end
|
144
|
+
|
124
145
|
def apply
|
125
|
-
job.update(Pathname.new(path),
|
146
|
+
job.content.update(Pathname.new(path), 'name' => filename)
|
126
147
|
end
|
127
148
|
end
|
128
149
|
|
129
150
|
class FetchUrl < Step
|
151
|
+
class ErrorResponse < RuntimeError
|
152
|
+
def initialize(status, body)
|
153
|
+
@status, @body = status, body
|
154
|
+
end
|
155
|
+
attr_reader :status, :body
|
156
|
+
end
|
157
|
+
class CannotHandle < RuntimeError; end
|
158
|
+
|
130
159
|
def init
|
131
|
-
job.
|
160
|
+
job.url_attributes.name = filename
|
132
161
|
end
|
133
|
-
|
134
|
-
|
162
|
+
|
163
|
+
def uri
|
164
|
+
args.first
|
135
165
|
end
|
136
|
-
|
137
|
-
|
166
|
+
|
167
|
+
def url
|
168
|
+
@url ||= uri =~ /^\w+:/ ? uri : "http://#{uri}"
|
138
169
|
end
|
170
|
+
|
139
171
|
def filename
|
140
|
-
|
172
|
+
return if data_uri?
|
173
|
+
@filename ||= URI.parse(url).path[/[^\/]+$/]
|
141
174
|
end
|
175
|
+
|
176
|
+
def data_uri?
|
177
|
+
uri =~ /^data:/
|
178
|
+
end
|
179
|
+
|
142
180
|
def apply
|
143
|
-
|
144
|
-
|
181
|
+
if data_uri?
|
182
|
+
update_from_data_uri
|
183
|
+
else
|
184
|
+
open(URI.escape(url)) do |f|
|
185
|
+
job.content.update(f.read, 'name' => filename)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
rescue OpenURI::HTTPError => e
|
189
|
+
status, message = e.io.status
|
190
|
+
raise ErrorResponse.new(status.to_i, e.io.read)
|
191
|
+
end
|
192
|
+
|
193
|
+
def update_from_data_uri
|
194
|
+
mime_type, b64_data = uri.scan(/^data:([^;]+);base64,(.*)$/)[0]
|
195
|
+
if mime_type && b64_data
|
196
|
+
data = Base64.decode64(b64_data)
|
197
|
+
ext = app.ext_for(mime_type)
|
198
|
+
job.content.update(data, 'name' => "file.#{ext}")
|
199
|
+
else
|
200
|
+
raise CannotHandle, "fetch_url can only deal with base64-encoded data uris with specified content type"
|
145
201
|
end
|
146
202
|
end
|
147
203
|
end
|
@@ -149,7 +205,6 @@ module Dragonfly
|
|
149
205
|
STEPS = [
|
150
206
|
Fetch,
|
151
207
|
Process,
|
152
|
-
Encode,
|
153
208
|
Generate,
|
154
209
|
FetchFile,
|
155
210
|
FetchUrl
|
@@ -173,10 +228,10 @@ module Dragonfly
|
|
173
228
|
|
174
229
|
def deserialize(string, app)
|
175
230
|
array = begin
|
176
|
-
Serializer.
|
231
|
+
Serializer.json_b64_decode(string)
|
177
232
|
rescue Serializer::BadString
|
178
233
|
if app.allow_legacy_urls
|
179
|
-
Serializer.
|
234
|
+
Serializer.marshal_b64_decode(string, :check_malicious => true) # legacy strings
|
180
235
|
else
|
181
236
|
raise
|
182
237
|
end
|
@@ -194,53 +249,24 @@ module Dragonfly
|
|
194
249
|
|
195
250
|
end
|
196
251
|
|
197
|
-
|
198
|
-
|
199
|
-
# This is needed because we need a way of overriding
|
200
|
-
# the methods added to Job objects by the analyser and by
|
201
|
-
# the job shortcuts like 'thumb', etc.
|
202
|
-
# If we had traits/classboxes in ruby maybe this wouldn't be needed
|
203
|
-
# Think of it as like a normal instance method but with a css-like !important after it
|
204
|
-
module OverrideInstanceMethods
|
205
|
-
|
206
|
-
def format
|
207
|
-
apply
|
208
|
-
meta[:format] || (ext.to_sym if ext && app.trust_file_extensions) || analyse(:format)
|
209
|
-
end
|
210
|
-
|
211
|
-
def mime_type
|
212
|
-
app.mime_type_for(format) || analyse(:mime_type) || app.fallback_mime_type
|
213
|
-
end
|
214
|
-
|
215
|
-
def to_s
|
216
|
-
super.sub(/#<Class:\w+>/, 'Extended Dragonfly::Job')
|
217
|
-
end
|
218
|
-
|
219
|
-
end
|
220
|
-
|
221
|
-
def initialize(app, content=nil, meta={}, url_attrs={})
|
252
|
+
def initialize(app, content="", meta={})
|
222
253
|
@app = app
|
223
|
-
@steps = []
|
224
254
|
@next_step_index = 0
|
225
|
-
@
|
226
|
-
|
227
|
-
|
255
|
+
@steps = []
|
256
|
+
@content = Content.new(app, content, meta)
|
257
|
+
@url_attributes = UrlAttributes.new
|
228
258
|
end
|
229
259
|
|
230
260
|
# Used by 'dup' and 'clone'
|
231
261
|
def initialize_copy(other)
|
232
|
-
|
262
|
+
@steps = other.steps.map do |step|
|
233
263
|
step.class.new(self, *step.args)
|
234
264
|
end
|
265
|
+
@content = other.content.dup
|
266
|
+
@url_attributes = other.url_attributes.dup
|
235
267
|
end
|
236
268
|
|
237
|
-
attr_reader :app, :steps
|
238
|
-
attr_reader :temp_object
|
239
|
-
|
240
|
-
def temp_object=(temp_object)
|
241
|
-
previous_temp_objects.push(@temp_object) if @temp_object
|
242
|
-
@temp_object = temp_object
|
243
|
-
end
|
269
|
+
attr_reader :app, :steps, :content
|
244
270
|
|
245
271
|
# define fetch(), fetch!(), process(), etc.
|
246
272
|
STEPS.each do |step_class|
|
@@ -258,10 +284,6 @@ module Dragonfly
|
|
258
284
|
)
|
259
285
|
end
|
260
286
|
|
261
|
-
def analyse(method, *args)
|
262
|
-
analyser.analyse(result, method, *args)
|
263
|
-
end
|
264
|
-
|
265
287
|
# Applying, etc.
|
266
288
|
|
267
289
|
def apply
|
@@ -283,9 +305,7 @@ module Dragonfly
|
|
283
305
|
end
|
284
306
|
|
285
307
|
def to_a
|
286
|
-
steps.map{|step|
|
287
|
-
[step.class.abbreviation, *step.args]
|
288
|
-
}
|
308
|
+
steps.map{|step| step.to_a }
|
289
309
|
end
|
290
310
|
|
291
311
|
# Serializing, etc.
|
@@ -295,10 +315,10 @@ module Dragonfly
|
|
295
315
|
end
|
296
316
|
|
297
317
|
def serialize
|
298
|
-
Serializer.
|
318
|
+
Serializer.json_b64_encode(to_a)
|
299
319
|
end
|
300
320
|
|
301
|
-
def
|
321
|
+
def signature
|
302
322
|
Digest::SHA1.hexdigest(to_unique_s)
|
303
323
|
end
|
304
324
|
|
@@ -320,17 +340,15 @@ module Dragonfly
|
|
320
340
|
# URLs, etc.
|
321
341
|
|
322
342
|
def url(opts={})
|
323
|
-
app.url_for(self,
|
324
|
-
end
|
325
|
-
|
326
|
-
def url_attrs=(hash)
|
327
|
-
@url_attrs = UrlAttributes[hash]
|
343
|
+
app.url_for(self, opts) unless steps.empty?
|
328
344
|
end
|
329
345
|
|
330
|
-
attr_reader :
|
346
|
+
attr_reader :url_attributes
|
331
347
|
|
332
|
-
def
|
333
|
-
|
348
|
+
def update_url_attributes(hash)
|
349
|
+
hash.each do |key, value|
|
350
|
+
url_attributes.send("#{key}=", value)
|
351
|
+
end
|
334
352
|
end
|
335
353
|
|
336
354
|
# to_stuff...
|
@@ -344,7 +362,8 @@ module Dragonfly
|
|
344
362
|
end
|
345
363
|
|
346
364
|
def to_fetched_job(uid)
|
347
|
-
new_job =
|
365
|
+
new_job = dup
|
366
|
+
new_job.steps = []
|
348
367
|
new_job.fetch!(uid)
|
349
368
|
new_job.next_step_index = 1
|
350
369
|
new_job
|
@@ -377,36 +396,14 @@ module Dragonfly
|
|
377
396
|
steps.select{|s| s.is_a?(Process) }
|
378
397
|
end
|
379
398
|
|
380
|
-
def encode_step
|
381
|
-
last_step_of_type(Encode)
|
382
|
-
end
|
383
|
-
|
384
399
|
def step_types
|
385
400
|
steps.map{|s| s.class.step_name }
|
386
401
|
end
|
387
402
|
|
388
403
|
# Misc
|
389
404
|
|
390
|
-
def store(opts={})
|
391
|
-
temp_object = result
|
392
|
-
app.store(temp_object, opts_for_store.merge(opts).merge(:meta => temp_object.meta))
|
393
|
-
end
|
394
|
-
|
395
405
|
def inspect
|
396
|
-
"<Dragonfly::Job app=#{app.name.inspect}, steps=#{steps.inspect},
|
397
|
-
end
|
398
|
-
|
399
|
-
def update(content, new_meta)
|
400
|
-
if new_meta
|
401
|
-
new_meta.merge!(new_meta.delete(:meta)) if new_meta[:meta] # legacy data etc. may have nested meta hash - deprecate gracefully here
|
402
|
-
end
|
403
|
-
old_meta = temp_object ? temp_object.meta : {}
|
404
|
-
self.temp_object = TempObject.new(content, old_meta.merge(new_meta || {}))
|
405
|
-
end
|
406
|
-
|
407
|
-
def close
|
408
|
-
previous_temp_objects.each{|temp_object| temp_object.close }
|
409
|
-
temp_object.close if temp_object
|
406
|
+
"<Dragonfly::Job app=#{app.name.inspect}, steps=#{steps.inspect}, content=#{content.inspect}, steps applied:#{applied_steps.length}/#{steps.length} >"
|
410
407
|
end
|
411
408
|
|
412
409
|
protected
|
@@ -418,25 +415,12 @@ module Dragonfly
|
|
418
415
|
|
419
416
|
def result
|
420
417
|
apply
|
421
|
-
|
418
|
+
content
|
422
419
|
end
|
423
420
|
|
424
|
-
def attributes_for_url
|
425
|
-
attrs = url_attrs.slice(*server.params_in_url)
|
426
|
-
attrs[:format] = (attrs[:format] || (url_attrs.ext if app.trust_file_extensions)).to_s if server.params_in_url.include?('format')
|
427
|
-
attrs.delete_if{|k, v| v.blank? }
|
428
|
-
attrs
|
429
|
-
end
|
430
|
-
|
431
|
-
attr_reader :previous_temp_objects
|
432
|
-
|
433
421
|
def last_step_of_type(type)
|
434
422
|
steps.select{|s| s.is_a?(type) }.last
|
435
423
|
end
|
436
424
|
|
437
|
-
def opts_for_store
|
438
|
-
{:mime_type => mime_type}
|
439
|
-
end
|
440
|
-
|
441
425
|
end
|
442
426
|
end
|