swf_file 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- ==Introduction
1
+ =swf_file
2
2
  Based on the swfutil lib, by Dennis Zhuang, the SWF File is lightweight gem to read swf file headers from within a Ruby application.
3
3
 
4
4
  ==Ruby compatibility
@@ -14,7 +14,23 @@
14
14
  Please refer to the LICENSE file.
15
15
 
16
16
  ==Example
17
- TODO
17
+ swf = SwfFile.header 'clicktag.swf' # load the file
18
+
19
+ # Access the various header options. Please check the unit tests for more usage examples.
20
+ puts swf.size
21
+ puts swf.compressed?
22
+ puts swf.version
23
+ puts swf.bit_count
24
+ puts swf.xmax
25
+ puts swf.ymax
26
+ puts swf.width # In pixels
27
+ puts swf.height # In pixels
28
+ puts swf.frame_rate
29
+ puts swf.frame_count
30
+ puts swf.duration # In milliseconds
31
+ puts swf.avm_version
32
+ puts swf.signature
33
+
18
34
 
19
35
  ==Issues, improvements, feedback an suggestions
20
36
  To report issues, please use GitHub's issue manager (http://github.com/DBA/swf_file/issues). Meanwhile, feel free to fork the project and submit your modifications.
@@ -23,5 +39,5 @@
23
39
 
24
40
  ==Pending
25
41
  * Cleanup the class PackedBitObject, which still suffers from the pure import from SwfUtil
26
- * Modularize SwfHeader a bit more
27
- * Docs
42
+ * Docs
43
+ * Modularize SwfHeader a bit more
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 1.0.0
@@ -0,0 +1,10 @@
1
+ module Assertions
2
+ def compressed?(memoize_result = true)
3
+ buffer_compressed?(memoize_result)
4
+ end
5
+
6
+ private
7
+ def swf?
8
+ @buffer[0,3] == 'FWS' || @buffer[0,3] == 'CWS'
9
+ end
10
+ end
@@ -4,7 +4,7 @@ module Compression
4
4
  if memoize_result
5
5
  @compressed ||= @buffer[0].ord == ?C.ord
6
6
  else
7
- @buffer[0].ord == ?C.ord
7
+ @compressed = @buffer[0].ord == ?C.ord
8
8
  end
9
9
  end
10
10
 
@@ -1,4 +1,23 @@
1
1
  module Conversions
2
+ def to_s
3
+ "#{@file} #{@width}x#{@height} #{@frame_rate}fps"
4
+ end
5
+
6
+ def to_hash
7
+ { :file => @file,
8
+ :signature => @signature,
9
+ :version => @version,
10
+ :avm_version => @avm_version,
11
+ :size => @size,
12
+ :bit_count => @bit_count,
13
+ :xmax => @xmax,
14
+ :ymax => @ymax,
15
+ :width => @width,
16
+ :height => @height,
17
+ :frame_rate => @frame_rate,
18
+ :frame_count => @frame_count }
19
+ end
20
+
2
21
  module Twips
3
22
  def self.from_pixels(pixels)
4
23
  pixels * 20
@@ -10,21 +29,4 @@ module Conversions
10
29
  twips / 20
11
30
  end
12
31
  end
13
-
14
- module Hash
15
- def self.from_swf_header(header)
16
- { file: header.file,
17
- signature: header.signature,
18
- version: header.version,
19
- avm_version: header.avm_version,
20
- size: header.size,
21
- bit_count: header.bit_count,
22
- xmax: header.xmax,
23
- ymax: header.ymax,
24
- width: header.width,
25
- height: header.height,
26
- frame_rate: header.frame_rate,
27
- frame_count: header.frame_count }
28
- end
29
- end
30
32
  end
@@ -1,54 +1,47 @@
1
- # TODO: Needs refactoring & cleanup
2
-
3
1
  class PackedBitObject
4
2
  attr_accessor :bitIndex, :byteIndex, :value, :nextBitIndex, :nextByteIndex, :nextByteBoundary
