russdeep 1.0.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 +5 -0
- data/LICENSE +16 -0
- data/README.rdoc +60 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/ext/ssdeep_native/extconf.rb +17 -0
- data/ext/ssdeep_native/ssdeep_native.c +80 -0
- data/lib/ffi/ssdeep.rb +75 -0
- data/lib/russdeep.rb +3 -0
- data/lib/ssdeep.rb +7 -0
- data/lib/ssdeep_ffi.rb +4 -0
- data/spec/ffi_ssdeep_spec.rb +24 -0
- data/spec/samples/sample1.txt +189 -0
- data/spec/samples/sample2.txt +534 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/ssdeep_behaviors.rb +84 -0
- data/spec/ssdeep_spec.rb +33 -0
- metadata +108 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
russdeep - Ruby language bindings for the 'libfuzzy' ssdeep library
|
2
|
+
Copyright (c) 2010 Eric Monti
|
3
|
+
|
4
|
+
This program is free software; you can redistribute it and/or
|
5
|
+
modify it under the terms of the GNU General Public License
|
6
|
+
as published by the Free Software Foundation; either version 2
|
7
|
+
of the License, or (at your option) any later version.
|
8
|
+
|
9
|
+
This program is distributed in the hope that it will be useful,
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
GNU General Public License for more details.
|
13
|
+
|
14
|
+
You should have received a copy of the GNU General Public License
|
15
|
+
along with this program; if not, write to the Free Software
|
16
|
+
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
data/README.rdoc
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
= russdeep
|
2
|
+
|
3
|
+
Ruby language bindings for the ssdeep 'libfuzzy' library api. This API lets you do
|
4
|
+
fuzzy hash comparisons between files and arbitrary string buffers. Fuzzy
|
5
|
+
hashes are also known as context triggered piecewise hashes (CTPH).
|
6
|
+
|
7
|
+
See the ssdeep homepage for more information:
|
8
|
+
http://ssdeep.sourceforge.net
|
9
|
+
|
10
|
+
== Requirements
|
11
|
+
|
12
|
+
* ssdeep's libfuzzy - http://ssdeep.sourceforge.net
|
13
|
+
The latest version of ssdeep known to work with russdeep is 2.5.
|
14
|
+
|
15
|
+
== Installation
|
16
|
+
|
17
|
+
First ensure you have installed the ssdeep package and that libfuzzy is in your libpath.
|
18
|
+
Then...
|
19
|
+
|
20
|
+
=== Gem
|
21
|
+
|
22
|
+
(sudo)? gem install russdeep
|
23
|
+
|
24
|
+
=== rake
|
25
|
+
|
26
|
+
git clone https://github.com/emonti/russdeep.git
|
27
|
+
cd russdeep
|
28
|
+
rake compile
|
29
|
+
|
30
|
+
== Example
|
31
|
+
|
32
|
+
require "ssdeep"
|
33
|
+
|
34
|
+
data1 =<<__EOM__
|
35
|
+
Ruby language bindings for the ssdeep 'libfuzzy' library api. This API lets you do
|
36
|
+
fuzzy hash comparisons between files and arbitrary string buffers. Fuzzy
|
37
|
+
hashes are also known as context triggered piecewise hashes (CTPH).
|
38
|
+
|
39
|
+
See the ssdeep homepage for more information:
|
40
|
+
http://ssdeep.sourceforge.net
|
41
|
+
__EOM__
|
42
|
+
|
43
|
+
|
44
|
+
hash1 = Ssdeep.from_string(data1)
|
45
|
+
hash2 = Ssdeep.from_string(data1 + "a little extra")
|
46
|
+
hash3 = Ssdeep.from_string(data1.gsub("ssdeep", "fuzzy"))
|
47
|
+
hash4 = Ssdeep.from_file("/etc/hosts")
|
48
|
+
hash5 = File.open("/etc/hosts"){|f| Ssdeep.from_fileno(f.fileno)}
|
49
|
+
|
50
|
+
Ssdeep.compare(hash1, hash1) # => 100
|
51
|
+
Ssdeep.compare(hash1, hash2) # => 97
|
52
|
+
Ssdeep.compare(hash1, hash3) # => 88
|
53
|
+
Ssdeep.compare(hash1, hash4) # => 0
|
54
|
+
Ssdeep.compare(hash4, hash5) # => 100
|
55
|
+
|
56
|
+
== License
|
57
|
+
|
58
|
+
See LICENSE.txt
|
59
|
+
|
60
|
+
Copyright (c) 2011 Eric Monti. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/extensiontask'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = "russdeep"
|
9
|
+
gem.summary = %Q{Ruby bindings for libfuzzy (from ssdeep)}
|
10
|
+
gem.description = %Q{Ruby bindings for libfuzzy, a fuzzy hashing implementation included with the ssdeep utility}
|
11
|
+
gem.email = "esmonti@gmail.com"
|
12
|
+
gem.homepage = "http://github.com/emonti/russdeep"
|
13
|
+
gem.authors = ["Eric Monti"]
|
14
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
15
|
+
gem.add_development_dependency "ffi", ">= 0"
|
16
|
+
|
17
|
+
if RUBY_PLATFORM !~ /java/
|
18
|
+
gem.extensions = FileList['ext/**/extconf.rb']
|
19
|
+
end
|
20
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
21
|
+
end
|
22
|
+
Jeweler::GemcutterTasks.new
|
23
|
+
rescue LoadError
|
24
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
25
|
+
end
|
26
|
+
|
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
|
31
|
+
end
|
32
|
+
|
33
|
+
if RUBY_PLATFORM !~ /java/
|
34
|
+
Rake::ExtensionTask.new("ssdeep_native")
|
35
|
+
|
36
|
+
CLEAN.include("lib/*.bundle")
|
37
|
+
CLEAN.include("lib/*.so")
|
38
|
+
CLEAN.include("tmp")
|
39
|
+
|
40
|
+
task :spec => :compile
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
#task :spec => :check_dependencies
|
45
|
+
|
46
|
+
task :default => :spec
|
47
|
+
|
48
|
+
require 'rake/rdoctask'
|
49
|
+
Rake::RDocTask.new do |rdoc|
|
50
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
51
|
+
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "russdeep #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.0
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
require 'rbconfig'
|
3
|
+
|
4
|
+
extension_name = "ssdeep_native"
|
5
|
+
|
6
|
+
dir_config(extension_name)
|
7
|
+
|
8
|
+
unless find_library("fuzzy", "fuzzy_hash_file", "/lib", "/usr/lib", "/usr/local/lib") and
|
9
|
+
find_library("fuzzy", "fuzzy_hash_filename", "/lib", "/usr/lib", "/usr/local/lib") and
|
10
|
+
find_library("fuzzy", "fuzzy_hash_buf", "/lib", "/usr/lib", "/usr/local/lib") and
|
11
|
+
find_library("fuzzy", "fuzzy_compare", "/lib", "/usr/lib", "/usr/local/lib") and
|
12
|
+
find_header("fuzzy.h", "/lib", "/usr/lib", "/usr/local/include")
|
13
|
+
raise "You must install the ssdeep package"
|
14
|
+
end
|
15
|
+
|
16
|
+
create_makefile(extension_name)
|
17
|
+
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include <fuzzy.h>
|
3
|
+
#include <stdio.h>
|
4
|
+
|
5
|
+
static VALUE module_Ssdeep = Qnil;
|
6
|
+
static VALUE error_HashError = Qnil;
|
7
|
+
|
8
|
+
VALUE ssdeep_from_string(VALUE klass, VALUE buf) {
|
9
|
+
char hash[FUZZY_MAX_RESULT];
|
10
|
+
int ret;
|
11
|
+
Check_Type(buf, T_STRING);
|
12
|
+
|
13
|
+
ret = fuzzy_hash_buf((unsigned char *) RSTRING_PTR(buf), RSTRING_LEN(buf), hash);
|
14
|
+
if (ret == 0)
|
15
|
+
return rb_str_new2(hash);
|
16
|
+
else
|
17
|
+
rb_raise(error_HashError, "An error occurred hashing a string: ret=%i", ret);
|
18
|
+
}
|
19
|
+
|
20
|
+
VALUE ssdeep_from_filename(VALUE klass, VALUE filename) {
|
21
|
+
char hash[FUZZY_MAX_RESULT];
|
22
|
+
int ret;
|
23
|
+
Check_Type(filename, T_STRING);
|
24
|
+
|
25
|
+
ret=fuzzy_hash_filename(RSTRING_PTR(filename), hash);
|
26
|
+
if (ret == 0)
|
27
|
+
return rb_str_new2(hash);
|
28
|
+
else
|
29
|
+
rb_raise(error_HashError, "An error occurred the file: %s -- ret=%i", RSTRING_PTR(filename), ret);
|
30
|
+
}
|
31
|
+
|
32
|
+
VALUE ssdeep_from_fileno(VALUE klass, VALUE fileno) {
|
33
|
+
char hash[FUZZY_MAX_RESULT];
|
34
|
+
int ret, fd;
|
35
|
+
FILE *file;
|
36
|
+
|
37
|
+
Check_Type(fileno, T_FIXNUM);
|
38
|
+
|
39
|
+
fd = FIX2INT(fileno);
|
40
|
+
|
41
|
+
if (!(file=fdopen(fd, "r"))) {
|
42
|
+
rb_sys_fail(0);
|
43
|
+
return Qnil;
|
44
|
+
}
|
45
|
+
|
46
|
+
ret=fuzzy_hash_file(file, hash);
|
47
|
+
if (ret == 0)
|
48
|
+
return rb_str_new2(hash);
|
49
|
+
else
|
50
|
+
rb_raise(error_HashError, "An error occurred the fileno: %i -- ret=%i", fd, ret);
|
51
|
+
}
|
52
|
+
|
53
|
+
VALUE ssdeep_compare(VALUE klass, VALUE sig1, VALUE sig2) {
|
54
|
+
int ret;
|
55
|
+
|
56
|
+
Check_Type(sig1, T_STRING);
|
57
|
+
Check_Type(sig2, T_STRING);
|
58
|
+
|
59
|
+
if (strncmp(RSTRING_PTR(sig1), RSTRING_PTR(sig2), FUZZY_MAX_RESULT) == 0)
|
60
|
+
return INT2NUM(100);
|
61
|
+
else if ( (ret=fuzzy_compare(RSTRING_PTR(sig1), RSTRING_PTR(sig2))) < 0)
|
62
|
+
rb_raise(error_HashError, "An error occurred comparing hashes");
|
63
|
+
else
|
64
|
+
return INT2NUM(ret);
|
65
|
+
}
|
66
|
+
|
67
|
+
void Init_ssdeep_native() {
|
68
|
+
module_Ssdeep = rb_define_module("Ssdeep");
|
69
|
+
|
70
|
+
error_HashError = rb_define_class_under(module_Ssdeep, "HashError", rb_eStandardError);
|
71
|
+
|
72
|
+
rb_define_singleton_method(module_Ssdeep, "from_string", ssdeep_from_string, 1);
|
73
|
+
rb_define_singleton_method(module_Ssdeep, "from_file", ssdeep_from_filename, 1);
|
74
|
+
rb_define_singleton_method(module_Ssdeep, "from_fileno", ssdeep_from_fileno, 1);
|
75
|
+
rb_define_singleton_method(module_Ssdeep, "compare", ssdeep_compare, 2);
|
76
|
+
|
77
|
+
rb_define_const(module_Ssdeep, "FUZZY_MAX_RESULT", INT2NUM(FUZZY_MAX_RESULT));
|
78
|
+
rb_define_const(module_Ssdeep, "SPAMSUM_LENGTH", INT2NUM(SPAMSUM_LENGTH));
|
79
|
+
}
|
80
|
+
|
data/lib/ffi/ssdeep.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'ffi'
|
7
|
+
|
8
|
+
module FFI
|
9
|
+
module Ssdeep
|
10
|
+
class HashError < StandardError
|
11
|
+
end
|
12
|
+
|
13
|
+
extend FFI::Library
|
14
|
+
|
15
|
+
ffi_lib 'fuzzy'
|
16
|
+
|
17
|
+
SPAMSUM_LENGTH = 64
|
18
|
+
FUZZY_MAX_RESULT = (SPAMSUM_LENGTH + (SPAMSUM_LENGTH/2 + 20))
|
19
|
+
|
20
|
+
typedef :pointer, :fuzzy_hash
|
21
|
+
|
22
|
+
attach_function :fuzzy_hash_buf, [:pointer, :uint32, :fuzzy_hash], :int
|
23
|
+
attach_function :fuzzy_hash_file, [:pointer, :fuzzy_hash], :int
|
24
|
+
attach_function :fuzzy_hash_filename, [:string, :fuzzy_hash], :int
|
25
|
+
attach_function :fuzzy_compare, [:fuzzy_hash, :fuzzy_hash], :int
|
26
|
+
|
27
|
+
attach_function :fdopen, [:int, :string], :pointer
|
28
|
+
|
29
|
+
|
30
|
+
def self.from_string(buf)
|
31
|
+
bufp = FFI::MemoryPointer.new(buf.size)
|
32
|
+
bufp.write_string(buf)
|
33
|
+
|
34
|
+
out = FFI::MemoryPointer.new(FUZZY_MAX_RESULT)
|
35
|
+
|
36
|
+
if (ret=fuzzy_hash_buf(bufp, bufp.size, out)) == 0
|
37
|
+
return out.read_string
|
38
|
+
else
|
39
|
+
raise(HashError, "An error occurred hashing a string: ret=#{ret}")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.from_fileno(fileno)
|
44
|
+
if (not fileno.kind_of?(Integer)) or (file=fdopen(fileno, "r")).null?
|
45
|
+
raise(HashError, "Unable to open file descriptor: #{fileno}")
|
46
|
+
end
|
47
|
+
|
48
|
+
out = FFI::MemoryPointer.new(FUZZY_MAX_RESULT)
|
49
|
+
|
50
|
+
if (ret=fuzzy_hash_file(file, out)) == 0
|
51
|
+
return out.read_string
|
52
|
+
else
|
53
|
+
raise(HashError, "An error occurred hashing the file descriptor: #{fileno} -- ret=#{ret}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.from_file(filename)
|
58
|
+
File.stat(filename)
|
59
|
+
out = FFI::MemoryPointer.new(FUZZY_MAX_RESULT)
|
60
|
+
|
61
|
+
if (ret=fuzzy_hash_filename(filename, out)) == 0
|
62
|
+
return out.read_string
|
63
|
+
else
|
64
|
+
raise(HashError, "An error occurred hashing the file: #{filename} -- ret=#{ret}");
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.compare(sig1, sig2)
|
69
|
+
psig1 = FFI::MemoryPointer.from_string(sig1)
|
70
|
+
psig2 = FFI::MemoryPointer.from_string(sig2)
|
71
|
+
|
72
|
+
return fuzzy_compare(psig1, psig2)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/russdeep.rb
ADDED
data/lib/ssdeep.rb
ADDED
data/lib/ssdeep_ffi.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'ffi/ssdeep'
|
3
|
+
|
4
|
+
describe FFI::Ssdeep do
|
5
|
+
before(:all) {
|
6
|
+
@klass = FFI::Ssdeep
|
7
|
+
@f1 = sample_file("sample1.txt")
|
8
|
+
@f2 = sample_file("sample2.txt")
|
9
|
+
|
10
|
+
@f1_hash = '96:tQWAFF4IMtG6z4FEmYqGPUyukJM4kbqkTKL+LGw6b8f/EZMhJvybtSryfubB:tO4a68FZYqyG4w2+Bbzhpybg6u9'
|
11
|
+
@f2_hash = '192:sO4a68FZYqyG4w2+Bbzhpybg6uTI6l7yrnUxioPmSKx/A0IV2vRqtJUF2CnHqVC2:sOf6aYqyG4w3ug6uTI6lQUxioOLx/AZt'
|
12
|
+
}
|
13
|
+
|
14
|
+
it "should be using the FFI implementation" do
|
15
|
+
FFI::Ssdeep.should respond_to(:fuzzy_compare)
|
16
|
+
FFI::Ssdeep.should respond_to(:fuzzy_hash_file)
|
17
|
+
FFI::Ssdeep.should respond_to(:fuzzy_hash_filename)
|
18
|
+
FFI::Ssdeep.should respond_to(:fuzzy_hash_buf)
|
19
|
+
FFI::Ssdeep.should respond_to(:fdopen)
|
20
|
+
end
|
21
|
+
|
22
|
+
it_should_behave_like 'the Ssdeep interface'
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
SCENE I. A desert place.
|
2
|
+
|
3
|
+
Thunder and lightning. Enter three Witches
|
4
|
+
|
5
|
+
First Witch
|
6
|
+
|
7
|
+
When shall we three meet again
|
8
|
+
In thunder, lightning, or in rain?
|
9
|
+
|
10
|
+
Second Witch
|
11
|
+
|
12
|
+
When the hurlyburly's done,
|
13
|
+
When the battle's lost and won.
|
14
|
+
|
15
|
+
Third Witch
|
16
|
+
|
17
|
+
That will be ere the set of sun.
|
18
|
+
|
19
|
+
First Witch
|
20
|
+
|
21
|
+
Where the place?
|
22
|
+
|
23
|
+
Second Witch
|
24
|
+
|
25
|
+
Upon the heath.
|
26
|
+
|
27
|
+
Third Witch
|
28
|
+
|
29
|
+
There to meet with Macbeth.
|
30
|
+
|
31
|
+
First Witch
|
32
|
+
|
33
|
+
I come, Graymalkin!
|
34
|
+
|
35
|
+
Second Witch
|
36
|
+
|
37
|
+
Paddock calls.
|
38
|
+
|
39
|
+
Third Witch
|
40
|
+
|
41
|
+
Anon.
|
42
|
+
|
43
|
+
ALL
|
44
|
+
|
45
|
+
Fair is foul, and foul is fair:
|
46
|
+
Hover through the fog and filthy air.
|
47
|
+
|
48
|
+
Exeunt
|
49
|
+
|
50
|
+
SCENE II. A camp near Forres.
|
51
|
+
|
52
|
+
Alarum within. Enter DUNCAN, MALCOLM, DONALBAIN, LENNOX, with Attendants, meeting a bleeding Sergeant
|
53
|
+
|
54
|
+
DUNCAN
|
55
|
+
|
56
|
+
What bloody man is that? He can report,
|
57
|
+
As seemeth by his plight, of the revolt
|
58
|
+
The newest state.
|
59
|
+
|
60
|
+
MALCOLM
|
61
|
+
|
62
|
+
This is the sergeant
|
63
|
+
Who like a good and hardy soldier fought
|
64
|
+
'Gainst my captivity. Hail, brave friend!
|
65
|
+
Say to the king the knowledge of the broil
|
66
|
+
As thou didst leave it.
|
67
|
+
|
68
|
+
Sergeant
|
69
|
+
|
70
|
+
Doubtful it stood;
|
71
|
+
As two spent swimmers, that do cling together
|
72
|
+
And choke their art. The merciless Macdonwald--
|
73
|
+
Worthy to be a rebel, for to that
|
74
|
+
The multiplying villanies of nature
|
75
|
+
Do swarm upon him--from the western isles
|
76
|
+
Of kerns and gallowglasses is supplied;
|
77
|
+
And fortune, on his damned quarrel smiling,
|
78
|
+
Show'd like a rebel's whore: but all's too weak:
|
79
|
+
For brave Macbeth--well he deserves that name--
|
80
|
+
Disdaining fortune, with his brandish'd steel,
|
81
|
+
Which smoked with bloody execution,
|
82
|
+
Like valour's minion carved out his passage
|
83
|
+
Till he faced the slave;
|
84
|
+
Which ne'er shook hands, nor bade farewell to him,
|
85
|
+
Till he unseam'd him from the nave to the chaps,
|
86
|
+
And fix'd his head upon our battlements.
|
87
|
+
|
88
|
+
DUNCAN
|
89
|
+
|
90
|
+
O valiant cousin! worthy gentleman!
|
91
|
+
|
92
|
+
Sergeant
|
93
|
+
|
94
|
+
As whence the sun 'gins his reflection
|
95
|
+
Shipwrecking storms and direful thunders break,
|
96
|
+
So from that spring whence comfort seem'd to come
|
97
|
+
Discomfort swells. Mark, king of Scotland, mark:
|
98
|
+
No sooner justice had with valour arm'd
|
99
|
+
Compell'd these skipping kerns to trust their heels,
|
100
|
+
But the Norweyan lord surveying vantage,
|
101
|
+
With furbish'd arms and new supplies of men
|
102
|
+
Began a fresh assault.
|
103
|
+
|
104
|
+
DUNCAN
|
105
|
+
|
106
|
+
Dismay'd not this
|
107
|
+
Our captains, Macbeth and Banquo?
|
108
|
+
|
109
|
+
Sergeant
|
110
|
+
|
111
|
+
Yes;
|
112
|
+
As sparrows eagles, or the hare the lion.
|
113
|
+
If I say sooth, I must report they were
|
114
|
+
As cannons overcharged with double cracks, so they
|
115
|
+
Doubly redoubled strokes upon the foe:
|
116
|
+
Except they meant to bathe in reeking wounds,
|
117
|
+
Or memorise another Golgotha,
|
118
|
+
I cannot tell.
|
119
|
+
But I am faint, my gashes cry for help.
|
120
|
+
|
121
|
+
DUNCAN
|
122
|
+
|
123
|
+
So well thy words become thee as thy wounds;
|
124
|
+
They smack of honour both. Go get him surgeons.
|
125
|
+
|
126
|
+
Exit Sergeant, attended
|
127
|
+
Who comes here?
|
128
|
+
|
129
|
+
Enter ROSS
|
130
|
+
|
131
|
+
MALCOLM
|
132
|
+
|
133
|
+
The worthy thane of Ross.
|
134
|
+
|
135
|
+
LENNOX
|
136
|
+
|
137
|
+
What a haste looks through his eyes! So should he look
|
138
|
+
That seems to speak things strange.
|
139
|
+
|
140
|
+
ROSS
|
141
|
+
|
142
|
+
God save the king!
|
143
|
+
|
144
|
+
DUNCAN
|
145
|
+
|
146
|
+
Whence camest thou, worthy thane?
|
147
|
+
|
148
|
+
ROSS
|
149
|
+
|
150
|
+
From Fife, great king;
|
151
|
+
Where the Norweyan banners flout the sky
|
152
|
+
And fan our people cold. Norway himself,
|
153
|
+
With terrible numbers,
|
154
|
+
Assisted by that most disloyal traitor
|
155
|
+
The thane of Cawdor, began a dismal conflict;
|
156
|
+
Till that Bellona's bridegroom, lapp'd in proof,
|
157
|
+
Confronted him with self-comparisons,
|
158
|
+
Point against point rebellious, arm 'gainst arm.
|
159
|
+
Curbing his lavish spirit: and, to conclude,
|
160
|
+
The victory fell on us.
|
161
|
+
|
162
|
+
DUNCAN
|
163
|
+
|
164
|
+
Great happiness!
|
165
|
+
|
166
|
+
ROSS
|
167
|
+
|
168
|
+
That now
|
169
|
+
Sweno, the Norways' king, craves composition:
|
170
|
+
Nor would we deign him burial of his men
|
171
|
+
Till he disbursed at Saint Colme's inch
|
172
|
+
Ten thousand dollars to our general use.
|
173
|
+
|
174
|
+
DUNCAN
|
175
|
+
|
176
|
+
No more that thane of Cawdor shall deceive
|
177
|
+
Our bosom interest: go pronounce his present death,
|
178
|
+
And with his former title greet Macbeth.
|
179
|
+
|
180
|
+
ROSS
|
181
|
+
|
182
|
+
I'll see it done.
|
183
|
+
|
184
|
+
DUNCAN
|
185
|
+
|
186
|
+
What he hath lost noble Macbeth hath won.
|
187
|
+
|
188
|
+
Exeunt
|
189
|
+
|
@@ -0,0 +1,534 @@
|
|
1
|
+
The Tragedy of Macbeth
|
2
|
+
Shakespeare homepage | Macbeth | Entire play
|
3
|
+
SCENE I. A desert place.
|
4
|
+
|
5
|
+
Thunder and lightning. Enter three Witches
|
6
|
+
|
7
|
+
First Witch
|
8
|
+
|
9
|
+
When shall we three meet again
|
10
|
+
In thunder, lightning, or in rain?
|
11
|
+
|
12
|
+
Second Witch
|
13
|
+
|
14
|
+
When the hurlyburly's done,
|
15
|
+
When the battle's lost and won.
|
16
|
+
|
17
|
+
Third Witch
|
18
|
+
|
19
|
+
That will be ere the set of sun.
|
20
|
+
|
21
|
+
First Witch
|
22
|
+
|
23
|
+
Where the place?
|
24
|
+
|
25
|
+
Second Witch
|
26
|
+
|
27
|
+
Upon the heath.
|
28
|
+
|
29
|
+
Third Witch
|
30
|
+
|
31
|
+
There to meet with Macbeth.
|
32
|
+
|
33
|
+
First Witch
|
34
|
+
|
35
|
+
I come, Graymalkin!
|
36
|
+
|
37
|
+
Second Witch
|
38
|
+
|
39
|
+
Paddock calls.
|
40
|
+
|
41
|
+
Third Witch
|
42
|
+
|
43
|
+
Anon.
|
44
|
+
|
45
|
+
ALL
|
46
|
+
|
47
|
+
Fair is foul, and foul is fair:
|
48
|
+
Hover through the fog and filthy air.
|
49
|
+
|
50
|
+
Exeunt
|
51
|
+
|
52
|
+
SCENE II. A camp near Forres.
|
53
|
+
|
54
|
+
Alarum within. Enter DUNCAN, MALCOLM, DONALBAIN, LENNOX, with Attendants, meeting a bleeding Sergeant
|
55
|
+
|
56
|
+
DUNCAN
|
57
|
+
|
58
|
+
What bloody man is that? He can report,
|
59
|
+
As seemeth by his plight, of the revolt
|
60
|
+
The newest state.
|
61
|
+
|
62
|
+
MALCOLM
|
63
|
+
|
64
|
+
This is the sergeant
|
65
|
+
Who like a good and hardy soldier fought
|
66
|
+
'Gainst my captivity. Hail, brave friend!
|
67
|
+
Say to the king the knowledge of the broil
|
68
|
+
As thou didst leave it.
|
69
|
+
|
70
|
+
Sergeant
|
71
|
+
|
72
|
+
Doubtful it stood;
|
73
|
+
As two spent swimmers, that do cling together
|
74
|
+
And choke their art. The merciless Macdonwald--
|
75
|
+
Worthy to be a rebel, for to that
|
76
|
+
The multiplying villanies of nature
|
77
|
+
Do swarm upon him--from the western isles
|
78
|
+
Of kerns and gallowglasses is supplied;
|
79
|
+
And fortune, on his damned quarrel smiling,
|
80
|
+
Show'd like a rebel's whore: but all's too weak:
|
81
|
+
For brave Macbeth--well he deserves that name--
|
82
|
+
Disdaining fortune, with his brandish'd steel,
|
83
|
+
Which smoked with bloody execution,
|
84
|
+
Like valour's minion carved out his passage
|
85
|
+
Till he faced the slave;
|
86
|
+
Which ne'er shook hands, nor bade farewell to him,
|
87
|
+
Till he unseam'd him from the nave to the chaps,
|
88
|
+
And fix'd his head upon our battlements.
|
89
|
+
|
90
|
+
DUNCAN
|
91
|
+
|
92
|
+
O valiant cousin! worthy gentleman!
|
93
|
+
|
94
|
+
Sergeant
|
95
|
+
|
96
|
+
As whence the sun 'gins his reflection
|
97
|
+
Shipwrecking storms and direful thunders break,
|
98
|
+
So from that spring whence comfort seem'd to come
|
99
|
+
Discomfort swells. Mark, king of Scotland, mark:
|
100
|
+
No sooner justice had with valour arm'd
|
101
|
+
Compell'd these skipping kerns to trust their heels,
|
102
|
+
But the Norweyan lord surveying vantage,
|
103
|
+
With furbish'd arms and new supplies of men
|
104
|
+
Began a fresh assault.
|
105
|
+
|
106
|
+
DUNCAN
|
107
|
+
|
108
|
+
Dismay'd not this
|
109
|
+
Our captains, Macbeth and Banquo?
|
110
|
+
|
111
|
+
Sergeant
|
112
|
+
|
113
|
+
Yes;
|
114
|
+
As sparrows eagles, or the hare the lion.
|
115
|
+
If I say sooth, I must report they were
|
116
|
+
As cannons overcharged with double cracks, so they
|
117
|
+
Doubly redoubled strokes upon the foe:
|
118
|
+
Except they meant to bathe in reeking wounds,
|
119
|
+
Or memorise another Golgotha,
|
120
|
+
I cannot tell.
|
121
|
+
But I am faint, my gashes cry for help.
|
122
|
+
|
123
|
+
DUNCAN
|
124
|
+
|
125
|
+
So well thy words become thee as thy wounds;
|
126
|
+
They smack of honour both. Go get him surgeons.
|
127
|
+
|
128
|
+
Exit Sergeant, attended
|
129
|
+
Who comes here?
|
130
|
+
|
131
|
+
Enter ROSS
|
132
|
+
|
133
|
+
MALCOLM
|
134
|
+
|
135
|
+
The worthy thane of Ross.
|
136
|
+
|
137
|
+
LENNOX
|
138
|
+
|
139
|
+
What a haste looks through his eyes! So should he look
|
140
|
+
That seems to speak things strange.
|
141
|
+
|
142
|
+
ROSS
|
143
|
+
|
144
|
+
God save the king!
|
145
|
+
|
146
|
+
DUNCAN
|
147
|
+
|
148
|
+
Whence camest thou, worthy thane?
|
149
|
+
|
150
|
+
ROSS
|
151
|
+
|
152
|
+
From Fife, great king;
|
153
|
+
Where the Norweyan banners flout the sky
|
154
|
+
And fan our people cold. Norway himself,
|
155
|
+
With terrible numbers,
|
156
|
+
Assisted by that most disloyal traitor
|
157
|
+
The thane of Cawdor, began a dismal conflict;
|
158
|
+
Till that Bellona's bridegroom, lapp'd in proof,
|
159
|
+
Confronted him with self-comparisons,
|
160
|
+
Point against point rebellious, arm 'gainst arm.
|
161
|
+
Curbing his lavish spirit: and, to conclude,
|
162
|
+
The victory fell on us.
|
163
|
+
|
164
|
+
DUNCAN
|
165
|
+
|
166
|
+
Great happiness!
|
167
|
+
|
168
|
+
ROSS
|
169
|
+
|
170
|
+
That now
|
171
|
+
Sweno, the Norways' king, craves composition:
|
172
|
+
Nor would we deign him burial of his men
|
173
|
+
Till he disbursed at Saint Colme's inch
|
174
|
+
Ten thousand dollars to our general use.
|
175
|
+
|
176
|
+
DUNCAN
|
177
|
+
|
178
|
+
No more that thane of Cawdor shall deceive
|
179
|
+
Our bosom interest: go pronounce his present death,
|
180
|
+
And with his former title greet Macbeth.
|
181
|
+
|
182
|
+
ROSS
|
183
|
+
|
184
|
+
I'll see it done.
|
185
|
+
|
186
|
+
DUNCAN
|
187
|
+
|
188
|
+
What he hath lost noble Macbeth hath won.
|
189
|
+
|
190
|
+
Exeunt
|
191
|
+
|
192
|
+
SCENE III. A heath near Forres.
|
193
|
+
|
194
|
+
Thunder. Enter the three Witches
|
195
|
+
|
196
|
+
First Witch
|
197
|
+
|
198
|
+
Where hast thou been, sister?
|
199
|
+
|
200
|
+
Second Witch
|
201
|
+
|
202
|
+
Killing swine.
|
203
|
+
|
204
|
+
Third Witch
|
205
|
+
|
206
|
+
Sister, where thou?
|
207
|
+
|
208
|
+
First Witch
|
209
|
+
|
210
|
+
A sailor's wife had chestnuts in her lap,
|
211
|
+
And munch'd, and munch'd, and munch'd:--
|
212
|
+
'Give me,' quoth I:
|
213
|
+
'Aroint thee, witch!' the rump-fed ronyon cries.
|
214
|
+
Her husband's to Aleppo gone, master o' the Tiger:
|
215
|
+
But in a sieve I'll thither sail,
|
216
|
+
And, like a rat without a tail,
|
217
|
+
I'll do, I'll do, and I'll do.
|
218
|
+
|
219
|
+
Second Witch
|
220
|
+
|
221
|
+
I'll give thee a wind.
|
222
|
+
|
223
|
+
First Witch
|
224
|
+
|
225
|
+
Thou'rt kind.
|
226
|
+
|
227
|
+
Third Witch
|
228
|
+
|
229
|
+
And I another.
|
230
|
+
|
231
|
+
First Witch
|
232
|
+
|
233
|
+
I myself have all the other,
|
234
|
+
And the very ports they blow,
|
235
|
+
All the quarters that they know
|
236
|
+
I' the shipman's card.
|
237
|
+
I will drain him dry as hay:
|
238
|
+
Sleep shall neither night nor day
|
239
|
+
Hang upon his pent-house lid;
|
240
|
+
He shall live a man forbid:
|
241
|
+
Weary se'nnights nine times nine
|
242
|
+
Shall he dwindle, peak and pine:
|
243
|
+
Though his bark cannot be lost,
|
244
|
+
Yet it shall be tempest-tost.
|
245
|
+
Look what I have.
|
246
|
+
|
247
|
+
Second Witch
|
248
|
+
|
249
|
+
Show me, show me.
|
250
|
+
|
251
|
+
First Witch
|
252
|
+
|
253
|
+
Here I have a pilot's thumb,
|
254
|
+
Wreck'd as homeward he did come.
|
255
|
+
|
256
|
+
Drum within
|
257
|
+
|
258
|
+
Third Witch
|
259
|
+
|
260
|
+
A drum, a drum!
|
261
|
+
Macbeth doth come.
|
262
|
+
|
263
|
+
ALL
|
264
|
+
|
265
|
+
The weird sisters, hand in hand,
|
266
|
+
Posters of the sea and land,
|
267
|
+
Thus do go about, about:
|
268
|
+
Thrice to thine and thrice to mine
|
269
|
+
And thrice again, to make up nine.
|
270
|
+
Peace! the charm's wound up.
|
271
|
+
|
272
|
+
Enter MACBETH and BANQUO
|
273
|
+
|
274
|
+
MACBETH
|
275
|
+
|
276
|
+
So foul and fair a day I have not seen.
|
277
|
+
|
278
|
+
BANQUO
|
279
|
+
|
280
|
+
How far is't call'd to Forres? What are these
|
281
|
+
So wither'd and so wild in their attire,
|
282
|
+
That look not like the inhabitants o' the earth,
|
283
|
+
And yet are on't? Live you? or are you aught
|
284
|
+
That man may question? You seem to understand me,
|
285
|
+
By each at once her chappy finger laying
|
286
|
+
Upon her skinny lips: you should be women,
|
287
|
+
And yet your beards forbid me to interpret
|
288
|
+
That you are so.
|
289
|
+
|
290
|
+
MACBETH
|
291
|
+
|
292
|
+
Speak, if you can: what are you?
|
293
|
+
|
294
|
+
First Witch
|
295
|
+
|
296
|
+
All hail, Macbeth! hail to thee, thane of Glamis!
|
297
|
+
|
298
|
+
Second Witch
|
299
|
+
|
300
|
+
All hail, Macbeth, hail to thee, thane of Cawdor!
|
301
|
+
|
302
|
+
Third Witch
|
303
|
+
|
304
|
+
All hail, Macbeth, thou shalt be king hereafter!
|
305
|
+
|
306
|
+
BANQUO
|
307
|
+
|
308
|
+
Good sir, why do you start; and seem to fear
|
309
|
+
Things that do sound so fair? I' the name of truth,
|
310
|
+
Are ye fantastical, or that indeed
|
311
|
+
Which outwardly ye show? My noble partner
|
312
|
+
You greet with present grace and great prediction
|
313
|
+
Of noble having and of royal hope,
|
314
|
+
That he seems rapt withal: to me you speak not.
|
315
|
+
If you can look into the seeds of time,
|
316
|
+
And say which grain will grow and which will not,
|
317
|
+
Speak then to me, who neither beg nor fear
|
318
|
+
Your favours nor your hate.
|
319
|
+
|
320
|
+
First Witch
|
321
|
+
|
322
|
+
Hail!
|
323
|
+
|
324
|
+
Second Witch
|
325
|
+
|
326
|
+
Hail!
|
327
|
+
|
328
|
+
Third Witch
|
329
|
+
|
330
|
+
Hail!
|
331
|
+
|
332
|
+
First Witch
|
333
|
+
|
334
|
+
Lesser than Macbeth, and greater.
|
335
|
+
|
336
|
+
Second Witch
|
337
|
+
|
338
|
+
Not so happy, yet much happier.
|
339
|
+
|
340
|
+
Third Witch
|
341
|
+
|
342
|
+
Thou shalt get kings, though thou be none:
|
343
|
+
So all hail, Macbeth and Banquo!
|
344
|
+
|
345
|
+
First Witch
|
346
|
+
|
347
|
+
Banquo and Macbeth, all hail!
|
348
|
+
|
349
|
+
MACBETH
|
350
|
+
|
351
|
+
Stay, you imperfect speakers, tell me more:
|
352
|
+
By Sinel's death I know I am thane of Glamis;
|
353
|
+
But how of Cawdor? the thane of Cawdor lives,
|
354
|
+
A prosperous gentleman; and to be king
|
355
|
+
Stands not within the prospect of belief,
|
356
|
+
No more than to be Cawdor. Say from whence
|
357
|
+
You owe this strange intelligence? or why
|
358
|
+
Upon this blasted heath you stop our way
|
359
|
+
With such prophetic greeting? Speak, I charge you.
|
360
|
+
|
361
|
+
Witches vanish
|
362
|
+
|
363
|
+
BANQUO
|
364
|
+
|
365
|
+
The earth hath bubbles, as the water has,
|
366
|
+
And these are of them. Whither are they vanish'd?
|
367
|
+
|
368
|
+
MACBETH
|
369
|
+
|
370
|
+
Into the air; and what seem'd corporal melted
|
371
|
+
As breath into the wind. Would they had stay'd!
|
372
|
+
|
373
|
+
BANQUO
|
374
|
+
|
375
|
+
Were such things here as we do speak about?
|
376
|
+
Or have we eaten on the insane root
|
377
|
+
That takes the reason prisoner?
|
378
|
+
|
379
|
+
MACBETH
|
380
|
+
|
381
|
+
Your children shall be kings.
|
382
|
+
|
383
|
+
BANQUO
|
384
|
+
|
385
|
+
You shall be king.
|
386
|
+
|
387
|
+
MACBETH
|
388
|
+
|
389
|
+
And thane of Cawdor too: went it not so?
|
390
|
+
|
391
|
+
BANQUO
|
392
|
+
|
393
|
+
To the selfsame tune and words. Who's here?
|
394
|
+
|
395
|
+
Enter ROSS and ANGUS
|
396
|
+
|
397
|
+
ROSS
|
398
|
+
|
399
|
+
The king hath happily received, Macbeth,
|
400
|
+
The news of thy success; and when he reads
|
401
|
+
Thy personal venture in the rebels' fight,
|
402
|
+
His wonders and his praises do contend
|
403
|
+
Which should be thine or his: silenced with that,
|
404
|
+
In viewing o'er the rest o' the selfsame day,
|
405
|
+
He finds thee in the stout Norweyan ranks,
|
406
|
+
Nothing afeard of what thyself didst make,
|
407
|
+
Strange images of death. As thick as hail
|
408
|
+
Came post with post; and every one did bear
|
409
|
+
Thy praises in his kingdom's great defence,
|
410
|
+
And pour'd them down before him.
|
411
|
+
|
412
|
+
ANGUS
|
413
|
+
|
414
|
+
We are sent
|
415
|
+
To give thee from our royal master thanks;
|
416
|
+
Only to herald thee into his sight,
|
417
|
+
Not pay thee.
|
418
|
+
|
419
|
+
ROSS
|
420
|
+
|
421
|
+
And, for an earnest of a greater honour,
|
422
|
+
He bade me, from him, call thee thane of Cawdor:
|
423
|
+
In which addition, hail, most worthy thane!
|
424
|
+
For it is thine.
|
425
|
+
|
426
|
+
BANQUO
|
427
|
+
|
428
|
+
What, can the devil speak true?
|
429
|
+
|
430
|
+
MACBETH
|
431
|
+
|
432
|
+
The thane of Cawdor lives: why do you dress me
|
433
|
+
In borrow'd robes?
|
434
|
+
|
435
|
+
ANGUS
|
436
|
+
|
437
|
+
Who was the thane lives yet;
|
438
|
+
But under heavy judgment bears that life
|
439
|
+
Which he deserves to lose. Whether he was combined
|
440
|
+
With those of Norway, or did line the rebel
|
441
|
+
With hidden help and vantage, or that with both
|
442
|
+
He labour'd in his country's wreck, I know not;
|
443
|
+
But treasons capital, confess'd and proved,
|
444
|
+
Have overthrown him.
|
445
|
+
|
446
|
+
MACBETH
|
447
|
+
|
448
|
+
[Aside] Glamis, and thane of Cawdor!
|
449
|
+
The greatest is behind.
|
450
|
+
|
451
|
+
To ROSS and ANGUS
|
452
|
+
Thanks for your pains.
|
453
|
+
|
454
|
+
To BANQUO
|
455
|
+
Do you not hope your children shall be kings,
|
456
|
+
When those that gave the thane of Cawdor to me
|
457
|
+
Promised no less to them?
|
458
|
+
|
459
|
+
BANQUO
|
460
|
+
|
461
|
+
That trusted home
|
462
|
+
Might yet enkindle you unto the crown,
|
463
|
+
Besides the thane of Cawdor. But 'tis strange:
|
464
|
+
And oftentimes, to win us to our harm,
|
465
|
+
The instruments of darkness tell us truths,
|
466
|
+
Win us with honest trifles, to betray's
|
467
|
+
In deepest consequence.
|
468
|
+
Cousins, a word, I pray you.
|
469
|
+
|
470
|
+
MACBETH
|
471
|
+
|
472
|
+
[Aside] Two truths are told,
|
473
|
+
As happy prologues to the swelling act
|
474
|
+
Of the imperial theme.--I thank you, gentlemen.
|
475
|
+
|
476
|
+
Aside
|
477
|
+
Cannot be ill, cannot be good: if ill,
|
478
|
+
Why hath it given me earnest of success,
|
479
|
+
Commencing in a truth? I am thane of Cawdor:
|
480
|
+
If good, why do I yield to that suggestion
|
481
|
+
Whose horrid image doth unfix my hair
|
482
|
+
And make my seated heart knock at my ribs,
|
483
|
+
Against the use of nature? Present fears
|
484
|
+
Are less than horrible imaginings:
|
485
|
+
My thought, whose murder yet is but fantastical,
|
486
|
+
Shakes so my single state of man that function
|
487
|
+
Is smother'd in surmise, and nothing is
|
488
|
+
But what is not.
|
489
|
+
|
490
|
+
BANQUO
|
491
|
+
|
492
|
+
Look, how our partner's rapt.
|
493
|
+
|
494
|
+
MACBETH
|
495
|
+
|
496
|
+
[Aside] If chance will have me king, why, chance may crown me,
|
497
|
+
Without my stir.
|
498
|
+
|
499
|
+
BANQUO
|
500
|
+
|
501
|
+
New horrors come upon him,
|
502
|
+
Like our strange garments, cleave not to their mould
|
503
|
+
But with the aid of use.
|
504
|
+
|
505
|
+
MACBETH
|
506
|
+
|
507
|
+
[Aside] Come what come may,
|
508
|
+
Time and the hour runs through the roughest day.
|
509
|
+
|
510
|
+
BANQUO
|
511
|
+
|
512
|
+
Worthy Macbeth, we stay upon your leisure.
|
513
|
+
|
514
|
+
MACBETH
|
515
|
+
|
516
|
+
Give me your favour: my dull brain was wrought
|
517
|
+
With things forgotten. Kind gentlemen, your pains
|
518
|
+
Are register'd where every day I turn
|
519
|
+
The leaf to read them. Let us toward the king.
|
520
|
+
Think upon what hath chanced, and, at more time,
|
521
|
+
The interim having weigh'd it, let us speak
|
522
|
+
Our free hearts each to other.
|
523
|
+
|
524
|
+
BANQUO
|
525
|
+
|
526
|
+
Very gladly.
|
527
|
+
|
528
|
+
MACBETH
|
529
|
+
|
530
|
+
Till then, enough. Come, friends.
|
531
|
+
|
532
|
+
Exeunt
|
533
|
+
|
534
|
+
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'spec'
|
4
|
+
require 'spec/autorun'
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/ssdeep_behaviors')
|
6
|
+
|
7
|
+
|
8
|
+
Spec::Runner.configure do |config|
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def sample_file(fname)
|
13
|
+
File.expand_path(File.join(File.dirname(__FILE__), "samples", fname))
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for 'the Ssdeep interface' do
|
4
|
+
it "should generate hashes for strings" do
|
5
|
+
@klass.from_string(File.read(@f1)).should == @f1_hash
|
6
|
+
@klass.from_string(File.read(@f2)).should == @f2_hash
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should generate hashes from filenames" do
|
10
|
+
@klass.from_file(@f1).should == @f1_hash
|
11
|
+
@klass.from_file(@f2).should == @f2_hash
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should generate hashes for file descriptor numbers" do
|
15
|
+
@klass.from_fileno(File.new(@f1, 'r').fileno).should == @f1_hash
|
16
|
+
@klass.from_fileno(File.new(@f2, 'r').fileno).should == @f2_hash
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should compare two hashes from the same string correctly" do
|
20
|
+
@klass.compare(
|
21
|
+
@klass.from_string(File.read @f1),
|
22
|
+
@klass.from_string(File.read @f1)
|
23
|
+
).should == 100
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
it "should compare two hashes from the different strings correctly" do
|
28
|
+
@klass.compare(
|
29
|
+
@klass.from_string(File.read @f1),
|
30
|
+
@klass.from_string(File.read @f2)
|
31
|
+
).should > 50
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should compare two hashes from the same filename correctly" do
|
35
|
+
@klass.compare(
|
36
|
+
@klass.from_file(@f1),
|
37
|
+
@klass.from_file(@f1)
|
38
|
+
).should == 100
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should compare two hashes from different filenames correctly" do
|
42
|
+
@klass.compare(
|
43
|
+
@klass.from_file(@f1),
|
44
|
+
@klass.from_file(@f2)
|
45
|
+
).should > 50
|
46
|
+
end
|
47
|
+
|
48
|
+
# this test seems to really confuse poor java... go figure...
|
49
|
+
# homer says: stupid java!
|
50
|
+
unless RUBY_PLATFORM =~ /java/
|
51
|
+
it "should compare two hashes from file descriptors with the same file" do
|
52
|
+
@klass.compare(
|
53
|
+
@klass.from_fileno(File.new(@f1, 'r').fileno),
|
54
|
+
@klass.from_fileno(File.new(@f1, 'r').fileno)
|
55
|
+
).should == 100
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should compare two hashes from different file descriptors" do
|
60
|
+
@klass.compare(
|
61
|
+
@klass.from_fileno(File.new(@f1, 'r').fileno),
|
62
|
+
@klass.from_fileno(File.new(@f2, 'r').fileno)
|
63
|
+
).should > 50
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
it "should raise an exception when hashing invalid objects" do
|
68
|
+
lambda {@klass.from_fileno(nil)}.should raise_error
|
69
|
+
lambda {@klass.from_string(nil)}.should raise_error
|
70
|
+
lambda {@klass.from_file(nil)}.should raise_error
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should raise an exception when hashing an invalid fileno" do
|
74
|
+
# ensure we're passing in an invalid fd, by opening and closing it ourself
|
75
|
+
fd = File.open(sample_file('sample1.txt')) {|f| f.fileno }
|
76
|
+
|
77
|
+
lambda {@klass.from_fileno(fd)}.should raise_error
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should raise an exception when hashing an invalid file" do
|
81
|
+
lambda {@klass.from_fileno(sample_file('bogusfile'))}.should raise_error
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/spec/ssdeep_spec.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'ssdeep'
|
3
|
+
|
4
|
+
describe Ssdeep do
|
5
|
+
before(:all) {
|
6
|
+
@klass = Ssdeep
|
7
|
+
|
8
|
+
@f1 = sample_file("sample1.txt")
|
9
|
+
@f2 = sample_file("sample2.txt")
|
10
|
+
|
11
|
+
@f1_hash = '96:tQWAFF4IMtG6z4FEmYqGPUyukJM4kbqkTKL+LGw6b8f/EZMhJvybtSryfubB:tO4a68FZYqyG4w2+Bbzhpybg6u9'
|
12
|
+
@f2_hash = '192:sO4a68FZYqyG4w2+Bbzhpybg6uTI6l7yrnUxioPmSKx/A0IV2vRqtJUF2CnHqVC2:sOf6aYqyG4w3ug6uTI6lQUxioOLx/AZt'
|
13
|
+
}
|
14
|
+
|
15
|
+
# this seems to really mess up java... go figure... homer says: stupid java!
|
16
|
+
unless RUBY_PLATFORM =~ /java/
|
17
|
+
it "should compare two hashes from file descriptors with the same file" do
|
18
|
+
@klass.compare(
|
19
|
+
@klass.from_fileno(File.new(@f1, 'r').fileno),
|
20
|
+
@klass.from_fileno(File.new(@f1, 'r').fileno)
|
21
|
+
).should == 100
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should compare two hashes from different file descriptors" do
|
25
|
+
@klass.compare(
|
26
|
+
@klass.from_fileno(File.new(@f1, 'r').fileno),
|
27
|
+
@klass.from_fileno(File.new(@f2, 'r').fileno)
|
28
|
+
).should > 50
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it_should_behave_like 'the Ssdeep interface'
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: russdeep
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 1.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Eric Monti
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-02-20 00:00:00 -06:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
31
|
+
version: 1.2.9
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: ffi
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
description: Ruby bindings for libfuzzy, a fuzzy hashing implementation included with the ssdeep utility
|
47
|
+
email: esmonti@gmail.com
|
48
|
+
executables: []
|
49
|
+
|
50
|
+
extensions:
|
51
|
+
- ext/ssdeep_native/extconf.rb
|
52
|
+
extra_rdoc_files:
|
53
|
+
- LICENSE
|
54
|
+
- README.rdoc
|
55
|
+
files:
|
56
|
+
- .document
|
57
|
+
- LICENSE
|
58
|
+
- README.rdoc
|
59
|
+
- Rakefile
|
60
|
+
- VERSION
|
61
|
+
- ext/ssdeep_native/extconf.rb
|
62
|
+
- ext/ssdeep_native/ssdeep_native.c
|
63
|
+
- lib/ffi/ssdeep.rb
|
64
|
+
- lib/russdeep.rb
|
65
|
+
- lib/ssdeep.rb
|
66
|
+
- lib/ssdeep_ffi.rb
|
67
|
+
- spec/ffi_ssdeep_spec.rb
|
68
|
+
- spec/samples/sample1.txt
|
69
|
+
- spec/samples/sample2.txt
|
70
|
+
- spec/spec.opts
|
71
|
+
- spec/spec_helper.rb
|
72
|
+
- spec/ssdeep_behaviors.rb
|
73
|
+
- spec/ssdeep_spec.rb
|
74
|
+
has_rdoc: true
|
75
|
+
homepage: http://github.com/emonti/russdeep
|
76
|
+
licenses: []
|
77
|
+
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
version: "0"
|
97
|
+
requirements: []
|
98
|
+
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 1.3.6
|
101
|
+
signing_key:
|
102
|
+
specification_version: 3
|
103
|
+
summary: Ruby bindings for libfuzzy (from ssdeep)
|
104
|
+
test_files:
|
105
|
+
- spec/ffi_ssdeep_spec.rb
|
106
|
+
- spec/spec_helper.rb
|
107
|
+
- spec/ssdeep_behaviors.rb
|
108
|
+
- spec/ssdeep_spec.rb
|