fastimage 2.0.1 → 2.1.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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.textile +8 -4
  3. data/lib/fastimage.rb +58 -18
  4. metadata +14 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8e91d72ee9017341028e1a4e39335bcbe38fd430
4
- data.tar.gz: 1967da0aa3c2814d4cf8451df75dff1c50bc2d98
3
+ metadata.gz: 8bdd1b1858b1101956c8d27e85509ad1c68a436b
4
+ data.tar.gz: 54021e4718ed2bf2480dd7972b59a8b6b711061c
5
5
  SHA512:
6
- metadata.gz: 272713d7824e59ef0f049f503ecbb57cbb2f65bb1e3a756aed3830ffd5131fcb2943d06d090d9bfb82f3f99ca64f385d76debf5f3b121b3974b16be6b7aa1676
7
- data.tar.gz: 390252f65f7d4770c00431de27f353835ec6d39ca2ed32be99337210daabc769e28d9823a24905b86f8f557c63edc0502cff5a1c34aaee25e004316bc3efda2c
6
+ metadata.gz: cf0bfcba525fbacbb09919754faf51e3702bdfba09430601db181485e5626949a0f6ed8797a34e37e1f13d19100fe4bf020e6f3ef7c77aad40efe544f7f3007d
7
+ data.tar.gz: bc307c6eda1000ad5a60be2bcfd98b18fa7bb33faf4bbf4db20c5fa4db3cb3653b55f39dba1653e83d0a8a8d3ec33ffe3a20da434d539993ae3b3447e8f3dea4
data/README.textile CHANGED
@@ -37,6 +37,8 @@ FastImage accepts additional HTTP headers. This can be used to set a user agent
37
37
 
38
38
  FastImage can give you information about the parsed display orientation of an image with Exif data (jpeg or tiff).
39
39
 
40
+ FastImage also handles "Data URIs":https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs correctly.
41
+
40
42
  h2. Security
41
43
 
42
44
  As of v1.6.7 FastImage no longer uses @openuri@ to open files, but directly calls @File.open@. Take care to sanitise the strings passed to FastImage; it will try to read from whatever is passed.
