virus_total 0.0.2
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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +98 -0
- data/Rakefile +2 -0
- data/lib/core_extensions.rb +23 -0
- data/lib/virus_total/base.rb +36 -0
- data/lib/virus_total/domain.rb +8 -0
- data/lib/virus_total/exception.rb +13 -0
- data/lib/virus_total/file.rb +23 -0
- data/lib/virus_total/ip.rb +8 -0
- data/lib/virus_total/parser.rb +38 -0
- data/lib/virus_total/url.rb +11 -0
- data/lib/virus_total/version.rb +3 -0
- data/lib/virus_total.rb +9 -0
- data/spec/shared_examples_spec.rb +18 -0
- data/spec/virus_total/base_spec.rb +26 -0
- data/spec/virus_total/domain_spec.rb +14 -0
- data/spec/virus_total/file_spec.rb +51 -0
- data/spec/virus_total/ip_spec.rb +14 -0
- data/spec/virus_total/parser_spec.rb +49 -0
- data/spec/virus_total/url_spec.rb +40 -0
- data/virus_total.gemspec +26 -0
- metadata +130 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 4cd640a88172cb1d3cd160a5be4ef045d36f4125
|
|
4
|
+
data.tar.gz: 0074bf1f636a55c21c8bdab4300ba496cbadbda1
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 1b9ea12c003845bb2c1922c67cae1c8fa18a1951073360706da6f86167ff9ea01c20e5bf455ef360f8dbfbe917ebf585398439f8a98b75c2d8e2f29d8c1d4f69
|
|
7
|
+
data.tar.gz: 505752f17dae22f2a85128bd27fb177b282a32f45f700d85acfe9c876dd2f7d2f67439197cd024a2db0bef480b8b687d70f58317fb4ced50bfc9215175461094
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2015 Andrii Saichuk
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# VirusTotal
|
|
2
|
+
[](http://badge.fury.io/rb/virus_total)
|
|
3
|
+
[](https://codeclimate.com/github/rubycop/virus_total)
|
|
4
|
+
|
|
5
|
+
####Ruby gem for VirusTotal API v2.0
|
|
6
|
+
|
|
7
|
+
API page: https://www.virustotal.com/en/documentation/public-api
|
|
8
|
+
|
|
9
|
+
VirusTotal is a free service that analyzes suspicious files and URLs and facilitates the quick detection of viruses, worms, trojans, and all kinds of malware.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
Add this line to your application's Gemfile:
|
|
14
|
+
|
|
15
|
+
gem 'virus_total'
|
|
16
|
+
|
|
17
|
+
And then execute:
|
|
18
|
+
|
|
19
|
+
$ bundle
|
|
20
|
+
|
|
21
|
+
Or install it yourself as:
|
|
22
|
+
|
|
23
|
+
$ gem install virus_total
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
### Scanning Url
|
|
27
|
+
```ruby
|
|
28
|
+
# initialize
|
|
29
|
+
url = VirusTotal::Url.new("https://www.example.com", "-- PUBLIC API KEY --")
|
|
30
|
+
|
|
31
|
+
url.scan # response from POST "url/scan"
|
|
32
|
+
url.report # response from POST "url/report"
|
|
33
|
+
```
|
|
34
|
+
### Scanning File
|
|
35
|
+
```ruby
|
|
36
|
+
# initialize
|
|
37
|
+
file = VirusTotal::File.new("path/to/file", "-- PUBLIC API KEY --")
|
|
38
|
+
|
|
39
|
+
file.scan # response from POST "file/scan"
|
|
40
|
+
file.report # response from POST "file/report"
|
|
41
|
+
file.rescan # response from POST "file/rescan"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
#### Parse response string
|
|
45
|
+
```ruby
|
|
46
|
+
# for example url.report
|
|
47
|
+
response = url.report
|
|
48
|
+
parser = Parser.new(response)
|
|
49
|
+
# <VirusTotal::Parser:0x0000000252eac0 @json_resp={
|
|
50
|
+
# "permalink"=>"https://www.virustotal.com/url/.../",
|
|
51
|
+
# "resource"=>"https://www.example.com",...,
|
|
52
|
+
# "scans"=>{"CLEAN MX"=>{"detected"=>true, "result"=>"clean site"},...}}>
|
|
53
|
+
|
|
54
|
+
parser.response_code #=> 1: OK, 0: result doesn't exist, -2: still queued
|
|
55
|
+
|
|
56
|
+
# general info from response
|
|
57
|
+
parser.info #=> {"permalink"=>"https://www.virustotal.com/url/.../", "resource"=>"..."}
|
|
58
|
+
|
|
59
|
+
# scanning info
|
|
60
|
+
parser.scans #=> {"CLEAN MX"=>{"detected"=>true, "result"=>"clean site"},...}
|
|
61
|
+
|
|
62
|
+
# information about positive threats
|
|
63
|
+
parser.dangers #=> {"CLEAN MX"=>{"detected"=>true, "result"=>"clean site"}}
|
|
64
|
+
|
|
65
|
+
# antiviruses which found positive threats
|
|
66
|
+
parser.danger_brands #=> ["CLEAN MX"]
|
|
67
|
+
```
|
|
68
|
+
Also we can get any key/value pair from response hash. If key (it is a string) from response has a whitespaces use underscore between words.
|
|
69
|
+
```ruby
|
|
70
|
+
parser.scans.CLEAN_MX #=> {"detected"=>true, "result"=>"clean site"}
|
|
71
|
+
parser.scans.CLEAN_MX.detected #=> true
|
|
72
|
+
```
|
|
73
|
+
### Implemented but not testing yet (needs a private apikey)
|
|
74
|
+
#### Scanning IP-Address
|
|
75
|
+
```ruby
|
|
76
|
+
# initialize
|
|
77
|
+
ip = VirusTotal::Ip.new("1.1.1.1", "-- PRIVATE API KEY--")
|
|
78
|
+
|
|
79
|
+
ip.report # response from GET "ip-address/report"
|
|
80
|
+
```
|
|
81
|
+
#### Scanning Domain
|
|
82
|
+
```ruby
|
|
83
|
+
# initialize
|
|
84
|
+
domain = VirusTotal::Domain.new("example.com", "-- PRIVATE API KEY--")
|
|
85
|
+
|
|
86
|
+
domain.report # response from GET "domain/report"
|
|
87
|
+
```
|
|
88
|
+
### Unsupported
|
|
89
|
+
* "comments/puts"
|
|
90
|
+
|
|
91
|
+
## Contributing
|
|
92
|
+
|
|
93
|
+
1. Fork it
|
|
94
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
95
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
96
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
97
|
+
5. Create new Pull Request
|
|
98
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class Array
|
|
2
|
+
def to_str(spliter = ", ")
|
|
3
|
+
join(spliter)
|
|
4
|
+
end
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class String
|
|
8
|
+
def to_str(*args)
|
|
9
|
+
self
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class Hash
|
|
14
|
+
def except_key(hash_key)
|
|
15
|
+
tap { |hash| hash.delete(hash_key) }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def method_missing(name, *args)
|
|
19
|
+
name = name.to_s
|
|
20
|
+
name.gsub!("_", " ")
|
|
21
|
+
self[name]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'rest-client'
|
|
2
|
+
|
|
3
|
+
module VirusTotal
|
|
4
|
+
class Base
|
|
5
|
+
BASE_URL = "https://www.virustotal.com/vtapi/v2/"
|
|
6
|
+
|
|
7
|
+
attr_reader :apikey, :resource
|
|
8
|
+
|
|
9
|
+
def initialize(resources, apikey)
|
|
10
|
+
@resource = resources
|
|
11
|
+
@apikey = apikey
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def api_response(url, params = {})
|
|
15
|
+
full_url = BASE_URL + url
|
|
16
|
+
params = default_params.merge(params)
|
|
17
|
+
|
|
18
|
+
api_request(full_url, params)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def default_params
|
|
24
|
+
{ 'apikey' => @apikey, method: :post }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def api_request(url, params)
|
|
28
|
+
RestClient.send(params[:method], url, params) do |resp, req, result, &block|
|
|
29
|
+
raise ExceedApiLimitError if resp.code == 204
|
|
30
|
+
raise AuthError if resp.code == 403
|
|
31
|
+
|
|
32
|
+
resp.return!(req, result, &block)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
module VirusTotal
|
|
2
|
+
# Whenever you exceed the public API request rate limit
|
|
3
|
+
# a 204 HTTP status code is returned.
|
|
4
|
+
class ExceedApiLimitError < StandardError
|
|
5
|
+
def message; "you exceed the public API request rate limit"; end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# If you try to perform calls to functions for which you do not have
|
|
9
|
+
# the required privileges an HTTP Error 403 Forbidden is raised
|
|
10
|
+
class AuthError < StandardError
|
|
11
|
+
def message; "you do not have the required priviledges"; end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module VirusTotal
|
|
2
|
+
class File < Base
|
|
3
|
+
def scan
|
|
4
|
+
api_response('file/scan', file: get_file, multipart: true)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def rescan
|
|
8
|
+
api_response('file/rescan', resource: @resource.to_str)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def report
|
|
12
|
+
api_response('file/report', resource: @resource.to_str)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def get_file
|
|
18
|
+
tmp = Tempfile.open('tmp')
|
|
19
|
+
tmp.write(IO::File.read(@resource.to_str))
|
|
20
|
+
tmp
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
module VirusTotal
|
|
4
|
+
class Parser
|
|
5
|
+
|
|
6
|
+
attr_reader :response
|
|
7
|
+
|
|
8
|
+
def initialize(resp)
|
|
9
|
+
@response = JSON.parse(resp)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def info
|
|
13
|
+
@response.except_key("scans")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def dangers
|
|
17
|
+
scans = @response.scans
|
|
18
|
+
return {} unless scans
|
|
19
|
+
|
|
20
|
+
dangers = {}
|
|
21
|
+
scans.each_pair do |key, hash|
|
|
22
|
+
next unless hash.detected
|
|
23
|
+
|
|
24
|
+
dangers.merge!({ key => hash })
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
dangers
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def danger_brands
|
|
31
|
+
dangers.keys
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def method_missing(name, *args)
|
|
35
|
+
@response[name.to_s]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/lib/virus_total.rb
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require "core_extensions"
|
|
2
|
+
require "virus_total/base"
|
|
3
|
+
require "virus_total/url"
|
|
4
|
+
require "virus_total/file"
|
|
5
|
+
require "virus_total/ip"
|
|
6
|
+
require "virus_total/domain"
|
|
7
|
+
require "virus_total/parser"
|
|
8
|
+
require "virus_total/exception"
|
|
9
|
+
require "virus_total/version"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
shared_examples_for 'single resource' do
|
|
2
|
+
let(:response) { JSON.parse(subject) }
|
|
3
|
+
|
|
4
|
+
it 'should returns correct response' do
|
|
5
|
+
response.should be_a_kind_of(Hash)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
shared_examples_for 'multiply resources' do
|
|
10
|
+
let(:response) { JSON.parse(subject) }
|
|
11
|
+
|
|
12
|
+
it 'should returns correct response' do
|
|
13
|
+
response.should be_a_kind_of(Array)
|
|
14
|
+
response.each do |item|
|
|
15
|
+
item.should be_a_kind_of(Hash)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "virus_total"
|
|
2
|
+
|
|
3
|
+
describe VirusTotal::Base do
|
|
4
|
+
let(:resource_param) { "first, second" }
|
|
5
|
+
let(:resource) { base.instance_variable_get("@resource") }
|
|
6
|
+
let(:base) { VirusTotal::Base.new(resource_param, "invalid_key") }
|
|
7
|
+
|
|
8
|
+
it "raises AuthError "\
|
|
9
|
+
"if you do not have the required priviledges" do
|
|
10
|
+
expect { base.api_response("url/scan") }.
|
|
11
|
+
to raise_error(VirusTotal::AuthError)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "for resource parameter" do
|
|
15
|
+
it "returns resource correctly" do
|
|
16
|
+
resource.to_str.should == "first, second"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:resource_param) { ["first", "second"] }
|
|
20
|
+
|
|
21
|
+
it "split resources array correctly" do
|
|
22
|
+
resource.to_str.should == "first, second"
|
|
23
|
+
resource.to_str("\n").should == "first\nsecond"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require "virus_total"
|
|
2
|
+
|
|
3
|
+
# to use this feature you must have a private apikey!
|
|
4
|
+
describe VirusTotal::Domain do
|
|
5
|
+
let(:api_key) { "--YOUR_PRIVATE_KEY--" }
|
|
6
|
+
let(:domain) { VirusTotal::Domain.new("heroku.com", api_key) }
|
|
7
|
+
|
|
8
|
+
skip "for single domain" do
|
|
9
|
+
context "for 'domain/report'" do
|
|
10
|
+
subject { domain.report }
|
|
11
|
+
it_should_behave_like 'single resource'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require "virus_total"
|
|
2
|
+
|
|
3
|
+
describe VirusTotal::File do
|
|
4
|
+
let(:api_key) { "b9f4c087d347d244685fa1ba067b3863"\
|
|
5
|
+
"59dd9f46e88558a3f95061e5d4673d5e" }
|
|
6
|
+
let(:resource) {
|
|
7
|
+
tmp = Tempfile.open('tmp')
|
|
8
|
+
tmp.write("some test data")
|
|
9
|
+
tmp.path
|
|
10
|
+
}
|
|
11
|
+
let(:file) { VirusTotal::File.new(resource, api_key) }
|
|
12
|
+
|
|
13
|
+
context "for single file" do
|
|
14
|
+
|
|
15
|
+
context "for 'file/scan'" do
|
|
16
|
+
subject { file.scan }
|
|
17
|
+
it_should_behave_like 'single resource'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "for 'file/report'" do
|
|
21
|
+
let(:resource) { "da39a3ee5e6b4b0d3255bfef95601890afd80709" }
|
|
22
|
+
|
|
23
|
+
subject { file.report }
|
|
24
|
+
it_should_behave_like 'single resource'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "for 'file/rescan'" do
|
|
28
|
+
let(:resource) { "da39a3ee5e6b4b0d3255bfef95601890afd80709" }
|
|
29
|
+
|
|
30
|
+
subject { file.rescan }
|
|
31
|
+
it_should_behave_like 'single resource'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "for multiply files" do
|
|
36
|
+
let(:api_key) { "fd59ac48e3005fa3c5e3f08c06fe666b"\
|
|
37
|
+
"998bf83cd14b6d9cefab9052b1ce76d5" }
|
|
38
|
+
let(:resource) { ["da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
|
39
|
+
"da39a3ee5e6b4b0d3255bfef95601890afd80709"] }
|
|
40
|
+
|
|
41
|
+
context "for 'file/report'" do
|
|
42
|
+
subject { file.report }
|
|
43
|
+
it_should_behave_like 'multiply resources'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "for 'file/rescan'" do
|
|
47
|
+
subject { file.rescan }
|
|
48
|
+
it_should_behave_like 'multiply resources'
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require "virus_total"
|
|
2
|
+
|
|
3
|
+
# to use this feature you must have a private apikey!
|
|
4
|
+
describe VirusTotal::Ip do
|
|
5
|
+
let(:api_key) { "--YOUR_PRIVATE_KEY--" }
|
|
6
|
+
let(:ip) { VirusTotal::Ip.new("128.0.0.1", api_key) }
|
|
7
|
+
|
|
8
|
+
skip "for single ip address" do
|
|
9
|
+
context "for 'ip-address/report'" do
|
|
10
|
+
subject { ip.report }
|
|
11
|
+
it_should_behave_like 'single resource'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require "virus_total"
|
|
2
|
+
|
|
3
|
+
describe VirusTotal::Parser do
|
|
4
|
+
let(:response) {
|
|
5
|
+
"{\"permalink\":\"https://www.virustotal.com/url\","\
|
|
6
|
+
"\"resource\":\"https://www.example.com\","\
|
|
7
|
+
"\"response_code\":1,"\
|
|
8
|
+
"\"scans\":{\"CLEAN MX\":{\"detected\":true}}}"
|
|
9
|
+
}
|
|
10
|
+
let(:parser) { VirusTotal::Parser.new(response) }
|
|
11
|
+
|
|
12
|
+
it "parse response correctly" do
|
|
13
|
+
parser.instance_variable_get("@response").should_not be_nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "returns info correctly" do
|
|
17
|
+
parser.info.should_not match(/scans/)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "returns dangers correctly" do
|
|
21
|
+
parser.dangers.should == {"CLEAN MX"=>{"detected"=>true}}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "returns danger brands correctly" do
|
|
25
|
+
parser.danger_brands.should == ["CLEAN MX"]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "returns hash value correctly" do
|
|
29
|
+
parser.response_code.should == 1
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe Hash do
|
|
34
|
+
let(:hash) { {"key1"=>"val1", "key2"=>{"key 3"=>"val3"}} }
|
|
35
|
+
|
|
36
|
+
it "returns hash value if we call method "\
|
|
37
|
+
"with the same name as a hash key" do
|
|
38
|
+
hash.key1.should == "val1"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "uses method with double underscore "\
|
|
42
|
+
"if hash key with a space" do
|
|
43
|
+
hash.key2.key_3.should == "val3"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "returns hash w/o key correctly" do
|
|
47
|
+
hash.except_key("key2").should == {"key1"=>"val1"}
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require "virus_total"
|
|
2
|
+
|
|
3
|
+
describe VirusTotal::Url do
|
|
4
|
+
let(:api_key) { "97bed3fb1eaf1d7e408d4f21735c26b0"\
|
|
5
|
+
"8453bcf64957e3a370e6fb56133bfe60" }
|
|
6
|
+
let(:resource) { VirusTotal::Url.new(uri, api_key) }
|
|
7
|
+
|
|
8
|
+
context "for single url" do
|
|
9
|
+
let(:uri) { "https://www.google.com" }
|
|
10
|
+
|
|
11
|
+
context "for 'url/scan'" do
|
|
12
|
+
subject { resource.scan }
|
|
13
|
+
it_should_behave_like 'single resource'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "for 'url/report'" do
|
|
17
|
+
subject { resource.report }
|
|
18
|
+
it_should_behave_like 'single resource'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "for multiply urls" do
|
|
23
|
+
let(:api_key) { "b9f4c087d347d244685fa1ba067b3863"\
|
|
24
|
+
"59dd9f46e88558a3f95061e5d4673d5e" }
|
|
25
|
+
let(:uri) {
|
|
26
|
+
["http://www.google.com", "http://www.virustotal.com"]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
context "for 'url/scan'" do
|
|
30
|
+
subject { resource.scan }
|
|
31
|
+
it_should_behave_like 'multiply resources'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# url/report not working for multiply urls.
|
|
35
|
+
skip "for 'url/report'" do
|
|
36
|
+
subject { resource.report }
|
|
37
|
+
it_should_behave_like 'multiply resources'
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
data/virus_total.gemspec
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'virus_total/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "virus_total"
|
|
8
|
+
spec.version = VirusTotal::VERSION
|
|
9
|
+
spec.authors = ["Rubycop"]
|
|
10
|
+
spec.email = ["saychuk.andriy@gmail.com"]
|
|
11
|
+
spec.summary = %q{gem for VirusTotal API version 2.0.}
|
|
12
|
+
spec.description = %q{gem for VirusTotal API version 2.0.}
|
|
13
|
+
spec.homepage = "https://github.com/rubycop/virus_total"
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
spec.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
23
|
+
spec.add_development_dependency "rspec", "~> 2.6"
|
|
24
|
+
|
|
25
|
+
spec.add_dependency "rest-client", "~> 1.6.7"
|
|
26
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: virus_total
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Rubycop
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-02-15 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.7'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.7'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '10.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '10.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '2.6'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '2.6'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rest-client
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 1.6.7
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 1.6.7
|
|
69
|
+
description: gem for VirusTotal API version 2.0.
|
|
70
|
+
email:
|
|
71
|
+
- saychuk.andriy@gmail.com
|
|
72
|
+
executables: []
|
|
73
|
+
extensions: []
|
|
74
|
+
extra_rdoc_files: []
|
|
75
|
+
files:
|
|
76
|
+
- ".gitignore"
|
|
77
|
+
- Gemfile
|
|
78
|
+
- LICENSE.txt
|
|
79
|
+
- README.md
|
|
80
|
+
- Rakefile
|
|
81
|
+
- lib/core_extensions.rb
|
|
82
|
+
- lib/virus_total.rb
|
|
83
|
+
- lib/virus_total/base.rb
|
|
84
|
+
- lib/virus_total/domain.rb
|
|
85
|
+
- lib/virus_total/exception.rb
|
|
86
|
+
- lib/virus_total/file.rb
|
|
87
|
+
- lib/virus_total/ip.rb
|
|
88
|
+
- lib/virus_total/parser.rb
|
|
89
|
+
- lib/virus_total/url.rb
|
|
90
|
+
- lib/virus_total/version.rb
|
|
91
|
+
- spec/shared_examples_spec.rb
|
|
92
|
+
- spec/virus_total/base_spec.rb
|
|
93
|
+
- spec/virus_total/domain_spec.rb
|
|
94
|
+
- spec/virus_total/file_spec.rb
|
|
95
|
+
- spec/virus_total/ip_spec.rb
|
|
96
|
+
- spec/virus_total/parser_spec.rb
|
|
97
|
+
- spec/virus_total/url_spec.rb
|
|
98
|
+
- virus_total.gemspec
|
|
99
|
+
homepage: https://github.com/rubycop/virus_total
|
|
100
|
+
licenses:
|
|
101
|
+
- MIT
|
|
102
|
+
metadata: {}
|
|
103
|
+
post_install_message:
|
|
104
|
+
rdoc_options: []
|
|
105
|
+
require_paths:
|
|
106
|
+
- lib
|
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - ">="
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: '0'
|
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0'
|
|
117
|
+
requirements: []
|
|
118
|
+
rubyforge_project:
|
|
119
|
+
rubygems_version: 2.4.5
|
|
120
|
+
signing_key:
|
|
121
|
+
specification_version: 4
|
|
122
|
+
summary: gem for VirusTotal API version 2.0.
|
|
123
|
+
test_files:
|
|
124
|
+
- spec/shared_examples_spec.rb
|
|
125
|
+
- spec/virus_total/base_spec.rb
|
|
126
|
+
- spec/virus_total/domain_spec.rb
|
|
127
|
+
- spec/virus_total/file_spec.rb
|
|
128
|
+
- spec/virus_total/ip_spec.rb
|
|
129
|
+
- spec/virus_total/parser_spec.rb
|
|
130
|
+
- spec/virus_total/url_spec.rb
|