From fc1710f9e755a7d39b632994f37cb7e06a4e491a Mon Sep 17 00:00:00 2001 From: Donald Piret Date: Thu, 15 Jan 2015 14:58:26 +0800 Subject: [PATCH 1/2] Add a no_local option that prevents the use of local hostnames --- lib/validate_url.rb | 4 +++- spec/resources/user_with_no_local.rb | 9 +++++++++ spec/spec_helper.rb | 1 + spec/validate_url_spec.rb | 21 +++++++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 spec/resources/user_with_no_local.rb diff --git a/lib/validate_url.rb b/lib/validate_url.rb index b86e53f..55b6883 100644 --- a/lib/validate_url.rb +++ b/lib/validate_url.rb @@ -11,6 +11,8 @@ class UrlValidator < ActiveModel::EachValidator def initialize(options) options.reverse_merge!(:schemes => %w(http https)) options.reverse_merge!(:message => :url) + options.reverse_merge!(:no_local => false) + super(options) end @@ -18,7 +20,7 @@ def validate_each(record, attribute, value) schemes = [*options.fetch(:schemes)].map(&:to_s) begin uri = Addressable::URI.parse(value) - unless uri && uri.host && schemes.include?(uri.scheme) + unless uri && uri.host && schemes.include?(uri.scheme) && (!options.fetch(:no_local) || uri.host.include?('.')) record.errors.add(attribute, options.fetch(:message), :value => value) end rescue Addressable::URI::InvalidURIError diff --git a/spec/resources/user_with_no_local.rb b/spec/resources/user_with_no_local.rb new file mode 100644 index 0000000..2e302e3 --- /dev/null +++ b/spec/resources/user_with_no_local.rb @@ -0,0 +1,9 @@ +require 'active_model/validations' + +class UserWithNoLocal + include ActiveModel::Validations + + attr_accessor :homepage + + validates :homepage, :url => {:no_local => true} +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 356301c..d5b1a00 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -24,3 +24,4 @@ autoload :UserWithArLegacy, 'resources/user_with_ar_legacy' autoload :UserWithCustomScheme, 'resources/user_with_custom_scheme' autoload :UserWithCustomMessage, 'resources/user_with_custom_message' +autoload :UserWithNoLocal, 'resources/user_with_no_local' diff --git a/spec/validate_url_spec.rb b/spec/validate_url_spec.rb index 8c44625..701aa9c 100644 --- a/spec/validate_url_spec.rb +++ b/spec/validate_url_spec.rb @@ -135,6 +135,27 @@ end end + context "with no_local" do + before do + @user = UserWithNoLocal.new + end + + it "should allow a valid internet url" do + @user.homepage = "http://www.example.com" + @user.should be_valid + end + + it "should not allow a local hostname" do + @user.homepage = "http://localhost" + @user.should_not be_valid + end + + it "should not allow weird urls that get interpreted as local hostnames" do + @user.homepage = "http://http://example.com" + @user.should_not be_valid + end + end + context "with legacy syntax" do before do @user = UserWithLegacySyntax.new From 574cf543c0c1e24553d4bc0ea6f2730ac380b4dc Mon Sep 17 00:00:00 2001 From: Donald Piret Date: Thu, 15 Jan 2015 15:01:19 +0800 Subject: [PATCH 2/2] Document the option --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index aec81e5..9f11cb4 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,9 @@ class Pony < ActiveRecord::Base # with allow_blank validates :homepage, :url => {:allow_blank => true} + + # without local hostnames + validates :homepage, :url => {:no_local => true} end ```