5
3
 
6
- def initialize(bitMarker,byteMarker,decimalValue)
7
- @bitIndex = bitMarker;
8
- @byteIndex = byteMarker;
9
- @value = decimalValue;
10
- @nextBitIndex = bitMarker;
11
- if ( bitMarker <= 7 )
12
- @nextBitIndex+=1
13
- @nextByteIndex =byteMarker
14
- @nextByteBoundary = (byteMarker+=1)
4
+ def initialize(bitMarker, byteMarker, decimalValue)
5
+ @nextBitIndex = @bitIndex = bitMarker
6
+ @byteIndex = byteMarker
7
+ @value = decimalValue
8
+
9
+ if bitMarker <= 7
10
+ @nextBitIndex += 1
11
+ @nextByteIndex = byteMarker
12
+ @nextByteBoundary = byteMarker += 1
15
13
  else
16
- @nextBitIndex = 0
17
- @nextByteIndex+=1
14
+ @nextBitIndex = 0
15
+ @nextByteIndex +=1
18
16
  @nextByteBoundary = @nextByteIndex;
19
17
  end
20
18
  end
21
19
 
22
20
  def self.from_packed_bits(bytes, byte_marker, bit_marker, length)
23
- total = 0
24
- shift = 7 - bit_marker
25
- counter = 0
26
- bit_index = bit_marker
27
- byte_index = byte_marker
21
+ counter = total = 0
22
+ shift = 7 - bit_marker
23
+ bit_index = bit_marker
24
+ byte_index = byte_marker
28
25
 
29
- while counter<length
26
+ while counter < length
30
27
  (bit_marker...8).each do |i|
31
- bit =((bytes[byte_marker].ord & 0xff ) >> shift ) & 1
32
- total = ( total << 1 ) + bit
28
+ bit = ((bytes[byte_marker].ord & 0xff ) >> shift) & 1
29
+ total = (total << 1) + bit
33
30
  bit_index = i
34
- shift-=1
35
- counter+=1
31
+ shift -= 1
32
+ counter += 1
36
33
 
37
- if counter==length
38
- break
39
- end
34
+ break if counter == length
40
35
  end
41
36
 
42
- byte_index = byte_marker
43
- byte_marker+=1
44
- bit_marker = 0
45
- shift = 7
37
+ byte_index = byte_marker
38
+ byte_marker +=1
39
+ bit_marker = 0
40
+ shift = 7
46
41
  end
47
42
 
48
43
  pbo = PackedBitObject.new(bit_index, byte_index, total)
49
-
50
44
  yield pbo if block_given?
51
-
52
45
  pbo
53
46
  end
54
47
  end
@@ -1,2 +1,48 @@
1
1
  module Parser
2
+ private
3
+ def parse_header
4
+ @buffer, @size = get_swf_buffer_and_size
5
+ raise RuntimeError, "The provided file does not appear to be an SWF", caller unless swf?
6
+
7
+ @signature = @buffer[0,3]
8
+ @version = @buffer[3].ord
9
+
10
+ decompress_buffer! if compressed?
11
+
12
+ @bit_count = ((@buffer[8].ord & 0xff) >> 3)
13
+ end
14
+
15
+ def parse_packed_bits
16
+ PackedBitObject.from_packed_bits(@buffer, 8, 5, @bit_count) do |pbo|
17
+
18
+ PackedBitObject.from_packed_bits(@buffer, pbo.nextByteIndex, pbo.nextBitIndex, @bit_count) do |pbo2|
19
+ @xmax = pbo2.value
20
+
21
+ PackedBitObject.from_packed_bits(@buffer, pbo2.nextByteIndex, pbo2.nextBitIndex, @bit_count) do |pbo3|
22
+
23
+ PackedBitObject.from_packed_bits(@buffer, pbo3.nextByteIndex, pbo3.nextBitIndex, @bit_count) do |pbo4|
24
+ @ymax = pbo4.value
25
+ @width = Conversions::Pixels.from_twips @xmax
26
+ @height = Conversions::Pixels.from_twips @ymax
27
+
28
+ byte_pointer = pbo4.nextByteIndex + 2
29
+
30
+ @frame_rate = @buffer[byte_pointer].ord
31
+ byte_pointer += 1
32
+
33
+ fc1 = @buffer[byte_pointer].ord & 0xFF
34
+ byte_pointer += 1
35
+
36
+ fc2 = @buffer[byte_pointer].ord & 0xFF
37
+ byte_pointer += 1
38
+
39
+ @frame_count = (fc2 << 8) + fc1
40
+ byte_pointer+=2
41
+
42
+ @avm_version = ((@buffer[byte_pointer].ord & 0x08) == 0) ? "AVM1" : "AVM2"
43
+ end #pbo4
44
+ end #pbo3
45
+ end #pbo2
46
+ end #pbo
47
+ end
2
48
  end
@@ -1,5 +1,8 @@
1
1
  class SwfHeader
2
+ include Parser
2
3
  include Compression
4
+ include Conversions
5
+ include Assertions
3
6
 
4
7
  attr_reader :file, :signature, :version, :avm_version, :size, :bit_count,
5
8
  :xmax, :ymax, :width, :height,
@@ -10,73 +13,17 @@ class SwfHeader
10
13
  parse_header
11
14
  parse_packed_bits
12
15
  end
13
-
14
- def compressed?(memoize_result = true)
15
- buffer_compressed?(memoize_result)
16
- end
17
-
16
+
18
17
  # Returns the duration in milliseconds
18
+ # The formula used in this method used to be +((@frame_count / @frame_rate.to_f).round(5) * 1000).round+.
19
+ # This however, was not compatible with ruby 1.8, thus reverted to its current form.
19
20
  def duration
20
- ((@frame_count / @frame_rate.to_f).round(5) * 1000).round
21
- end
22
-
23
- def to_s
24
- "#{@file} #{@width}x#{@height} #{@frame_rate}fps"
25
- end
26
-
27
- def to_hash
28
- Conversions::Hash.from_swf_header self
21
+ ((@frame_count / @frame_rate.to_f * 10**5).round.to_f / 10**5 * 1000).round
29
22
  end
30
23
 
31
24
  alias :inspect :to_hash
32
25
 
33
26
  private
34
- def parse_header
35
- @buffer, @size = get_swf_buffer_and_size
36
- raise RuntimeError, "The provided file does not appear to be an SWF", caller unless swf?
37
-
38
- @signature = @buffer[0,3]
39
- @version = @buffer[3].ord
40
-
41
- decompress_buffer! if compressed?
42
-
43
- @bit_count = ((@buffer[8].ord & 0xff) >> 3)
44
- end
45
-
46
- def parse_packed_bits
47
- PackedBitObject.from_packed_bits(@buffer, 8, 5, @bit_count) do |pbo|
48
-
49
- PackedBitObject.from_packed_bits(@buffer, pbo.nextByteIndex, pbo.nextBitIndex, @bit_count) do |pbo2|
50
- @xmax = pbo2.value
51
-
52
- PackedBitObject.from_packed_bits(@buffer, pbo2.nextByteIndex, pbo2.nextBitIndex, @bit_count) do |pbo3|
53
-
54
- PackedBitObject.from_packed_bits(@buffer, pbo3.nextByteIndex, pbo3.nextBitIndex, @bit_count) do |pbo4|
55
- @ymax = pbo4.value
56
- @width = Conversions::Pixels.from_twips @xmax
57
- @height = Conversions::Pixels.from_twips @ymax
58
-
59
- byte_pointer = pbo4.nextByteIndex + 2
60
-
61
- @frame_rate = @buffer[byte_pointer].ord
62
- byte_pointer += 1
63
-
64
- fc1 = @buffer[byte_pointer].ord & 0xFF
65
- byte_pointer += 1
66
-
67
- fc2 = @buffer[byte_pointer].ord & 0xFF
68
- byte_pointer += 1
69
-
70
- @frame_count = (fc2 << 8) + fc1
71
- byte_pointer+=2
72
-
73
- @avm_version = ((@buffer[byte_pointer].ord & 0x08) == 0) ? "AVM1" : "AVM2"
74
- end #pbo4
75
- end #pbo3
76
- end #pbo2
77
- end #pbo
78
- end
79
-
80
27
  def get_swf_buffer_and_size
