rack-address_munging 0.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: '0009c47a3ddb287023fd4a5fa33d7829862b8b97'
4
+ data.tar.gz: dc0c58999b312febe87685f553ca042a6c4cb667
5
+ SHA512:
6
+ metadata.gz: 579dc7548505cc0adf879989cf0a6729d3c2693e0526d03974dc965e9c37ff154471f8c78bfa7795ae1fe80d81862a0c33ec0a16a0e13f0dcd8687c9c5913ae8
7
+ data.tar.gz: 7b0a2e00f16816470029a9bd01c26d8a9cdcda1f3f6aab76bb09f804653359d0b8a3838bba5eaf5b0fdcaf3d65ea5b3cd885f20c35a504bc0bc69673b3276b36
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ Metrics/LineLength:
2
+ Max: 150
3
+
4
+ Style/Semicolon:
5
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ sudo: false
3
+ script: "bundle exec rake clean spec"
4
+
5
+ rvm:
6
+ - 2.2
7
+ - 2.3
8
+ - 2.4
9
+
10
+ gemfile:
11
+ - Gemfile
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in rack-address_munging.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rack-address_munging (0.1.1)
5
+ mail (> 2.5.0)
6
+ rack (>= 0.9.1)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ ast (2.4.0)
12
+ diff-lcs (1.3)
13
+ mail (2.7.0)
14
+ mini_mime (>= 0.1.1)
15
+ mini_mime (1.0.0)
16
+ parallel (1.12.1)
17
+ parser (2.5.0.3)
18
+ ast (~> 2.4.0)
19
+ powerpack (0.1.1)
20
+ rack (2.0.4)
21
+ rainbow (3.0.0)
22
+ rake (10.5.0)
23
+ rspec (3.7.0)
24
+ rspec-core (~> 3.7.0)
25
+ rspec-expectations (~> 3.7.0)
26
+ rspec-mocks (~> 3.7.0)
27
+ rspec-core (3.7.1)
28
+ rspec-support (~> 3.7.0)
29
+ rspec-expectations (3.7.0)
30
+ diff-lcs (>= 1.2.0, < 2.0)
31
+ rspec-support (~> 3.7.0)
32
+ rspec-mocks (3.7.0)
33
+ diff-lcs (>= 1.2.0, < 2.0)
34
+ rspec-support (~> 3.7.0)
35
+ rspec-support (3.7.1)
36
+ rubocop (0.53.0)
37
+ parallel (~> 1.10)
38
+ parser (>= 2.5)
39
+ powerpack (~> 0.1)
40
+ rainbow (>= 2.2.2, < 4.0)
41
+ ruby-progressbar (~> 1.7)
42
+ unicode-display_width (~> 1.0, >= 1.0.1)
43
+ ruby-progressbar (1.9.0)
44
+ unicode-display_width (1.3.0)
45
+
46
+ PLATFORMS
47
+ ruby
48
+
49
+ DEPENDENCIES
50
+ bundler (~> 1.16)
51
+ rack-address_munging!
52
+ rake (~> 10.0)
53
+ rspec (~> 3.7.0)
54
+ rubocop
55
+
56
+ BUNDLED WITH
57
+ 1.16.1
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2018 notus.sh
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # Rack::AddressMunging
2
+
3
+ [![Build Status](https://travis-ci.org/notus-sh/rack-address_munging.svg?branch=master)](https://travis-ci.org/notus-sh/rack-address_munging)
4
+
5
+ `Rack::AddressMunging` is a Rack middleware for automatic [e-mail addresses munging](https://en.wikipedia.org/wiki/Address_munging).
6
+
7
+ Once added to your middleware stack, `Rack::AddressMunging` will parse the body of any HTML response and mung it to obfuscate email addresses, in hope to prevent spambots to collect them too easily.
8
+
9
+ ## Installation
10
+
11
+ `Rack::AddressMunging` is distributed as a gem and available on [rubygems.org](https://rubygems.org/gems/rack-address_munging) so you can add it to your `Gemfile` or install it manually with:
12
+
13
+ ```ruby
14
+ gem install rack-address_munging
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ To use the middleware with it's default configuration, just drop it in your middleware stack:
20
+
21
+ ```ruby
22
+ # In config.ru or wherever your stack is defined
23
+ require 'rack/address_munging'
24
+
25
+ use Rack::AddressMunging
26
+ ```
27
+
28
+ If you want to use another munging strategy, precise it as an argument:
29
+
30
+ ```ruby
31
+ # In a Rails initializer
32
+ require 'rack/address_munging'
33
+
34
+ module YourRailsAppName
35
+ class Application
36
+ config.middleware.use Rack::AddressMunging, strategy: :hex
37
+ end
38
+ end
39
+ ```
40
+
41
+ ## Supported Strategies
42
+
43
+ ### `:Hex`
44
+
45
+ Replace email addresses and mailto href attributes values with an hexadecimal entities alternative.
46
+
47
+ Input: email@example.com
48
+ Output: &#101;&#109;&#97;&#105;&#108;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;
49
+
50
+ `:Hex` is the default strategy.
51
+
52
+ ### `:Rot13JS`
53
+
54
+ Replace email addresses and full mailto links with a `<script>` tag that will print it back into the page, based on a [ROT13](https://en.wikipedia.org/wiki/ROT13) version.
55
+
56
+ Input: email@example.com
57
+ Output: <script type="text/javascript">document.write("rznvy(at)rknzcyr.pbz".replace(/(at)/, '@').replace(/[a-z]/gi,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});))</script>
58
+
59
+ For more informations about the exact behavior of each strategy, please refer to the [strategies specs data](https://github.com/notus-sh/rack-address_munging/blob/master/spec/data/strategy.yml).
60
+
61
+ ## Contributing
62
+
63
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/notus-sh/rack-address_munging>.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+
5
+ require 'rspec/core/rake_task'
6
+ RSpec::Core::RakeTask.new
7
+
8
+ require 'rubocop/rake_task'
9
+ RuboCop::RakeTask.new
10
+
11
+ task default: :spec
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mail'
4
+ require 'ipaddr'
5
+
6
+ module Rack
7
+ class AddressMunging
8
+ # This module contains email address detection and validation methods.
9
+ # It is meant to be included in any munging strategy.
10
+ module Detection
11
+ REGEXP_EMAIL = /[a-z0-9][^@\s'":<>]+@[^@\s'":<>]+[a-z0-9]/i
12
+ REGEXP_MAILTO = /mailto:#{REGEXP_EMAIL}/i
13
+ REGEXP_LINK = %r{<a[^>]+?href="#{REGEXP_MAILTO}"[^>]*?>.+?</a>}i
14
+
15
+ def email?(string)
16
+ m = ::Mail::Address.new(string)
17
+ return false unless m.address == string
18
+ return false unless valid_local?(m.local)
19
+ return false unless valid_domain?(m.domain)
20
+ true
21
+ rescue StandardError
22
+ false
23
+ end
24
+
25
+ private
26
+
27
+ def valid_local?(local)
28
+ return false if local.include?('..') # Can't contain ..
29
+ return false if local.include?('@') # Can't contain an @
30
+ return false unless local !~ /^"?\s+"?$/ # Can't be blank
31
+ true
32
+ end
33
+
34
+ def valid_domain?(domain)
35
+ return false if ip_address?(domain)
36
+ return false if local_domain?(domain)
37
+ return false if hires_image?(domain)
38
+ return false if domain.include?('..') # Can't contain ..
39
+ true
40
+ end
41
+
42
+ def ip_address?(domain)
43
+ ip = IpAddr.new(domain)
44
+ ip.to_s == domain
45
+ rescue StandardError
46
+ false
47
+ end
48
+
49
+ def local_domain?(domain)
50
+ !domain.include?('.') # Must contain at least a .
51
+ end
52
+
53
+ # /path/to/image@2x.format should not be matched as a valid email
54
+ # Hashed version of the path shouldn't match either
55
+ def hires_image?(domain)
56
+ !(domain !~ /^\dx\.(jpe?g|gif|png|webp)$/ && domain !~ /^\dx-[0-9a-f]{32}\.(jpe?g|gif|png|webp)$/)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class AddressMunging
5
+ module Strategy
6
+ # The <tt>:Hex</tt> munging strategy
7
+ #
8
+ # Will replace email addresses and mailto href attributes values with
9
+ # an hexadecimal HTML entities alternative.
10
+ class Hex
11
+ include Detection
12
+
13
+ def apply(munged, original)
14
+ original.each do |part|
15
+ part = part.dup if part.frozen?
16
+ part.gsub!(REGEXP_MAILTO) { |m| maybe_encode(m) }
17
+ part.gsub!(REGEXP_EMAIL) { |m| maybe_encode(m) }
18
+ munged.write part
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def maybe_encode(string)
25
+ s = to_s(string)
26
+ email?(s.gsub(/^mailto:/, '')) ? encode(s) : s
27
+ end
28
+
29
+ def encode(str)
30
+ to_s(str).unpack('C*').map { |c| format('&#%<c>d;', c: c) }.join
31
+ end
32
+
33
+ # Normalize a match as a string
34
+ # (gsub return ActiveSupport::SafeBuffer when ActiveSupport is loaded)
35
+ def to_s(string)
36
+ string.respond_to?(:to_str) ? string.to_str : string.try(:to_s)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class AddressMunging
5
+ module Strategy
6
+ # The <tt>:Rot13JS</tt> munging strategy
7
+ #
8
+ # Will replace email addresses and full mailto links with a <tt><script></tt> tag
9
+ # that will print it back into the page, based on a ROT13 version.
10
+ #
11
+ # The ROT13 implementation used here is a bit different as the original one will not
12
+ # replace <tt>@</tt>. This fix it, applying a second replacement to switch <tt>@</tt>
13
+ # with <tt>(at)</tt> in the munged string.
14
+ #
15
+ # This strategy does not handle email addresses containing UTF-8 entities.
16
+ class Rot13JS
17
+ include Detection
18
+
19
+ def apply(munged, original)
20
+ original.each do |part|
21
+ part = part.dup if part.frozen?
22
+ part.gsub!(REGEXP_LINK) { |m| maybe_encode(m) }
23
+ part.gsub!(REGEXP_EMAIL) { |m| maybe_encode(m) }
24
+ munged.write part
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def maybe_encode(string)
31
+ s = to_s(string)
32
+ s.scan(REGEXP_EMAIL).collect { |m| email?(to_s(m)) }.any? ? encode(s) : s
33
+ end
34
+
35
+ def encode(str)
36
+ <<-ENCODED.strip
37
+ <script type="text/javascript">document.write("#{to_s(str).tr('A-Za-z', 'N-ZA-Mn-za-m').gsub('@', '(at)')}".replace(/\(at\)/, '@').replace(/[a-z]/gi,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});))</script>
38
+ ENCODED
39
+ end
40
+
41
+ # Normalize a match as a string
42
+ # (gsub return ActiveSupport::SafeBuffer when ActiveSupport is loaded)
43
+ def to_s(string)
44
+ string.respond_to?(:to_str) ? string.to_str : string.try(:to_s)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class AddressMunging
5
+ # This module group all available munging strategies.
6
+ #
7
+ # When the Rack::AddressMunging middleware is instanciated, the required
8
+ # strategy is loaded as a child constant of this module. If you want to
9
+ # write your own munging strategy, you must create it as a subclass of
10
+ # <tt>Rack::AddressMunging::Strategy</tt> for it to be usable.
11
+ module Strategy
12
+ autoload :Hex, 'rack/address_munging/strategy/hex'
13
+ autoload :Rot13JS, 'rack/address_munging/strategy/rot13js'
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class AddressMunging
5
+ VERSION = '0.1.1'
6
+ end
7
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack/response'
4
+
5
+ module Rack
6
+ # The Rack::AddressMunging middleware, meant to be used in your Rack stack.
7
+ #
8
+ # All other modules meant for use in your application are <tt>autoload</tt>ed here,
9
+ # so it should be enough just to <tt>require 'rack/address_munging'</tt> in your code.
10
+ #
11
+ # To add the middleware to your stack, use:
12
+ # <code>use Rack::AddressMunging</code>
13
+ #
14
+ # If you want to use another munging strategy, precise it as an argument:
15
+ # <code>use Rack::AddressMunging, strategy: :hex</code>
16
+ class AddressMunging
17
+ autoload :Strategy, 'rack/address_munging/strategy'
18
+ autoload :Detection, 'rack/address_munging/detection'
19
+
20
+ attr_reader :strategy
21
+
22
+ def initialize(app, options = {})
23
+ @app = app
24
+ @options = { strategy: :Hex }.merge(options)
25
+ @strategy = Strategy.const_get(@options[:strategy]).new
26
+ end
27
+
28
+ def call(env)
29
+ @status, @headers, @response = @app.call(env)
30
+ mung! if html?
31
+ [@status, @headers, @response]
32
+ end
33
+
34
+ private
35
+
36
+ def html?
37
+ !(@headers['Content-Type'] =~ /html/).nil?
38
+ end
39
+
40
+ def mung!
41
+ @response = Response.new([], @status, @headers).tap do |r|
42
+ @strategy.apply(r, @response)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rack/address_munging/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'rack-address_munging'
9
+ spec.version = Rack::AddressMunging::VERSION
10
+ spec.licenses = ['Apache-2.0']
11
+ spec.authors = ['Gaël-Ian Havard']
12
+ spec.email = ['gael-ian@notus.sh']
13
+
14
+ spec.summary = 'Rack middleware for automatic address munging.'
15
+ spec.description = 'A Rack middleware for automatic e-mail addresses munging.'
16
+ spec.homepage = 'https://github.com/notus-sh/rack-address_munging'
17
+
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata["allowed_push_host"] = 'https://rubygems.org'
20
+ else
21
+ raise "RubyGems 2.0 or newer is required."
22
+ end
23
+
24
+ spec.require_paths = ['lib']
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(test|spec|features)/})
27
+ end
28
+
29
+ spec.add_dependency 'mail', '> 2.5.0'
30
+ spec.add_dependency 'rack', '>= 0.9.1'
31
+
32
+ spec.add_development_dependency 'bundler', '~> 1.16'
33
+ spec.add_development_dependency 'rake', '~> 10.0'
34
+ spec.add_development_dependency 'rspec', '~> 3.7.0'
35
+ spec.add_development_dependency 'rubocop'
36
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-address_munging
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Gaël-Ian Havard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mail
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.5.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.5.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rack
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.9.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.9.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.16'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.16'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.7.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.7.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: A Rack middleware for automatic e-mail addresses munging.
98
+ email:
99
+ - gael-ian@notus.sh
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - ".rubocop.yml"
107
+ - ".travis.yml"
108
+ - Gemfile
109
+ - Gemfile.lock
110
+ - LICENSE
111
+ - README.md
112
+ - Rakefile
113
+ - lib/rack/address_munging.rb
114
+ - lib/rack/address_munging/detection.rb
115
+ - lib/rack/address_munging/strategy.rb
116
+ - lib/rack/address_munging/strategy/hex.rb
117
+ - lib/rack/address_munging/strategy/rot13js.rb
118
+ - lib/rack/address_munging/version.rb
119
+ - rack-address_munging.gemspec
120
+ homepage: https://github.com/notus-sh/rack-address_munging
121
+ licenses:
122
+ - Apache-2.0
123
+ metadata:
124
+ allowed_push_host: https://rubygems.org
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.6.14
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Rack middleware for automatic address munging.
145
+ test_files: []