swf_file 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .DS_Store
2
+ .bundle
3
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ This gem is based on Dennis Zhuang's swf-util library, made available at http://code.google.com/p/swf-util/, under the Apache License 2.0 (vide http://www.apache.org/licenses/LICENSE-2.0).
2
+
3
+ The fixture files smallgoat.jpg, clicktag-decompressed.swf, clicktag.swf, originally made available under the MIT license (vide http://www.opensource.org/licenses/mit-license.php) at http://github.com/2performant/swiff, are included in this gem, without modification, under their original copyright © 2010 held by 2Perfomant.
4
+
5
+ All modifications and additions contained within this gem, made available at http://github.com/DBA/swfheader, are licensed under the following terms and conditions:
6
+
7
+ Copyright (c) 2010 Diogo Almeida
8
+
9
+ Permission is hereby granted, free of charge, to any person
10
+ obtaining a copy of this software and associated documentation
11
+ files (the "Software"), to deal in the Software without
12
+ restriction, including without limitation the rights to use,
13
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the
15
+ Software is furnished to do so, subject to the following
16
+ conditions:
17
+
18
+ The above copyright notice and this permission notice shall be
19
+ included in all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,27 @@
1
+ ==Introduction
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
+
4
+ ==Ruby compatibility
5
+ Target version: 1.9.2dev
6
+ Also compatible with: 1.9.1-p376 and 1.8.7-p
7
+
8
+ Not tested with versions under 1.8.7-p. Should you use this lib with other ruby versions, please provide feedback.
9
+
10
+ ==Install
11
+ gem install swf_file
12
+
13
+ ==LICENSE
14
+ Please refer to the LICENSE file.
15
+
16
+ ==Example
17
+ TODO
18
+
19
+ ==Issues, improvements, feedback an suggestions
20
+ 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.
21
+
22
+ Should you wish to contact me directly, please use GitHub's message box or the email available at the Rakefile.
23
+
24
+ ==Pending
25
+ * Cleanup the class PackedBitObject, which still suffers from the pure import from SwfUtil
26
+ * Modularize SwfHeader a bit more
27
+ * Docs
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ require 'rake'
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |gemspec|
6
+ gemspec.name = "swf_file"
7
+ gemspec.summary = "SWF File is lightweight gem to read swf file headers from within a Ruby application"
8
+ gemspec.description = "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"
9
+ gemspec.email = "dba@gnomeslab.com"
10
+ gemspec.homepage = "http://github.com/DBA/swf_file"
11
+ gemspec.authors = ["DBA"]
12
+
13
+ # dependencies defined in Gemfile
14
+ end
15
+ rescue LoadError
16
+ puts "Jeweler not available. Install it with: gem install jeweler"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ #test_files_pattern = 'test/{unit,functional,other,matchers}/**/*_test.rb'
21
+ test_files_pattern = 'test/unit/swf_file_test.rb'
22
+ Rake::TestTask.new do |t|
23
+ t.libs << 'lib'
24
+ t.pattern = test_files_pattern
25
+ t.verbose = true
26
+ end
27
+
28
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
Binary file
Binary file
Binary file
@@ -0,0 +1,25 @@
1
+ module Compression
2
+ private
3
+ def buffer_compressed?(memoize_result = true)
4
+ if memoize_result
5
+ @compressed ||= @buffer[0].ord == ?C.ord
6
+ else
7
+ @buffer[0].ord == ?C.ord
8
+ end
9
+ end
10
+
11
+ def decompress_buffer!
12
+ return @buffer unless buffer_compressed?(false)
13
+
14
+ _buffer = @buffer # local buffer copy
15
+ _buffer = Zlib::Inflate.new.inflate strip_buffer_header(_buffer)
16
+ _buffer = _buffer[0,8] + _buffer
17
+ _buffer[0] = ?F
18
+
19
+ @buffer = _buffer
20
+ end
21
+
22
+ def strip_buffer_header(buffer)
23
+ buffer[8, buffer.size - 8]
24
+ end
25
+ end
@@ -0,0 +1,30 @@
1
+ module Conversions
2
+ module Twips
3
+ def self.from_pixels(pixels)
4
+ pixels * 20
5
+ end
6
+ end
7
+
8
+ module Pixels
9
+ def self.from_twips(twips)
10
+ twips / 20
11
+ end
12
+ 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
+ end
@@ -0,0 +1,54 @@
1
+ # TODO: Needs refactoring & cleanup
2
+
3
+ class PackedBitObject
4
+ attr_accessor :bitIndex, :byteIndex, :value, :nextBitIndex, :nextByteIndex, :nextByteBoundary
5
+
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)
15
+ else
16
+ @nextBitIndex = 0
17
+ @nextByteIndex+=1
18
+ @nextByteBoundary = @nextByteIndex;
19
+ end
20
+ end
21
+
22
+ 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
28
+
29
+ while counter<length
30
+ (bit_marker...8).each do |i|
31
+ bit =((bytes[byte_marker].ord & 0xff ) >> shift ) & 1
32
+ total = ( total << 1 ) + bit
33
+ bit_index = i
34
+ shift-=1
35
+ counter+=1
36
+
37
+ if counter==length
38
+ break
39
+ end
40
+ end
41
+
42
+ byte_index = byte_marker
43
+ byte_marker+=1
44
+ bit_marker = 0
45
+ shift = 7
46
+ end
47
+
48
+ pbo = PackedBitObject.new(bit_index, byte_index, total)
49
+
50
+ yield pbo if block_given?
51
+
52
+ pbo
53
+ end
54
+ end
@@ -0,0 +1,2 @@
1
+ module Parser
2
+ end
@@ -0,0 +1,97 @@
1
+ class SwfHeader
2
+ include Compression
3
+
4
+ attr_reader :file, :signature, :version, :avm_version, :size, :bit_count,
5
+ :xmax, :ymax, :width, :height,
6
+ :frame_rate, :frame_count
7
+
8
+ def initialize(swf_file)
9
+ @file = swf_file
10
+ parse_header
11
+ parse_packed_bits
12
+ end
13
+
14
+ def compressed?(memoize_result = true)
15
+ buffer_compressed?(memoize_result)
16
+ end
17
+
18
+ # Returns the duration in milliseconds
19
+ 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
29
+ end
30
+
31
+ alias :inspect :to_hash
32
+
33
+ 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
+ def get_swf_buffer_and_size
81
+ size = 0
82
+
83
+ buffer = File.open(@file,"rb") do |file|
84
+ file.seek(4, IO::SEEK_CUR)
85
+ size = file.read(4).unpack("L")[0]
86
+
87
+ file.rewind
88
+ file.read
89
+ end
90
+
91
+ [buffer, size]
92
+ end
93
+
94
+ def swf?
95
+ @buffer[0,3] == 'FWS' || @buffer[0,3] == 'CWS'
96
+ end
97
+ end
data/lib/swf_file.rb ADDED
@@ -0,0 +1,20 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'swf_file') unless $:.include? File.join(File.dirname(__FILE__), 'swf_file')
2
+
3
+ require 'zlib'
4
+ require 'parser'
5
+ require 'compression'
6
+ require 'conversions'
7
+ require 'packed_bit_object'
8
+ require 'swf_header'
9
+
10
+ class SwfFile
11
+ def initialize(swf_path)
12
+ raise RuntimeError, "SWF file not found.", caller unless File.exists?(swf_path)
13
+ end
14
+
15
+ def self.header(swf_path)
16
+ raise RuntimeError, "SWF file not found.", caller unless File.exists?(swf_path)
17
+
18
+ SwfHeader.new(swf_path)
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'test/unit'
4
+ require 'shoulda'
5
+ #require 'swfheader'
6
+ require 'ruby-debug'
7
+ require 'swf_file'
8
+
9
+ def fixture_path(filename)
10
+ File.join(File.dirname(__FILE__), '..', 'fixtures', filename)
11
+ end
@@ -0,0 +1,99 @@
1
+ require_relative '../test_helper'
2
+
3
+ class SwfFileTest < Test::Unit::TestCase
4
+
5
+ context "SwfFile" do
6
+ context "Initialization" do
7
+ should "not be initializable without an SWF file path" do
8
+ assert_raise(ArgumentError) { SwfFile.new }
9
+ end
10
+
11
+ should "raise an error if an invalid path is provided" do
12
+ assert_raise(RuntimeError) { SwfFile.new "/path_to_imaginary_file" }
13
+ end
14
+ end # Initialization context
15
+
16
+ context "class method header" do
17
+ should "raise an error when not provided with an SWF" do
18
+ assert_raise(RuntimeError) { SwfFile.header fixture_path('smallgoat.jpg') }
19
+ end
20
+
21
+ setup do
22
+ @header = SwfFile.header fixture_path('clicktag.swf')
23
+ end
24
+
25
+ should "return an instance of SwfHeader" do
26
+ assert_equal SwfHeader, @header.class
27
+ end
28
+
29
+ should "indicate the file's size" do
30
+ assert_equal 4156, @header.size
31
+ end
32
+
33
+ should "state if the swf was originally compressed" do
34
+ assert @header.compressed?
35
+ refute SwfFile.header(fixture_path('clicktag-decompressed.swf')).compressed?
36
+ end
37
+
38
+ should "not make available private compression module methods" do
39
+ %w{ :buffer_compressed? :strip_buffer_header :decompress_buffer! }.each do |method|
40
+ refute @header.respond_to?(method)
41
+ end
42
+ end
43
+
44
+ should "state if its buffer is currently compressed" do
45
+ assert @header.compressed?
46
+ refute @header.compressed?(false)
47
+ end
48
+
49
+ should "have the version" do
50
+ assert_equal 8, @header.version
51
+ end
52
+
53
+ should "have the bit count" do
54
+ assert_equal 15, @header.bit_count
55
+ end
56
+
57
+ should "have the xmax and ymax values" do
58
+ assert_equal 9360, @header.xmax
59
+ assert_equal 1200, @header.ymax
60
+ end
61
+
62
+ should "have the width and height values" do
63
+ assert_equal 468, @header.width
64
+ assert_equal 60, @header.height
65
+ end
66
+
67
+ should "have the frame rate and frame count" do
68
+ assert_equal 24, @header.frame_rate
69
+ assert_equal 1, @header.frame_count
70
+ end
71
+
72
+ should "include the duration of the swf file" do
73
+ assert_equal 42, @header.duration
74
+ end
75
+
76
+ should "contain the avm version" do
77
+ assert_equal 'AVM1', @header.avm_version
78
+ end
79
+
80
+ should "include the swf signature" do
81
+ assert_equal 'CWS', @header.signature
82
+ end
83
+
84
+ should "output basing information when to_s is invoked" do
85
+ assert @header.to_s =~ /.+clicktag.swf\s\d+x\d+\s\d\dfps/
86
+ end
87
+
88
+ should "be have a hash converter" do
89
+ assert_equal Hash, @header.to_hash.class
90
+ end
91
+
92
+ should "have the same output for the instance methods inspect and to_hash" do
93
+ assert_equal @header.to_hash, @header.inspect
94
+ end
95
+
96
+ end # SWF operations context
97
+
98
+ end # SwfFile context
99
+ end # SwfFileTest
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: swf_file
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - DBA
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-06 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: 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
22
+ email: dba@gnomeslab.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - LICENSE
29
+ - README
30
+ files:
31
+ - .gitignore
32
+ - LICENSE
33
+ - README
34
+ - Rakefile
35
+ - VERSION
36
+ - fixtures/clicktag-decompressed.swf
37
+ - fixtures/clicktag.swf
38
+ - fixtures/smallgoat.jpg
39
+ - lib/swf_file.rb
40
+ - lib/swf_file/compression.rb
41
+ - lib/swf_file/conversions.rb
42
+ - lib/swf_file/packed_bit_object.rb
43
+ - lib/swf_file/parser.rb
44
+ - lib/swf_file/swf_header.rb
45
+ - test/test_helper.rb
46
+ - test/unit/swf_file_test.rb
47
+ has_rdoc: true
48
+ homepage: http://github.com/DBA/swf_file
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --charset=UTF-8
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ requirements: []
73
+
74
+ rubyforge_project:
75
+ rubygems_version: 1.3.7
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: SWF File is lightweight gem to read swf file headers from within a Ruby application
79
+ test_files:
80
+ - test/test_helper.rb
81
+ - test/unit/swf_file_test.rb