rack-honeypot 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rack/honeypot.rb CHANGED
@@ -16,52 +16,56 @@ module Rack
16
16
  def call(env)
17
17
  if spambot_submission?(Rack::Request.new(env).params)
18
18
  @logger.warn("[Rack::Honeypot] Spam bot detected; responded with null") unless @logger.nil?
19
- send_to_dead_end
19
+ null_response
20
20
  else
21
21
  status, headers, response = @app.call(env)
22
- new_body = insert_honeypot(build_response_body(response))
23
- new_headers = recalculate_body_length(headers, new_body)
22
+ new_body = insert_honeypot(response_body(response))
23
+ new_headers = response_headers(headers, new_body)
24
24
  [status, new_headers, new_body]
25
25
  end
26
26
  end
27
27
 
28
+ private
29
+
28
30
  def spambot_submission?(form_hash)
29
31
  form_hash && form_hash[@input_name] && form_hash[@input_name] != @input_value
30
32
  end
31
33
 
32
- def send_to_dead_end
34
+ def null_response
33
35
  [200, {'Content-Type' => 'text/html', "Content-Length" => "0"}, []]
34
36
  end
35
37
 
36
- def build_response_body(response)
37
- response_body = ""
38
- response.each { |part| response_body += part }
39
- response_body
38
+ def response_body(response)
39
+ response.join("")
40
40
  end
41
41
 
42
- def recalculate_body_length(headers, body)
43
- new_headers = headers
44
- new_headers["Content-Length"] = body.length.to_s
45
- new_headers
42
+ def response_headers(headers, body)
43
+ headers.merge("Content-Length" => body.length.to_s)
46
44
  end
47
45
 
48
46
  def insert_honeypot(body)
49
- css = unindent <<-BLOCK
47
+ body.gsub!(/<\/head>/, css + "\n</head>")
48
+ body.gsub!(/<form(.*)>/, '<form\1>' + "\n" + div)
49
+ body
50
+ end
51
+
52
+ def css
53
+ unindent <<-BLOCK
50
54
  <style type='text/css' media='all'>
51
55
  div.#{@class_name} {
52
56
  display:none;
53
57
  }
54
58
  </style>
55
59
  BLOCK
56
- div = unindent <<-BLOCK
60
+ end
61
+
62
+ def div
63
+ unindent <<-BLOCK
57
64
  <div class='#{@class_name}'>
58
65
  <label for='#{@input_name}'>#{@label}</label>
59
66
  <input type='text' name='#{@input_name}' value='#{@input_value}'/>
60
67
  </div>
61
68
  BLOCK
62
- body.gsub!(/<\/head>/, css + "\n</head>")
63
- body.gsub!(/<form(.*)>/, '<form\1>' + "\n" + div)
64
- body
65
69
  end
66
70
 
67
71
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-honeypot
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Luigi Montanez
@@ -19,24 +19,10 @@ cert_chain: []
19
19
 
20
20
  date: 2011-10-05 00:00:00 Z
21
21
  dependencies:
22
- - !ruby/object:Gem::Dependency
23
- name: rake
24
- prerelease: false
25
- requirement: &id001 !ruby/object:Gem::Requirement
26
- none: false
27
- requirements:
28
- - - ">="
29
- - !ruby/object:Gem::Version
30
- hash: 3
31
- segments:
32
- - 0
33
- version: "0"
34
- type: :runtime
35
- version_requirements: *id001
36
22
  - !ruby/object:Gem::Dependency
37
23
  name: unindentable
38
24
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ requirement: &id001 !ruby/object:Gem::Requirement
40
26
  none: false
41
27
  requirements:
42
28
  - - "="
@@ -48,25 +34,11 @@ dependencies:
48
34
  - 4
49
35
  version: 0.0.4
50
36
  type: :runtime
51
- version_requirements: *id002
37
+ version_requirements: *id001
52
38
  - !ruby/object:Gem::Dependency
53
39
  name: rack
54
40
  prerelease: false
55
- requirement: &id003 !ruby/object:Gem::Requirement
56
- none: false
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- hash: 3
61
- segments:
62
- - 0
63
- version: "0"
64
- type: :runtime
65
- version_requirements: *id003
66
- - !ruby/object:Gem::Dependency
67
- name: rack-test
68
- prerelease: false
69
- requirement: &id004 !ruby/object:Gem::Requirement
41
+ requirement: &id002 !ruby/object:Gem::Requirement
70
42
  none: false
