cloudinary 1.27.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,15 +4,14 @@
4
4
  require 'digest/sha1'
5
5
  require 'zlib'
6
6
  require 'uri'
7
- require 'aws_cf_signer'
8
7
  require 'json'
9
8
  require 'cgi'
9
+ require 'faraday'
10
+ require 'faraday/multipart'
10
11
  require 'cloudinary/auth_token'
11
12
  require 'cloudinary/responsive'
12
13
 
13
14
  class Cloudinary::Utils
14
- # @deprecated Use Cloudinary::SHARED_CDN
15
- SHARED_CDN = Cloudinary::SHARED_CDN
16
15
  MODE_DOWNLOAD = "download"
17
16
  DEFAULT_RESPONSIVE_WIDTH_TRANSFORMATION = {:width => :auto, :crop => :limit}
18
17
  CONDITIONAL_OPERATORS = {
@@ -98,7 +97,6 @@ class Cloudinary::Utils
98
97
  secure_distribution
99
98
  shorten
100
99
  sign_url
101
- ssl_detected
102
100
  type
103
101
  url_suffix
104
102
  use_root_path
@@ -155,7 +153,7 @@ class Cloudinary::Utils
155
153
  zoom
156
154
  ].map(&:to_sym)
157
155
 
158
- REMOTE_URL_REGEX = %r(^ftp:|^https?:|^s3:|^gs:|^data:([\w-]+\/[\w-]+(\+[\w-]+)?)?(;[\w-]+=[\w-]+)*;base64,([a-zA-Z0-9\/+\n=]+)$)
156
+ REMOTE_URL_REGEX = %r(^ftp:|^https?:|^s3:|^gs:|^data:([\w-]+\/[\w-]+(\.[\w-]+)*(\+[\w-]+)?)?(;[\w-]+=[\w-]+)*;base64,([a-zA-Z0-9\/+\n=]+)$)
159
157
 
160
158
  LONG_URL_SIGNATURE_LENGTH = 32
161
159
  SHORT_URL_SIGNATURE_LENGTH = 8
@@ -513,7 +511,7 @@ class Cloudinary::Utils
513
511
  end
514
512
 
515
513
  # Warning: options are being destructively updated!
516
- def self.unsigned_download_url(source, options = {})
514
+ def self.cloudinary_url(source, options = {})
517
515
 
518
516
  patch_fetch_format(options)
519
517
  type = options.delete(:type)
@@ -530,7 +528,6 @@ class Cloudinary::Utils
530
528
 
531
529
  sign_url = config_option_consume(options, :sign_url)
532
530
  secret = config_option_consume(options, :api_secret)
533
- sign_version = config_option_consume(options, :sign_version) # Deprecated behavior
534
531
  url_suffix = options.delete(:url_suffix)
535
532
  use_root_path = config_option_consume(options, :use_root_path)
536
533
  auth_token = config_option_consume(options, :auth_token)
