cloudinary 1.11.1 → 1.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
- data/.github/pull_request_template.md +24 -0
- data/.gitignore +6 -1
- data/.travis.yml +15 -5
- data/CHANGELOG.md +149 -0
- data/Rakefile +3 -45
- data/cloudinary.gemspec +20 -4
- data/lib/active_storage/blob_key.rb +20 -0
- data/lib/active_storage/service/cloudinary_service.rb +229 -0
- data/lib/cloudinary.rb +31 -22
- data/lib/cloudinary/api.rb +173 -5
- data/lib/cloudinary/auth_token.rb +6 -4
- data/lib/cloudinary/carrier_wave.rb +3 -1
- data/lib/cloudinary/carrier_wave/remote.rb +3 -2
- data/lib/cloudinary/carrier_wave/storage.rb +2 -1
- data/lib/cloudinary/cloudinary_controller.rb +2 -4
- data/lib/cloudinary/helper.rb +30 -3
- data/lib/cloudinary/railtie.rb +7 -3
- data/lib/cloudinary/uploader.rb +35 -6
- data/lib/cloudinary/utils.rb +112 -40
- data/lib/cloudinary/version.rb +1 -1
- data/lib/cloudinary/video_helper.rb +96 -22
- data/lib/tasks/cloudinary/fetch_assets.rake +48 -0
- data/lib/tasks/{cloudinary.rake → cloudinary/sync_static.rake} +0 -0
- data/tools/allocate_test_cloud.sh +9 -0
- data/tools/get_test_cloud.sh +9 -0
- data/tools/update_version +29 -11
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +48 -14
- data/vendor/assets/javascripts/cloudinary/jquery.fileupload.js +24 -4
- data/vendor/assets/javascripts/cloudinary/jquery.ui.widget.js +741 -561
- data/vendor/assets/javascripts/cloudinary/load-image.all.min.js +1 -1
- metadata +62 -67
- data/spec/access_control_spec.rb +0 -102
- data/spec/api_spec.rb +0 -567
- data/spec/archive_spec.rb +0 -129
- data/spec/auth_token_spec.rb +0 -77
- data/spec/cache_spec.rb +0 -109
- data/spec/cloudinary_helper_spec.rb +0 -325
- data/spec/cloudinary_spec.rb +0 -32
- data/spec/data/sync_static/app/assets/javascripts/1.coffee +0 -1
- data/spec/data/sync_static/app/assets/javascripts/1.js +0 -1
- data/spec/data/sync_static/app/assets/stylesheets/1.css +0 -3
- data/spec/docx.docx +0 -0
- data/spec/favicon.ico +0 -0
- data/spec/image_spec.rb +0 -107
- data/spec/logo.png +0 -0
- data/spec/rake_spec.rb +0 -160
- data/spec/sample_asset_file.tsv +0 -4
- data/spec/search_spec.rb +0 -109
- data/spec/spec_helper.rb +0 -266
- data/spec/storage_spec.rb +0 -44
- data/spec/streaminig_profiles_api_spec.rb +0 -74
- data/spec/support/helpers/temp_file_helpers.rb +0 -22
- data/spec/support/shared_contexts/rake.rb +0 -19
- data/spec/uploader_spec.rb +0 -392
- data/spec/utils_methods_spec.rb +0 -54
- data/spec/utils_spec.rb +0 -970
- data/spec/video_tag_spec.rb +0 -253
- data/spec/video_url_spec.rb +0 -185
data/lib/cloudinary.rb
CHANGED
@@ -29,8 +29,8 @@ module Cloudinary
|
|
29
29
|
OLD_AKAMAI_SHARED_CDN = "cloudinary-a.akamaihd.net"
|
30
30
|
SHARED_CDN = AKAMAI_SHARED_CDN
|
31
31
|
|
32
|
-
USER_AGENT = "CloudinaryRuby
|
33
|
-
@@user_platform = ""
|
32
|
+
USER_AGENT = "CloudinaryRuby/#{VERSION} (Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
|
33
|
+
@@user_platform = defined?(Rails.version) ? "Rails/#{Rails.version}" : ""
|
34
34
|
|
35
35
|
# Add platform information to the USER_AGENT header
|
36
36
|
# This is intended for platform information and not individual applications!
|
@@ -44,7 +44,7 @@ module Cloudinary
|
|
44
44
|
|
45
45
|
def self.USER_AGENT
|
46
46
|
if @@user_platform.empty?
|
47
|
-
|
47
|
+
USER_AGENT
|
48
48
|
else
|
49
49
|
"#{@@user_platform} #{USER_AGENT}"
|
50
50
|
end
|
@@ -64,19 +64,7 @@ module Cloudinary
|
|
64
64
|
first_time = @@config.nil?
|
65
65
|
@@config ||= OpenStruct.new((YAML.load(ERB.new(IO.read(config_dir.join("cloudinary.yml"))).result)[config_env] rescue {}))
|
66
66
|
|
67
|
-
|
68
|
-
if first_time && ENV["CLOUDINARY_CLOUD_NAME"]
|
69
|
-
set_config(
|
70
|
-
"cloud_name" => ENV["CLOUDINARY_CLOUD_NAME"],
|
71
|
-
"api_key" => ENV["CLOUDINARY_API_KEY"],
|
72
|
-
"api_secret" => ENV["CLOUDINARY_API_SECRET"],
|
73
|
-
"secure_distribution" => ENV["CLOUDINARY_SECURE_DISTRIBUTION"],
|
74
|
-
"private_cdn" => ENV["CLOUDINARY_PRIVATE_CDN"].to_s == 'true',
|
75
|
-
"secure" => ENV["CLOUDINARY_SECURE"].to_s == 'true'
|
76
|
-
)
|
77
|
-
elsif first_time && ENV["CLOUDINARY_URL"]
|
78
|
-
config_from_url(ENV["CLOUDINARY_URL"])
|
79
|
-
end
|
67
|
+
config_from_env if first_time
|
80
68
|
|
81
69
|
set_config(new_config) if new_config
|
82
70
|
yield(@@config) if block_given?
|
@@ -86,7 +74,12 @@ module Cloudinary
|
|
86
74
|
|
87
75
|
def self.config_from_url(url)
|
88
76
|
@@config ||= OpenStruct.new
|
89
|
-
|
77
|
+
return unless url && !url.empty?
|
78
|
+
uri = URI.parse(url)
|
79
|
+
if !uri.scheme || "cloudinary" != uri.scheme.downcase
|
80
|
+
raise(CloudinaryException,
|
81
|
+
"Invalid CLOUDINARY_URL scheme. Expecting to start with 'cloudinary://'")
|
82
|
+
end
|
90
83
|
set_config(
|
91
84
|
"cloud_name" => uri.host,
|
92
85
|
"api_key" => uri.user,
|
@@ -100,7 +93,7 @@ module Cloudinary
|
|
100
93
|
if isNestedKey? key
|
101
94
|
putNestedKey key, value
|
102
95
|
else
|
103
|
-
set_config(key =>
|
96
|
+
set_config(key => Utils.smart_unescape(value))
|
104
97
|
end
|
105
98
|
end
|
106
99
|
end
|
@@ -135,18 +128,34 @@ module Cloudinary
|
|
135
128
|
end
|
136
129
|
|
137
130
|
private
|
138
|
-
|
131
|
+
|
132
|
+
def self.config_from_env
|
133
|
+
# Heroku support
|
134
|
+
if ENV["CLOUDINARY_CLOUD_NAME"]
|
135
|
+
config_keys = ENV.keys.select! { |key| key.start_with? "CLOUDINARY_" }
|
136
|
+
config_keys -= ["CLOUDINARY_URL"] # ignore it when explicit options are passed
|
137
|
+
config_keys.each do |full_key|
|
138
|
+
conf_key = full_key["CLOUDINARY_".length..-1].downcase # convert "CLOUDINARY_CONFIG_NAME" to "config_name"
|
139
|
+
conf_val = ENV[full_key]
|
140
|
+
conf_val = conf_val == 'true' if %w[true false].include?(conf_val) # cast relevant boolean values
|
141
|
+
set_config(conf_key => conf_val)
|
142
|
+
end
|
143
|
+
elsif ENV["CLOUDINARY_URL"]
|
144
|
+
config_from_url(ENV["CLOUDINARY_URL"])
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
139
148
|
def self.config_env
|
140
149
|
return ENV["CLOUDINARY_ENV"] if ENV["CLOUDINARY_ENV"]
|
141
150
|
return Rails.env if defined? Rails::env
|
142
151
|
nil
|
143
152
|
end
|
144
|
-
|
153
|
+
|
145
154
|
def self.config_dir
|
146
|
-
return Pathname.new(ENV["CLOUDINARY_CONFIG_DIR"]) if ENV["CLOUDINARY_CONFIG_DIR"]
|
155
|
+
return Pathname.new(ENV["CLOUDINARY_CONFIG_DIR"]) if ENV["CLOUDINARY_CONFIG_DIR"]
|
147
156
|
self.app_root.join("config")
|
148
157
|
end
|
149
|
-
|
158
|
+
|
150
159
|
def self.set_config(new_config)
|
151
160
|
new_config.each{|k,v| @@config.send(:"#{k}=", v) if !v.nil?}
|
152
161
|
end
|
data/lib/cloudinary/api.rb
CHANGED
@@ -78,8 +78,9 @@ class Cloudinary::Api
|
|
78
78
|
resource_type = options[:resource_type] || "image"
|
79
79
|
type = options[:type] || "upload"
|
80
80
|
uri = "resources/#{resource_type}/#{type}/#{public_id}"
|
81
|
-
call_api(:get, uri,
|
82
|
-
only(options,
|
81
|
+
call_api(:get, uri,
|
82
|
+
only(options,
|
83
|
+
:cinemagraph_analysis,
|
83
84
|
:colors,
|
84
85
|
:coordinates,
|
85
86
|
:exif,
|
@@ -88,7 +89,9 @@ class Cloudinary::Api
|
|
88
89
|
:max_results,
|
89
90
|
:pages,
|
90
91
|
:phash,
|
91
|
-
:quality_analysis
|
92
|
+
:quality_analysis,
|
93
|
+
:derived_next_cursor,
|
94
|
+
:accessibility_analysis
|
92
95
|
), options)
|
93
96
|
end
|
94
97
|
|
@@ -226,11 +229,21 @@ class Cloudinary::Api
|
|
226
229
|
end
|
227
230
|
|
228
231
|
def self.root_folders(options={})
|
229
|
-
|
232
|
+
params = only(options, :max_results, :next_cursor)
|
233
|
+
call_api(:get, "folders", params, options)
|
230
234
|
end
|
231
235
|
|
232
236
|
def self.subfolders(of_folder_path, options={})
|
233
|
-
|
237
|
+
params = only(options, :max_results, :next_cursor)
|
238
|
+
call_api(:get, "folders/#{of_folder_path}", params, options)
|
239
|
+
end
|
240
|
+
|
241
|
+
def self.delete_folder(path, options={})
|
242
|
+
call_api(:delete, "folders/#{path}", {}, options)
|
243
|
+
end
|
244
|
+
|
245
|
+
def self.create_folder(folder_name, options={})
|
246
|
+
call_api(:post, "folders/#{folder_name}", {}, options)
|
234
247
|
end
|
235
248
|
|
236
249
|
def self.upload_mappings(options={})
|
@@ -335,6 +348,144 @@ class Cloudinary::Api
|
|
335
348
|
call_json_api('GET', json_url, {}, 60, {})
|
336
349
|
end
|
337
350
|
|
351
|
+
# Returns a list of all metadata field definitions.
|
352
|
+
#
|
353
|
+
# @see https://cloudinary.com/documentation/admin_api#get_metadata_fields Get metadata fields API reference
|
354
|
+
#
|
355
|
+
# @param [Hash] options Additional options
|
356
|
+
# @return [Cloudinary::Api::Response]
|
357
|
+
# @raise [Cloudinary::Api::Error]
|
358
|
+
def self.list_metadata_fields(options = {})
|
359
|
+
call_metadata_api(:get, [], {}, options)
|
360
|
+
end
|
361
|
+
|
362
|
+
# Gets a metadata field by external id.
|
363
|
+
#
|
364
|
+
# @see https://cloudinary.com/documentation/admin_api#get_a_metadata_field_by_external_id Get metadata field by external ID API reference
|
365
|
+
#
|
366
|
+
# @param [String] field_external_id The ID of the metadata field to retrieve
|
367
|
+
# @param [Hash] options Additional options
|
368
|
+
# @return [Cloudinary::Api::Response]
|
369
|
+
# @raise [Cloudinary::Api::Error]
|
370
|
+
def self.metadata_field_by_field_id(field_external_id, options = {})
|
371
|
+
uri = [field_external_id]
|
372
|
+
|
373
|
+
call_metadata_api(:get, uri, {}, options)
|
374
|
+
end
|
375
|
+
|
376
|
+
# Creates a new metadata field definition.
|
377
|
+
#
|
378
|
+
# @see https://cloudinary.com/documentation/admin_api#create_a_metadata_field Create metadata field API reference
|
379
|
+
#
|
380
|
+
# @param [Hash] field The field to add
|
381
|
+
# @param [Hash] options Additional options
|
382
|
+
# @return [Cloudinary::Api::Response]
|
383
|
+
# @raise [Cloudinary::Api::Error]
|
384
|
+
def self.add_metadata_field(field, options = {})
|
385
|
+
params = only(field, :type, :external_id, :label, :mandatory, :default_value, :validation, :datasource)
|
386
|
+
|
387
|
+
call_metadata_api(:post, [], params, options)
|
388
|
+
end
|
389
|
+
|
390
|
+
# Updates a metadata field by external id.
|
391
|
+
#
|
392
|
+
# Updates a metadata field definition (partially, no need to pass the entire object) passed as JSON data.
|
393
|
+
# See https://cloudinary.com/documentation/admin_api#generic_structure_of_a_metadata_field for the generic structure
|
394
|
+
# of a metadata field.
|
395
|
+
#
|
396
|
+
# @see https://cloudinary.com/documentation/admin_api#update_a_metadata_field_by_external_id Update metadata field API reference
|
397
|
+
#
|
398
|
+
# @param [String] field_external_id The id of the metadata field to update
|
399
|
+
# @param [Hash] field The field definition
|
400
|
+
# @param [Hash] options Additional options
|
401
|
+
# @return [Cloudinary::Api::Response]
|
402
|
+
# @raise [Cloudinary::Api::Error]
|
403
|
+
def self.update_metadata_field(field_external_id, field, options = {})
|
404
|
+
uri = [field_external_id]
|
405
|
+
params = only(field, :label, :mandatory, :default_value, :validation)
|
406
|
+
|
407
|
+
call_metadata_api(:put, uri, params, options)
|
408
|
+
end
|
409
|
+
|
410
|
+
# Deletes a metadata field definition.
|
411
|
+
#
|
412
|
+
# The field should no longer be considered a valid candidate for all other endpoints.
|
413
|
+
#
|
414
|
+
# @see https://cloudinary.com/documentation/admin_api#delete_a_metadata_field_by_external_id Delete metadata field API reference
|
415
|
+
#
|
416
|
+
# @param [String] field_external_id The external id of the field to delete
|
417
|
+
# @param [Hash] options Additional options
|
418
|
+
# @return [Cloudinary::Api::Response] A hash with a "message" key. "ok" value indicates a successful deletion
|
419
|
+
# @raise [Cloudinary::Api::Error]
|
420
|
+
def self.delete_metadata_field(field_external_id, options = {})
|
421
|
+
uri = [field_external_id]
|
422
|
+
|
423
|
+
call_metadata_api(:delete, uri, {}, options)
|
424
|
+
end
|
425
|
+
|
426
|
+
# Deletes entries in a metadata field datasource.
|
427
|
+
#
|
428
|
+
# Deletes (blocks) the datasource entries for a specified metadata field definition. Sets the state of the
|
429
|
+
# entries to inactive. This is a soft delete, the entries still exist under the hood and can be activated
|
430
|
+
# again with the restore datasource entries method.
|
431
|
+
#
|
432
|
+
# @see https://cloudinary.com/documentation/admin_api#delete_entries_in_a_metadata_field_datasource Delete entries in a metadata field datasource API reference
|
433
|
+
#
|
434
|
+
# @param [String] field_external_id The id of the field to update
|
435
|
+
# @param [Array] entries_external_id The ids of all the entries to delete from the datasource
|
436
|
+
# @param [Hash] options Additional options
|
437
|
+
# @return [Cloudinary::Api::Response] The remaining datasource entries
|
438
|
+
# @raise [Cloudinary::Api::Error]
|
439
|
+
def self.delete_datasource_entries(field_external_id, entries_external_id, options = {})
|
440
|
+
uri = [field_external_id, "datasource"]
|
441
|
+
params = {:external_ids => entries_external_id }
|
442
|
+
|
443
|
+
call_metadata_api(:delete, uri, params, options)
|
444
|
+
end
|
445
|
+
|
446
|
+
# Updates a metadata field datasource.
|
447
|
+
#
|
448
|
+
# Updates the datasource of a supported field type (currently only enum and set), passed as JSON data. The
|
449
|
+
# update is partial: datasource entries with an existing external_id will be updated and entries with new
|
450
|
+
# external_id’s (or without external_id’s) will be appended.
|
451
|
+
#
|
452
|
+
# @see https://cloudinary.com/documentation/admin_api#update_a_metadata_field_datasource Update a metadata field datasource API reference
|
453
|
+
#
|
454
|
+
# @param [String] field_external_id The external id of the field to update
|
455
|
+
# @param [Array] entries_external_id
|
456
|
+
# @param [Hash] options Additional options
|
457
|
+
# @return [Cloudinary::Api::Response]
|
458
|
+
# @raise [Cloudinary::Api::Error]
|
459
|
+
def self.update_metadata_field_datasource(field_external_id, entries_external_id, options = {})
|
460
|
+
uri = [field_external_id, "datasource"]
|
461
|
+
|
462
|
+
params = entries_external_id.each_with_object({:values => [] }) do |item, hash|
|
463
|
+
item = only(item, :external_id, :value)
|
464
|
+
hash[:values ] << item if item.present?
|
465
|
+
end
|
466
|
+
|
467
|
+
call_metadata_api(:put, uri, params, options)
|
468
|
+
end
|
469
|
+
|
470
|
+
# Restores entries in a metadata field datasource.
|
471
|
+
#
|
472
|
+
# Restores (unblocks) any previously deleted datasource entries for a specified metadata field definition.
|
473
|
+
# Sets the state of the entries to active.
|
474
|
+
#
|
475
|
+
# @see https://cloudinary.com/documentation/admin_api#restore_entries_in_a_metadata_field_datasource Restore entries in a metadata field datasource API reference
|
476
|
+
#
|
477
|
+
# @param [String] field_external_id The ID of the metadata field
|
478
|
+
# @param [Array] entries_external_ids An array of IDs of datasource entries to restore (unblock)
|
479
|
+
# @param [Hash] options Additional options
|
480
|
+
# @return [Cloudinary::Api::Response]
|
481
|
+
# @raise [Cloudinary::Api::Error]
|
482
|
+
def self.restore_metadata_field_datasource(field_external_id, entries_external_ids, options = {})
|
483
|
+
uri = [field_external_id, "datasource_restore"]
|
484
|
+
params = {:external_ids => entries_external_ids }
|
485
|
+
|
486
|
+
call_metadata_api(:post, uri, params, options)
|
487
|
+
end
|
488
|
+
|
338
489
|
protected
|
339
490
|
|
340
491
|
def self.call_api(method, uri, params, options)
|
@@ -343,6 +494,7 @@ class Cloudinary::Api
|
|
343
494
|
api_key = options[:api_key] || Cloudinary.config.api_key || raise("Must supply api_key")
|
344
495
|
api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise("Must supply api_secret")
|
345
496
|
timeout = options[:timeout] || Cloudinary.config.timeout || 60
|
497
|
+
uri = Cloudinary::Utils.smart_escape(uri)
|
346
498
|
api_url = [cloudinary, "v1_1", cloud_name, uri].join("/")
|
347
499
|
# Add authentication
|
348
500
|
api_url.sub!(%r(^(https?://)), "\\1#{api_key}:#{api_secret}@")
|
@@ -382,6 +534,22 @@ class Cloudinary::Api
|
|
382
534
|
raise GeneralError.new("Error parsing server response (#{response.code}) - #{response.body}. Got - #{e}")
|
383
535
|
end
|
384
536
|
|
537
|
+
# Protected function that assists with performing an API call to the metadata_fields part of the Admin API.
|
538
|
+
#
|
539
|
+
# @protected
|
540
|
+
# @param [Symbol] method The HTTP method. Valid methods: get, post, put, delete
|
541
|
+
# @param [Array] uri REST endpoint of the API (without 'metadata_fields')
|
542
|
+
# @param [Hash] params Query/body parameters passed to the method
|
543
|
+
# @param [Hash] options Additional options. Can be an override of the configuration, headers, etc.
|
544
|
+
# @return [Cloudinary::Api::Response]
|
545
|
+
# @raise [Cloudinary::Api::Error]
|
546
|
+
def self.call_metadata_api(method, uri, params, options)
|
547
|
+
options[:content_type] = :json
|
548
|
+
uri = ["metadata_fields", uri].reject(&:empty?).join("/")
|
549
|
+
|
550
|
+
call_api(method, uri, params, options)
|
551
|
+
end
|
552
|
+
|
385
553
|
def self.only(hash, *keys)
|
386
554
|
result = {}
|
387
555
|
keys.each do |key|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'openssl'
|
2
4
|
if RUBY_VERSION > "2"
|
3
5
|
require "ostruct"
|
@@ -10,6 +12,7 @@ module Cloudinary
|
|
10
12
|
module AuthToken
|
11
13
|
SEPARATOR = '~'
|
12
14
|
UNSAFE = /[ "#%&\'\/:;<=>?@\[\\\]^`{\|}~]/
|
15
|
+
EMPTY_TOKEN = {}.freeze
|
13
16
|
|
14
17
|
def self.generate(options = {})
|
15
18
|
key = options[:key]
|
@@ -42,12 +45,11 @@ module Cloudinary
|
|
42
45
|
"#{name}=#{token.join(SEPARATOR)}"
|
43
46
|
end
|
44
47
|
|
45
|
-
|
46
48
|
# Merge token2 to token1 returning a new
|
47
49
|
# Requires to support Ruby 1.9
|
48
50
|
def self.merge_auth_token(token1, token2)
|
49
|
-
token1 = token1 ||
|
50
|
-
token2 = token2 ||
|
51
|
+
token1 = token1 || EMPTY_TOKEN
|
52
|
+
token2 = token2 || EMPTY_TOKEN
|
51
53
|
token1 = token1.respond_to?( :to_h) ? token1.to_h : token1
|
52
54
|
token2 = token2.respond_to?( :to_h) ? token2.to_h : token2
|
53
55
|
token1.merge(token2)
|
@@ -69,4 +71,4 @@ module Cloudinary
|
|
69
71
|
OpenSSL::HMAC.hexdigest(digest, bin_key, message)
|
70
72
|
end
|
71
73
|
end
|
72
|
-
end
|
74
|
+
end
|
@@ -9,8 +9,10 @@ module Cloudinary::CarrierWave
|
|
9
9
|
|
10
10
|
def self.included(base)
|
11
11
|
base.storage Cloudinary::CarrierWave::Storage
|
12
|
+
base.cache_storage = :file if base.cache_storage.blank?
|
12
13
|
base.extend ClassMethods
|
13
|
-
base.class_attribute :
|
14
|
+
base.class_attribute :metadata
|
15
|
+
base.class_attribute :storage_type, instance_reader: false
|
14
16
|
override_in_versions(base, :blank?, :full_public_id, :my_public_id, :all_versions_processors, :stored_version)
|
15
17
|
end
|
16
18
|
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module Cloudinary::CarrierWave
|
2
2
|
def download!(uri, *args)
|
3
|
-
return super
|
3
|
+
return super unless self.cloudinary_should_handle_remote?
|
4
4
|
if respond_to?(:process_uri)
|
5
5
|
uri = process_uri(uri)
|
6
6
|
else # Backward compatibility with old CarrierWave
|
7
|
-
|
7
|
+
remote_url_unsafe_chars = /([^a-zA-Z0-9_.\-\/:?&=]+)/ # In addition allow query string characters: "?","&" and "="
|
8
|
+
uri = URI.parse(Cloudinary::Utils.smart_escape(Cloudinary::Utils.smart_unescape(uri), remote_url_unsafe_chars))
|
8
9
|
end
|
9
10
|
return if uri.to_s.blank?
|
10
11
|
self.original_filename = @cache_id = @filename = File.basename(uri.path).gsub(/[^a-zA-Z0-9\.\-\+_]/, '')
|
@@ -1,7 +1,8 @@
|
|
1
1
|
class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
|
2
2
|
|
3
3
|
def store!(file)
|
4
|
-
return
|
4
|
+
return unless uploader.enable_processing
|
5
|
+
|
5
6
|
if uploader.is_main_uploader?
|
6
7
|
case file
|
7
8
|
when Cloudinary::CarrierWave::PreloadedCloudinaryFile
|
@@ -1,13 +1,11 @@
|
|
1
1
|
module Cloudinary::CloudinaryController
|
2
2
|
protected
|
3
|
-
|
3
|
+
|
4
4
|
def valid_cloudinary_response?
|
5
5
|
received_signature = request.query_parameters[:signature]
|
6
6
|
calculated_signature = Cloudinary::Utils.api_sign_request(
|
7
7
|
request.query_parameters.select{|key, value| [:public_id, :version].include?(key.to_sym)},
|
8
8
|
Cloudinary.config.api_secret)
|
9
9
|
return received_signature == calculated_signature
|
10
|
-
end
|
10
|
+
end
|
11
11
|
end
|
12
|
-
|
13
|
-
ActionController::Base.send :include, Cloudinary::CloudinaryController
|
data/lib/cloudinary/helper.rb
CHANGED
@@ -286,7 +286,7 @@ module CloudinaryHelper
|
|
286
286
|
Cloudinary::Utils.private_download_url(public_id, format, options)
|
287
287
|
end
|
288
288
|
|
289
|
-
# Helper method that uses the deprecated ZIP download API.
|
289
|
+
# Helper method that uses the deprecated ZIP download API.
|
290
290
|
# Replaced by cl_download_zip_url that uses the more advanced and robust archive generation and download API
|
291
291
|
# @deprecated
|
292
292
|
def cl_zip_download_url(tag, options = {})
|
@@ -296,7 +296,7 @@ module CloudinaryHelper
|
|
296
296
|
# @see {Cloudinary::Utils.download_archive_url}
|
297
297
|
def cl_download_archive_url(options = {})
|
298
298
|
Cloudinary::Utils.download_archive_url(options)
|
299
|
-
end
|
299
|
+
end
|
300
300
|
|
301
301
|
# @see {Cloudinary::Utils.download_zip_url}
|
302
302
|
def cl_download_zip_url(options = {})
|
@@ -318,7 +318,7 @@ module CloudinaryHelper
|
|
318
318
|
if Cloudinary.config.enhance_image_tag
|
319
319
|
alias_method :image_tag, :image_tag_with_cloudinary
|
320
320
|
alias_method :image_path, :image_path_with_cloudinary
|
321
|
-
end
|
321
|
+
end
|
322
322
|
end
|
323
323
|
end
|
324
324
|
|
@@ -419,3 +419,30 @@ rescue LoadError
|
|
419
419
|
# no sass support. Ignore.
|
420
420
|
end
|
421
421
|
|
422
|
+
begin
|
423
|
+
require 'sassc'
|
424
|
+
require 'sassc/script/functions'
|
425
|
+
module SassC::Script::Functions
|
426
|
+
# Helper method for generating cloudinary_url in scss files.
|
427
|
+
#
|
428
|
+
# As opposed to sass(deprecated), optional named arguments are not supported, use hash map instead.
|
429
|
+
#
|
430
|
+
# Example:
|
431
|
+
# Sass: cloudinary-url("sample", $quality: "auto", $fetch_format: "auto");
|
432
|
+
# becomes
|
433
|
+
# SassC: cloudinary-url("sample", ("quality": "auto", "fetch_format": "auto"));
|
434
|
+
#
|
435
|
+
# @param [::SassC::Script::Value::String] public_id The public ID of the resource
|
436
|
+
# @param [::SassC::Script::Value::Map] sass_options Additional options
|
437
|
+
#
|
438
|
+
# @return [::SassC::Script::Value::String]
|
439
|
+
def cloudinary_url(public_id, sass_options = {})
|
440
|
+
options = {}
|
441
|
+
sass_options.to_h.each { |k, v| options[k.value.to_sym] = v.value }
|
442
|
+
url = Cloudinary::Utils.cloudinary_url(public_id.value, {:type => :asset}.merge(options))
|
443
|
+
::SassC::Script::Value::String.new("url(#{url})")
|
444
|
+
end
|
445
|
+
end
|
446
|
+
rescue LoadError
|
447
|
+
# no sassc support. Ignore.
|
448
|
+
end
|