-
-
Save sporkmonger/23660 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Percent encodes a URI or component. | |
# | |
# @param [String, #to_str] uri The URI or component to encode. | |
# | |
# @option [String, Regexp] character_class | |
# The characters which are not percent encoded. If a <tt>String</tt> | |
# is passed, the <tt>String</tt> must be formatted as a regular | |
# expression character class. (Do not include the surrounding square | |
# brackets.) For example, <tt>"b-zB-Z0-9"</tt> would cause everything | |
# but the letters 'b' through 'z' and the numbers '0' through '9' to be | |
# percent encoded. If a <tt>Regexp</tt> is passed, the value | |
# <tt>/[^b-zB-Z0-9]/</tt> would have the same effect. | |
# A set of useful <tt>String</tt> values may be found in the | |
# <tt>Addressable::URI::CharacterClasses</tt> module. The default value | |
# is the reserved plus unreserved character classes specified in | |
# <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>. | |
# | |
# @return [String] The encoded component. | |
# | |
# @example | |
# Addressable::URI.encode( | |
# "simple/example", :character_class => "b-zB-Z0-9" | |
# ) | |
# => "simple%2Fex%61mple" | |
# Addressable::URI.encode( | |
# "simple/example", :character_class => /[^b-zB-Z0-9]/ | |
# ) | |
# => "simple%2Fex%61mple" | |
# Addressable::URI.encode( | |
# "simple/example", | |
# :character_class => Addressable::URI::CharacterClasses::UNRESERVED | |
# ) | |
# => "simple%2Fexample" | |
# Addressable::URI.encode( | |
# "simple/example", | |
# :character_class => Addressable::URI::CharacterClasses::UNRESERVED | |
# ) | |
# => "simple%2Fexample" | |
def self.encode(uri, options={}) | |
return nil if uri.nil? | |
if !uri.respond_to?(:to_str) | |
raise TypeError, "Can't convert #{uri.class} into String." | |
end | |
# Process optional parameters | |
if options.kind_of?(Regexp) | |
options = {:character_class => options} | |
elsif options.kind_of?(Class) | |
options = {:returning => options} | |
end | |
options = { | |
:character_class => nil, | |
:returning => String, | |
:component => nil | |
}.merge(options) | |
encode_all = !options[:character_class] && !options[:component] | |
if options[:character_class] == nil | |
case options[:component] | |
when :scheme | |
options[:character_class] = | |
Addressable::URI::CharacterClasses::SCHEME | |
when :user, :password, :host, :port, :userinfo, :authority | |
options[:character_class] = | |
Addressable::URI::CharacterClasses::AUTHORITY | |
when :path | |
options[:character_class] = | |
Addressable::URI::CharacterClasses::PATH | |
when :query | |
options[:character_class] = | |
Addressable::URI::CharacterClasses::QUERY | |
when :fragment | |
options[:character_class] = | |
Addressable::URI::CharacterClasses::FRAGMENT | |
else | |
options[:character_class] = | |
CharacterClasses::RESERVED + CharacterClasses::UNRESERVED | |
end | |
end | |
if ![String, ::Addressable::URI].include?(options[:returning]) | |
raise TypeError, | |
"Expected String or Addressable::URI, " + | |
"got #{options[:returning].inspect}" | |
end | |
if ![String, Regexp].include?(options[:character_class]) | |
raise TypeError, | |
"Expected String or Regexp, " + | |
"got #{options[:character_class].inspect}" | |
end | |
if encode_all | |
uri = uri.kind_of?(self) ? uri : self.parse(uri.to_str) | |
encoded_uri = Addressable::URI.new( | |
:scheme => self.encode( | |
uri.scheme, :component => :scheme | |
), | |
:authority => self.encode_component( | |
uri.authority, :component => :authority | |
), | |
:path => self.encode_component( | |
uri.path, :component => :path | |
), | |
:query => self.encode_component( | |
uri.query, :component => :query | |
), | |
:fragment => self.encode_component( | |
uri.fragment, :component => :fragment | |
) | |
) | |
if returning == String | |
return encoded_uri.to_s | |
elsif returning == ::Addressable::URI | |
return encoded_uri | |
end | |
else | |
component = uri.to_str | |
if options[:character_class].kind_of?(String) | |
options[:character_class] = /[^#{options[:character_class]}]/ | |
end | |
return component.gsub(options[:character_class]) do |sequence| | |
(sequence.unpack('C*').map { |c| "%#{c.to_s(16).upcase}" }).join("") | |
end | |
end | |
end | |
class << self | |
alias_method :escape, :encode | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment