russdeep 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document CHANGED
@@ -1,5 +1,6 @@
1
1
  README.rdoc
2
2
  lib/**/*.rb
3
+ ext/**/*.c
3
4
  bin/*
4
5
  features/**/*.feature
5
6
  LICENSE
File without changes
@@ -0,0 +1,9 @@
1
+ == 1.1.0 / 2011-03-21
2
+ * Added FuzzyComparable mixin
3
+ * Aliass for ffi-ssdeep backward compatability
4
+ * Moved to rspec 2
5
+ * Better rdoc/yard documentation
6
+
7
+ == 1.0.0 / 2011-02-20
8
+ * Initial version published.
9
+
data/Rakefile CHANGED
@@ -16,6 +16,7 @@ begin
16
16
 
17
17
  if RUBY_PLATFORM !~ /java/
18
18
  gem.extensions = FileList['ext/**/extconf.rb']
19
+ gem.extra_rdoc_files += FileList['ext/**/*.c']
19
20
  end
20
21
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
21
22
  end
@@ -24,18 +25,20 @@ rescue LoadError
24
25
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
25
26
  end
26
27
 
27
- require 'spec/rake/spectask'
28
- Spec::Rake::SpecTask.new(:spec) do |spec|
29
- spec.libs << 'lib' << 'spec'
30
- spec.spec_files = FileList['spec/ssdeep_spec.rb', 'spec/**/*_spec.rb'].uniq
28
+ require 'rspec/core/rake_task'
29
+ RSpec::Core::RakeTask.new(:spec) do |spec|
30
+ spec.pattern = FileList['spec/ssdeep_spec.rb', 'spec/**/*_spec.rb'].uniq
31
31
  end
32
32
 
33
33
  if RUBY_PLATFORM !~ /java/
34
34
  Rake::ExtensionTask.new("ssdeep_native")
35
35
 
36
+ CLEAN.include("doc")
37
+ CLEAN.include("rdoc")
38
+ CLEAN.include("coverage")
39
+ CLEAN.include("tmp")
36
40
  CLEAN.include("lib/*.bundle")
37
41
  CLEAN.include("lib/*.so")
38
- CLEAN.include("tmp")
39
42
 
40
43
  task :spec => :compile
41
44
  end
@@ -53,4 +56,9 @@ Rake::RDocTask.new do |rdoc|
53
56
  rdoc.title = "russdeep #{version}"
54
57
  rdoc.rdoc_files.include('README*')
55
58
  rdoc.rdoc_files.include('lib/**/*.rb')
59
+ rdoc.rdoc_files.include('ext/**/*.c')
56
60
  end
61
+
62
+ require 'yard'
63
+ YARD::Rake::YardocTask.new
64
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.1.0
@@ -5,6 +5,17 @@
5
5
  static VALUE module_Ssdeep = Qnil;
6
6
  static VALUE error_HashError = Qnil;
7
7
 
