spambust 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTk2ZWQ3NDRhM2Y4ZTExYTYzMzcyYmU0NDdlNjc0MTYwZDFlZDFkNA==
5
+ data.tar.gz: !binary |-
6
+ ZGNiOWU4ODM5MjViOWZhNWQ5ZDdmYjI0MTBjYzAzYjRkZDIwNGM0ZQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZGIwMzYzMjA3NjIxODkwNzE5MjQ5YTRhZWE3YmU5YjA4ZDAyMjhhYWVmZGZi
10
+ NDQ4ZDk0MjNlYmQwYTdkYzU5ZjNhY2YwNGM3MmZiOTY1NmU2NWI3NTQ2ZmRj
11
+ ODhhNzNkZTllYjdiZjZlOTBlMDc1MDU1NTU1OTg5OTAxOWZiZGI=
12
+ data.tar.gz: !binary |-
13
+ NzMyYzRlY2QzOWE4MDg4NDA5NTM0YmQ2OTc3YWU2YzZkN2Y4NzQ3NmNiYzlj
14
+ YzFmYWYwNWQ2YTk3ZmQxMDYzYWQ0YzJjYmJiNzQ1NDk0NTZiMzZjODY5OWZj
15
+ NDcyNGE4MWNiNzk0ZGZlYWMxZDM3N2QzZWQ3M2QyZjRhM2FjMDA=
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Chirantan Mitra
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ 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, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,8 @@
1
+ spambust
2
+ =======
3
+
4
+ Sinatra form helper to reduce spams
5
+
6
+ Render input tags with a masked name. The input tags with proper tags are hidden.
7
+ We expect a spam bot to fill the incorrect input tags. The server would pick the spam bot
8
+ and respond accordingly.
@@ -0,0 +1,46 @@
1
+ require "digest/md5"
2
+
3
+ module Spambust
4
+ module FormHelpers
5
+ def input(paths, options = {})
6
+ type = options.delete(:type) || "text"
7
+ options_without_id = options.select { |key, value| key != :id }
8
+ others = hash_to_options(options)
9
+ others_without_id = hash_to_options(options_without_id)
10
+ digested_paths = paths.map { |path| Digest::MD5.hexdigest(path) }
11
+ %Q(<input type="#{type}" name="#{namify digested_paths}"#{others} /><input type="hidden" name="#{namify paths}"#{others_without_id} />)
12
+ end
13
+
14
+ def submit(text, options = {})
15
+ others = hash_to_options(options)
16
+ %Q(<input type="submit" value="#{text}"#{others} />)
17
+ end
18
+
19
+ def namify(paths)
20
+ first = paths[0]
21
+ rest = paths[1..-1].reduce("") { |acc, path| acc << "[#{path}]" }
22
+ "#{first}#{rest}"
23
+ end
24
+
25
+ def decrypt(lookup, global)
26
+ fake = global[lookup] || {}
27
+ hashed_lookup = Digest::MD5.hexdigest(lookup)
28
+ subset = global[hashed_lookup] || {}
29
+
30
+ fake.reduce({}) do |real, (key, value)|
31
+ real[key] = subset[Digest::MD5.hexdigest(key)]
32
+ real
33
+ end
34
+ end
35
+
36
+ def valid?(lookup, global)
37
+ fake = global[lookup] || {}
38
+ fake.none? { |key, value| value != "" }
39
+ end
40
+
41
+ def hash_to_options(hash)
42
+ hash.reduce("") { |acc, (key, value)| acc << %Q( #{key}="#{value}") }
43
+ end
44
+ private :hash_to_options
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ module Spambust
2
+ VERSION="0.1.1"
3
+ end
data/lib/spambust.rb ADDED
@@ -0,0 +1 @@
1
+ require_relative "spambust/form_helpers"
@@ -0,0 +1,29 @@
1
+ require "sinatra"
2
+ require File.expand_path "../../lib/spambust/form_helpers", File.dirname(__FILE__)
3
+
4
+ module Spambust
5
+ class TestApp < Sinatra::Base
6
+ helpers Spambust::FormHelpers
7
+
8
+ class << self
9
+ def start_app
10
+ run!
11
+ end
12
+
13
+ def direct_script_execution?
14
+ app_file == $0
15
+ end
16
+ end
17
+
18
+ get "/" do
19
+ erb :index
20
+ end
21
+
22
+ post '/' do
23
+ @result = valid?("user", params) ? "Users is #{decrypt("user", params)}" : "Faking is bad"
24
+ erb :index
25
+ end
26
+
27
+ start_app if direct_script_execution? && ENV["environment"] != "test"
28
+ end
29
+ end
@@ -0,0 +1,63 @@
1
+ require File.expand_path "../spec_helper", File.dirname(__FILE__)
2
+ require File.expand_path "demo_app", File.dirname(__FILE__)
3
+
4
+ describe "test application" do
5
+ include Rack::Test::Methods
6
+
7
+ let(:app) { Spambust::TestApp }
8
+
9
+ let(:user_md5) { Digest::MD5.hexdigest("user") }
10
+ let(:first_name_md5) { Digest::MD5.hexdigest("first_name") }
11
+ let(:last_name_md5) { Digest::MD5.hexdigest("last_name") }
12
+ let(:email_md5) { Digest::MD5.hexdigest("email") }
13
+
14
+ describe "when loading a form" do
15
+ it "contains hidden input fields" do
16
+ get "/"
17
+
18
+ last_response.body.must_include %Q(<input type="hidden" name="user[email]" size="40" />)
19
+ end
20
+ end
21
+
22
+ describe "when posting a form" do
23
+ describe "when hidden fields aren't filled" do
24
+ it "is accepted" do
25
+ params = {
26
+ user_md5 => {
27
+ first_name_md5 => "True first name",
28
+ last_name_md5 => "True last name",
29
+ email_md5 => "True email",
30
+ },
31
+ "user" => {
32
+ "first_name" => "",
33
+ "last_name" => "",
34
+ "email" => "",
35
+ }
36
+ }
37
+
38
+ post "/", params
39
+ last_response.body.must_include %Q({"first_name"=>"True first name", "last_name"=>"True last name", "email"=>"True email"})
40
+ end
41
+ end
42
+
43
+ describe "when hidden fields aren't filled" do
44
+ it "is is identified as fake" do
45
+ params = {
46
+ user_md5 => {
47
+ first_name_md5 => "True first name",
48
+ last_name_md5 => "True last name",
49
+ email_md5 => "True email",
50
+ },
51
+ "user" => {
52
+ "first_name" => "Fake first name",
53
+ "last_name" => "Fake last name",
54
+ "email" => "Fake email",
55
+ }
56
+ }
57
+
58
+ post "/", params
59
+ last_response.body.must_include "Faking is bad"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,123 @@
1
+ require "digest/md5"
2
+
3
+ require File.expand_path "../spec_helper", File.dirname(__FILE__)
4
+ require File.expand_path "../../lib/spambust/form_helpers", File.dirname(__FILE__)
5
+
6
+ class TestApp
7
+ include Spambust::FormHelpers
8
+ end
9
+
10
+ describe "Bustspam::FormHelpers" do
11
+ subject { TestApp.new }
12
+
13
+ let(:user_md5) { Digest::MD5.hexdigest("user") }
14
+ let(:name_md5) { Digest::MD5.hexdigest("name") }
15
+
16
+ describe "#input" do
17
+ describe "when type is not mentioned" do
18
+ it "renders an input tag of type 'text'" do
19
+ subject.input(["user", "name"]).must_equal %Q(<input type="text" name="#{user_md5}[#{name_md5}]" /><input type="hidden" name="user[name]" />)
20
+ end
21
+ end
22
+
23
+ describe "when type is mentioned" do
24
+ it "renders an input tag of specified type" do
25
+ subject.input(["user", "name"], :type => "password").must_equal %Q(<input type="password" name="#{user_md5}[#{name_md5}]" /><input type="hidden" name="user[name]" />)
26
+ end
27
+ end
28
+
29
+ describe "when other options are mentioned" do
30
+ it "renders the options" do
31
+ subject.input(["user", "name"], :id => "name", :class => "name").must_equal %Q(<input type="text" name="#{user_md5}[#{name_md5}]" id="name" class="name" /><input type="hidden" name="user[name]" class="name" />)
32
+ end
33
+ end
34
+ end
35
+
36
+ describe "#submit" do
37
+ describe "when type is mentioned" do
38
+ it "renders an input tag of specified 'submit" do
39
+ subject.submit("Submit").must_equal %Q(<input type="submit" value="Submit" />)
40
+ end
41
+ end
42
+
43
+ describe "when other options are mentioned" do
44
+ it "renders the options" do
45
+ subject.submit("Submit", :id => "submit", :class => "submit").must_equal %Q(<input type="submit" value="Submit" id="submit" class="submit" />)
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "#namify" do
51
+ describe "when size is one" do
52
+ it "is the word itself" do
53
+ subject.namify(["user"]).must_equal "user"
54
+ end
55
+ end
56
+
57
+ describe "when size is more than one" do
58
+ it "nests the items in successive square brackets" do
59
+ subject.namify(["user", "name", "first"]).must_equal "user[name][first]"
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#decrypt" do
65
+ it "pulls the values corresponding to decrypted the keys under the lookup" do
66
+ params = {
67
+ "user" => { "name" => "spam value"},
68
+ user_md5 => { name_md5 => "true value" }
69
+ }
70
+
71
+ subject.decrypt("user", params).must_equal("name" => "true value")
72
+ end
73
+
74
+ describe "when lookup doesn't exist" do
75
+ it "is empty" do
76
+ params = {
77
+ "user" => { "name" => "spam value"},
78
+ user_md5 => { name_md5 => "true value" }
79
+ }
80
+ subject.decrypt("missing_user", params).must_equal({})
81
+ end
82
+ end
83
+
84
+ describe "when fake keys don't conform to the decrypted keys" do
85
+ it "populates the key with a nil value" do
86
+ params = {
87
+ "user" => { "name" => "spam value"},
88
+ user_md5.succ => { name_md5 => "true value" }
89
+ }
90
+ subject.decrypt("user", params).must_equal({"name" => nil})
91
+ end
92
+ end
93
+ end
94
+
95
+ describe "#valid?" do
96
+ it "is true is none of the paths under lookup are populated" do
97
+ params = {
98
+ "user" => { "name" => ""},
99
+ user_md5 => { name_md5 => "true value" }
100
+ }
101
+
102
+ subject.valid?("user", params).must_equal true
103
+ end
104
+
105
+ it "is false is one of the paths under lookup is populated" do
106
+ params = {
107
+ "user" => { "name" => "spam value"},
108
+ user_md5 => { name_md5 => "true value" }
109
+ }
110
+
111
+ subject.valid?("user", params).must_equal false
112
+ end
113
+
114
+ it "is true is lookup doesn't exist" do
115
+ params = {
116
+ "user" => { "name" => "spam value"},
117
+ user_md5 => { name_md5 => "true value" }
118
+ }
119
+
120
+ subject.valid?("user_missing", params).must_equal true
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,21 @@
1
+ <html>
2
+ <head>
3
+ <title>Sample Sinatra application</title>
4
+ </head>
5
+ <body>
6
+ <div id="result"><%= @result %></div>
7
+
8
+ <form method="post" action="/">
9
+ <label for="user-first-name">First name</label>
10
+ <%= input ["user", "first_name"], :id => "user-first-name" %>
11
+
12
+ <label for="user-last-name">Last name</label>
13
+ <%= input ["user", "last_name"], :id => "user-last-name" %>
14
+
15
+ <label for="user-email">Email</label>
16
+ <%= input ["user", "email"], :size => 40, :id => "user-email" %>
17
+
18
+ <%= submit "Create account", :id => "user-submit" %>
19
+ </form>
20
+ </body>
21
+ </html>
@@ -0,0 +1,8 @@
1
+ <html>
2
+ <head>
3
+ <title>Sample Sinatra application</title>
4
+ </head>
5
+ <body>
6
+ <%= yield %>
7
+ </body>
8
+ </html>
@@ -0,0 +1,7 @@
1
+ require "rack/test"
2
+ require "sinatra/base"
3
+
4
+ require "minitest/autorun"
5
+ require "minitest/spec"
6
+
7
+ ENV["environment"] = "test"
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spambust
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Chirantan Mitra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sinatra
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: ! 'Render input tags with a masked name. The input tags with proper tags
56
+ are hidden.
57
+
58
+ We expect a spam bot to fill the incorrect input tags. The server would pick the
59
+ spam bot
60
+
61
+ and respond accordingly.
62
+
63
+ '
64
+ email:
65
+ - chirantan.mitra@gmail.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - lib/spambust/form_helpers.rb
71
+ - lib/spambust/version.rb
72
+ - lib/spambust.rb
73
+ - spec/spambust/demo_app.rb
74
+ - spec/spambust/form_helpers_integration_spec.rb
75
+ - spec/spambust/form_helpers_spec.rb
76
+ - spec/spambust/views/index.erb
77
+ - spec/spambust/views/layout.erb
78
+ - spec/spec_helper.rb
79
+ - LICENSE
80
+ - README.md
81
+ homepage: https://github.com/chiku/spambust
82
+ licenses: []
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project: spambust
100
+ rubygems_version: 2.1.10
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Sinatra form helper to reduce spams
104
+ test_files:
105
+ - spec/spambust/demo_app.rb
106
+ - spec/spambust/form_helpers_integration_spec.rb
107
+ - spec/spambust/form_helpers_spec.rb
108
+ - spec/spambust/views/index.erb
109
+ - spec/spambust/views/layout.erb
110
+ - spec/spec_helper.rb