71
43
  requirements:
72
44
  - - ">="
@@ -76,7 +48,7 @@ dependencies:
76
48
  - 0
77
49
  version: "0"
78
50
  type: :runtime
79
- version_requirements: *id004
51
+ version_requirements: *id002
80
52
  description: This middleware acts as a spam trap. It inserts, into every outputted <form>, a text field that a spambot will really want to fill in, but is actually not used by the app. The field is hidden to humans via CSS, and includes a warning label for screenreading software.
81
53
  email: luigi.montanez@gmail.com
82
54
  executables: []
@@ -87,13 +59,10 @@ extra_rdoc_files:
87
59
  - LICENSE.md
88
60
  - README.md
89
61
  files:
90
- - Gemfile
91
62
  - LICENSE.md
92
63
  - README.md
93
- - Rakefile
94
64
  - VERSION
95
65
  - lib/rack/honeypot.rb
96
- - test/test_honeypot.rb
97
66
  homepage: http://github.com/sunlightlabs/rack-honeypot
98
67
  licenses: []
99
68
 
data/Gemfile DELETED
@@ -1,7 +0,0 @@
1
- source 'http://rubygems.org/'
2
-
3
- gem 'rake'
4
- gem 'unindentable', '0.0.4'
5
- gem 'rack'
6
- gem 'mocha'
7
- gem 'rack-test'
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
-
2
- require 'rake/testtask'
3
-
4
- Rake::TestTask.new do |task|
5
- task.test_files = FileList['test/test_*.rb']
6
- end
@@ -1,87 +0,0 @@
1
- require 'rack/test'
2
- require 'test/unit'
3
- require 'mocha'
4
- require 'unindentable'
5
-
6
- require File.expand_path(File.dirname(__FILE__) + '/../lib/rack/honeypot')
7
-
8
- # To run this test, you need to have rack-test gem installed: sudo gem install rack-test
9
-
10
- class HoneypotTest < Test::Unit::TestCase
11
- include Rack::Test::Methods
12
- include Unindentable
13
-
14
- def setup
15
- @logger = stub("logger", :warn => nil)
16
- end
17
-
18
- def app
19
- content = unindent <<-BLOCK
20
- <html>
21
- <head>
22
- </head>
23
- <body>
24
- <form></form>
25
- Hello World!
26
- </body>
27
- </html>
28
- BLOCK
29
-
30
- hello_world_app = lambda do |env|
31
- [
32
- 200,
33
- {
34
- 'Content-Type' => 'text/plain',
35
- 'Content-Length' => content.length.to_s
36
- },
37
- [content]
38
- ]
39
- end
40
-
41
- Rack::Honeypot.new(hello_world_app, :input_name => 'honeypot_email', :logger => @logger)
42
- end
43
-
44
- def test_normal_request_should_go_through
45
- get '/'
46
- assert_equal 200, last_response.status
47
- assert_not_equal '', last_response.body
48
- end
49
-
50
- def test_request_with_form_should_add_honeypot_css
51
- get '/'
52
- assert_equal 200, last_response.status
53
- css = unindent <<-BLOCK
54
- <style type='text/css' media='all'>
55
- div.phonetoy {
56
- display:none;
57
- }
58
- </style>
59
- BLOCK
60
- assert last_response.body.index(css)
61
- end
62
-
63
- def test_request_with_form_should_add_honeypot_div
64
- get '/'
65
- assert_equal 200, last_response.status
66
-
67
- div = unindent <<-BLOCK
68
- <div class='phonetoy'>
69
- <label for='honeypot_email'>Don't fill in this field</label>
70
- <input type='text' name='honeypot_email' value=''/>
71
- </div>
72
- BLOCK
73
- assert last_response.body.index(div)
74
- end
75
-
76
- def test_spam_request_should_be_sent_to_dead_end
77
- post '/', :honeypot_email => 'joe@example.com'
78
- assert_equal 200, last_response.status
79
- assert_equal '', last_response.body
80
- end
81
-
82
- def test_spam_request_should_be_logged
83
- @logger.expects(:warn).with("[Rack::Honeypot] Spam bot detected; responded with null")
84
- post '/', :honeypot_email => 'joe@example.com'
85
- end
86
-
87
- end