swf_file 0.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.
- data/.gitignore +3 -0
- data/LICENSE +28 -0
- data/README +27 -0
- data/Rakefile +28 -0
- data/VERSION +1 -0
- data/fixtures/clicktag-decompressed.swf +0 -0
- data/fixtures/clicktag.swf +0 -0
- data/fixtures/smallgoat.jpg +0 -0
- data/lib/swf_file/compression.rb +25 -0
- data/lib/swf_file/conversions.rb +30 -0
- data/lib/swf_file/packed_bit_object.rb +54 -0
- data/lib/swf_file/parser.rb +2 -0
- data/lib/swf_file/swf_header.rb +97 -0
- data/lib/swf_file.rb +20 -0
- data/test/test_helper.rb +11 -0
- data/test/unit/swf_file_test.rb +99 -0
- metadata +81 -0
data/.gitignore
ADDED
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,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
|
data/test/test_helper.rb
ADDED
@@ -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
|