blocklist 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +58 -0
- data/Rakefile +49 -0
- data/bin/blocklist +3 -0
- data/blocklist.gemspec +32 -0
- data/lib/blocklist/cli.rb +102 -0
- data/lib/blocklist.rb +111 -0
- data/spec/blocklist/cli_spec.rb +56 -0
- data/spec/blocklist_spec.rb +100 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +9 -0
- metadata +70 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Wes Oldenbeuving
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
= Blocklist
|
2
|
+
Blocklist manages /etc/hosts with the goal of routing distracting websites to localhost. It also works well as an ad blocker.
|
3
|
+
|
4
|
+
== Usage
|
5
|
+
|
6
|
+
You'll need read/write access to /etc/hosts to make this work. It might also be a good idea to keep a backup of /etc/hosts, just in case. Keeping it in a git repo works for me. YMMV.
|
7
|
+
|
8
|
+
Blocklist makes a couple of assumtions about how /etc/hosts is set up. Here's a typical dummy file:
|
9
|
+
# localhost
|
10
|
+
127.0.0.1 localhost
|
11
|
+
255.255.255.255 broadcasthost
|
12
|
+
::1 localhost
|
13
|
+
|
14
|
+
# disabled
|
15
|
+
# 127.0.0.1 example.org
|
16
|
+
|
17
|
+
The above shows that there are blocks of lines, separated by one or more blank lines. Each of these blocks starts with a single comment that names it. Commented-out blocks are prefixed with "# "; hash-space.
|
18
|
+
|
19
|
+
=== List all blocks
|
20
|
+
$ blocklist list
|
21
|
+
localhost
|
22
|
+
ads
|
23
|
+
disabled
|
24
|
+
|
25
|
+
=== Toggle a block to be commented-out or not
|
26
|
+
$ blocklist toggle disabled
|
27
|
+
# localhost
|
28
|
+
127.0.0.1 localhost
|
29
|
+
255.255.255.255 broadcasthost
|
30
|
+
::1 localhost
|
31
|
+
|
32
|
+
# disabled
|
33
|
+
127.0.0.1 example.org
|
34
|
+
|
35
|
+
=== Add a domain
|
36
|
+
Add a domain to a new or existing block. It automatically adds the subdomain you specified, but it also adds the full domain and the www. subdomain.
|
37
|
+
There is support for domains on a TLD that always have a subdomain. The only one that is added out of the box is .co.uk. When you need more, please submit a patch.
|
38
|
+
|
39
|
+
$ blocklist add someblock news.example.org
|
40
|
+
# localhost
|
41
|
+
127.0.0.1 localhost
|
42
|
+
255.255.255.255 broadcasthost
|
43
|
+
::1 localhost
|
44
|
+
|
45
|
+
# disabled
|
46
|
+
127.0.0.1 example.org
|
47
|
+
|
48
|
+
# someblock
|
49
|
+
127.0.0.1 news.example.org example.org www.example.org
|
50
|
+
|
51
|
+
== Development
|
52
|
+
|
53
|
+
You'll need rspec and fakefs to get the specs running.
|
54
|
+
|
55
|
+
Patches are always welcome. Please add tests or specs and create a github issue or send a pull request.
|
56
|
+
|
57
|
+
== Authors
|
58
|
+
* Wes 'Narnach' Oldenbeuving <http://github.com/Narnach>
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/clean"
|
3
|
+
require "rake/gempackagetask"
|
4
|
+
require 'rubygems'
|
5
|
+
|
6
|
+
################################################################################
|
7
|
+
### Gem
|
8
|
+
################################################################################
|
9
|
+
|
10
|
+
begin
|
11
|
+
# Parse gemspec using the github safety level.
|
12
|
+
file = Dir['*.gemspec'].first
|
13
|
+
data = File.read(file)
|
14
|
+
spec = nil
|
15
|
+
# FIXME: Lowered SAFE from 3 to 2 to work with Ruby 1.9 due to rubygems
|
16
|
+
# performing a require internally
|
17
|
+
Thread.new { spec = eval("$SAFE = 2\n%s" % data)}.join
|
18
|
+
|
19
|
+
# Create the gem tasks
|
20
|
+
Rake::GemPackageTask.new(spec) do |package|
|
21
|
+
package.gem_spec = spec
|
22
|
+
end
|
23
|
+
rescue Exception => e
|
24
|
+
printf "WARNING: Error caught (%s): %s\n%s", e.class.name, e.message, e.backtrace[0...5].map {|l| ' %s' % l}.join("\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Package and install the gem for the current version'
|
28
|
+
task :install => :gem do
|
29
|
+
system "sudo gem install -l pkg/%s-%s.gem" % [spec.name, spec.version]
|
30
|
+
end
|
31
|
+
|
32
|
+
desc 'Show files missing from gemspec'
|
33
|
+
task :diff do
|
34
|
+
files = %w[
|
35
|
+
Rakefile
|
36
|
+
*README*
|
37
|
+
*LICENSE*
|
38
|
+
*.gemspec
|
39
|
+
bin/*
|
40
|
+
lib/**/*
|
41
|
+
spec/**/*
|
42
|
+
].map {|pattern| Dir.glob(pattern)}.flatten.select{|f| File.file?(f)}
|
43
|
+
missing_files = files - spec.files
|
44
|
+
extra_files = spec.files - files
|
45
|
+
puts "Missing files:"
|
46
|
+
puts missing_files.join(" ")
|
47
|
+
puts "Extra files:"
|
48
|
+
puts extra_files.join(" ")
|
49
|
+
end
|
data/bin/blocklist
ADDED
data/blocklist.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
# Project
|
3
|
+
s.name = 'blocklist'
|
4
|
+
s.summary = "Blocklist manages /etc/hosts"
|
5
|
+
s.description = "Blocklist manages /etc/hosts with the goal of routing distracting websites to localhost. It also works well as an ad blocker."
|
6
|
+
s.version = '0.1.0'
|
7
|
+
s.date = '2009-09-15'
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Wes Oldenbeuving"]
|
10
|
+
s.email = "narnach@gmail.com"
|
11
|
+
s.homepage = "http://www.github.com/Narnach/blocklist"
|
12
|
+
|
13
|
+
# Files
|
14
|
+
root_files = %w[MIT-LICENSE README.rdoc Rakefile blocklist.gemspec]
|
15
|
+
bin_files = %w[blocklist]
|
16
|
+
lib_files = %w[blocklist blocklist/cli]
|
17
|
+
spec_files = %w[blocklist blocklist/cli]
|
18
|
+
other_files = %w[spec/spec.opts spec/spec_helper.rb]
|
19
|
+
s.bindir = "bin"
|
20
|
+
s.require_path = "lib"
|
21
|
+
s.executables = bin_files
|
22
|
+
s.test_files = spec_files.map {|f| 'spec/%s_spec.rb' % f}
|
23
|
+
s.files = root_files + s.test_files + other_files + bin_files.map {|f| 'bin/%s' % f} + lib_files.map {|f| 'lib/%s.rb' % f}
|
24
|
+
|
25
|
+
# rdoc
|
26
|
+
s.has_rdoc = true
|
27
|
+
s.extra_rdoc_files = %w[ README.rdoc MIT-LICENSE]
|
28
|
+
s.rdoc_options << '--inline-source' << '--line-numbers' << '--main' << 'README.rdoc'
|
29
|
+
|
30
|
+
# Requirements
|
31
|
+
s.required_ruby_version = ">= 1.8.0"
|
32
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'blocklist'
|
2
|
+
|
3
|
+
class Blocklist
|
4
|
+
class Cli
|
5
|
+
COMMANDS = %w[add list toggle help]
|
6
|
+
def initialize(argv)
|
7
|
+
@argv = argv
|
8
|
+
@bl = Blocklist.new
|
9
|
+
@bl.parse(File.read('/etc/hosts'))
|
10
|
+
@dry_run = !@argv.delete('-d').nil?
|
11
|
+
@quiet = !@argv.delete('-q').nil?
|
12
|
+
@command = @argv.shift || 'help'
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
if COMMANDS.include? @command
|
17
|
+
self.send(@command)
|
18
|
+
else
|
19
|
+
help "Command unknown: '#{@command}'"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
def list
|
26
|
+
puts @bl.blocks.map {|block| block.name}.join("\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def add
|
30
|
+
block_name = @argv.shift
|
31
|
+
block = @bl.block(block_name) || Blocklist::Block.new(block_name)
|
32
|
+
|
33
|
+
domains = block.lines.map {|line| line.domains}.flatten
|
34
|
+
saved_domains = @argv.map do |domain|
|
35
|
+
dom_segments = domain.split(".")
|
36
|
+
tld_size = 1
|
37
|
+
tld_size = 2 if %w[uk].include? dom_segments.last
|
38
|
+
tld = dom_segments[-tld_size..-1].join(".")
|
39
|
+
dom_no_tld = dom_segments[0...-tld_size]
|
40
|
+
domain_base = dom_no_tld.last
|
41
|
+
subdomain = dom_no_tld.size == 1 ? nil : dom_no_tld[0...-1].join(".")
|
42
|
+
new_domains = [nil, 'www', subdomain].uniq.map {|sub| [sub, domain_base, tld].compact.join(".")} - domains
|
43
|
+
if new_domains.size > 0
|
44
|
+
block.lines << Blocklist::Line.new('127.0.0.1', *new_domains)
|
45
|
+
domains.concat(new_domains)
|
46
|
+
end
|
47
|
+
new_domains
|
48
|
+
end
|
49
|
+
display_result
|
50
|
+
save if saved_domains.flatten.size > 0
|
51
|
+
end
|
52
|
+
|
53
|
+
def toggle
|
54
|
+
block_name = @argv.shift
|
55
|
+
unless block = @bl.block(block_name)
|
56
|
+
help "Could not toggle non-existing block '#{block_name}'"
|
57
|
+
return
|
58
|
+
end
|
59
|
+
block.toggle_comments
|
60
|
+
display_result
|
61
|
+
save
|
62
|
+
end
|
63
|
+
|
64
|
+
def help(msg=nil)
|
65
|
+
if msg
|
66
|
+
$stderr.puts(msg)
|
67
|
+
$stderr.puts('')
|
68
|
+
end
|
69
|
+
$stderr.puts <<-STR
|
70
|
+
Syntax: #{$0} [flags] <command>
|
71
|
+
|
72
|
+
Flags:
|
73
|
+
-d
|
74
|
+
Perform a dry-run. Does not modify /etc/hosts
|
75
|
+
-q
|
76
|
+
Quiet mode. Minimizes the output to STDOUT
|
77
|
+
|
78
|
+
Commands:
|
79
|
+
add <block name> [domain1] .. [domainN]
|
80
|
+
Add a number of domains to the specified block.
|
81
|
+
Each domain will automatically be added with the www subdomain and without subdomain.
|
82
|
+
Duplicate domains are skipped.
|
83
|
+
list
|
84
|
+
Shows a list of all blocks currently defined
|
85
|
+
toggle <block name>
|
86
|
+
Toggle the comment status of all lines in this block.
|
87
|
+
help
|
88
|
+
Show this page
|
89
|
+
STR
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def display_result
|
95
|
+
puts @bl unless @quiet
|
96
|
+
end
|
97
|
+
|
98
|
+
def save
|
99
|
+
File.open('/etc/hosts','w') {|f| f.puts(@bl.to_s)} unless @dry_run
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/lib/blocklist.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
class Blocklist
|
2
|
+
attr_accessor :blocks
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
self.blocks = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def parse(content)
|
9
|
+
block = Block.new
|
10
|
+
content.each_line do |line|
|
11
|
+
parsed_line = Line.parse(line)
|
12
|
+
case parsed_line
|
13
|
+
when nil
|
14
|
+
self.blocks << block
|
15
|
+
block = Block.new
|
16
|
+
when String
|
17
|
+
block.name ||= parsed_line
|
18
|
+
when Line
|
19
|
+
block.lines << parsed_line
|
20
|
+
else
|
21
|
+
raise "Unexpected line: #{line}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
if block.name or block.lines.size > 0
|
25
|
+
self.blocks << block
|
26
|
+
end
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def block(name)
|
31
|
+
blocks.find {|block| block.name == name}
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
blocks.join("\n\n")
|
36
|
+
end
|
37
|
+
|
38
|
+
class Block
|
39
|
+
attr_accessor :name, :lines
|
40
|
+
|
41
|
+
def initialize(name=nil, *lines)
|
42
|
+
self.name = name
|
43
|
+
self.lines = lines
|
44
|
+
end
|
45
|
+
|
46
|
+
def ==(other)
|
47
|
+
return false unless other.class == self.class
|
48
|
+
return false unless other.name == self.name
|
49
|
+
return false unless other.lines == self.lines
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def toggle_comments
|
54
|
+
lines.each {|line| line.toggle_comment}
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
"# #{name}\n" + lines.join("\n")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class Line
|
63
|
+
COMMENT_PREFIX = /\A#+\s+/
|
64
|
+
IPV4 = /\A\d{1,3}(\.\d{1,3}){3}/
|
65
|
+
# Took this huge regexp from http://vernon.mauery.com/content/projects/linux/ipv6_regex
|
66
|
+
IPV6 = /(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,6}\Z)|(\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}\Z)|(\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}\Z)|(\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}\Z)|(\A([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}\Z)|(\A([0-9a-f]{1,4}:){1,6}(:[0-9a-f]{1,4}){1,1}\Z)|(\A(([0-9a-f]{1,4}:){1,7}|:):\Z)|(\A:(:[0-9a-f]{1,4}){1,7}\Z)|(\A((([0-9a-f]{1,4}:){6})(25[0-5]|2[0-4]d|[0-1]?d?d)(.(25[0-5]|2[0-4]d|[0-1]?d?d)){3})\Z)|(\A(([0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:(25[0-5]|2[0-4]d|[0-1]?d?d)(.(25[0-5]|2[0-4]d|[0-1]?d?d)){3})\Z)|(\A([0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:(25[0-5]|2[0-4]d|[0-1]?d?d)(.(25[0-5]|2[0-4]d|[0-1]?d?d)){3}\Z)|(\A([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,4}:(25[0-5]|2[0-4]d|[0-1]?d?d)(.(25[0-5]|2[0-4]d|[0-1]?d?d)){3}\Z)|(\A([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,3}:(25[0-5]|2[0-4]d|[0-1]?d?d)(.(25[0-5]|2[0-4]d|[0-1]?d?d)){3}\Z)|(\A([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,2}:(25[0-5]|2[0-4]d|[0-1]?d?d)(.(25[0-5]|2[0-4]d|[0-1]?d?d)){3}\Z)|(\A([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,1}:(25[0-5]|2[0-4]d|[0-1]?d?d)(.(25[0-5]|2[0-4]d|[0-1]?d?d)){3}\Z)|(\A(([0-9a-f]{1,4}:){1,5}|:):(25[0-5]|2[0-4]d|[0-1]?d?d)(.(25[0-5]|2[0-4]d|[0-1]?d?d)){3}\Z)|(\A:(:[0-9a-f]{1,4}){1,5}:(25[0-5]|2[0-4]d|[0-1]?d?d)(.(25[0-5]|2[0-4]d|[0-1]?d?d)){3}\Z)/
|
67
|
+
|
68
|
+
attr_accessor :ip, :domains, :commented
|
69
|
+
|
70
|
+
def initialize(ip, *domains)
|
71
|
+
self.ip = ip
|
72
|
+
self.domains = domains
|
73
|
+
self.commented = false
|
74
|
+
end
|
75
|
+
|
76
|
+
def ==(other)
|
77
|
+
return false unless other.class == self.class
|
78
|
+
return false unless other.ip == self.ip
|
79
|
+
return false unless other.domains == self.domains
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
def toggle_comment
|
84
|
+
self.commented = !commented
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_s
|
88
|
+
prefix = commented ? "# " : ""
|
89
|
+
"%s%s%s%s" % [prefix, ip, " " * (16 - ip.size), domains.join(" ")]
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.parse(line)
|
93
|
+
stripped_line = line.strip
|
94
|
+
return nil if stripped_line == ''
|
95
|
+
return Line.new(*stripped_line.split(" ")) unless stripped_line =~ COMMENT_PREFIX
|
96
|
+
uncommented_line = stripped_line.gsub(COMMENT_PREFIX, '')
|
97
|
+
split_line = uncommented_line.split(" ")
|
98
|
+
if split_line.first =~ IPV4
|
99
|
+
parsed_line = Line.new(*split_line)
|
100
|
+
parsed_line.commented = true
|
101
|
+
parsed_line
|
102
|
+
elsif split_line.first =~ IPV6
|
103
|
+
parsed_line = Line.new(*split_line)
|
104
|
+
parsed_line.commented = true
|
105
|
+
parsed_line
|
106
|
+
else # comment or title
|
107
|
+
uncommented_line
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
require 'blocklist/cli'
|
3
|
+
begin
|
4
|
+
require 'fakefs/safe'
|
5
|
+
rescue LoadError
|
6
|
+
$stderr.puts "!! You need to install fakefs to run the CLI specs.\n!! Look on http://github/defunkt/fakefs or use gemcutter.org."
|
7
|
+
exit 1
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Blocklist::Cli do
|
11
|
+
before(:each) do
|
12
|
+
FakeFS.activate!
|
13
|
+
end
|
14
|
+
|
15
|
+
after(:each) do
|
16
|
+
FakeFS.deactivate!
|
17
|
+
end
|
18
|
+
|
19
|
+
def fake_hosts(content='')
|
20
|
+
File.open('/etc/hosts','w') {|f| f.puts content}
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should display help when no command is given' do
|
24
|
+
fake_hosts
|
25
|
+
cli = Blocklist::Cli.new([])
|
26
|
+
cli.should_receive(:help)
|
27
|
+
cli.run
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'list' do
|
31
|
+
it 'should show all blocks in /etc/hosts' do
|
32
|
+
fake_hosts <<-STR
|
33
|
+
# localhost
|
34
|
+
|
35
|
+
# blocked
|
36
|
+
STR
|
37
|
+
cli = Blocklist::Cli.new(%w[list])
|
38
|
+
cli.should_receive(:puts).with("localhost\nblocked")
|
39
|
+
cli.run
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'add' do
|
44
|
+
it "should add a domain and its www-subdomain to a block's lines" do
|
45
|
+
fake_hosts <<-STR
|
46
|
+
# localhost
|
47
|
+
STR
|
48
|
+
cli = Blocklist::Cli.new(%w[add localhost example.org])
|
49
|
+
cli.run
|
50
|
+
File.read('/etc/hosts').should == <<-STR
|
51
|
+
# localhost
|
52
|
+
127.0.0.1 example.org www.example.org
|
53
|
+
STR
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
require 'blocklist'
|
3
|
+
|
4
|
+
describe Blocklist do
|
5
|
+
describe '#parse' do
|
6
|
+
it 'should parse all blocks' do
|
7
|
+
hosts = <<-STR
|
8
|
+
# localhost
|
9
|
+
127.0.0.1 localhost
|
10
|
+
255.255.255.255 broadcasthost
|
11
|
+
|
12
|
+
# blocked
|
13
|
+
127.0.0.1 news.ycombinator.com
|
14
|
+
STR
|
15
|
+
bl = Blocklist.new
|
16
|
+
bl.parse(hosts)
|
17
|
+
bl.blocks.map {|block| block.name}.should == %w[localhost blocked]
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should parse all domains on a line' do
|
21
|
+
hosts = <<-STR
|
22
|
+
# blocked
|
23
|
+
127.0.0.1 news.ycombinator.com ycombinator.com
|
24
|
+
STR
|
25
|
+
bl = Blocklist.new
|
26
|
+
bl.parse(hosts)
|
27
|
+
bl.blocks.first.should == Blocklist::Block.new('blocked',
|
28
|
+
Blocklist::Line.new('127.0.0.1', *%w[news.ycombinator.com ycombinator.com]))
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should handle ipv6 addresses' do
|
32
|
+
hosts = <<-STR.strip
|
33
|
+
# localhost
|
34
|
+
127.0.0.1 localhost
|
35
|
+
::1 localhost
|
36
|
+
STR
|
37
|
+
bl = Blocklist.new
|
38
|
+
bl.parse(hosts)
|
39
|
+
bl.blocks.first.should == Blocklist::Block.new('localhost',
|
40
|
+
Blocklist::Line.new('127.0.0.1', 'localhost'),
|
41
|
+
Blocklist::Line.new('::1', 'localhost'))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#to_s' do
|
46
|
+
it 'should display a Blocklist in the /etc/hosts format' do
|
47
|
+
block1 = Blocklist::Block.new('localhost')
|
48
|
+
block1.lines << Blocklist::Line.new('127.0.0.1', 'localhost')
|
49
|
+
block2 = Blocklist::Block.new('blocked')
|
50
|
+
block2.lines << Blocklist::Line.new('127.0.0.1', 'news.ycombinator.com', 'ycombinator.com')
|
51
|
+
bl = Blocklist.new
|
52
|
+
bl.blocks << block1
|
53
|
+
bl.blocks << block2
|
54
|
+
bl.to_s.should == <<-STR.strip
|
55
|
+
# localhost
|
56
|
+
127.0.0.1 localhost
|
57
|
+
|
58
|
+
# blocked
|
59
|
+
127.0.0.1 news.ycombinator.com ycombinator.com
|
60
|
+
STR
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#block' do
|
65
|
+
it 'should find the first block by name' do
|
66
|
+
bl = Blocklist.new
|
67
|
+
bl.parse(<<-STR.strip)
|
68
|
+
# localhost
|
69
|
+
127.0.0.1 localhost
|
70
|
+
|
71
|
+
# blocked
|
72
|
+
127.0.0.1 news.ycombinator.com ycombinator.com
|
73
|
+
STR
|
74
|
+
bl.block('blocked').lines.first.domains.should == %w[news.ycombinator.com ycombinator.com]
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should return nil if no block can be found' do
|
78
|
+
Blocklist.new.block('nothing').should be_nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe Blocklist::Block do
|
84
|
+
describe '#toggle_comments' do
|
85
|
+
it 'should toggle lines between commented-out and not commented' do
|
86
|
+
hosts = <<-STR.strip
|
87
|
+
# blocked
|
88
|
+
127.0.0.1 news.ycombinator.com ycombinator.com
|
89
|
+
STR
|
90
|
+
bl = Blocklist.new
|
91
|
+
bl.parse(hosts)
|
92
|
+
bl.blocks.first.toggle_comments
|
93
|
+
bl.to_s.should_not == hosts
|
94
|
+
bl2 = Blocklist.new
|
95
|
+
bl2.parse(bl.to_s)
|
96
|
+
bl2.blocks.first.toggle_comments
|
97
|
+
bl2.to_s.should == hosts
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blocklist
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Wes Oldenbeuving
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-09-15 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Blocklist manages /etc/hosts with the goal of routing distracting websites to localhost. It also works well as an ad blocker.
|
17
|
+
email: narnach@gmail.com
|
18
|
+
executables:
|
19
|
+
- blocklist
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
- MIT-LICENSE
|
25
|
+
files:
|
26
|
+
- MIT-LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
- Rakefile
|
29
|
+
- blocklist.gemspec
|
30
|
+
- spec/blocklist_spec.rb
|
31
|
+
- spec/blocklist/cli_spec.rb
|
32
|
+
- spec/spec.opts
|
33
|
+
- spec/spec_helper.rb
|
34
|
+
- bin/blocklist
|
35
|
+
- lib/blocklist.rb
|
36
|
+
- lib/blocklist/cli.rb
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://www.github.com/Narnach/blocklist
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options:
|
43
|
+
- --inline-source
|
44
|
+
- --line-numbers
|
45
|
+
- --main
|
46
|
+
- README.rdoc
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.8.0
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 1.3.4
|
65
|
+
signing_key:
|
66
|
+
specification_version: 3
|
67
|
+
summary: Blocklist manages /etc/hosts
|
68
|
+
test_files:
|
69
|
+
- spec/blocklist_spec.rb
|
70
|
+
- spec/blocklist/cli_spec.rb
|