@@ -578,7 +575,7 @@ class Cloudinary::Utils
578
575
  transformation = transformation.gsub(%r(([^:])//), '\1/')
579
576
  if sign_url && ( !auth_token || auth_token.empty?)
580
577
  raise(CloudinaryException, "Must supply api_secret") if (secret.nil? || secret.empty?)
581
- to_sign = [transformation, sign_version && version, source_to_sign].reject(&:blank?).join("/")
578
+ to_sign = [transformation, source_to_sign].reject(&:blank?).join("/")
582
579
  to_sign = fully_unescape(to_sign)
583
580
  signature_algorithm = long_url_signature ? ALGO_SHA256 : signature_algorithm
584
581
  hash = hash("#{to_sign}#{secret}", signature_algorithm)
@@ -590,12 +587,22 @@ class Cloudinary::Utils
590
587
  prefix = build_distribution_domain(options)
591
588
 
592
589
  source = [prefix, resource_type, type, signature, transformation, version, source].reject(&:blank?).join("/")
590
+
591
+ token = nil
593
592
  if sign_url && auth_token && !auth_token.empty?
594
593
  auth_token[:url] = URI.parse(source).path
595
594
  token = Cloudinary::AuthToken.generate auth_token
596
- source += "?#{token}"
597
595
  end
598
596
 
597
+ analytics = config_option_consume(options, :analytics, true)
598
+ analytics_token = nil
599
+ if analytics && ! original_source.include?("?") # Disable analytics for public IDs containing query params.
600
+ analytics_token = Cloudinary::Analytics.sdk_analytics_query_param
601
+ end
602
+
603
+ query_params = [token, analytics_token].compact.join("&")
604
+
605
+ source += "?#{query_params}" unless query_params.empty?
599
606
  source
600
607
  end
601
608
 
@@ -678,7 +685,7 @@ class Cloudinary::Utils
678
685
  shared_domain = !private_cdn
679
686
 
680
687
  if secure
681
- if secure_distribution.nil? || secure_distribution == Cloudinary::OLD_AKAMAI_SHARED_CDN
688
+ if secure_distribution.nil?
682
689
  secure_distribution = private_cdn ? "#{cloud_name}-res.cloudinary.com" : Cloudinary::SHARED_CDN
683
690
  end
684
691
  shared_domain ||= secure_distribution == Cloudinary::SHARED_CDN
@@ -705,9 +712,7 @@ class Cloudinary::Utils
705
712
  cloud_name = config_option_consume(options, :cloud_name) || raise(CloudinaryException, "Must supply cloud_name in tag or in configuration")
706
713
 
707
714
  source = options.delete(:source)
708
- secure = options.delete(:secure)
709
- ssl_detected = options.delete(:ssl_detected)
710
- secure = ssl_detected || Cloudinary.config.secure if secure.nil?
715
+ secure = config_option_consume(options, :secure, true)
711
716
  private_cdn = config_option_consume(options, :private_cdn)
712
717
  secure_distribution = config_option_consume(options, :secure_distribution)
713
718
  cname = config_option_consume(options, :cname)
@@ -726,8 +731,9 @@ class Cloudinary::Utils
726
731
  def self.base_api_url(path, options = {})
727
732
  cloudinary = options[:upload_prefix] || Cloudinary.config.upload_prefix || UPLOAD_PREFIX
728
733
  cloud_name = options[:cloud_name] || Cloudinary.config.cloud_name || raise(CloudinaryException, 'Must supply cloud_name')
734
+ api_version = options[:api_version] || Cloudinary.config.api_version || 'v1_1'
729
735
 
730
- [cloudinary, 'v1_1', cloud_name, path].join('/')
736
+ [cloudinary, api_version, cloud_name, path].join('/')
731
737
  end
732
738
 
733
739
  def self.cloudinary_api_url(action = 'upload', options = {})
@@ -796,14 +802,6 @@ class Cloudinary::Utils
796
802
  return Cloudinary::Utils.cloudinary_api_url("download", options) + "?" + hash_query_params(cloudinary_params)
797
803
  end
798
804
 
799
- # Utility method that uses the deprecated ZIP download API.
800
- # @deprecated Replaced by {download_zip_url} that uses the more advanced and robust archive generation and download API
801
- def self.zip_download_url(tag, options = {})
802
- warn "zip_download_url is deprecated. Please use download_zip_url instead."
803
- cloudinary_params = sign_request({:timestamp=>Time.now.to_i, :tag=>tag, :transformation=>generate_transformation_string(options)}, options)
804
- return Cloudinary::Utils.cloudinary_api_url("download_tag.zip", options) + "?" + hash_query_params(cloudinary_params)
805
- end
806
-
807
805
  # Returns a URL that when invokes creates an archive and returns it.
808
806
  # @param options [Hash]
809
807
  # @option options [String|Symbol] :resource_type The resource type of files to include in the archive. Must be one of :image | :video | :raw
@@ -853,31 +851,6 @@ class Cloudinary::Utils
853
851
  download_archive_url(options.merge(:resource_type => resource_type, :prefixes => folder_path))
854
852
  end
855
853
 
856
- def self.signed_download_url(public_id, options = {})
857
- aws_private_key_path = options[:aws_private_key_path] || Cloudinary.config.aws_private_key_path
858
- if aws_private_key_path
859
- aws_key_pair_id = options[:aws_key_pair_id] || Cloudinary.config.aws_key_pair_id || raise(CloudinaryException, "Must supply aws_key_pair_id")
860
- authenticated_distribution = options[:authenticated_distribution] || Cloudinary.config.authenticated_distribution || raise(CloudinaryException, "Must supply authenticated_distribution")
861
- @signers ||= Hash.new{|h,k| path, id = k; h[k] = AwsCfSigner.new(path, id)}
862
- signer = @signers[[aws_private_key_path, aws_key_pair_id]]
863
- url = Cloudinary::Utils.unsigned_download_url(public_id, {:type=>:authenticated}.merge(options).merge(:secure=>true, :secure_distribution=>authenticated_distribution, :private_cdn=>true))
864
- expires_at = options[:expires_at] || (Time.now+3600)
865
- return signer.sign(url, :ending => expires_at)
866
- else
867
- return Cloudinary::Utils.unsigned_download_url( public_id, options)
868
- end
869
-
870
- end
871
-
872
- def self.cloudinary_url(public_id, options = {})
873
- if options[:type].to_s == 'authenticated' && !options[:sign_url]
874
- result = signed_download_url(public_id, options)
875
- else
876
- result = unsigned_download_url(public_id, options)
877
- end
878
- return result
879
- end
880
-
881
854
  def self.asset_file_name(path)
882
855
  data = Cloudinary.app_root.join(path).read(:mode=>"rb")
883
856
  ext = path.extname
@@ -998,6 +971,12 @@ class Cloudinary::Utils
998
971
  option_value.nil? ? default_value : option_value
999
972
  end
1000
973
 
974
+ def self.config_option_fetch(options, option_name, default_value = nil)
975
+ return options.fetch(option_name) if options.include?(option_name)
976
+ option_value = Cloudinary.config.send(option_name)
977
+ option_value.nil? ? default_value : option_value
978
+ end
979
+
1001
980
  def self.as_bool(value)
1002
981
  case value
1003
982
  when nil then nil
@@ -1250,7 +1229,8 @@ class Cloudinary::Utils
1250
1229
  # @param options url and transformation options. This argument may be changed by the function!
1251
1230
  #
1252
1231
  def self.patch_fetch_format(options={})
1253
- if options[:type] === :fetch
1232
+ use_fetch_format = config_option_consume(options, :use_fetch_format)
1233
+ if options[:type] === :fetch || use_fetch_format
1254
1234
  format_arg = options.delete(:format)
1255
1235
  options[:fetch_format] ||= format_arg
1256
1236
  end
@@ -1295,6 +1275,31 @@ class Cloudinary::Utils
1295
1275
  }
1296
1276
  end
1297
1277
 
1278
+ # Handles file parameter.
1279
+ #
1280
+ # @param [Pathname, StringIO, File, String, int, _ToPath] file
1281
+ # @return [StringIO, File, String] A File object.
1282
+ #
1283
+ # @private
1284
+ def self.handle_file_param(file, options = {})
1285
+ original_filename = options[:original_filename] || "cloudinaryfile"
1286
+ content_type = options[:content_type] || "application/octet-stream"
1287
+ if file.is_a?(Pathname)
1288
+ return Faraday::FilePart.new(file.to_s, content_type)
1289
+ elsif file.is_a?(Cloudinary::Blob)
1290
+ return Faraday::FilePart.new(file, file.content_type, file.original_filename)
1291
+ elsif file.is_a?(StringIO)
1292
+ file.rewind
1293
+ return Faraday::FilePart.new(file, content_type, original_filename)
1294
+ elsif file.respond_to?(:read)
1295
+ return Faraday::FilePart.new(file, content_type, original_filename)
1296
+ elsif Cloudinary::Utils.is_remote?(file)
1297
+ return file.to_s
1298
+ end
1299
+ # we got file path
1300
+ Faraday::FilePart.new(file.to_s, content_type)
1301
+ end
1302
+
1298
1303
  # The returned url should allow downloading the backedup asset based on the version and asset id
1299
1304
  #
1300
1305
  # asset and version id are returned with resource(<PUBLIC_ID1>, { versions: true })
@@ -1,4 +1,4 @@
1
1
  # Copyright Cloudinary
2
2
  module Cloudinary
3
- VERSION = "1.27.0"
3
+ VERSION = "2.3.0"
4
4
  end
@@ -53,7 +53,7 @@ module CloudinaryHelper
53
53
  # }
54
54
  # ])
55
55
  def cl_video_tag(source, options = {}, &block)
56
- source = strip_known_ext(source)
56
+ source = strip_known_ext(source) unless Cloudinary::Utils.config_option_fetch(options, :use_fetch_format)
57
57
  video_attributes = [:autoplay,:controls,:loop,:muted,:poster, :preload]
58
58
  options = Cloudinary::Utils.deep_symbolize_keys(DEFAULT_VIDEO_OPTIONS.merge(options))
59
59
 
@@ -155,8 +155,9 @@ module CloudinaryHelper
155
155
  content_tag('video', tag_options.merge(video_options)) do
156
156
  source_tags = sources.map do |source|
157
157
  type = source[:type]
158
+ options[:format] = type
158
159
  transformation = source[:transformations] || {}
159
- cloudinary_tag("#{source_name}.#{type}", options.merge(transformation)) do |url, _tag_options|
160
+ cloudinary_tag(source_name, options.merge(transformation)) do |url, _tag_options|
160
161
  mime_type = "video/#{(type == 'ogv' ? 'ogg' : type)}"
161
162
  if source[:codecs]
162
163
  codecs = source[:codecs].is_a?(Array) ? source[:codecs].join(", ") : source[:codecs]
data/lib/cloudinary.rb CHANGED
@@ -1,10 +1,6 @@
1
1
  # Copyright Cloudinary
2
- if RUBY_VERSION > "2"
3
- require "ostruct"
4
- else
5
- require "cloudinary/ostruct2"
6
- end
7
2
 
3
+ require "ostruct"
8
4
  require "pathname"
9
5
  require "yaml"
10
6
  require "uri"
@@ -29,11 +25,9 @@ module Cloudinary
29
25
  autoload :CarrierWave, "cloudinary/carrier_wave"
30
26
  autoload :Search, "cloudinary/search"
31
27
  autoload :SearchFolders, "cloudinary/search_folders"
28
+ autoload :Analytics, "cloudinary/analytics"
32
29
 
33
- CF_SHARED_CDN = "d3jpl91pxevbkh.cloudfront.net"
34
- AKAMAI_SHARED_CDN = "res.cloudinary.com"
35
- OLD_AKAMAI_SHARED_CDN = "cloudinary-a.akamaihd.net"
36
- SHARED_CDN = AKAMAI_SHARED_CDN
30
+ SHARED_CDN = "res.cloudinary.com"
37
31
 
38
32
  USER_AGENT = "CloudinaryRuby/#{VERSION} (Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL})"
39
33
  @@user_platform = defined?(Rails.version) ? "Rails/#{Rails.version}" : ""
@@ -1,7 +1,9 @@
1
1
  require 'tmpdir'
2
- require 'rest_client'
2
+ require 'faraday'
3
+ require 'faraday/follow_redirects'
3
4
  require 'json'
4
5
  require 'rubygems/package'
6
+ require 'stringio'
5
7
 
6
8
  unless Rake::Task.task_defined?('cloudinary:fetch_assets') # prevent double-loading/execution
7
9
  namespace :cloudinary do
@@ -11,7 +13,7 @@ unless Rake::Task.task_defined?('cloudinary:fetch_assets') # prevent double-load
11
13
  processing_files = %w[canvas-to-blob.min.js load-image.all.min.js jquery.fileupload-process.js jquery.fileupload-image.js jquery.fileupload-validate.js]
12
14
  files = index_files + processing_files
13
15
 
14
- release = JSON(RestClient.get("https://api.github.com/repos/cloudinary/cloudinary_js/releases/latest"))
16
+ release = JSON(Faraday.get("https://api.github.com/repos/cloudinary/cloudinary_js/releases/latest").body)
15
17
 
16
18
  FileUtils.rm_rf 'vendor/assets'
17
19
  html_folder = 'vendor/assets/html'
@@ -20,7 +22,11 @@ unless Rake::Task.task_defined?('cloudinary:fetch_assets') # prevent double-load
20
22
  FileUtils.mkdir_p js_folder
21
23
 
22
24
  puts "Fetching cloudinary_js version #{release["tag_name"]}\n\n"
23
- sio = StringIO.new(RestClient.get(release["tarball_url"]).body)
25
+ conn = Faraday.new do |faraday|
26
+ faraday.response :follow_redirects
27
+ faraday.adapter Faraday.default_adapter
28
+ end
29
+ sio = StringIO.new(conn.get(release["tarball_url"]).body)
24
30
  file = Zlib::GzipReader.new(sio)
25
31
  tar = Gem::Package::TarReader.new(file)
26
32
  tar.each_entry do |entry|
@@ -422,7 +422,7 @@ var slice = [].slice,
422
422
  * @returns {boolean} true if item is empty
423
423
  */
424
424
  isEmpty = function(item) {
425
- return (item == null) || (jQuery.isArray(item) || Util.isString(item)) && item.length === 0 || (jQuery.isPlainObject(item) && jQuery.isEmptyObject(item));
425
+ return (item == null) || (Array.isArray(item) || Util.isString(item)) && item.length === 0 || (jQuery.isPlainObject(item) && jQuery.isEmptyObject(item));
426
426
  };
427
427
 
428
428
  /**
@@ -565,7 +565,7 @@ var slice = [].slice,
565
565
  setData: setData,
566
566
  width: width,
567
567
  isString: isString,
568
- isArray: jQuery.isArray,
568
+ isArray: Array.isArray,
569
569
  isEmpty: isEmpty,
570
570
 
571
571
  /**
@@ -4728,7 +4728,7 @@ var slice = [].slice,
4728
4728
  return k + '=' + v;
4729
4729
  }).join('|');
4730
4730
  } else if (Util.isArray(value)) {
4731
- if (value.length > 0 && jQuery.isArray(value[0])) {
4731
+ if (value.length > 0 && Array.isArray(value[0])) {
4732
4732
  upload_params[key] = jQuery.map(value, function(array_value) {
4733
4733
  return array_value.join(',');
4734
4734
  }).join('|');