81
28
  size = 0
82
29
 
@@ -90,8 +37,4 @@ class SwfHeader
90
37
 
91
38
  [buffer, size]
92
39
  end
93
-
94
- def swf?
95
- @buffer[0,3] == 'FWS' || @buffer[0,3] == 'CWS'
96
- end
97
40
  end
data/lib/swf_file.rb CHANGED
@@ -4,17 +4,33 @@ require 'zlib'
4
4
  require 'parser'
5
5
  require 'compression'
6
6
  require 'conversions'
7
+ require 'assertions'
7
8
  require 'packed_bit_object'
8
9
  require 'swf_header'
9
10
 
10
11
  class SwfFile
11
- def initialize(swf_path)
12
+ # Class methods
13
+ def self.header(swf_path)
12
14
  raise RuntimeError, "SWF file not found.", caller unless File.exists?(swf_path)
15
+
16
+ header = SwfHeader.new(swf_path)
17
+ yield(header) if block_given?
18
+ header
13
19
  end
14
20
 
15
- def self.header(swf_path)
21
+ # Instance methods
22
+ def initialize(swf_path)
16
23
  raise RuntimeError, "SWF file not found.", caller unless File.exists?(swf_path)
17
24
 
18
- SwfHeader.new(swf_path)
25
+ @header = SwfHeader.new(swf_path)
26
+ end
27
+
28
+ def header
29
+ yield(@header) if block_given?
30
+ @header
31
+ end
32
+
33
+ def compressed?
34
+ @header.compressed?
19
35
  end
20
36
  end
