russdeep 1.0.0 → 1.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/.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