rippersnapper 0.0.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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +65 -0
- data/Rakefile +1 -0
- data/lib/rippersnapper.rb +10 -0
- data/lib/rippersnapper/domain_parser.rb +56 -0
- data/lib/rippersnapper/public_suffix.dat +6998 -0
- data/lib/rippersnapper/suffix_file_reader.rb +40 -0
- data/lib/rippersnapper/url.rb +49 -0
- data/lib/rippersnapper/version.rb +3 -0
- data/rippersnapper.gemspec +24 -0
- data/rippersnapper.jpg +0 -0
- data/spec/rippersnapper/domain_parser_spec.rb +21 -0
- data/spec/rippersnapper/suffix_file_validator_spec.rb +67 -0
- data/spec/rippersnapper/url_spec.rb +46 -0
- data/spec/rippersnapper_spec.rb +6 -0
- data/spec/spec_helper.rb +19 -0
- metadata +110 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
module Rippersnapper
|
2
|
+
|
3
|
+
###
|
4
|
+
# Single Responsibility:
|
5
|
+
# Finds a suffix match in a list of suffixes
|
6
|
+
|
7
|
+
class SuffixFileReader
|
8
|
+
attr_reader :file
|
9
|
+
|
10
|
+
def initialize file = nil
|
11
|
+
@file = file || File.open(File.dirname(__FILE__) + "/public_suffix.dat", 'r')
|
12
|
+
# Recursive hash of hashes http://stackoverflow.com/a/170240/973860
|
13
|
+
#@public_suffixes = Hash.new(&(p=lambda{|h,k| h[k] = Hash.new(&p)}))
|
14
|
+
@public_suffixes = Hash.new { false }
|
15
|
+
parse_file
|
16
|
+
end
|
17
|
+
|
18
|
+
def contains? suffix
|
19
|
+
@public_suffixes[suffix] || begin
|
20
|
+
suffix_parts = suffix.split('.')
|
21
|
+
suffix_parts.shift
|
22
|
+
asterix_suffix = ["*", suffix_parts].join('.')
|
23
|
+
@public_suffixes[asterix_suffix]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def parse_file
|
30
|
+
file.each_line do |line|
|
31
|
+
line = line.strip
|
32
|
+
unless line.empty? || (line =~ /\/\//)
|
33
|
+
@public_suffixes[line] = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Rippersnapper
|
2
|
+
class Url
|
3
|
+
attr_accessor :subdomain, :domain
|
4
|
+
|
5
|
+
def initialize url
|
6
|
+
@url = url
|
7
|
+
end
|
8
|
+
|
9
|
+
def uri
|
10
|
+
@uri ||= URI.parse url
|
11
|
+
end
|
12
|
+
|
13
|
+
def url
|
14
|
+
return @url if @url =~ /:\/\//
|
15
|
+
"http://#{@url}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def suffix
|
19
|
+
parsed_domain.suffix
|
20
|
+
end
|
21
|
+
|
22
|
+
def domain
|
23
|
+
parsed_domain.domain
|
24
|
+
end
|
25
|
+
|
26
|
+
def subdomain
|
27
|
+
parsed_domain.subdomain
|
28
|
+
end
|
29
|
+
|
30
|
+
def scheme
|
31
|
+
uri.scheme
|
32
|
+
end
|
33
|
+
|
34
|
+
def host
|
35
|
+
uri.host
|
36
|
+
end
|
37
|
+
|
38
|
+
def path
|
39
|
+
return "#{uri.path}?#{uri.query}" if uri.query
|
40
|
+
uri.path
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def parsed_domain
|
46
|
+
@parsed_domain ||= DomainParser.new host
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rippersnapper/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rippersnapper"
|
8
|
+
spec.version = Rippersnapper::VERSION
|
9
|
+
spec.authors = ["Micah Woods"]
|
10
|
+
spec.email = ["micahwoods@gmail.com"]
|
11
|
+
spec.description = %q{Rip and snap domains using Rippersnappers jaws of steele!}
|
12
|
+
spec.summary = %q{Named after the worst decepticon ever, a shark with T-Rex arms...}
|
13
|
+
spec.homepage = %q{https://github.com/mwoods79/rippersnapper}
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec", "~> 2.13.0"
|
24
|
+
end
|
data/rippersnapper.jpg
ADDED
Binary file
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Rippersnapper
|
4
|
+
|
5
|
+
describe DomainParser do
|
6
|
+
|
7
|
+
context "simple domain" do
|
8
|
+
subject { DomainParser.new "www.google.com" }
|
9
|
+
its(:subdomain) { should eq "www" }
|
10
|
+
its(:domain) { should eq "google" }
|
11
|
+
its(:suffix) { should eq "com" }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "complex domain" do
|
15
|
+
subject { DomainParser.new "my.drive.google.whatever.sapporo.jp" }
|
16
|
+
its(:subdomain) { should eq "my.drive" }
|
17
|
+
its(:domain) { should eq "google" }
|
18
|
+
its(:suffix) { should eq "whatever.sapporo.jp" }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Rippersnapper
|
5
|
+
|
6
|
+
describe SuffixFileReader do
|
7
|
+
|
8
|
+
describe '#initialize' do
|
9
|
+
|
10
|
+
context 'passing in a file' do
|
11
|
+
let(:file) { stub :file, each_line: [] }
|
12
|
+
subject { SuffixFileReader.new file }
|
13
|
+
its(:file) { should be file}
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'file default' do
|
17
|
+
subject { SuffixFileReader.new }
|
18
|
+
its(:file) { should be_a_kind_of File }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#contains?' do
|
23
|
+
subject { SuffixFileReader.new }
|
24
|
+
|
25
|
+
it { should respond_to :contains? }
|
26
|
+
|
27
|
+
context "matching valid data" do
|
28
|
+
|
29
|
+
it 'matches a single suffix' do
|
30
|
+
expect(subject.contains?("com")).to be_true
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'matches a nested suffix' do
|
34
|
+
expect(subject.contains?("la.us")).to be_true
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'matches a suffix with a single asterix' do
|
38
|
+
expect(subject.contains?("whatever.uk")).to be_true
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'matches a suffix with multiple asterix' do
|
42
|
+
expect(subject.contains?("whatever.sapporo.jp")).to be_true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "rejecting invalid data" do
|
47
|
+
it "doesn't match suffix that is not in file" do
|
48
|
+
expect(subject.contains?("foo")).to be_false
|
49
|
+
end
|
50
|
+
|
51
|
+
it "doesn't match complex suffix that are not in file" do
|
52
|
+
expect(subject.contains?("doesnt.exist.sapporo.jp")).to be_false
|
53
|
+
end
|
54
|
+
|
55
|
+
it "doesn't match comments" do
|
56
|
+
expect(subject.contains?("// comment")).to be_false
|
57
|
+
end
|
58
|
+
|
59
|
+
it "doesn't match empty lines" do
|
60
|
+
expect(subject.contains?("")).to be_false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Rippersnapper
|
4
|
+
|
5
|
+
describe Url do
|
6
|
+
subject { Url.new "www.google.com" }
|
7
|
+
|
8
|
+
it { should respond_to :domain }
|
9
|
+
it { should respond_to :scheme }
|
10
|
+
it { should respond_to :host }
|
11
|
+
it { should respond_to :path }
|
12
|
+
it { should respond_to :url }
|
13
|
+
it { should respond_to :suffix }
|
14
|
+
it { should respond_to :subdomain }
|
15
|
+
|
16
|
+
|
17
|
+
context "with a scheme" do
|
18
|
+
subject { Url.new "http://drive.google.com/micah" }
|
19
|
+
its(:url) { should eq "http://drive.google.com/micah" }
|
20
|
+
its(:path) { should eq "/micah" }
|
21
|
+
its(:scheme) { should eq "http" }
|
22
|
+
its(:host) { should eq "drive.google.com" }
|
23
|
+
its(:suffix) { should eq "com" }
|
24
|
+
its(:domain) { should eq "google" }
|
25
|
+
its(:subdomain) { should eq "drive" }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "without a scheme" do
|
29
|
+
subject { Url.new "www.google.com/micah" }
|
30
|
+
its(:url) { should eq "http://www.google.com/micah" }
|
31
|
+
its(:path) { should eq "/micah" }
|
32
|
+
its(:scheme) { should eq "http" }
|
33
|
+
its(:host) { should eq "www.google.com" }
|
34
|
+
its(:suffix) { should eq "com" }
|
35
|
+
its(:domain) { should eq "google" }
|
36
|
+
its(:subdomain) { should eq "www" }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "with a query string" do
|
40
|
+
subject { Url.new "www.google.com/micah?date=today" }
|
41
|
+
its(:path) { should eq "/micah?date=today" }
|
42
|
+
its(:suffix) { should eq "com" }
|
43
|
+
its(:domain) { should eq "google" }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rippersnapper'
|
2
|
+
|
3
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
4
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
5
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
6
|
+
# loaded once.
|
7
|
+
#
|
8
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
11
|
+
config.run_all_when_everything_filtered = true
|
12
|
+
config.filter_run :focus
|
13
|
+
|
14
|
+
# Run specs in random order to surface order dependencies. If you find an
|
15
|
+
# order dependency and want to debug it, you can fix the order by providing
|
16
|
+
# the seed, which is printed after each run.
|
17
|
+
# --seed 1234
|
18
|
+
config.order = 'random'
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rippersnapper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Micah Woods
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-04-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
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: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.13.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.13.0
|
55
|
+
description: Rip and snap domains using Rippersnappers jaws of steele!
|
56
|
+
email:
|
57
|
+
- micahwoods@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- .rspec
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE.txt
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- lib/rippersnapper.rb
|
69
|
+
- lib/rippersnapper/domain_parser.rb
|
70
|
+
- lib/rippersnapper/public_suffix.dat
|
71
|
+
- lib/rippersnapper/suffix_file_reader.rb
|
72
|
+
- lib/rippersnapper/url.rb
|
73
|
+
- lib/rippersnapper/version.rb
|
74
|
+
- rippersnapper.gemspec
|
75
|
+
- rippersnapper.jpg
|
76
|
+
- spec/rippersnapper/domain_parser_spec.rb
|
77
|
+
- spec/rippersnapper/suffix_file_validator_spec.rb
|
78
|
+
- spec/rippersnapper/url_spec.rb
|
79
|
+
- spec/rippersnapper_spec.rb
|
80
|
+
- spec/spec_helper.rb
|
81
|
+
homepage: https://github.com/mwoods79/rippersnapper
|
82
|
+
licenses:
|
83
|
+
- MIT
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 2.0.0
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: Named after the worst decepticon ever, a shark with T-Rex arms...
|
105
|
+
test_files:
|
106
|
+
- spec/rippersnapper/domain_parser_spec.rb
|
107
|
+
- spec/rippersnapper/suffix_file_validator_spec.rb
|
108
|
+
- spec/rippersnapper/url_spec.rb
|
109
|
+
- spec/rippersnapper_spec.rb
|
110
|
+
- spec/spec_helper.rb
|