dragonfly 1.4.0 → 1.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16341445bb67f27ae4dc7492244b038df290440a5f4b64d71cca3c637fd8b4d0
4
- data.tar.gz: '0285f83e005198572fb9a52dea16eef2acca80ded36e9fa905b88d66701221fe'
3
+ metadata.gz: a21082636a15ad436d2ee93b887de5347733de38d670411c7aabb084afee9f7f
4
+ data.tar.gz: cc68822a3c32077c576fed5ca215952983af2e49038103c661ea95ef8a3703b7
5
5
  SHA512:
6
- metadata.gz: ea5f8440e718e3521eaca6824b3dd600817994ed144b5c69a9e609fa24ff8e9583a415a9a2ee9a309e7f622d7d33e0712525ce18ed020942a1585b80ef889cef
7
- data.tar.gz: 1c81c3c4ed0bfe6421d3ca6ca69432929a4e8233b468d582586fca5d308758bbc9c6042d830e42bd4421c198452df019e802fcf151c277e3ac7248942cf30af0
6
+ metadata.gz: 80e0fb82c3d0b3551da0036e7e19a688aa94a0525b4128139f1e4f288f18ff73427e556ff49a84b7165dfdbd600648469a1f6ac135603f75f538472ddc84863b
7
+ data.tar.gz: 6514c3a64cbffd11cad972dc8d2aeabe39da7a9bc4744b20743703d70f34e9e7a3fb3a67198bbbd001a86073f546e89f55684083c48b098b512229846a5ab9e1
data/Gemfile CHANGED
@@ -5,4 +5,10 @@ gemspec
5
5
  group :development do
6
6
  gem 'pry'
7
7
  gem 'rake'
8
+ # No longer in the standard library as of ruby 4.0
9
+ # (needed by rack/mock and activerecord respectively)
10
+ gem 'cgi'
11
+ gem 'benchmark'
12
+ # Needed by irb, and no longer a default gem as of ruby 4.0
13
+ gem 'rdoc'
8
14
  end
data/History.md CHANGED
@@ -1,3 +1,15 @@
1
+ # 1.4.2 (2026-07-21)
2
+
3
+ ## Fixes
4
+
5
+ - Security fix for CRLF filename header injection in servers that don't sanitize
6
+
7
+ # 1.4.1 (2025-01-03)
8
+
9
+ ## Fixes
10
+
11
+ - Added ostruct dependency as Ruby 3.5 will remove it from stdlib
12
+
1
13
  # 1.4.0 (2021-05-19)
2
14
 
3
15
  ## Changes
@@ -6,7 +18,7 @@
6
18
 
7
19
  ## Fixes
8
20
 
9
- - Better security for all job steps with parameter validations
21
+ - Better security for all job steps with parameter validations - addresses CVE-2021-33564
10
22
 
11
23
  # 1.3.0 (2021-01-09)
12
24
 
data/README.md CHANGED
@@ -47,7 +47,7 @@ Installation
47
47
 
48
48
  or in your Gemfile
49
49
  ```ruby
50
- gem 'dragonfly', '~> 1.2.2'
50
+ gem 'dragonfly', '~> 1.4.2'
51
51
  ```
52
52
 
53
53
  Require with
