Skip to content

Commit

Permalink
fix multiple sharp signs in URIs
Browse files Browse the repository at this point in the history
rename HttpUrlValidator as UriValidator
  • Loading branch information
Trim committed Jan 7, 2023
1 parent 3ac001b commit 0f0164c
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 52 deletions.
17 changes: 3 additions & 14 deletions app/models/bookmark.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,11 @@ class Bookmark < Content
validates :title, presence: { message: "Le titre est obligatoire" },
length: { maximum: 100, message: "Le titre est trop long" }
validates :link, presence: { message: "Vous ne pouvez pas poster un lien vide" },
http_url: { message: "Le lien n'est pas valide" },
uri: { message: "Le lien n'est pas valide" },
length: { maximum: 255, message: "Le lien est trop long" }

def link=(raw)
raw.strip!
return write_attribute :url, nil if raw.blank?
uri = URI.parse(raw)
# Default to HTTP link if neither scheme nor host is found
if uri.scheme.blank? && uri.host.blank?
raw = "http://#{raw}"
uri = URI.parse(raw)
end
write_attribute :link, uri.to_s
# Let raw value if error when parsed, HttpUrlValidator will manage it
rescue URI::InvalidURIError
write_attribute :link, raw
before_validation do |bookmark|
bookmark.link = UriValidator.before_validation(bookmark.link);
end

def create_node(attrs={})
Expand Down
16 changes: 3 additions & 13 deletions app/models/link.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,12 @@ class Link < ActiveRecord::Base

validates :title, presence: { message: "Un lien doit obligatoirement avoir un titre" },
length: { maximum: 100, message: "Le titre est trop long" }
validates :url, http_url: { protocols: PROTOCOLS, message: "L'adresse n'est pas valide" },
validates :url, uri: { protocols: PROTOCOLS, message: "L'adresse n'est pas valide" },
presence: { message: "Un lien doit obligatoirement avoir une adresse" },
length: { maximum: 255, message: "L’adresse est trop longue" }

def url=(raw)
raw.strip!
return write_attribute :url, nil if raw.blank?
uri = URI.parse(raw)
if uri.scheme.blank? && uri.host.blank?
raw = "http://#{raw}"
uri = URI.parse(raw)
end
write_attribute :url, uri.to_s
# Let raw value if error when parsed, HttpUrlValidator will manage it
rescue URI::InvalidURIError
write_attribute :url, raw
before_validation do |link|
link.url = UriValidator.before_validation(link.url);
end

### Behaviour ###
Expand Down
25 changes: 0 additions & 25 deletions app/validators/http_url_validator.rb

This file was deleted.

57 changes: 57 additions & 0 deletions app/validators/uri_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Validate if a value is a URI
class UriValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if value.present? && not(valid?(value, options))
record.errors.add attribute, (options[:message] || "n'est pas un lien valide")
end
end

private

def valid?(value, options)
# Valid links can be parsed by URI
uri = URI.parse(value)

# Authorize only given protocol
if options.has_key?(:protocols)
return options[:protocols].include?(uri.scheme)
end

# Links starting with "//MY_DOMAIN" are current scheme dependent and are valid
return true if uri.scheme.nil? && uri.host == MY_DOMAIN

# All other links are valid only if scheme and host exists
return uri.scheme.present? && uri.host.present?
rescue URI::InvalidURIError
false
end

def self.before_validation(raw, default_scheme='http://')
raw.strip!
return nil if raw.blank?

# Automatically encodes sharp signs (#) found in URI fragment:
# RFC 3986 uses sharp to define URI fragment and requires other sharps
# to be percent encoded
fragments = raw.split("#")
if (fragments.length > 2)
raw = fragments[0] + '#' + fragments[1..-1].join('%23')
end

uri = URI.parse(raw)

# If user forgot to add scheme, add default
if default_scheme.present? && uri.scheme.blank? && uri.host.blank?
raw = "#{default_scheme}#{raw}"
uri = URI.parse(raw)
end

return uri.to_s

# Let raw value if error occured when we tried to parse it, because
# the HttpUrlValidator will manage it itself on validation
rescue URI::InvalidURIError
return raw
end

end

0 comments on commit 0f0164c

Please sign in to comment.