Skip to content

Commit

Permalink
Merge pull request #1 from carrierwaveuploader/master
Browse files Browse the repository at this point in the history
Upgrade forked branch to latest changes
  • Loading branch information
dmoore5050 authored Feb 27, 2024
2 parents a81450a + ed87991 commit b3b1b2f
Show file tree
Hide file tree
Showing 36 changed files with 2,395 additions and 102 deletions.
20 changes: 10 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,35 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby: [ '2.5', '2.6', '2.7', '3.0', '3.1', jruby ]
gemfile: [ gemfiles/rails-6-1.gemfile ]
ruby: [ '2.7', '3.0', '3.1', '3.2', jruby ]
gemfile: [ gemfiles/rails-7-0.gemfile ]
experimental: [ false ]
include:
- ruby: '3.0'
- ruby: '2.5'
gemfile: gemfiles/rails-6-0.gemfile
experimental: false
- ruby: '3.0'
gemfile: gemfiles/rails-7-0.gemfile
- ruby: '2.6'
gemfile: gemfiles/rails-6-1.gemfile
experimental: false
- ruby: '3.2'
gemfile: gemfiles/rails-7-0.gemfile
gemfile: gemfiles/rails-7-1.gemfile
experimental: false
- ruby: '3.2'
gemfile: gemfiles/rails-main.gemfile
experimental: true
- ruby: ruby-head
gemfile: gemfiles/rails-7-0.gemfile
gemfile: gemfiles/rails-7-1.gemfile
experimental: false
- ruby: jruby-head
gemfile: gemfiles/rails-6-1.gemfile
gemfile: gemfiles/rails-7-0.gemfile
experimental: true
runs-on: ubuntu-20.04
continue-on-error: ${{ matrix.experimental }}
env:
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
JRUBY_OPTS: --debug
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup ImageMagick policy
run: sudo sh -c 'echo '\''<policymap><policy domain="coder" rights="read|write" pattern="PDF" /></policymap>'\'' > /etc/ImageMagick-6/policy.xml'
- name: Update package list
Expand All @@ -59,7 +59,7 @@ jobs:
name: RuboCop
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
Expand Down
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,41 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## 3.0.5 - 2023-11-29

### Fixed
* Remove unnecessary if clause within #filename left in the uploader template (@rajyan, [#2711](https://github.com/carrierwaveuploader/carrierwave/pull/2711))