data/swf_file.gemspec ADDED
@@ -0,0 +1,59 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{swf_file}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["DBA"]
12
+ s.date = %q{2010-05-08}
13
+ s.description = %q{Based on the swfutil lib, by Dennis Zhuang, the SWF File is lightweight gem to read swf file headers from within a Ruby application. This gem is fully written in Ruby and is compatible with Ruby v1.9.x}
14
+ s.email = %q{dba@gnomeslab.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "fixtures/clicktag-decompressed.swf",
26
+ "fixtures/clicktag.swf",
27
+ "fixtures/smallgoat.jpg",
28
+ "lib/swf_file.rb",
29
+ "lib/swf_file/assertions.rb",
30
+ "lib/swf_file/compression.rb",
31
+ "lib/swf_file/conversions.rb",
32
+ "lib/swf_file/packed_bit_object.rb",
33
+ "lib/swf_file/parser.rb",
34
+ "lib/swf_file/swf_header.rb",
35
+ "swf_file.gemspec",
36
+ "test/test_helper.rb",
37
+ "test/unit/swf_file_test.rb"
38
+ ]
39
+ s.homepage = %q{http://github.com/DBA/swf_file}
40
+ s.rdoc_options = ["--charset=UTF-8"]
41
+ s.require_paths = ["lib"]
42
+ s.rubygems_version = %q{1.3.7}
43
+ s.summary = %q{SWF File is lightweight gem to read swf file headers from within a Ruby application}
44
+ s.test_files = [
45
+ "test/test_helper.rb",
46
+ "test/unit/swf_file_test.rb"
47
+ ]
48
+
49
+ if s.respond_to? :specification_version then
50
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
51
+ s.specification_version = 3
52
+
53
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ else
55
+ end
56
+ else
57
+ end
58
+ end
59
+
data/test/test_helper.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
 
3
+ require 'rubygems' if RUBY_VERSION =~ /1\.8.+/
3
4
  require 'test/unit'
4
5
  require 'shoulda'
5
- #require 'swfheader'
6
6
  require 'ruby-debug'
7
7
  require 'swf_file'
8
8
 
@@ -1,9 +1,11 @@
1
- require_relative '../test_helper'
1
+ $:.unshift(File.join(File.dirname(__FILE__), '../', '../', 'test'))
2
+
3
+ require 'test_helper'
2
4
 
3
5
  class SwfFileTest < Test::Unit::TestCase
4
6
 
5
7
  context "SwfFile" do
6
- context "Initialization" do
8
+ context "instance methods" do
7
9
  should "not be initializable without an SWF file path" do
8
10
  assert_raise(ArgumentError) { SwfFile.new }
9
11
  end
@@ -11,7 +13,14 @@ class SwfFileTest < Test::Unit::TestCase
11
13
  should "raise an error if an invalid path is provided" do
12
14
  assert_raise(RuntimeError) { SwfFile.new "/path_to_imaginary_file" }
13
15
  end
14
- end # Initialization context
16
+
17
+ should "return a header with the regular properties" do
18
+ swf = SwfFile.new fixture_path('clicktag.swf')
19
+ assert_equal SwfHeader, swf.header.class
20
+ assert_equal 4156, swf.header.size
21
+ assert_equal swf.compressed?, swf.header.compressed?
22
+ end
23
+ end # instance methods
15
24
 
16
25
  context "class method header" do
17
26
  should "raise an error when not provided with an SWF" do
@@ -32,18 +41,18 @@ class SwfFileTest < Test::Unit::TestCase
32
41
 
33
42
  should "state if the swf was originally compressed" do
34
43
  assert @header.compressed?
35
- refute SwfFile.header(fixture_path('clicktag-decompressed.swf')).compressed?
44
+ assert !SwfFile.header(fixture_path('clicktag-decompressed.swf')).compressed?
36
45
  end
37
46
 
38
47
  should "not make available private compression module methods" do
39
48
  %w{ :buffer_compressed? :strip_buffer_header :decompress_buffer! }.each do |method|
40
- refute @header.respond_to?(method)
49
+ assert !@header.respond_to?(method)
41
50
  end
42
51
  end
43
52
 
44
53
  should "state if its buffer is currently compressed" do
45
54
  assert @header.compressed?
46
- refute @header.compressed?(false)
55
+ assert !@header.compressed?(false)
47
56
  end
48
57
 
49
58
  should "have the version" do
metadata CHANGED
@@ -3,10 +3,10 @@ name: swf_file
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
- - 0
7
6
  - 1
8
7
  - 0
9
- version: 0.1.0
8
+ - 0
9
+ version: 1.0.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - DBA
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-06 00:00:00 +01:00
17
+ date: 2010-05-08 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -26,22 +26,24 @@ extensions: []
26
26
 
27
27
  extra_rdoc_files:
28
28
  - LICENSE
29
- - README
29
+ - README.rdoc
30
30
  files:
31
31
  - .gitignore
32
32
  - LICENSE
33
- - README
33
+ - README.rdoc
34
34
  - Rakefile
35
35
  - VERSION
36
36
  - fixtures/clicktag-decompressed.swf
37
37
  - fixtures/clicktag.swf
38
38
  - fixtures/smallgoat.jpg
39
39
  - lib/swf_file.rb
40
+ - lib/swf_file/assertions.rb
40
41
  - lib/swf_file/compression.rb
41
42
  - lib/swf_file/conversions.rb
42
43
  - lib/swf_file/packed_bit_object.rb
43
44
  - lib/swf_file/parser.rb
44
45
  - lib/swf_file/swf_header.rb
46
+ - swf_file.gemspec
45
47
  - test/test_helper.rb
46
48
  - test/unit/swf_file_test.rb
47
49
  has_rdoc: true