fastimage 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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