defensio 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/LICENSE +21 -0
- data/README +0 -0
- data/Rakefile +26 -0
- data/VERSION +1 -0
- data/lib/defensio.rb +173 -0
- data/test/defensio_test.rb +288 -0
- metadata +71 -0
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2009 Websense Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gemspec|
|
7
|
+
gemspec.name = "defensio"
|
8
|
+
gemspec.summary = "Official Ruby library for Defensio 2.0"
|
9
|
+
gemspec.description = "Official Ruby library for Defensio 2.0"
|
10
|
+
gemspec.email = "support@defensio.com"
|
11
|
+
gemspec.homepage = "http://github.com/defensio/defensio-ruby"
|
12
|
+
gemspec.authors = ["Carl Mercier"]
|
13
|
+
gemspec.add_dependency('patron', '>= 0.4.4')
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler -s http://gemcutter.org"
|
18
|
+
end
|
19
|
+
|
20
|
+
Rake::TestTask.new(:test) do |t|
|
21
|
+
t.libs << 'lib' << 'test'
|
22
|
+
t.pattern = 'test/**/*_test.rb'
|
23
|
+
t.verbose = false
|
24
|
+
end
|
25
|
+
|
26
|
+
task :default => :test
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.9.0
|
data/lib/defensio.rb
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
#
|
2
|
+
# Defensio-Ruby version 0.1
|
3
|
+
# Written by the Defensio team at Websense, Inc.
|
4
|
+
#
|
5
|
+
# Make sure to install the necessary gems by running the following commands:
|
6
|
+
# $ sudo gem install patron -v 0.4.4
|
7
|
+
# On Linux, you'll also need to install the libcurl development package. On Ubuntu, simply do:
|
8
|
+
# $ sudo apt-get install libcurl4-openssl-dev
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'rubygems'
|
12
|
+
require 'patron'
|
13
|
+
require 'uri'
|
14
|
+
|
15
|
+
class Defensio
|
16
|
+
# You shouldn't modify these values unless you really know what you are doing. And then again...
|
17
|
+
API_VERSION = 2.0
|
18
|
+
API_HOST = "http://api.defensio.com"
|
19
|
+
|
20
|
+
# You should't modify anything below this line.
|
21
|
+
LIB_VERSION = "0.9"
|
22
|
+
ROOT_NODE = "defensio-result"
|
23
|
+
FORMAT = :yaml
|
24
|
+
USER_AGENT = "Defensio-Ruby #{LIB_VERSION}"
|
25
|
+
CLIENT = "Defensio-Ruby | #{LIB_VERSION} | Carl Mercier | cmercier@websense.com"
|
26
|
+
KEEP_ALIVE = false
|
27
|
+
|
28
|
+
attr_reader :http_session, :client
|
29
|
+
|
30
|
+
def initialize(api_key, client = CLIENT)
|
31
|
+
@client = client
|
32
|
+
@api_key = api_key
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get information about the api key
|
36
|
+
def get_user
|
37
|
+
call :get, api_url
|
38
|
+
end
|
39
|
+
|
40
|
+
# Create and analyze a new document
|
41
|
+
# @param [Hash] data The parameters to be sent to Defensio. Keys can either be Strings or Symbols
|
42
|
+
# @return [Array] An array containing 2 values: the HTTP status code & a Hash with the values returned by Defensio
|
43
|
+
def post_document(data)
|
44
|
+
data = { :client => @client }.merge(data)
|
45
|
+
call :post, api_url("documents"), data
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get the status of an existing document
|
49
|
+
# @param [String] signature The signature of the document to retrieve
|
50
|
+
# @return [Array] An array containing 2 values: the HTTP status code & a Hash with the values returned by Defensio
|
51
|
+
def get_document(signature)
|
52
|
+
call :get, api_url("documents", signature)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Modify the properties of an existing document
|
56
|
+
# @param [String] signature The signature of the document to modify
|
57
|
+
# @param [Hash] data The parameters to be sent to Defensio. Keys can either be Strings or Symbols
|
58
|
+
# @return [Array] An array containing 2 values: the HTTP status code & a Hash with the values returned by Defensio
|
59
|
+
def put_document(signature, data)
|
60
|
+
call :put, api_url("documents", signature), data
|
61
|
+
end
|
62
|
+
|
63
|
+
# Get basic statistics for the current user
|
64
|
+
# @return [Array] An array containing 2 values: the HTTP status code & a Hash with the values returned by Defensio
|
65
|
+
def get_basic_stats
|
66
|
+
call :get, api_url("basic-stats")
|
67
|
+
end
|
68
|
+
|
69
|
+
# Get more exhaustive statistics for the current user
|
70
|
+
# @param [Hash] data The parameters to be sent to Defensio. Keys can either be Strings or Symbols
|
71
|
+
# @return [Array] An array containing 2 values: the HTTP status code & a Hash with the values returned by Defensio
|
72
|
+
def get_extended_stats(data)
|
73
|
+
result = call(:get, api_url("extended-stats"), data)
|
74
|
+
0.upto(result[1]["data"].size - 1) do |i|
|
75
|
+
result[1]["data"][i]["date"] = Date.parse(result[1]["data"][i]["date"])
|
76
|
+
end
|
77
|
+
|
78
|
+
result
|
79
|
+
end
|
80
|
+
|
81
|
+
# Filter a set of values based on a pre-defined dictionary
|
82
|
+
def post_profanity_filter(data)
|
83
|
+
call :post, api_url("profanity-filter"), data
|
84
|
+
end
|
85
|
+
|
86
|
+
# Takes the request object (Rails, Sinatra, Merb) of an async request callback and returns a hash
|
87
|
+
# containing the status of the document being analyzed.
|
88
|
+
# @param [ActionController::Request, Sinatra::Request, String] request The request object created after Defensio POSTed to your site, or a string representation of the POST data.
|
89
|
+
# @return [Hash] Status of the document
|
90
|
+
def handle_post_document_async_callback(request)
|
91
|
+
if request.is_a?(String)
|
92
|
+
data = request
|
93
|
+
elsif request.respond_to?(:body) && request.body.is_a?(StringIO)
|
94
|
+
data = request.body.read
|
95
|
+
else
|
96
|
+
raise ArgumentError, "Unknown request type: #{request.class}"
|
97
|
+
end
|
98
|
+
|
99
|
+
parse_body(data)
|
100
|
+
end
|
101
|
+
|
102
|
+
# See handle_post_document_async_callback
|
103
|
+
def self.handle_post_document_async_callback(request)
|
104
|
+
Defensio.new(nil).handle_post_document_async_callback(request)
|
105
|
+
end
|
106
|
+
|
107
|
+
protected
|
108
|
+
def api_url(action = nil, id = nil)
|
109
|
+
path = "#{API_HOST}/#{API_VERSION}/users/#{@api_key}"
|
110
|
+
path += "/#{action}" if action
|
111
|
+
path += "/#{id}" if id
|
112
|
+
path += ".#{FORMAT}"
|
113
|
+
end
|
114
|
+
|
115
|
+
def http_session
|
116
|
+
return @http_session if KEEP_ALIVE && @http_session
|
117
|
+
@http_session = Patron::Session.new
|
118
|
+
@http_session.timeout = 20
|
119
|
+
@http_session.headers['User-Agent'] = USER_AGENT
|
120
|
+
@http_session.headers['Content-Type'] = "text/#{FORMAT}"
|
121
|
+
@http_session
|
122
|
+
end
|
123
|
+
|
124
|
+
def http_session=(session)
|
125
|
+
@http_session = session
|
126
|
+
end
|
127
|
+
|
128
|
+
def call(method, url, data = nil)
|
129
|
+
data = hash_to_query_string(data) if data.is_a?(Hash)
|
130
|
+
url = url + "?#{data}" unless data.nil? || data.empty?
|
131
|
+
|
132
|
+
response = case method
|
133
|
+
when :get
|
134
|
+
http_session.get(url)
|
135
|
+
when :delete
|
136
|
+
http_session.delete(url)
|
137
|
+
when :post
|
138
|
+
http_session.post(url, {})
|
139
|
+
when :put
|
140
|
+
http_session.put(url, {})
|
141
|
+
else
|
142
|
+
raise(ArgumentError, "Invalid HTTP method: #{method}")
|
143
|
+
end
|
144
|
+
|
145
|
+
http_session = nil unless KEEP_ALIVE
|
146
|
+
|
147
|
+
[response.status, parse_body(response.body)]
|
148
|
+
end
|
149
|
+
|
150
|
+
def parse_body(str)
|
151
|
+
if FORMAT == :yaml
|
152
|
+
return YAML::load(str)[ROOT_NODE]
|
153
|
+
else
|
154
|
+
raise(NotImplementedError, "This library doesn't support this format: #{FORMAT}")
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def hash_to_query_string(data)
|
159
|
+
return nil unless data.is_a?(Hash)
|
160
|
+
out = ""
|
161
|
+
sort_hash_by_key(data).each do |item|
|
162
|
+
k, v = item[0], item[1]
|
163
|
+
out += "&" unless out.empty?
|
164
|
+
k = k.to_s.gsub(/_/, "-") if k.is_a?(Symbol)
|
165
|
+
out += "#{k}=#{URI.escape(v.to_s)}"
|
166
|
+
end
|
167
|
+
out
|
168
|
+
end
|
169
|
+
|
170
|
+
def sort_hash_by_key(hash)
|
171
|
+
hash.keys.sort_by {|s| s.to_s}.map {|key| [key, hash[key]] }
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,288 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../lib/defensio"
|
2
|
+
DEFENSIO_ENV = "test"
|
3
|
+
require 'test/unit'
|
4
|
+
require 'mocha'
|
5
|
+
require 'redgreen'
|
6
|
+
require 'ostruct'
|
7
|
+
|
8
|
+
class DefensioTest < Test::Unit::TestCase
|
9
|
+
MOCK_RESPONSE = true
|
10
|
+
API_KEY = "1234567890"
|
11
|
+
OWNER_URL = "http://example.org"
|
12
|
+
SIGNATURE = "abcdefghijklmnop"
|
13
|
+
|
14
|
+
API_VERSION = 2.0
|
15
|
+
API_HOST = "http://api.defensio.com"
|
16
|
+
FORMAT = :yaml
|
17
|
+
HEADERS = {"User-Agent" => "Defensio-Ruby #{Defensio::LIB_VERSION}", "Content-Type" => "text/yaml"}
|
18
|
+
|
19
|
+
# API METHOD TESTS -- Useful to learn how to use the library
|
20
|
+
def test_get_user
|
21
|
+
if MOCK_RESPONSE
|
22
|
+
Patron::Session.any_instance.expects(:get).with("#{API_HOST}/#{API_VERSION}/users/#{API_KEY}.#{FORMAT}").once.returns(FakePatronResponse.new(200, user_body))
|
23
|
+
end
|
24
|
+
|
25
|
+
status, body = @d.get_user
|
26
|
+
assert body.is_a?(Hash)
|
27
|
+
assert_equal 200, status
|
28
|
+
assert_equal "success", body["status"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_post_document
|
32
|
+
if MOCK_RESPONSE
|
33
|
+
query = "client=Defensio-Ruby%20%7C%20#{Defensio::LIB_VERSION}%20%7C%20Carl%20Mercier%20%7C%20cmercier@websense.com&content=We%20sell%20cheap%20Viagra!%20[spam,0.95]&platform=my_awesome_app&type=test"
|
34
|
+
Patron::Session.any_instance.expects(:post).with("#{API_HOST}/#{API_VERSION}/users/#{API_KEY}/documents.#{FORMAT}?#{query}", {}).once.returns(FakePatronResponse.new(200, document_body(SIGNATURE)))
|
35
|
+
end
|
36
|
+
|
37
|
+
data = { :content => "We sell cheap Viagra! [spam,0.95]", :platform => "my_awesome_app", :type => "test" }
|
38
|
+
status, body = @d.post_document(data)
|
39
|
+
assert body.is_a?(Hash)
|
40
|
+
assert_equal 200, status
|
41
|
+
assert_equal "success", body["status"]
|
42
|
+
assert body["signature"].is_a?(String)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_get_document
|
46
|
+
if MOCK_RESPONSE
|
47
|
+
Patron::Session.any_instance.expects(:get).with("#{API_HOST}/#{API_VERSION}/users/#{API_KEY}/documents/#{SIGNATURE}.#{FORMAT}").once.returns(FakePatronResponse.new(200, document_body(SIGNATURE)))
|
48
|
+
end
|
49
|
+
|
50
|
+
status, body = @d.get_document(SIGNATURE)
|
51
|
+
assert body.is_a?(Hash)
|
52
|
+
assert_equal 200, status
|
53
|
+
assert_equal "success", body["status"]
|
54
|
+
assert_equal SIGNATURE, body["signature"]
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_put_document
|
58
|
+
if MOCK_RESPONSE
|
59
|
+
query = "allow=true"
|
60
|
+
Patron::Session.any_instance.expects(:put).with("#{API_HOST}/#{API_VERSION}/users/#{API_KEY}/documents/#{SIGNATURE}.#{FORMAT}?#{query}", {}).once.returns(FakePatronResponse.new(200, document_body_allowed(SIGNATURE)))
|
61
|
+
end
|
62
|
+
|
63
|
+
status, body = @d.put_document(SIGNATURE, :allow => true)
|
64
|
+
assert body.is_a?(Hash)
|
65
|
+
assert_equal 200, status
|
66
|
+
assert_equal "success", body["status"]
|
67
|
+
assert_equal SIGNATURE, body["signature"]
|
68
|
+
assert_equal true, body["allow"]
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_get_basic_stats
|
72
|
+
if MOCK_RESPONSE
|
73
|
+
Patron::Session.any_instance.expects(:get).with("#{API_HOST}/#{API_VERSION}/users/#{API_KEY}/basic-stats.#{FORMAT}").once.returns(FakePatronResponse.new(200, basic_stats_body))
|
74
|
+
end
|
75
|
+
|
76
|
+
status, body = @d.get_basic_stats
|
77
|
+
assert body.is_a?(Hash)
|
78
|
+
assert_equal 200, status
|
79
|
+
assert_equal "success", body["status"]
|
80
|
+
assert body["unwanted"]["total"].is_a?(Integer)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_get_extended_stats
|
84
|
+
if MOCK_RESPONSE
|
85
|
+
query="from=2009-09-01&to=2009-09-03"
|
86
|
+
Patron::Session.any_instance.expects(:get).with("#{API_HOST}/#{API_VERSION}/users/#{API_KEY}/extended-stats.#{FORMAT}?#{query}").once.returns(FakePatronResponse.new(200, extended_stats_body))
|
87
|
+
end
|
88
|
+
|
89
|
+
status, body = @d.get_extended_stats(:from => Date.new(2009, 9, 1), :to => Date.new(2009, 9, 3))
|
90
|
+
assert body.is_a?(Hash)
|
91
|
+
assert_equal 200, status
|
92
|
+
assert_equal "success", body["status"]
|
93
|
+
assert body["data"].is_a?(Array)
|
94
|
+
assert body["data"][0]["date"].is_a?(Date)
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_post_profanity_filter
|
98
|
+
if MOCK_RESPONSE
|
99
|
+
query="OtherField=hello%20again&field1=hello%20world"
|
100
|
+
Patron::Session.any_instance.expects(:post).with("#{API_HOST}/#{API_VERSION}/users/#{API_KEY}/profanity-filter.#{FORMAT}?#{query}", {}).once.returns(FakePatronResponse.new(200, profanity_filter_body))
|
101
|
+
end
|
102
|
+
|
103
|
+
status, body = @d.post_profanity_filter("field1"=>"hello world", "OtherField"=>"hello again")
|
104
|
+
assert body.is_a?(Hash)
|
105
|
+
assert_equal 200, status
|
106
|
+
assert_equal "success", body["status"]
|
107
|
+
assert body["filtered"].is_a?(Hash)
|
108
|
+
assert body["filtered"].keys.include?("field1")
|
109
|
+
assert body["filtered"].keys.include?("OtherField")
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_handle_post_document_async_callback__string
|
113
|
+
result = { "api-version" => API_VERSION,
|
114
|
+
"status" => "success",
|
115
|
+
"message" => nil,
|
116
|
+
"signature" => SIGNATURE,
|
117
|
+
"allow" => false,
|
118
|
+
"classification" => "malicious",
|
119
|
+
"spaminess" => 0.95,
|
120
|
+
"profanity-match" => true }
|
121
|
+
|
122
|
+
assert_equal result, @d.class.handle_post_document_async_callback(document_body(SIGNATURE))
|
123
|
+
assert_equal result, @d.handle_post_document_async_callback(document_body(SIGNATURE))
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_handle_post_document_async_callback__request_object
|
127
|
+
result = { "api-version" => API_VERSION,
|
128
|
+
"status" => "success",
|
129
|
+
"message" => nil,
|
130
|
+
"signature" => SIGNATURE,
|
131
|
+
"allow" => false,
|
132
|
+
"classification" => "malicious",
|
133
|
+
"spaminess" => 0.95,
|
134
|
+
"profanity-match" => true }
|
135
|
+
|
136
|
+
fake_request_object = OpenStruct.new(:body => StringIO.new(document_body(SIGNATURE)))
|
137
|
+
assert_equal result, @d.class.handle_post_document_async_callback(fake_request_object)
|
138
|
+
|
139
|
+
fake_request_object = OpenStruct.new(:body => StringIO.new(document_body(SIGNATURE)))
|
140
|
+
assert_equal result, @d.handle_post_document_async_callback(fake_request_object)
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_handle_post_document_async_callback__invalid_object_type
|
144
|
+
assert_raise(ArgumentError) { @d.class.handle_post_document_async_callback(nil) }
|
145
|
+
assert_raise(ArgumentError) { @d.handle_post_document_async_callback(nil) }
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
# OTHER TESTS
|
150
|
+
def test_http_session
|
151
|
+
s = @d.send(:http_session)
|
152
|
+
assert s.is_a?(Patron::Session)
|
153
|
+
if @d.class.class_eval("KEEP_ALIVE")
|
154
|
+
assert_equal s, @d.send(:http_session) # make sure sessions are reused when KEEP_ALIVE is true
|
155
|
+
else
|
156
|
+
assert_not_equal s, @d.send(:http_session) # make sure sessions are dropped when KEEP_ALIVE is false
|
157
|
+
end
|
158
|
+
|
159
|
+
assert_equal HEADERS, s.headers
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_api_url
|
163
|
+
assert_equal "#{API_HOST}/#{API_VERSION}/users/#{API_KEY}.yaml", @d.send(:api_url)
|
164
|
+
assert_equal "#{API_HOST}/#{API_VERSION}/users/#{API_KEY}/documents.yaml", @d.send(:api_url, "documents")
|
165
|
+
assert_equal "#{API_HOST}/#{API_VERSION}/users/#{API_KEY}/documents/abcdefghijklmnop.yaml", @d.send(:api_url, "documents", "abcdefghijklmnop")
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_hash_to_query_string
|
169
|
+
assert_equal "hello-world=true", @d.send(:hash_to_query_string, {:hello_world => true} )
|
170
|
+
assert_equal "hello-world=this%20has%20spaces%20and%20characters%20($%20?%20&%20%5E%20%C3%A9)%20that%20should%20be%20escaped",
|
171
|
+
@d.send(:hash_to_query_string, {:hello_world => "this has spaces and characters ($ ? & ^ é) that should be escaped"} )
|
172
|
+
assert_equal "value1=true&value2=true&value3=true", @d.send(:hash_to_query_string, { "value1" => true, "value2" => true, :value3 => true})
|
173
|
+
assert_equal "date=2009-01-01", @d.send(:hash_to_query_string, { "date" => Date.new(2009,1,1) })
|
174
|
+
assert_nil @d.send(:hash_to_query_string, nil)
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_parse_body
|
178
|
+
parsed = {"hello"=>"world"}
|
179
|
+
assert_equal parsed, @d.send(:parse_body, "---\ndefensio-result:\n hello: world")
|
180
|
+
end
|
181
|
+
|
182
|
+
# HELPERS AND SETUP
|
183
|
+
def setup
|
184
|
+
@d = Defensio.new(API_KEY)
|
185
|
+
end
|
186
|
+
|
187
|
+
def http_session
|
188
|
+
@d.send(:http_session)
|
189
|
+
end
|
190
|
+
|
191
|
+
def base_url
|
192
|
+
"#{API_HOST}/#{API_VERSION}"
|
193
|
+
end
|
194
|
+
|
195
|
+
# MOCKING
|
196
|
+
class FakePatronResponse < Struct.new(:status, :body); end
|
197
|
+
|
198
|
+
def user_body
|
199
|
+
{ "defensio-result" => {"api-version" => API_VERSION, "status" => "success", "message" => nil, "owner-url" => OWNER_URL} }.send("to_#{FORMAT}")
|
200
|
+
end
|
201
|
+
|
202
|
+
def document_body(signature)
|
203
|
+
{ "defensio-result" => {
|
204
|
+
"api-version" => API_VERSION,
|
205
|
+
"status" => "success",
|
206
|
+
"message" => nil,
|
207
|
+
"signature" => signature,
|
208
|
+
"allow" => false,
|
209
|
+
"classification" => "malicious",
|
210
|
+
"spaminess" => 0.95,
|
211
|
+
"profanity-match" => true }
|
212
|
+
}.send("to_#{FORMAT}")
|
213
|
+
end
|
214
|
+
|
215
|
+
def document_body_allowed(signature)
|
216
|
+
{ "defensio-result" => {
|
217
|
+
"api-version" => API_VERSION,
|
218
|
+
"status" => "success",
|
219
|
+
"message" => nil,
|
220
|
+
"signature" => signature,
|
221
|
+
"allow" => true,
|
222
|
+
"classification" => "innocent",
|
223
|
+
"spaminess" => 0.95,
|
224
|
+
"profanity-match" => true }
|
225
|
+
}.send("to_#{FORMAT}")
|
226
|
+
end
|
227
|
+
|
228
|
+
def basic_stats_body
|
229
|
+
{ "defensio-result" => {
|
230
|
+
"api-version" => API_VERSION,
|
231
|
+
"status" => "success",
|
232
|
+
"message" => nil,
|
233
|
+
"recent-accuracy" => 0.9975,
|
234
|
+
"legitimate" => { "total" => 100 },
|
235
|
+
"unwanted" => { "total" => 100, "malicious" => 50, "spam" => 100},
|
236
|
+
"false-positives" => 1,
|
237
|
+
"false-negatices" => 2,
|
238
|
+
"learning" => true,
|
239
|
+
"learning-status" => "Details about learning mode" }
|
240
|
+
}.send("to_#{FORMAT}")
|
241
|
+
end
|
242
|
+
|
243
|
+
def extended_stats_body
|
244
|
+
{ "defensio-result" => {
|
245
|
+
"api-version" => API_VERSION,
|
246
|
+
"status" => "success",
|
247
|
+
"message" => nil,
|
248
|
+
"data" => [
|
249
|
+
{ "date" => "2009-09-01",
|
250
|
+
"recent-accuracy" => 0.9975,
|
251
|
+
"legitimate" => 100,
|
252
|
+
"unwanted" => 500,
|
253
|
+
"false-positives" => 1,
|
254
|
+
"false-negatives" => 0 },
|
255
|
+
{
|
256
|
+
"date" => "2009-09-02",
|
257
|
+
"recent-accuracy" => 0.9985,
|
258
|
+
"legitimate" => 50,
|
259
|
+
"unwanted" => 475,
|
260
|
+
"false-positives" => 0,
|
261
|
+
"false-negatives" => 0 },
|
262
|
+
{ "date" => "2009-09-03",
|
263
|
+
"recent-accuracy" => 0.9992,
|
264
|
+
"legitimate" => 100,
|
265
|
+
"unwanted" => 500,
|
266
|
+
"false-positives" => 1,
|
267
|
+
"false-negatives" => 0 }
|
268
|
+
],
|
269
|
+
"chart-urls" => {
|
270
|
+
"recent-accuracy" => "http://domain.com/chart/123456",
|
271
|
+
"total-unwanted" => "http://domain.com/chart/abcdef",
|
272
|
+
"total-legitimate" => "http://domain.com/chart/xyzabc" }
|
273
|
+
}
|
274
|
+
}.send("to_#{FORMAT}")
|
275
|
+
end
|
276
|
+
|
277
|
+
def profanity_filter_body
|
278
|
+
{ "defensio-result" => {
|
279
|
+
"api-version" => API_VERSION,
|
280
|
+
"status" => "success",
|
281
|
+
"message" => nil,
|
282
|
+
"filtered" =>
|
283
|
+
{ "field1" => "hello world",
|
284
|
+
"OtherField" => "hello again" }
|
285
|
+
}
|
286
|
+
}.send("to_#{FORMAT}")
|
287
|
+
end
|
288
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: defensio
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Carl Mercier
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-07 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: patron
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.4.4
|
24
|
+
version:
|
25
|
+
description: Official Ruby library for Defensio 2.0
|
26
|
+
email: support@defensio.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- LICENSE
|
33
|
+
- README
|
34
|
+
files:
|
35
|
+
- .gitignore
|
36
|
+
- LICENSE
|
37
|
+
- README
|
38
|
+
- Rakefile
|
39
|
+
- VERSION
|
40
|
+
- lib/defensio.rb
|
41
|
+
- test/defensio_test.rb
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://github.com/defensio/defensio-ruby
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --charset=UTF-8
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: "0"
|
56
|
+
version:
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
requirements: []
|
64
|
+
|
65
|
+
rubyforge_project:
|
66
|
+
rubygems_version: 1.3.5
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: Official Ruby library for Defensio 2.0
|
70
|
+
test_files:
|
71
|
+
- test/defensio_test.rb
|