@@ -62,6 +64,8 @@ FastImage.size("http://stephensykes.com/images/ss.com_x.gif", :http_header => {'
62
64
  => [266, 56]
63
65
  FastImage.new("http://stephensykes.com/images/ExifOrientation3.jpg").orientation
64
66
  => 3
67
+ FastImage.size("data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==")
68
+ => [1, 1]
65
69
  </code></pre>
66
70
 
67
71
  h2. Installation
@@ -97,7 +101,7 @@ irb> uri = "http://upload.wikimedia.org/wikipedia/commons/b/b4/Mardin_1350660_13
97
101
  irb> puts Benchmark.measure {open(uri, 'rb') {|fh| p ImageSize.new(fh).size}}
98
102
  [9545, 6623]
99
103
  0.680000 0.250000 0.930000 ( 7.571887)
100
-
104
+
101
105
  irb> puts Benchmark.measure {p FastImage.size(uri)}
102
106
  [9545, 6623]
103
107
  0.010000 0.000000 0.010000 ( 0.090640)
@@ -114,7 +118,7 @@ irb> uri = "http://upload.wikimedia.org/wikipedia/commons/1/11/Shinbutsureijoush
114
118
  irb> puts Benchmark.measure {open(uri, 'rb') {|fh| p ImageSize.new(fh).size}}
115
119
  [1120, 1559]
116
120
  1.080000 0.370000 1.450000 ( 13.766962)
117
-
121
+
118
122
  irb> puts Benchmark.measure {p FastImage.size(uri)}
119
123
  [1120, 1559]
120
124
  3.490000 3.810000 7.300000 ( 11.754315)
@@ -124,8 +128,8 @@ h2. Tests
124
128
 
125
129
  You'll need to @gem install fakeweb@ and possibly also @gem install test-unit@ to be able to run the tests.
126
130
 
127
- bc.. $ ruby test.rb
128
- Run options:
131
+ bc.. $ ruby test.rb
132
+ Run options:
129
133
 
130
134
  # Running tests:
131
135
 
data/lib/fastimage.rb CHANGED
@@ -28,7 +28,7 @@
28
28
  # or referrer which some servers require. Pass an :http_header argument to specify headers,
29
29
  # e.g., :http_header => {'User-Agent' => 'Fake Browser'}.
30
30
  #
31
- # FastImage can give you information about the parsed display orientation of an image with Exif
31
+ # FastImage can give you information about the parsed display orientation of an image with Exif
32
32
  # data (jpeg or tiff).
33
33
  #
34
34
  # === Examples
@@ -55,10 +55,18 @@
55
55
  #
56
56
 
57
57
  require 'net/https'
58
- require 'addressable/uri'
59
58
  require 'delegate'
60
59
  require 'pathname'
61
60
  require 'zlib'
61
+ require 'base64'
62
+ require 'uri'
63
+
64
+ # see http://stackoverflow.com/questions/5208851/i/41048816#41048816
65
+ if RUBY_VERSION < "2.2"
66
+ module URI
67
+ DEFAULT_PARSER = Parser.new(:HOSTNAME => "(?:(?:[a-zA-Z\\d](?:[-\\_a-zA-Z\\d]*[a-zA-Z\\d])?)\\.)*(?:[a-zA-Z](?:[-\\_a-zA-Z\\d]*[a-zA-Z\\d])?)\\.?")
68
+ end
69
+ end
62
70
 
63
71
  class FastImage
64
72
  attr_reader :size, :type, :content_length, :orientation
@@ -184,10 +192,12 @@ class FastImage
184
192
 
185
193
  if uri.respond_to?(:read)
186
194
  fetch_using_read(uri)
195
+ elsif uri.start_with?('data:')
196
+ fetch_using_base64(uri)
187
197
  else
188
198
  begin
189
- @parsed_uri = Addressable::URI.parse(uri)
190
- rescue Addressable::URI::InvalidURIError
199
+ @parsed_uri = URI.parse(uri)
200
+ rescue URI::InvalidURIError
191
201
  fetch_using_file_open
192
202
  else
193
203
  if @parsed_uri.scheme == "http" || @parsed_uri.scheme == "https"
@@ -237,14 +247,16 @@ class FastImage
237
247
  if res.is_a?(Net::HTTPRedirection) && @redirect_count < 4
238
248
  @redirect_count += 1
239
249
  begin
240
- newly_parsed_uri = Addressable::URI.parse(res['Location'])
250
+ newly_parsed_uri = URI.parse(res['Location'])
241
251
  # The new location may be relative - check for that
242
- if newly_parsed_uri.scheme != "http" && newly_parsed_uri.scheme != "https"
252
+ if protocol_relative_url?(res['Location'])
253
+ @parsed_uri = URI.parse("#{@parsed_uri.scheme}:#{res['Location']}")
254
+ elsif newly_parsed_uri.scheme != "http" && newly_parsed_uri.scheme != "https"
243
255
  @parsed_uri.path = res['Location']
244
256
  else
245
257
  @parsed_uri = newly_parsed_uri
246
258
  end
247
- rescue Addressable::URI::InvalidURIError
259
+ rescue URI::InvalidURIError
248
260
  else
249
261
  fetch_using_http_from_parsed_uri
250
262
  break
@@ -282,14 +294,18 @@ class FastImage
282
294
  end
283
295
  end
284
296
 
297
+ def protocol_relative_url?(url)
298
+ url.start_with?("//")
299
+ end
300
+
285
301
  def proxy_uri
286
302
  begin
287
303
  if @options[:proxy]
288
- proxy = Addressable::URI.parse(@options[:proxy])
304
+ proxy = URI.parse(@options[:proxy])
289
305
  else
290
- proxy = ENV['http_proxy'] && ENV['http_proxy'] != "" ? Addressable::URI.parse(ENV['http_proxy']) : nil
306
+ proxy = ENV['http_proxy'] && ENV['http_proxy'] != "" ? URI.parse(ENV['http_proxy']) : nil
291
307
  end
292
- rescue Addressable::URI::InvalidURIError
308
+ rescue URI::InvalidURIError
293
309
  proxy = nil
294
310
  end
295
311
  proxy
@@ -299,9 +315,9 @@ class FastImage
299
315
  proxy = proxy_uri
300
316
 
301
317
  if proxy
302
- @http = Net::HTTP::Proxy(proxy.host, proxy.port).new(@parsed_uri.host, @parsed_uri.inferred_port)
318
+ @http = Net::HTTP::Proxy(proxy.host, proxy.port).new(@parsed_uri.host, @parsed_uri.port)
303
319
  else
304
- @http = Net::HTTP.new(@parsed_uri.host, @parsed_uri.inferred_port)
320
+ @http = Net::HTTP.new(@parsed_uri.host, @parsed_uri.port)
305
321
  end
306
322
  @http.use_ssl = (@parsed_uri.scheme == "https")
307
323
  @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
@@ -334,6 +350,7 @@ class FastImage
334
350
  end
335
351
 
336
352
  def fetch_using_file_open
353
+ @content_length = File.size?(@uri)
337
354
  File.open(@uri) do |s|
338
355
  fetch_using_read(s)
339
356
  end
@@ -351,7 +368,7 @@ class FastImage
351
368
  else
352
369
  @orientation = 1
353
370
  end
354
-
371
+
355
372
  instance_variable_set("@#{@property}", result)
356
373
  else
357
374
  raise CannotParseImage
@@ -366,6 +383,11 @@ class FastImage
366
383
  send("parse_size_for_#{@type}")
367
384
  end
368
385
 
386
+ def fetch_using_base64(uri)
387
+ data = uri.split(',')[1]
388
+ fetch_using_read StringIO.new(Base64.decode64(data))
389
+ end
390
+
369
391
  module StreamUtil # :nodoc:
370
392
  def read_byte
371
393
  read(1)[0].ord
@@ -395,6 +417,7 @@ class FastImage
395
417
  @str = ''
396
418
  end
397
419
 
420
+ # Peeking beyond the end of the input will raise
398
421
  def peek(n)
399
422
  while @strpos + n - 1 >= @str.size
400
423
  unused_str = @str[@strpos..-1]
@@ -466,9 +489,16 @@ class FastImage
466
489
  when "<s"
467
490
  :svg
468
491
  when "<?"
469
- :svg if @stream.peek(100).include?("<svg")
492
+ # Peek 10 more chars each time, and if end of file is reached just raise
493
+ # unknown. We assume the <svg tag cannot be within 10 chars of the end of
494
+ # the file, and is within the first 250 chars.
495
+ begin
496
+ :svg if (1..25).detect {|n| @stream.peek(10 * n).include?("<svg")}
497
+ rescue FiberError
498
+ nil
499
+ end
470
500
  end
471
-
501
+
472
502
  parsed_type or raise UnknownImageType
473
503
  end
474
504
 
@@ -644,7 +674,7 @@ class FastImage
644
674
  end
645
675
 
646
676
  parse_exif_ifd
647
-
677
+
648
678
  @orientation ||= 1
649
679
  end
650
680
 
@@ -676,6 +706,10 @@ class FastImage
676
706
  [@width, @width / @ratio]
677
707
  elsif @height && @ratio
678
708
  [@height * @ratio, @height]
709
+ elsif @viewbox_width && @viewbox_height
710
+ [@viewbox_width, @viewbox_height]
711
+ else
712
+ nil
679
713
  end
680
714
  end
681
715
 
@@ -698,14 +732,20 @@ class FastImage
698
732
  return if @width
699
733
  elsif attr_name.join =~ /viewbox/i
700
734
  values = attr_value.split(/\s/)
701
- @ratio = values[2].to_f / values[3].to_f
735
+ if values[2].to_f > 0 && values[3].to_f > 0
736
+ @ratio = values[2].to_f / values[3].to_f
737
+ @viewbox_width = values[2].to_i
738
+ @viewbox_height = values[3].to_i
739
+ end
702
740
  end
703
741
  when /\w/
704
742
  attr_name << char
743
+ when "<"
744
+ attr_name = [char]
705
745
  when ">"
706
746
  state = :stop if state == :started
707
747
  else
708
- state = :started if attr_name.join == "svg"
748
+ state = :started if attr_name.join == "<svg"
709
749
  attr_name.clear
710
750
  end
711
751
  end
metadata CHANGED
@@ -1,83 +1,69 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastimage
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Sykes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-03 00:00:00.000000000 Z
11
+ date: 2017-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: addressable
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: fakeweb
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
- - - "~>"
17
+ - - ~>
32
18
  - !ruby/object:Gem::Version
33
19
  version: '1.3'
34
20
  type: :development
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
- - - "~>"
24
+ - - ~>
39
25
  - !ruby/object:Gem::Version
40
26
  version: '1.3'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rake
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
- - - "~>"
31
+ - - ~>
46
32
  - !ruby/object:Gem::Version
47
33
  version: '10.5'
48
34
  type: :development
49
35
  prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
- - - "~>"
38
+ - - ~>
53
39
  - !ruby/object:Gem::Version
54
40
  version: '10.5'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rdoc
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
- - - ">="
45
+ - - '>='
60
46
  - !ruby/object:Gem::Version
61
47
  version: '0'
62
48
  type: :development
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
- - - ">="
52
+ - - '>='
67
53
  - !ruby/object:Gem::Version
68
54
  version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: test-unit
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
- - - ">="
59
+ - - '>='
74
60
  - !ruby/object:Gem::Version
75
61
  version: '0'
76
62
  type: :development
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
- - - ">="
66
+ - - '>='
81
67
  - !ruby/object:Gem::Version
82
68
  version: '0'
83
69
  description: FastImage finds the size or type of an image given its uri by fetching
@@ -97,22 +83,22 @@ licenses:
97
83
  metadata: {}
98
84
  post_install_message:
99
85
  rdoc_options:
100
- - "--charset=UTF-8"
86
+ - --charset=UTF-8
101
87
  require_paths:
102
88
  - lib
103
89
  required_ruby_version: !ruby/object:Gem::Requirement
104
90
  requirements:
105
- - - ">="
91
+ - - '>='
106
92
  - !ruby/object:Gem::Version
107
93
  version: 1.9.2
108
94
  required_rubygems_version: !ruby/object:Gem::Requirement
109
95
  requirements:
110
- - - ">="
96
+ - - '>='
111
97
  - !ruby/object:Gem::Version
112
98
  version: '0'
113
99
  requirements: []
114
100
  rubyforge_project:
115
- rubygems_version: 2.4.5
101
+ rubygems_version: 2.0.14.1
116
102
  signing_key:
117
103
  specification_version: 4
118
104
  summary: FastImage - Image info fast