### Security
* Fix Content-Type allowlist bypass vulnerability, possibly leading to XSS (@mshibuya, [863d425](https://github.com/carrierwaveuploader/carrierwave/commit/863d425c76eba12c3294227b39018f6b2dccbbf3), [GHSA-gxhx-g4fq-49hj](https://github.com/carrierwaveuploader/carrierwave/security/advisories/GHSA-gxhx-g4fq-49hj))

## 3.0.4 - 2023-10-08

### Fixed
* Fix model's dirty state remaining after update (@rajyan [#2707](https://github.com/carrierwaveuploader/carrierwave/pull/2707), [#2702](https://github.com/carrierwaveuploader/carrierwave/issues/2702))
* Fix #dup modifying the original object (@rajyan [#2690](https://github.com/carrierwaveuploader/carrierwave/pull/2690), [#2706](https://github.com/carrierwaveuploader/carrierwave/pull/2706), [#2689](https://github.com/carrierwaveuploader/carrierwave/issues/2689), [#2700](https://github.com/carrierwaveuploader/carrierwave/issues/2700))
* Fix #dup not respecting the :mount_on option, causing MissingAttributeError (@marsz [#2691](https://github.com/carrierwaveuploader/carrierwave/pull/2691))

## 3.0.3 - 2023-08-21

### Fixed
* Fix #dup modifying the original object (@mshibuya [37f36f7](https://github.com/carrierwaveuploader/carrierwave/commit/37f36f7ccf035ffb19cbd3964928b3abf2d5e1b1), [#2687](https://github.com/carrierwaveuploader/carrierwave/issues/2687))
* Fix wrongly removing files on transaction rollback (@mshibuya, @rajyan [eb03fe1](https://github.com/carrierwaveuploader/carrierwave/commit/eb03fe124c3a7acf3ffc913c7d432208ba3aa7ca), [#2686](https://github.com/carrierwaveuploader/carrierwave/pull/2686), [#2685](https://github.com/carrierwaveuploader/carrierwave/issues/2685))

## 3.0.2 - 2023-08-01

### Fixed
* Fix deduplicated filename not being persisted (@mshibuya [#2679](https://github.com/carrierwaveuploader/carrierwave/pull/2679), [#2678](https://github.com/carrierwaveuploader/carrierwave/issues/2678), [#2677](https://github.com/carrierwaveuploader/carrierwave/pull/2677))

## 3.0.1 - 2023-07-22

### Fixed
* Fix not respecting the parent's #enable_processing value after reading its own (@mshibuya [2df0f53](https://github.com/carrierwaveuploader/carrierwave/commit/2df0f53f1d5fa30a198aa148ef33f1ab924404e4), [#2676](https://github.com/carrierwaveuploader/carrierwave/issues/2676))
* Fix NoMethodError when a record is rolled back (@y-yagi [#2674](https://github.com/carrierwaveuploader/carrierwave/pull/2674), [#2675](https://github.com/carrierwaveuploader/carrierwave/issues/2675))
* Fix filename suffix being removed due to unnecessary deduplication (@mshibuya [d68a111](https://github.com/carrierwaveuploader/carrierwave/commit/d68a1111cfae4309d703caa19d9c19226bc01686), [#2672](https://github.com/carrierwaveuploader/carrierwave/issues/2672))
* Fix #dup causing unintended name deduplication of copied files (@mshibuya [b732acd](https://github.com/carrierwaveuploader/carrierwave/commit/b732acd63209897e6375a3706330df2c38e3f327), [#2670](https://github.com/carrierwaveuploader/carrierwave/issues/2670))
* Fix initialization failing when active_support/core_ext is not loaded yet (@mshibuya [875d972](https://github.com/carrierwaveuploader/carrierwave/commit/875d972dc78b8416de7768457793baa4d6220a4f))

## 3.0.0 - 2023-07-02

_No changes._
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
CarrierWave thrives on a large number of [contributors](https://github.com/carrierwaveuploader/carrierwave/contributors),
and pull requests are very welcome. Before submitting a pull request, please make sure that your changes are well tested.

First, make sure you have `imagemagick` and `ghostscript` installed. You may need `libmagic` as well.
First, make sure you have `imagemagick`, `ghostscript` and `libvips` installed. You may need `libmagic` as well.

Then, you'll need to install the gem dependencies:

Expand Down
3 changes: 2 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
source "https://rubygems.org"

gem "rails", ">= 6.0.0"
gem "activemodel-serializers-xml"
gem 'sqlite3', platforms: :ruby
gem "activerecord-jdbcsqlite3-adapter", platform: [:jruby, :truffleruby]
# See https://github.com/fog/fog-google/issues/535 for this restriction.
gem "fog-google", "~> 1.13.0" if RUBY_VERSION.to_f < 2.6
gem "fog-google", "~> 1.13.0" if RUBY_VERSION.to_f < 2.7

gemspec
68 changes: 59 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -659,14 +659,19 @@ end
## Testing with CarrierWave

It's a good idea to test your uploaders in isolation. In order to speed up your
tests, it's recommended to switch off processing in your tests, and to use the
tests, it's recommended to switch off processing in your tests, and to use the file storage.
Also, you can disable SSRF protection at your own risk using the `skip_ssrf_protection` configuration.

In Rails you could do that by adding an initializer with:

file storage. In Rails you could do that by adding an initializer with:

```ruby
if Rails.env.test? or Rails.env.cucumber?
CarrierWave.configure do |config|
config.storage = :file
config.enable_processing = false
config.skip_ssrf_protection = true
end
end
```
Expand Down Expand Up @@ -764,6 +769,10 @@ CarrierWave.configure do |config|
config.fog_directory = 'name_of_bucket' # required
config.fog_public = false # optional, defaults to true
config.fog_attributes = { cache_control: "public, max-age=#{365.days.to_i}" } # optional, defaults to {}
# Use this if you have AWS S3 ACLs disabled.
# config.fog_attributes = { 'x-amz-acl' => 'bucket-owner-full-control' }
# Use this if you have Google Cloud Storage uniform bucket-level access enabled.
# config.fog_attributes = { uniform: true }
# For an application which utilizes multiple servers but does not need caches persisted across requests,
# uncomment the line :file instead of the default :storage. Otherwise, it will use AWS as the temp cache store.
# config.cache_storage = :file
Expand Down Expand Up @@ -970,14 +979,6 @@ class AvatarUploader < CarrierWave::Uploader::Base
end
```

#### List of available processing methods:

- `convert` - Changes the image encoding format to the given format(eg. jpg). This operation is treated specially to trigger the change of the file extension, so it matches with the format of the resulting file.
- `resize_to_limit` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. Will only resize the image if it is larger than the specified dimensions. The resulting image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.
- `resize_to_fit` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. The image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.
- `resize_to_fill` - Resize the image to fit within the specified dimensions while retaining the aspect ratio of the original image. If necessary, crop the image in the larger dimension. Optionally, a "gravity" may be specified, for example "Center", or "NorthEast".
- `resize_and_pad` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. If necessary, will pad the remaining area with the given color, which defaults to transparent (for gif and png, white for jpeg). Optionally, a "gravity" may be specified, as above.

See `carrierwave/processing/mini_magick.rb` for details.

### Using RMagick
Expand Down Expand Up @@ -1009,6 +1010,54 @@ end
Check out the manipulate! method, which makes it easy for you to write your own
manipulation methods.

### Using Vips

CarrierWave version 2.2.0 added support for the `libvips` image processing library, through [ImageProcessing::Vips](https://github.com/janko/image_processing/blob/master/doc/vips.md). Its functionality matches that of the RMagick and MiniMagick processors, but it uses less memory and offers [faster processing](https://github.com/libvips/libvips/wiki/Speed-and-memory-use). To use the Vips processing module you must first install `libvips`, for example:

````bash
$ sudo apt install libvips
````

You also need to tell your uploader to use Vips:

````ruby
class ImageFileUploader < CarrierWave::Uploader::Base
include CarrierWave::Vips
end
````

### List of available processing methods:

> [!NOTE]
> While the intetion is to provide uniform interfaces to al three processing libraries the availability and implementation of processing methods can <a href="supported-processing-methods">vary slightly between them</a>.
- `convert` - Changes the image encoding format to the given format (eg. jpg). This operation is treated specially to trigger the change of the file extension, so it matches with the format of the resulting file.
- `resize_to_limit` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. Will only resize the image if it is larger than the specified dimensions. The resulting image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.
- `resize_to_fit` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. The image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.
- `resize_to_fill` - Resize the image to fit within the specified dimensions while retaining the aspect ratio of the original image. If necessary, crop the image in the larger dimension. Optionally, a "gravity" may be specified, for example "Center", or "NorthEast".
- `resize_and_pad` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. If necessary, will pad the remaining area with the given color, which defaults to transparent (for gif and png, white for jpeg). Optionally, a "gravity" may be specified, as above.
- `crop` - Crop the image to the contents of a box with the specified height and width, positioned a given number of pixels from the top and left. The original image edge will be retained should the bottom and/or right edge of the box fall outside the image bounds.

#### Supported processing methods

The following table shows which processing methods are supported by each processing library, and which parameters they accept:

Method|RMagick|MiniMagick|Vips
------|-----------------|-----------------|-----------------|
`convert`|`format`|`format`, `page`<sup>1</sup>|`format`, `page`<sup>1</sup>
`resize_to_limit`|`width`, `height`|`width`, `height`|`width`, `height`
`resize_to_fit`|`width`, `height`|`width`, `height`|`width`, `height`
`resize_to_fill`|`width`, `height`, `gravity`<sup>2</sup>|`width`, `height`, `gravity`<sup>2</sup>|`width`, `height`
`resize_and_pad`|`width`, `height`, `background`, `gravity`<sup>2</sup>|`width`, `height`, `background`, `gravity`<sup>2</sup>|`width`, `height`, `background`, `gravity`<sup>2</sup>
`resize_to_geometry_string`|`geometry_string`<sup>3</sup>|*not implemented*|*not implemented*
`crop`|`left`, `top`, `width`, `height`|`left`, `top`, `width`, `height`|`left`, `top`, `width`, `height`

<sup>1</sup>`page` refers to the page number when converting from PDF, frame number when converting from GIF, and layer number when converting from PSD.

<sup>2</sup>`gravity` refers to an image position given as one of `Center`, `North`, `NorthWest`, `West`, `SouthWest`, `South`, `SouthEast`, `East`, or `NorthEast`.

<sup>3</sup>`geometry_string` is an [ImageMagick geometry string](https://rmagick.github.io/imusage.html#geometry).

## Migrating from Paperclip

If you are using Paperclip, you can use the provided compatibility module:
Expand Down Expand Up @@ -1133,6 +1182,7 @@ cache
process
remove
retrieve_from_cache
retrieve_from_store
store
```

Expand Down
3 changes: 2 additions & 1 deletion carrierwave.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Gem::Specification.new do |s|
s.add_dependency "marcel", "~> 1.0.0"
s.add_dependency "addressable", "~> 2.6"
s.add_dependency "ssrf_filter", "~> 1.0"
s.add_development_dependency "rails", ">= 6.0.0"
s.add_development_dependency "csv", "~> 3.0"
s.add_development_dependency "cucumber", "~> 2.3"
s.add_development_dependency "rspec", "~> 3.4"
s.add_development_dependency "rspec-retry"
Expand All @@ -37,6 +37,7 @@ Gem::Specification.new do |s|
s.add_development_dependency "fog-local"
s.add_development_dependency "fog-rackspace"
s.add_development_dependency "mini_magick", ">= 3.6.0"

if RUBY_ENGINE != 'jruby'
s.add_development_dependency "rmagick", ">= 2.16"
end
Expand Down
1 change: 1 addition & 0 deletions gemfiles/rails-6-0.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ gem "rails", "~> 6.0.0"
gem "activemodel-serializers-xml"
gem 'sqlite3', platforms: :ruby
gem "activerecord-jdbcsqlite3-adapter", platform: [:jruby, :truffleruby]
gem "fog-google", "~> 1.13.0" if RUBY_VERSION < '2.7'

gemspec :path => "../"
9 changes: 9 additions & 0 deletions gemfiles/rails-7-1.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
source "https://rubygems.org"

gem "rails", "~> 7.1.0"
gem "activemodel-serializers-xml"
gem 'sqlite3', platforms: :ruby
gem "activerecord-jdbcsqlite3-adapter", platform: [:jruby, :truffleruby]
gem "observer" # Workaround for https://github.com/rmagick/rmagick/pull/1411

gemspec :path => "../"
2 changes: 1 addition & 1 deletion lib/carrierwave/downloader/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def process_uri(source)
# my_uploader.downloader = CarrierWave::Downloader::CustomDownloader
#
def skip_ssrf_protection?(uri)
false
@uploader.skip_ssrf_protection
end
end
end
Expand Down
5 changes: 5 additions & 0 deletions lib/carrierwave/mount.rb
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@ def write_uploader(column, identifier); end

private

def initialize_dup(other)
@_mounters = @_mounters.dup
super
end

def _mounter(column)
# We cannot memoize in frozen objects :(
return Mounter.build(self, column) if frozen?
Expand Down
20 changes: 11 additions & 9 deletions lib/carrierwave/mounter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,20 +139,22 @@ def remote_urls=(urls)
end

def store!
additions, remains = uploaders.partition(&:cached?)
existing_paths = (@removed_uploaders + remains).map(&:store_path)
additions.each do |uploader|
uploader.deduplicate(existing_paths)
uploader.store!
existing_paths << uploader.store_path
end
@added_uploaders += additions
uploaders.each(&:store!)
end

def write_identifier
return if record.frozen?

clear! if remove?

additions, remains = uploaders.partition(&:cached?)
existing_identifiers = (@removed_uploaders + remains).map(&:identifier)
additions.each do |uploader|
uploader.deduplicate(existing_identifiers)
existing_identifiers << uploader.identifier
end
@added_uploaders += additions

record.write_uploader(serialization_column, identifier)
end

Expand Down Expand Up @@ -202,7 +204,7 @@ def remove_previous
end

def remove_added
current_paths = (@removed_uploaders + @uploaders.select(&:staged)).map(&:path)
current_paths = (@removed_uploaders + uploaders.select(&:staged)).map(&:path)
@added_uploaders
.reject {|uploader| current_paths.include?(uploader.path) }
.each { |uploader| uploader.remove! }
Expand Down
17 changes: 12 additions & 5 deletions lib/carrierwave/orm/activerecord.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ def mount_base(column, uploader=nil, options={}, &block)

after_save :"store_#{column}!"
before_save :"write_#{column}_identifier"
if ::ActiveRecord.try(:run_after_transaction_callbacks_in_order_defined)
after_commit :"remove_previously_stored_#{column}", :on => :update
after_commit :"reset_previous_changes_for_#{column}"
after_commit :"mark_remove_#{column}_false", :on => :update
else
after_commit :"mark_remove_#{column}_false", :on => :update
after_commit :"reset_previous_changes_for_#{column}"
after_commit :"remove_previously_stored_#{column}", :on => :update
end
after_commit :"remove_#{column}!", :on => :destroy
after_commit :"mark_remove_#{column}_false", :on => :update

after_commit :"reset_previous_changes_for_#{column}"
after_commit :"remove_previously_stored_#{column}", :on => :update
after_rollback :"remove_rolled_back_#{column}"

mod = Module.new
Expand All @@ -45,8 +50,10 @@ def reload(*args)
# Reset cached mounter on record dup
def initialize_dup(other)
old_uploaders = _mounter(:"#{column}").uploaders
@_mounters[:"#{column}"] = nil
super
@_mounters[:"#{column}"] = nil
# The attribute needs to be cleared to prevent it from picked up as identifier
write_attribute(_mounter(:#{column}).serialization_column, nil)
_mounter(:"#{column}").cache(old_uploaders)
end
Expand Down
29 changes: 29 additions & 0 deletions lib/carrierwave/processing/mini_magick.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ def resize_to_fill(width, height, gravity='Center')
def resize_and_pad(width, height, background=:transparent, gravity='Center')
process :resize_and_pad => [width, height, background, gravity]
end

def crop(left, top, width, height)
process :crop => [left, top, width, height]
end
end

##
Expand Down Expand Up @@ -210,6 +214,31 @@ def resize_and_pad(width, height, background=:transparent, gravity='Center', com
end
end

##
# Crop the image to the contents of a box positioned at [left] and [top], with the dimensions given
# by [width] and [height]. The original image bottom/right edge is preserved if the cropping box falls
# outside the image bounds.
#
# === Parameters
#
# [left (integer)] left edge of area to extract
# [top (integer)] top edge of area to extract
# [width (Integer)] width of area to extract
# [height (Integer)] height of area to extract
#
# === Yields
#
# [MiniMagick::Image] additional manipulations to perform
#
def crop(left, top, width, height, combine_options: {}, &block)
width, height = resolve_dimensions(width, height)

minimagick!(block) do |builder|
builder.crop(left, top, width, height)
.apply(combine_options)
end
end

##
# Returns the width of the image in pixels.
#
Expand Down
Loading

0 comments on commit b3b1b2f

Please sign in to comment.