8
+ /* call-seq: from_string(buf)
9
+ *
10
+ * Create a fuzzy hash from a ruby string
11
+ *
12
+ * @param String buf The string to hash
13
+ *
14
+ * @return String The fuzzy hash of the string
15
+ *
16
+ * @raise HashError
17
+ * An exception is raised if the libfuzzy library encounters an error.
18
+ */
8
19
  VALUE ssdeep_from_string(VALUE klass, VALUE buf) {
9
20
  char hash[FUZZY_MAX_RESULT];
10
21
  int ret;
@@ -17,6 +28,17 @@ VALUE ssdeep_from_string(VALUE klass, VALUE buf) {
17
28
  rb_raise(error_HashError, "An error occurred hashing a string: ret=%i", ret);
18
29
  }
19
30
 
31
+ /* call-seq: from_file(filename)
32
+ *
33
+ * Create a fuzzy hash from a file
34
+ *
35
+ * @param String fielname The file to read and hash
36
+ *
37
+ * @return String The fuzzy hash of the file input
38
+ *
39
+ * @raise HashError
40
+ * An exception is raised if the libfuzzy library encounters an error.
41
+ */
20
42
  VALUE ssdeep_from_filename(VALUE klass, VALUE filename) {
21
43
  char hash[FUZZY_MAX_RESULT];
22
44
  int ret;
@@ -29,6 +51,17 @@ VALUE ssdeep_from_filename(VALUE klass, VALUE filename) {
29
51
  rb_raise(error_HashError, "An error occurred the file: %s -- ret=%i", RSTRING_PTR(filename), ret);
30
52
  }
31
53
 
54
+ /* call-seq: from_fileno(fileno)
55
+ *
56
+ * Create a fuzzy hash from a file descriptor fileno
57
+ *
58
+ * @param Integer fileno The file descriptor to read and hash
59
+ *
60
+ * @return String The fuzzy hash of the file descriptor input
61
+ *
62
+ * @raise HashError
63
+ * An exception is raised if the libfuzzy library encounters an error.
64
+ */
32
65
  VALUE ssdeep_from_fileno(VALUE klass, VALUE fileno) {
33
66
  char hash[FUZZY_MAX_RESULT];
34
67
  int ret, fd;
@@ -50,6 +83,17 @@ VALUE ssdeep_from_fileno(VALUE klass, VALUE fileno) {
50
83
  rb_raise(error_HashError, "An error occurred the fileno: %i -- ret=%i", fd, ret);
51
84
  }
52
85
 
86
+ /* call-seq: compare(sig1, sig2)
87
+ *
88
+ * Compare two hashes
89
+ *
90
+ * @param String sig1 A fuzzy hash which will be compared to sig2
91
+ *
92
+ * @param String sig2 A fuzzy hash which will be compared to sig1
93
+ *
94
+ * @return Integer
95
+ * A value between 0 and 100 indicating the percentage of similarity.
96
+ */
53
97
  VALUE ssdeep_compare(VALUE klass, VALUE sig1, VALUE sig2) {
54
98
  int ret;
55
99
 
@@ -27,6 +27,14 @@ module Ssdeep
27
27
  attach_function :fdopen, [:int, :string], :pointer
28
28
 
29
29
 
30
+ # Create a fuzzy hash from a ruby string
31
+ #
32
+ # @param String buf The string to hash
33
+ #
34
+ # @return String The fuzzy hash of the string
35
+ #
36
+ # @raise HashError
37
+ # An exception is raised if the libfuzzy library encounters an error.
30
38
  def self.from_string(buf)
31
39
  bufp = FFI::MemoryPointer.new(buf.size)
32
40
  bufp.write_string(buf)
@@ -40,6 +48,14 @@ module Ssdeep
40
48
  end
41
49
  end
42
50
 
51
+ # Create a fuzzy hash from a file descriptor fileno
52
+ #
53
+ # @param Integer fileno The file descriptor to read and hash
54
+ #
55
+ # @return String The fuzzy hash of the file descriptor input
56
+ #
57
+ # @raise HashError
58
+ # An exception is raised if the libfuzzy library encounters an error.
43
59
  def self.from_fileno(fileno)
44
60
  if (not fileno.kind_of?(Integer)) or (file=fdopen(fileno, "r")).null?
45
61
  raise(HashError, "Unable to open file descriptor: #{fileno}")
@@ -54,6 +70,14 @@ module Ssdeep
54
70
  end
55
71
  end
56
72
 
73
+ # Create a fuzzy hash from a file
74
+ #
75
+ # @param String fielname The file to read and hash
76
+ #
77
+ # @return String The fuzzy hash of the file input
78
+ #
79
+ # @raise HashError
80
+ # An exception is raised if the libfuzzy library encounters an error.
57
81
  def self.from_file(filename)
58
82
  File.stat(filename)
59
83
  out = FFI::MemoryPointer.new(FUZZY_MAX_RESULT)
@@ -65,6 +89,14 @@ module Ssdeep
65
89
  end
66
90
  end
67
91
 
92
+ # Compare two hashes
93
+ #
94
+ # @param String sig1 A fuzzy hash which will be compared to sig2
95
+ #
96
+ # @param String sig2 A fuzzy hash which will be compared to sig1
97
+ #
98
+ # @return Integer
99
+ # A value between 0 and 100 indicating the percentage of similarity.
68
100
  def self.compare(sig1, sig2)
69
101
  psig1 = FFI::MemoryPointer.from_string(sig1)
70
102
  psig2 = FFI::MemoryPointer.from_string(sig2)
@@ -1,3 +1,48 @@
1
1
  require 'ssdeep'
2
2
 
3
+
4
+ module Ssdeep
5
+ # The FuzzyComparable module adds mixins for doing fuzzy hash comparisons.
6
+ # The object extending must simply implement the 'ssdeep' method, which
7
+ # should return a string containing a fuzzy CTPH hash.
8
+ module FuzzyComparable
9
+ # Returns a CTPH comparison score between this object and another's
10
+ # fuzzy hash.
11
+ #
12
+ # @param String,Object other
13
+ # The hash string or other object to compare to. If other is not
14
+ # a string, it just needs to implement the 'ssdeep' method.
15
+ #
16
+ def fuzzy_score(other)
17
+ other_hash=
18
+ if other.is_a? String
19
+ other
20
+ elsif other.respond_to? :ssdeep
21
+ other.ssdeep
22
+ else
23
+ raise(TypeError, "can't handle type for other: #{other.class}")
24
+ end
25
+
26
+ Ssdeep.compare(self.ssdeep, other_hash)
27
+ end
28
+
29
+ # Returns true/false whether the sample matches a CTPH (fuzzy hash)
30
+ # with a score above a specified threshold
31
+ #
32
+ # @param String,Object other
33
+ # The hash string or other object to compare to. If other is not
34
+ # a string, it just needs to implement the 'ssdeep' method.
35
+ #
36
+ # @param Integer threshold
37
+ # The theshold above-which a match is considered true. If a threshold
38
+ # is supplied above 100, it is treated as 100.
39
+ #
40
+ # @return true,false
41
+ # Whether a match occurred.
42
+ def fuzzy_match(other, threshold=25)
43
+ return (fuzzy_score(other) >= [threshold, 100].min)
44
+ end
45
+ end
46
+ end
47
+
3
48
  RuSsdeep = Ssdeep
@@ -5,3 +5,54 @@ else
5
5
  require 'ssdeep_native'
6
6
  end
7
7
 
8
+ module Ssdeep
9
+ # The FuzzyComparable module adds mixins for doing fuzzy hash comparisons.
10
+ # To mix in the module your object must simply implement the 'ssdeep'
11
+ # method, which should return a string containing a fuzzy CTPH hash.
12
+ module FuzzyComparable
13
+ # Returns a CTPH comparison score between this object and another's
14
+ # fuzzy hash.
15
+ #
16
+ # @param String,Object other
17
+ # The hash string or other object to compare to. If other is not
18
+ # a string, it just needs to implement the 'ssdeep' method.
19
+ #
20
+ def fuzzy_score(other)
21
+ other_hash=
22
+ if other.is_a? String
23
+ other
24
+ elsif other.respond_to? :ssdeep
25
+ other.ssdeep
26
+ else
27
+ raise(TypeError, "can't handle type for other: #{other.class}")
28
+ end
29
+
30
+ Ssdeep.compare(self.ssdeep, other_hash)
31
+ end
32
+
33
+ # Returns true/false whether the sample matches a CTPH (fuzzy hash)
34
+ # with a score above a specified threshold
35
+ #
36
+ # @param String,Object other
37
+ # The hash string or other object to compare to. If other is not
38
+ # a string, it just needs to implement the 'ssdeep' method.
39
+ #
40
+ # @param Integer threshold
41
+ # The theshold above-which a match is considered true. If a threshold
42
+ # is supplied above 100, it is treated as 100.
43
+ #
44
+ # @return true,false
45
+ # Whether a match occurred.
46
+ def fuzzy_match(other, threshold=25)
47
+ return (fuzzy_score(other) >= [threshold, 100].min)
48
+ end
49
+ end
50
+
51
+ class << self
52
+ alias :hash_string :from_string
53
+ alias :hash_file :from_file
54
+ alias :hash_fileno :from_fileno
55
+ end
56
+ end
57
+
58
+
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'ssdeep'
3
+
4
+ class TestFuzzyComparable
5
+ include Ssdeep::FuzzyComparable
6
+
7
+ def ssdeep
8
+ '96:tQWAFF4IMtG6z4FEmYqGPUyukJM4kbqkTKL+LGw6b8f/EZMhJvybtSryfubB:tO4a68FZYqyG4w2+Bbzhpybg6u9'
9
+ end
10
+ end
11
+
12
+ describe Ssdeep::FuzzyComparable do
13
+ before :all do
14
+ @obj = TestFuzzyComparable.new
15
+ end
16
+
17
+ it "should compare itself to another fuzzy hash string" do
18
+ @obj.fuzzy_score(Ssdeep.from_file sample_file("sample1.txt")).should == 100
19
+ @obj.fuzzy_match(Ssdeep.from_file sample_file("sample1.txt")).should be_true
20
+ end
21
+ end
@@ -1,7 +1,6 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
- require 'spec'
4
- require 'spec/autorun'
3
+ require 'rspec'
5
4
  require File.expand_path(File.dirname(__FILE__) + '/ssdeep_behaviors')
6
5
 
7
6
 
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
+ - 1
7
8
  - 0
8
- - 0
9
- version: 1.0.0
9
+ version: 1.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Eric Monti
@@ -14,13 +14,14 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-02-20 00:00:00 -06:00
17
+ date: 2011-03-22 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rspec
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
24
25
  requirements:
25
26
  - - ">="
26
27
  - !ruby/object:Gem::Version
@@ -35,6 +36,7 @@ dependencies:
35
36
  name: ffi
36
37
  prerelease: false
37
38
  requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
38
40
  requirements:
39
41
  - - ">="
40
42
  - !ruby/object:Gem::Version
@@ -52,8 +54,11 @@ extensions:
52
54
  extra_rdoc_files:
53
55
  - LICENSE
54
56
  - README.rdoc
57
+ - ext/ssdeep_native/ssdeep_native.c
55
58
  files:
56
59
  - .document
60
+ - .rspec
61
+ - History.txt
57
62
  - LICENSE
58
63
  - README.rdoc
59
64
  - Rakefile
@@ -65,9 +70,9 @@ files:
65
70
  - lib/ssdeep.rb
66
71
  - lib/ssdeep_ffi.rb
67
72
  - spec/ffi_ssdeep_spec.rb
73
+ - spec/fuzzy_comparable_spec.rb
68
74
  - spec/samples/sample1.txt
69
75
  - spec/samples/sample2.txt
70
- - spec/spec.opts
71
76
  - spec/spec_helper.rb
72
77
  - spec/ssdeep_behaviors.rb
73
78
  - spec/ssdeep_spec.rb
@@ -81,6 +86,7 @@ rdoc_options: []
81
86
  require_paths:
82
87
  - lib
83
88
  required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
84
90
  requirements:
85
91
  - - ">="
86
92
  - !ruby/object:Gem::Version
@@ -88,6 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
88
94
  - 0
89
95
  version: "0"
90
96
  required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
91
98
  requirements:
92
99
  - - ">="
93
100
  - !ruby/object:Gem::Version
@@ -97,12 +104,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
104
  requirements: []
98
105
 
99
106
  rubyforge_project:
100
- rubygems_version: 1.3.6
107
+ rubygems_version: 1.3.7
101
108
  signing_key:
102
109
  specification_version: 3
103
110
  summary: Ruby bindings for libfuzzy (from ssdeep)
104
111
  test_files:
105
112
  - spec/ffi_ssdeep_spec.rb
113
+ - spec/fuzzy_comparable_spec.rb
106
114
  - spec/spec_helper.rb
107
115
  - spec/ssdeep_behaviors.rb
108
116
  - spec/ssdeep_spec.rb