safe_redirection 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.
- data/Gemfile +2 -0
- data/Gemfile.lock +36 -0
- data/README.md +46 -0
- data/Rakefile +17 -0
- data/example.rb +20 -0
- data/features/support/env.rb +0 -0
- data/lib/safe_redirection/constants.rb +3 -0
- data/lib/safe_redirection/resolvers/exceptions_resolver.rb +22 -0
- data/lib/safe_redirection/resolvers/resolver.rb +15 -0
- data/lib/safe_redirection/resolvers.rb +2 -0
- data/lib/safe_redirection/sanitizer.rb +30 -0
- data/lib/safe_redirection.rb +8 -0
- data/safe_redirection.gemspec +21 -0
- data/spec/lib/safe_redirection/resolvers/exceptions_resolver_spec.rb +31 -0
- data/spec/lib/safe_redirection/sanitizer_spec.rb +59 -0
- data/spec/spec_helper.rb +3 -0
- metadata +108 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
safe_redirection (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
builder (3.0.0)
|
10
|
+
cucumber (1.2.1)
|
11
|
+
builder (>= 2.1.2)
|
12
|
+
diff-lcs (>= 1.1.3)
|
13
|
+
gherkin (~> 2.11.0)
|
14
|
+
json (>= 1.4.6)
|
15
|
+
diff-lcs (1.1.3)
|
16
|
+
gherkin (2.11.1)
|
17
|
+
json (>= 1.4.6)
|
18
|
+
json (1.7.3)
|
19
|
+
rake (0.9.2.2)
|
20
|
+
rspec (2.11.0)
|
21
|
+
rspec-core (~> 2.11.0)
|
22
|
+
rspec-expectations (~> 2.11.0)
|
23
|
+
rspec-mocks (~> 2.11.0)
|
24
|
+
rspec-core (2.11.0)
|
25
|
+
rspec-expectations (2.11.1)
|
26
|
+
diff-lcs (~> 1.1.3)
|
27
|
+
rspec-mocks (2.11.1)
|
28
|
+
|
29
|
+
PLATFORMS
|
30
|
+
ruby
|
31
|
+
|
32
|
+
DEPENDENCIES
|
33
|
+
cucumber
|
34
|
+
rake
|
35
|
+
rspec
|
36
|
+
safe_redirection!
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# SafeRedirection
|
2
|
+
|
3
|
+
SafeRedirection allows you to easily sanitize your URLs.
|
4
|
+
|
5
|
+
## Getting started
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
require 'safe_redirection'
|
9
|
+
|
10
|
+
class MyResolver < SafeRedirection::Resolvers::Resolver
|
11
|
+
def recognize_path(path, options = {})
|
12
|
+
if path =~ /^special/
|
13
|
+
"http://my.app.tld/special_page"
|
14
|
+
else
|
15
|
+
raise 'Not found'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
resolver = MyResolver.new
|
21
|
+
my_sanitizer = SafeRedirection::Sanitizer.new(resolver, 'http://my.app.tld/root/path/', 'http://my.app.tld/root/path/default_url')
|
22
|
+
|
23
|
+
my_sanitizer.safe_url_for 'http://www.outside.tld/some/path'
|
24
|
+
# => "http://my.app.tld/root/path/default_url"
|
25
|
+
my_sanitizer.safe_url_for 'http://my.app.tld/root/path/special/subpath'
|
26
|
+
# => "http://my.app.tld/special_page"
|
27
|
+
my_sanitizer.safe_url_for 'ftp://my.app.tld/root/path/special/subpath'
|
28
|
+
# => "http://my.app.tld/root/path/default_url"
|
29
|
+
my_sanitizer.safe_url_for 'http://my.app.tld2/root/path/special/subpath'
|
30
|
+
# => "http://my.app.tld/special_page"
|
31
|
+
```
|
32
|
+
|
33
|
+
Everything that responds to `recognize_path` could be a resolver and guess what! `ActionController::Routing::Routes` with Rails 2.x and `MyApplication::Application.routes` in Rails 3.x do respond to this method. It can therefore be used as a resolver in a code like this :
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
resolver = SafeRedirection::Resolvers::ExceptionsResolver.new(MyApplication::Application.routes)
|
37
|
+
resolver.legitimate_base_urls << "http://www.outsite.tld/"
|
38
|
+
sanitizer = SafeRedirection::Sanitizer.new(resolver, 'http://my.app.tld/', 'http://my.app.tld/')
|
39
|
+
|
40
|
+
sanitizer.safe_url_for "http://my.app.tld/articles/2"
|
41
|
+
# => { :controller => "articles", :action => "show", :id => 2 }
|
42
|
+
sanitizer.safe_url_for "http://www.outside.tld/path"
|
43
|
+
# => "http://www.outside.tld/path"
|
44
|
+
sanitizer.safe_url_fo "http://www.outside.but_somewhere_else.com/"
|
45
|
+
# => "http://my.app.tld/"
|
46
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "cucumber/rake/task"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
$:.unshift File.expand_path('lib', __FILE__)
|
5
|
+
|
6
|
+
Cucumber::Rake::Task.new(:cucumber) do |task|
|
7
|
+
end
|
8
|
+
|
9
|
+
namespace :cucumber do
|
10
|
+
Cucumber::Rake::Task.new(:wip) do |task|
|
11
|
+
task.cucumber_opts = %w{--tags @wip}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
RSpec::Core::RakeTask.new do |t|
|
16
|
+
t.rspec_opts = '--color'
|
17
|
+
end
|
data/example.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
$:.unshift File.expand_path('lib', File.dirname(__FILE__))
|
2
|
+
require 'safe_redirection'
|
3
|
+
|
4
|
+
class MyResolver < SafeRedirection::Resolvers::Resolver
|
5
|
+
def recognize_path(path, options = {})
|
6
|
+
if path =~ /^special/
|
7
|
+
"http://my.app.tld/special_page"
|
8
|
+
else
|
9
|
+
raise 'Not found'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
resolver = MyResolver.new
|
15
|
+
my_sanitizer = SafeRedirection::Sanitizer.new(resolver, 'http://my.app.tld/root/path/', 'http://my.app.tld/root/path/default_url')
|
16
|
+
|
17
|
+
puts my_sanitizer.safe_url_for('http://www.outside.tld/some/path')
|
18
|
+
puts my_sanitizer.safe_url_for('http://my.app.tld/root/path/special/subpath')
|
19
|
+
puts my_sanitizer.safe_url_for('ftp://my.app.tld/root/path/special/subpath')
|
20
|
+
puts my_sanitizer.safe_url_for('http://my.app.tld2/root/path/special/subpath')
|
File without changes
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module SafeRedirection
|
2
|
+
module Resolvers
|
3
|
+
class ExceptionsResolver < Resolver
|
4
|
+
attr_accessor :legitimate_urls, :legitimate_base_urls
|
5
|
+
|
6
|
+
def initialize(*args)
|
7
|
+
super(*args)
|
8
|
+
@legitimate_urls = []
|
9
|
+
@legitimate_base_urls = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def recognize_path(path, options = {})
|
13
|
+
if self.legitimate_urls.include?(path) ||
|
14
|
+
self.legitimate_base_urls.any? { |base| path.start_with? base }
|
15
|
+
path
|
16
|
+
else
|
17
|
+
resolver.recognize_path path, options
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SafeRedirection
|
2
|
+
class Sanitizer
|
3
|
+
attr_accessor :resolver, :base_url, :default_url
|
4
|
+
|
5
|
+
def initialize(resolver, base_url, default_url)
|
6
|
+
@resolver = resolver
|
7
|
+
@base_url = base_url
|
8
|
+
@default_url = default_url
|
9
|
+
end
|
10
|
+
|
11
|
+
def safe_url_for(redirect_url)
|
12
|
+
uri = URI(redirect_url)
|
13
|
+
path = relative_path(uri.path)
|
14
|
+
|
15
|
+
if %w{http https}.include? uri.scheme
|
16
|
+
resolver.recognize_path(path, :method => :get) rescue default_url
|
17
|
+
else
|
18
|
+
default_url
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def base_path
|
23
|
+
URI(base_url).path
|
24
|
+
end
|
25
|
+
|
26
|
+
def relative_path(path)
|
27
|
+
path.start_with?(base_path) ? path.sub(base_path, '') : path
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
2
|
+
require "safe_redirection/constants"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "safe_redirection"
|
6
|
+
s.version = SafeRedirection::VERSION
|
7
|
+
s.authors = ["Thomas Feron"]
|
8
|
+
s.description = "A small library for sanitization of URLs for redirections in Rails"
|
9
|
+
s.summary = "safe_redirection-#{s.version}"
|
10
|
+
s.email = "tho.feron@gmail.com"
|
11
|
+
|
12
|
+
s.platform = Gem::Platform::RUBY
|
13
|
+
|
14
|
+
s.add_development_dependency "rake"
|
15
|
+
s.add_development_dependency "cucumber"
|
16
|
+
s.add_development_dependency "rspec"
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n").reject { |path| path =~ /\.gitignore$/ }
|
19
|
+
s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
20
|
+
s.require_path = "lib"
|
21
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SafeRedirection::Resolvers::ExceptionsResolver do
|
4
|
+
let(:resolver) { double('resolver') }
|
5
|
+
|
6
|
+
subject { SafeRedirection::Resolvers::ExceptionsResolver.new(resolver) }
|
7
|
+
|
8
|
+
describe "#recognize_path" do
|
9
|
+
it "should delegate to the resolver" do
|
10
|
+
resolver.should_receive(:recognize_path)
|
11
|
+
subject.recognize_path("http://test.tld/some/path")
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with a legitimate URL" do
|
15
|
+
it "should return this URL" do
|
16
|
+
legitimate_url = "http://else.where/far/far/away"
|
17
|
+
subject.legitimate_urls << legitimate_url
|
18
|
+
subject.recognize_path(legitimate_url).should == legitimate_url
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with a legitimate base URL" do
|
23
|
+
it "should return the URL passed" do
|
24
|
+
legitimate_base_url = "http://else.where/far/"
|
25
|
+
legitimate_url = "#{legitimate_base_url}far/away"
|
26
|
+
subject.legitimate_base_urls << legitimate_base_url
|
27
|
+
subject.recognize_path(legitimate_url).should == legitimate_url
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SafeRedirection::Sanitizer do
|
4
|
+
let(:resolver) { double('resolver') }
|
5
|
+
let(:base_url) { "http://test.tld/" }
|
6
|
+
let(:default_url) { "http://test.tld/default" }
|
7
|
+
|
8
|
+
subject { SafeRedirection::Sanitizer.new(resolver, base_url, default_url) }
|
9
|
+
|
10
|
+
describe '#safe_url_for' do
|
11
|
+
context "with a valid URL" do
|
12
|
+
let(:valid_url) { "http://test.tld/valid" }
|
13
|
+
let(:params) { { :controller => 'home', :action => 'valid' } }
|
14
|
+
|
15
|
+
it "should return this very URL" do
|
16
|
+
resolver.should_receive(:recognize_path).with('valid', anything).and_return(params)
|
17
|
+
subject.safe_url_for(valid_url).should == params
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "with an invalid URL" do
|
22
|
+
it "should return the default URL" do
|
23
|
+
resolver.should_receive(:recognize_path).with('rubbish', anything).and_raise('ActionController::RoutingError')
|
24
|
+
subject.safe_url_for("http://test.tld/rubbish").should == default_url
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should return the default URL with a non-HTTP(s) scheme" do
|
28
|
+
subject.safe_url_for("ftp://test.tld/").should == default_url
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when the application is not at the root" do
|
33
|
+
let(:base_url) { "http://test.tld/some/path/" }
|
34
|
+
|
35
|
+
it "should try to resolve the subpath" do
|
36
|
+
resolver.should_receive(:recognize_path).with('subpath', anything)
|
37
|
+
subject.safe_url_for('http://test.tld/some/path/subpath')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#relative_path" do
|
43
|
+
let(:base_url) { "http://test.tld/in/so.me/path/" }
|
44
|
+
|
45
|
+
it "should strip the base path" do
|
46
|
+
subject.relative_path('/in/so.me/path/subpath').should == 'subpath'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not strip it if it's not in the beginning" do
|
50
|
+
path = '/not/in/so.me/path/subpath'
|
51
|
+
subject.relative_path(path).should == path
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should not interpret regular expressions in the base URL's path" do
|
55
|
+
path = '/in/soZme/path/subpath'
|
56
|
+
subject.relative_path(path).should == path
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: safe_redirection
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Thomas Feron
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: cucumber
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: A small library for sanitization of URLs for redirections in Rails
|
63
|
+
email: tho.feron@gmail.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- Gemfile
|
69
|
+
- Gemfile.lock
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- example.rb
|
73
|
+
- features/support/env.rb
|
74
|
+
- lib/safe_redirection.rb
|
75
|
+
- lib/safe_redirection/constants.rb
|
76
|
+
- lib/safe_redirection/resolvers.rb
|
77
|
+
- lib/safe_redirection/resolvers/exceptions_resolver.rb
|
78
|
+
- lib/safe_redirection/resolvers/resolver.rb
|
79
|
+
- lib/safe_redirection/sanitizer.rb
|
80
|
+
- safe_redirection.gemspec
|
81
|
+
- spec/lib/safe_redirection/resolvers/exceptions_resolver_spec.rb
|
82
|
+
- spec/lib/safe_redirection/sanitizer_spec.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
homepage:
|
85
|
+
licenses: []
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.8.24
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: safe_redirection-0.0.1
|
108
|
+
test_files: []
|