@@ -72,6 +72,10 @@ See [the Add-ons wiki](http://github.com/markevans/dragonfly/wiki/Dragonfly-add-
72
72
 
73
73
  Please feel free to contribute!!
74
74
 
75
+ Security notice!
76
+ =================
77
+ If you have set `verify_urls` to `false` (which is **not** recommended) then you should upgrade to version `1.4.x` for a security fix ([CVE-2021-33564](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-33564)).
78
+
75
79
  Issues
76
80
  ======
77
81
  Please use the <a href="http://github.com/markevans/dragonfly/issues">github issue tracker</a> if you have any issues.
data/dev/test.ru CHANGED
@@ -24,7 +24,7 @@ class App
24
24
  end
25
25
  [
26
26
  200,
27
- {'Content-Type' => 'text/html'},
27
+ {'content-type' => 'text/html'},
28
28
  [%(
29
29
  <style>
30
30
  form, input {
data/dragonfly.gemspec CHANGED
@@ -25,9 +25,10 @@ Gem::Specification.new do |spec|
25
25
  spec.add_runtime_dependency("rack", ">= 1.3")
26
26
  spec.add_runtime_dependency("multi_json", "~> 1.0")
27
27
  spec.add_runtime_dependency("addressable", "~> 2.3")
28
+ spec.add_runtime_dependency("ostruct", "~> 0.6.1")
28
29
 
29
30
  # Development dependencies
30
- spec.add_development_dependency("rspec", "~> 2.5")
31
+ spec.add_development_dependency("rspec", "~> 3.0")
31
32
  spec.add_development_dependency("webmock")
32
33
  spec.add_development_dependency("activemodel")
33
34
  if RUBY_PLATFORM == "java"
@@ -10,7 +10,8 @@ module Dragonfly
10
10
 
11
11
  def call(env)
12
12
  response = Dragonfly.app(@dragonfly_app_name).call(env)
13
- if response[1]['X-Cascade'] == 'pass'
13
+ headers = response[1].transform_keys(&:downcase)
14
+ if headers['x-cascade'] == 'pass'
14
15
  @app.call(env)
15
16
  else
16
17
  response
@@ -26,10 +26,10 @@ module Dragonfly
26
26
  end
27
27
  rescue Job::Fetch::NotFound => e
28
28
  Dragonfly.warn(e.message)
29
- [404, {"Content-Type" => "text/plain"}, ["Not found"]]
29
+ [404, {"content-type" => "text/plain"}, ["Not found"]]
30
30
  rescue RuntimeError => e
31
31
  Dragonfly.warn("caught error - #{e.message}")
32
- [500, {"Content-Type" => "text/plain"}, ["Internal Server Error"]]
32
+ [500, {"content-type" => "text/plain"}, ["Internal Server Error"]]
33
33
  end
34
34
  log_response(response)
35
35
  response
@@ -65,8 +65,8 @@ module Dragonfly
65
65
 
66
66
  def method_not_allowed_headers
67
67
  {
68
- 'Content-Type' => 'text/plain',
69
- 'Allow' => 'GET, HEAD'
68
+ 'content-type' => 'text/plain',
69
+ 'allow' => 'GET, HEAD'
70
70
  }
71
71
  end
72
72
 
@@ -78,16 +78,16 @@ module Dragonfly
78
78
 
79
79
  def standard_headers
80
80
  {
81
- "Content-Type" => job.mime_type,
82
- "Content-Length" => job.size.to_s,
83
- "Content-Disposition" => filename_string
81
+ "content-type" => job.mime_type,
82
+ "content-length" => job.size.to_s,
83
+ "content-disposition" => filename_string
84
84
  }
85
85
  end
86
86
 
87
87
  def cache_headers
88
88
  {
89
- "Cache-Control" => "public, max-age=31536000", # (1 year)
90
- "ETag" => %("#{job.signature}")
89
+ "cache-control" => "public, max-age=31536000", # (1 year)
90
+ "etag" => %("#{job.signature}")
91
91
  }
92
92
  end
93
93
 
@@ -99,7 +99,8 @@ module Dragonfly
99
99
 
100
100
  def filename_string
101
101
  return unless job.name
102
- filename = request_from_msie? ? CGI.escape(job.name) : job.name
102
+ name = job.name.gsub(/[\r\n]/, "")
103
+ filename = request_from_msie? ? CGI.escape(name) : name
103
104
  %(filename="#{filename}")
104
105
  end
105
106
 
@@ -45,7 +45,7 @@ module Dragonfly
45
45
  end
46
46
 
47
47
  def plain_response(status, message)
48
- [status, {"Content-Type" => "text/plain"}, [message]]
48
+ [status, {"content-type" => "text/plain"}, [message]]
49
49
  end
50
50
  end
51
51
  end
@@ -59,18 +59,18 @@ module Dragonfly
59
59
  response.to_response
60
60
  end
61
61
  else
62
- [404, {'Content-Type' => 'text/plain', 'X-Cascade' => 'pass'}, ['Not found']]
62
+ [404, {'content-type' => 'text/plain', 'x-cascade' => 'pass'}, ['Not found']]
63
63
  end
64
64
  rescue Job::NoSHAGiven => e
65
- [400, {"Content-Type" => 'text/plain'}, ["You need to give a SHA parameter"]]
65
+ [400, {"content-type" => 'text/plain'}, ["You need to give a SHA parameter"]]
66
66
  rescue Job::IncorrectSHA => e
67
- [400, {"Content-Type" => 'text/plain'}, ["The SHA parameter you gave is incorrect"]]
67
+ [400, {"content-type" => 'text/plain'}, ["The SHA parameter you gave is incorrect"]]
68
68
  rescue JobNotAllowed => e
69
69
  Dragonfly.warn(e.message)
70
- [403, {"Content-Type" => 'text/plain'}, ["Forbidden"]]
70
+ [403, {"content-type" => 'text/plain'}, ["Forbidden"]]
71
71
  rescue Serializer::BadString, Serializer::MaliciousString, Job::InvalidArray => e
72
72
  Dragonfly.warn(e.message)
73
- [404, {'Content-Type' => 'text/plain'}, ['Not found']]
73
+ [404, {'content-type' => 'text/plain'}, ['Not found']]
74
74
  end
75
75
 
76
76
  def url_for(job, opts={})
@@ -111,8 +111,8 @@ module Dragonfly
111
111
  V
112
112
  DRAGONFLY
113
113
  [200, {
114
- 'Content-Type' => 'text/plain',
115
- 'Content-Size' => body.bytesize.to_s
114
+ 'content-type' => 'text/plain',
115
+ 'content-size' => body.bytesize.to_s
116
116
  },
117
117
  [body]
118
118
  ]
@@ -1,3 +1,3 @@
1
1
  module Dragonfly
2
- VERSION = "1.4.0"
2
+ VERSION = "1.4.2"
3
3
  end
@@ -138,7 +138,7 @@ describe Dragonfly::App do
138
138
  }.should raise_error(NotImplementedError)
139
139
  end
140
140
  it "should correctly call it if the datastore provides it" do
141
- @app.datastore.should_receive(:url_for).with('some_uid', :some => :opts).and_return 'http://egg.head'
141
+ @app.datastore.should_receive(:url_for).with('some_uid', {:some => :opts}).and_return 'http://egg.head'
142
142
  @app.remote_url_for('some_uid', :some => :opts).should == 'http://egg.head'
143
143
  end
144
144
  end
@@ -65,7 +65,7 @@ describe Dragonfly::Configurable do
65
65
  configurer = Dragonfly::Configurable::Configurer.new do
66
66
  meth :jobby, :nobby
67
67
  end
68
- obj.should_receive(:jobby).with('beans', :make => 5)
68
+ obj.should_receive(:jobby).with('beans', {:make => 5})
69
69
  obj.should_receive(:nobby).with(['nuts'])
70
70
  configurer.configure(obj) do
71
71
  jobby 'beans', :make => 5
@@ -79,7 +79,7 @@ describe Dragonfly::Configurable do
79
79
  end
80
80
  egg = double('egg')
81
81
  obj.should_receive(:egg).and_return(egg)
82
- egg.should_receive(:jobby).with('beans', :make => 5)
82
+ egg.should_receive(:jobby).with('beans', {:make => 5})
83
83
  configurer.configure(obj) do
84
84
  jobby 'beans', :make => 5
85
85
  end
@@ -93,7 +93,7 @@ describe Dragonfly::Configurable do
93
93
 
94
94
  it "provides 'plugin' for using plugins" do
95
95
  pluggy = double('plugin')
96
- pluggy.should_receive(:call).with(obj, :a, 'few' => ['args'])
96
+ pluggy.should_receive(:call).with(obj, :a, {'few' => ['args']})
97
97
  configurer.configure(obj) do
98
98
  plugin pluggy, :a, 'few' => ['args']
99
99
  end
@@ -101,7 +101,7 @@ describe Dragonfly::Configurable do
101
101
 
102
102
  it "allows using 'plugin' with symbols" do
103
103
  pluggy = double('plugin')
104
- pluggy.should_receive(:call).with(obj, :a, 'few' => ['args'])
104
+ pluggy.should_receive(:call).with(obj, :a, {'few' => ['args']})
105
105
  configurer.register_plugin(:pluggy){ pluggy }
106
106
  configurer.configure(obj) do
107
107
  plugin :pluggy, :a, 'few' => ['args']
@@ -320,7 +320,7 @@ describe Dragonfly::Content do
320
320
  end
321
321
 
322
322
  it "allows passing options" do
323
- app.datastore.should_receive(:write).with(content, :hello => 'there')
323
+ app.datastore.should_receive(:write).with(content, {:hello => 'there'})
324
324
  content.store(:hello => 'there')
325
325
  end
326
326
  end
@@ -9,11 +9,11 @@ describe Dragonfly::FileDataStore do
9
9
  end
10
10
 
11
11
  def assert_exists(path)
12
- File.exists?(path).should be_truthy
12
+ File.exist?(path).should be_truthy
13
13
  end
14
14
 
15
15
  def assert_does_not_exist(path)
16
- File.exists?(path).should be_falsey
16
+ File.exist?(path).should be_falsey
17
17
  end
18
18
 
19
19
  def assert_contains(dir, filepattern)
@@ -21,7 +21,7 @@ describe Dragonfly::Job::FetchUrl do
21
21
  end
22
22
 
23
23
  it "should set the mime_type when returned by the request" do
24
- stub_request(:get, %r{http://thing\.com.*}).to_return(:body => '<ok />', :headers => {'Content-Type' => 'text/html'})
24
+ stub_request(:get, %r{http://thing\.com.*}).to_return(:body => '<ok />', :headers => {'content-type' => 'text/html'})
25
25
  expect(job.fetch_url('http://place.com').mime_type).to eq('application/octet-stream')
26
26
  expect(job.fetch_url('http://thing.com').mime_type).to eq('text/html')
27
27
  end
@@ -50,22 +50,22 @@ describe Dragonfly::JobEndpoint do
50
50
  it "should return a correct response to a successful GET request" do
51
51
  response = make_request(@job)
52
52
  response.status.should == 200
53
- response['ETag'].should =~ /^"\w+"$/
54
- response['Cache-Control'].should == "public, max-age=31536000"
55
- response['Content-Type'].should == 'text/plain'
56
- response['Content-Length'].should == '6'
57
- response['Content-Disposition'].should == 'filename="gung.txt"'
53
+ response['etag'].should =~ /^"\w+"$/
54
+ response['cache-control'].should == "public, max-age=31536000"
55
+ response['content-type'].should == 'text/plain'
56
+ response['content-length'].should == '6'
57
+ response['content-disposition'].should == 'filename="gung.txt"'
58
58
  response.body.should == 'GUNGLE'
59
59
  end
60
60
 
61
61
  it "should return the correct headers and no content to a successful HEAD request" do
62
62
  response = make_request(@job, :method => :head)
63
63
  response.status.should == 200
64
- response['ETag'].should =~ /^"\w+"$/
65
- response['Cache-Control'].should == "public, max-age=31536000"
66
- response['Content-Type'].should == 'text/plain'
67
- response['Content-Length'].should == '6'
68
- response['Content-Disposition'].should == 'filename="gung.txt"'
64
+ response['etag'].should =~ /^"\w+"$/
65
+ response['cache-control'].should == "public, max-age=31536000"
66
+ response['content-type'].should == 'text/plain'
67
+ response['content-length'].should == '6'
68
+ response['content-disposition'].should == 'filename="gung.txt"'
69
69
  response.body.should == ''
70
70
  end
71
71
 
@@ -74,8 +74,8 @@ describe Dragonfly::JobEndpoint do
74
74
  it "should return a 405 error for a #{method} request" do
75
75
  response = make_request(@job, :method => method)
76
76
  response.status.should == 405
77
- response['Allow'].should == "GET, HEAD"
78
- response['Content-Type'].should == 'text/plain'
77
+ response['allow'].should == "GET, HEAD"
78
+ response['content-type'].should == 'text/plain'
79
79
  response.body.should == "method not allowed"
80
80
  end
81
81
 
@@ -102,12 +102,18 @@ describe Dragonfly::JobEndpoint do
102
102
 
103
103
  it "doesn't encode utf8 characters" do
104
104
  response = make_request(@job)
105
- response['Content-Disposition'].should == 'filename="güng.txt"'
105
+ response['content-disposition'].should == 'filename="güng.txt"'
106
106
  end
107
107
 
108
108
  it "does encode them if the request is from IE" do
109
109
  response = make_request(@job, 'HTTP_USER_AGENT' => "Mozilla/5.0 (Windows; U; MSIE 7.0; Windows NT 6.0; el-GR)")
110
- response['Content-Disposition'].should == 'filename="g%C3%BCng.txt"'
110
+ response['content-disposition'].should == 'filename="g%C3%BCng.txt"'
111
+ end
112
+
113
+ it "doesn't allow \\r or \\n characters" do
114
+ @job.name = "\nthis\nis\r\na\n\rbad\rone\r.txt"
115
+ response = make_request(@job)
116
+ response['content-disposition'].should == 'filename="thisisabadone.txt"'
111
117
  end
112
118
  end
113
119
 
@@ -121,7 +127,7 @@ describe Dragonfly::JobEndpoint do
121
127
  describe "ETag" do
122
128
  it "should return an ETag" do
123
129
  response = make_request(@job)
124
- response.headers['ETag'].should =~ /^"\w+"$/
130
+ response.headers['etag'].should =~ /^"\w+"$/
125
131
  end
126
132
 
127
133
  [
@@ -134,8 +140,8 @@ describe Dragonfly::JobEndpoint do
134
140
  @job.should_receive(:signature).at_least(:once).and_return('dingle')
135
141
  response = make_request(@job, 'HTTP_IF_NONE_MATCH' => header)
136
142
  response.status.should == 304
137
- response['ETag'].should == '"dingle"'
138
- response['Cache-Control'].should == "public, max-age=31536000"
143
+ response['etag'].should == '"dingle"'
144
+ response['cache-control'].should == "public, max-age=31536000"
139
145
  response.body.should be_empty
140
146
  end
141
147
  end
@@ -151,25 +157,25 @@ describe Dragonfly::JobEndpoint do
151
157
  @app.configure{ response_header 'This-is', 'brill' }
152
158
  end
153
159
  it "should allow specifying custom headers" do
154
- make_request(@job).headers['This-is'].should == 'brill'
160
+ make_request(@job).headers['this-is'].should == 'brill'
155
161
  end
156
162
  it "should not interfere with other headers" do
157
- make_request(@job).headers['Content-Length'].should == '6'
163
+ make_request(@job).headers['content-length'].should == '6'
158
164
  end
159
165
  it "should allow overridding other headers" do
160
- @app.response_headers['Cache-Control'] = 'try me'
161
- make_request(@job).headers['Cache-Control'].should == 'try me'
166
+ @app.response_headers['cache-control'] = 'try me'
167
+ make_request(@job).headers['cache-control'].should == 'try me'
162
168
  end
163
169
  it "should allow giving a proc" do
164
- @app.response_headers['Cache-Control'] = proc{|job, request, headers|
165
- [job.basename.reverse.upcase, request['a'], headers['Cache-Control'].chars.first].join(',')
170
+ @app.response_headers['cache-control'] = proc{|job, request, headers|
171
+ [job.basename.reverse.upcase, request.params['a'], headers['cache-control'].chars.first].join(',')
166
172
  }
167
173
  response = make_request(@job, 'QUERY_STRING' => 'a=egg')
168
- response['Cache-Control'].should == 'GNUG,egg,p'
174
+ response['cache-control'].should == 'GNUG,egg,p'
169
175
  end
170
176
  it "should allow removing by setting to nil" do
171
- @app.response_headers['Cache-Control'] = nil
172
- make_request(@job).headers.should_not have_key('Cache-Control')
177
+ @app.response_headers['cache-control'] = nil
178
+ make_request(@job).headers.should_not have_key('cache-control')
173
179
  end
174
180
  end
175
181
 
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
  require 'rack'
3
3
 
4
4
  def dummy_rack_app
5
- lambda{|env| [200, {"Content-Type" => "text/html"}, ["dummy_rack_app body"]] }
5
+ lambda{|env| [200, {"content-type" => "text/html"}, ["dummy_rack_app body"]] }
6
6
  end
7
7
 
8
8
  describe Dragonfly::Middleware do
@@ -19,9 +19,18 @@ describe Dragonfly::Middleware do
19
19
  end
20
20
  end
21
21
 
22
- it "should pass through if the app returns X-Cascade: pass" do
22
+ it "should pass through if the app returns x-cascade: pass" do
23
23
  Dragonfly.app.should_receive(:call).and_return(
24
- [404, {"Content-Type" => 'text/plain', 'X-Cascade' => 'pass'}, ['Not found']]
24
+ [404, {"content-type" => 'text/plain', 'x-cascade' => 'pass'}, ['Not found']]
25
+ )
26
+ response = make_request(@stack, '/media/hello.png?howare=you')
27
+ response.body.should == 'dummy_rack_app body'
28
+ response.status.should == 200
29
+ end
30
+
31
+ it "should still pass through using deprecated uppercase X-Cascade: pass" do
32
+ Dragonfly.app.should_receive(:call).and_return(
33
+ [404, {"content-type" => 'text/plain', 'X-Cascade' => 'pass'}, ['Not found']]
25
34
  )
26
35
  response = make_request(@stack, '/media/hello.png?howare=you')
27
36
  response.body.should == 'dummy_rack_app body'
@@ -30,7 +39,7 @@ describe Dragonfly::Middleware do
30
39
 
31
40
  it "should return a 404 if the app returns a 404" do
32
41
  Dragonfly.app.should_receive(:call).and_return(
33
- [404, {"Content-Type" => 'text/plain'}, ['Not found']]
42
+ [404, {"content-type" => 'text/plain'}, ['Not found']]
34
43
  )
35
44
  response = make_request(@stack, '/media/hello.png?howare=you')
36
45
  response.status.should == 404
@@ -38,7 +47,7 @@ describe Dragonfly::Middleware do
38
47
 
39
48
  it "should return as per the dragonfly app if the app returns a 200" do
40
49
  Dragonfly.app.should_receive(:call).and_return(
41
- [200, {"Content-Type" => 'text/plain'}, ['ABCD']]
50
+ [200, {"content-type" => 'text/plain'}, ['ABCD']]
42
51
  )
43
52
  response = make_request(@stack, '/media/hello.png?howare=you')
44
53
  response.status.should == 200
@@ -57,7 +66,7 @@ describe Dragonfly::Middleware do
57
66
  it "should use the specified dragonfly app" do
58
67
  Dragonfly.app.should_not_receive(:call)
59
68
  Dragonfly.app(:images).should_receive(:call).and_return([
60
- 200, {"Content-Type" => 'text/plain'}, ['booboo']
69
+ 200, {"content-type" => 'text/plain'}, ['booboo']
61
70
  ])
62
71
  response = make_request(@stack, '/media/hello.png?howare=you')
63
72
  response.body.should == 'booboo'
@@ -9,7 +9,7 @@ unless RUBY_PLATFORM == "java"
9
9
  let! :dragonfly_app do test_app(:test_ar) end
10
10
 
11
11
  before :all do
12
- @connection = ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
12
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
13
13
 
14
14
  ActiveRecord::Migration.verbose = false
15
15
 
@@ -27,7 +27,7 @@ unless RUBY_PLATFORM == "java"
27
27
 
28
28
  after :all do
29
29
  Photo.destroy_all
30
- ActiveRecord::Base.remove_connection(@connection)
30
+ ActiveRecord::Base.remove_connection()
31
31
  end
32
32
 
33
33
  describe "destroying" do
@@ -367,7 +367,7 @@ describe "models" do
367
367
  describe "remote_url" do
368
368
  it "should give the remote url if the uid is set" do
369
369
  @item.preview_image_uid = 'some/uid'
370
- @app.should_receive(:remote_url_for).with('some/uid', :some => 'param').and_return('http://egg.nog')
370
+ @app.should_receive(:remote_url_for).with('some/uid', {:some => 'param'}).and_return('http://egg.nog')
371
371
  @item.preview_image.remote_url(:some => 'param').should == 'http://egg.nog'
372
372
  end
373
373
  it "should return nil if the content is not yet saved" do
@@ -81,7 +81,7 @@ describe Dragonfly::Server do
81
81
  response.status.should == 404
82
82
  response.body.should == 'Not found'
83
83
  response.content_type.should == 'text/plain'
84
- response.headers['X-Cascade'].should == 'pass'
84
+ response.headers['x-cascade'].should == 'pass'
85
85
  end
86
86
  end
87
87
 
@@ -90,7 +90,7 @@ describe Dragonfly::Server do
90
90
  response.status.should == 404
91
91
  response.body.should == 'Not found'
92
92
  response.content_type.should == 'text/plain'
93
- response.headers['X-Cascade'].should be_nil
93
+ response.headers['x-cascade'].should be_nil
94
94
  end
95
95
 
96
96
  it "should return a 404 when the url isn't known at all" do
@@ -98,7 +98,7 @@ describe Dragonfly::Server do
98
98
  response.status.should == 404
99
99
  response.body.should == 'Not found'
100
100
  response.content_type.should == 'text/plain'
101
- response.headers['X-Cascade'].should == 'pass'
101
+ response.headers['x-cascade'].should == 'pass'
102
102
  end
103
103
 
104
104
  it "should return a 404 when the url is a well-encoded but bad array" do
@@ -107,7 +107,7 @@ describe Dragonfly::Server do
107
107
  response.status.should == 404
108
108
  response.body.should == 'Not found'
109
109
  response.content_type.should == 'text/plain'
110
- response.headers['X-Cascade'].should be_nil
110
+ response.headers['x-cascade'].should be_nil
111
111
  end
112
112
 
113
113
  it "should return a 403 Forbidden when someone uses fetch_url" do
@@ -111,14 +111,14 @@ describe Dragonfly::TempObject do
111
111
  describe "to_file" do
112
112
  before(:each) do
113
113
  @filename = 'tmp/eggnog.txt'
114
- FileUtils.rm_f(@filename) if File.exists?(@filename)
114
+ FileUtils.rm_f(@filename) if File.exist?(@filename)
115
115
  end
116
116
  after(:each) do
117
- FileUtils.rm_f(@filename) if File.exists?(@filename)
117
+ FileUtils.rm_f(@filename) if File.exist?(@filename)
118
118
  end
119
119
  it "should write to a file" do
120
120
  @temp_object.to_file(@filename)
121
- File.exists?(@filename).should be_truthy
121
+ File.exist?(@filename).should be_truthy
122
122
  end
123
123
  it "should write the correct data to the file" do
124
124
  @temp_object.to_file(@filename)
@@ -140,12 +140,12 @@ describe Dragonfly::TempObject do
140
140
  it "should create intermediate subdirs" do
141
141
  filename = 'tmp/gog/mcgee'
142
142
  @temp_object.to_file(filename)
143
- File.exists?(filename).should be_truthy
143
+ File.exist?(filename).should be_truthy
144
144
  FileUtils.rm_rf('tmp/gog')
145
145
  end
146
146
  it "should allow not creating intermediate subdirs" do
147
147
  filename = 'tmp/gog/mcgee'
148
- expect{ @temp_object.to_file(filename, :mkdirs => false) }.to raise_error()
148
+ expect{ @temp_object.to_file(filename, :mkdirs => false) }.to raise_error(/No such file or directory/)
149
149
  end
150
150
  end
151
151
 
@@ -15,7 +15,7 @@ describe "getting rack response directly" do
15
15
  response.should be_a(Array)
16
16
  response.length.should == 3
17
17
  response[0].should == 200
18
- response[1]['Content-Type'].should == 'application/octet-stream'
18
+ response[1]['content-type'].should == 'application/octet-stream'
19
19
  response[2].data.should == 'bunheads'
20
20
  end
21
21
 
@@ -24,7 +24,7 @@ describe "getting rack response directly" do
24
24
  response.should be_a(Array)
25
25
  response.length.should == 3
26
26
  response[0].should == 405
27
- response[1]['Content-Type'].should == 'text/plain'
27
+ response[1]['content-type'].should == 'text/plain'
28
28
  response[2].should == ["method not allowed"]
29
29
  end
30
30
 
@@ -6,7 +6,7 @@ describe "urls" do
6
6
  Dragonfly::Response.should_receive(:new).with(
7
7
  satisfy{|job| job.to_a == array },
8
8
  instance_of(Hash)
9
- ).and_return(double('response', :to_response => [200, {'Content-Type' => 'text/plain'}, ["OK"]]))
9
+ ).and_return(double('response', :to_response => [200, {'content-type' => 'text/plain'}, ["OK"]]))
10
10
  end
11
11
 
12
12
  let (:app) {
data/spec/spec_helper.rb CHANGED
@@ -17,6 +17,12 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
17
17
  SAMPLES_DIR = Pathname.new(File.expand_path("../../samples", __FILE__))
18
18
 
19
19
  RSpec.configure do |c|
20
+ c.expect_with(:rspec) do |expectations|
21
+ expectations.syntax = [:should, :expect]
22
+ end
23
+ c.mock_with(:rspec) do |mocks|
24
+ mocks.syntax = [:should, :expect]
25
+ end
20
26
  c.include ModelHelpers
21
27
  c.include RackHelpers
22
28
  end
@@ -22,7 +22,7 @@ end
22
22
  match do |actual|
23
23
  value.should === image_properties(actual)[property]
24
24
  end
25
- failure_message_for_should do |actual|
25
+ failure_message do |actual|
26
26
  "expected image to have #{property} #{value.inspect}, but it had #{image_properties(actual)[property].inspect}"
27
27
  end
28
28
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dragonfly
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Evans
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2021-05-19 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rack
@@ -52,20 +51,34 @@ dependencies:
52
51
  - - "~>"
53
52
  - !ruby/object:Gem::Version
54
53
  version: '2.3'
54
+ - !ruby/object:Gem::Dependency
55
+ name: ostruct
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 0.6.1
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 0.6.1
55
68
  - !ruby/object:Gem::Dependency
56
69
  name: rspec
57
70
  requirement: !ruby/object:Gem::Requirement
58
71
  requirements:
59
72
  - - "~>"
60
73
  - !ruby/object:Gem::Version
61
- version: '2.5'
74
+ version: '3.0'
62
75
  type: :development
63
76
  prerelease: false
64
77
  version_requirements: !ruby/object:Gem::Requirement
65
78
  requirements:
66
79
  - - "~>"
67
80
  - !ruby/object:Gem::Version
68
- version: '2.5'
81
+ version: '3.0'
69
82
  - !ruby/object:Gem::Dependency
70
83
  name: webmock
71
84
  requirement: !ruby/object:Gem::Requirement
@@ -271,7 +284,6 @@ homepage: http://github.com/markevans/dragonfly
271
284
  licenses:
272
285
  - MIT
273
286
  metadata: {}
274
- post_install_message:
275
287
  rdoc_options: []
276
288
  require_paths:
277
289
  - lib
@@ -286,8 +298,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
286
298
  - !ruby/object:Gem::Version
287
299
  version: '0'
288
300
  requirements: []
289
- rubygems_version: 3.2.15
290
- signing_key:
301
+ rubygems_version: 4.0.10
291
302
  specification_version: 4
292
303
  summary: Ideal gem for handling attachments in Rails, Sinatra and Rack applications.
293
304
  test_files: