module OpenID::URINorm

Constants

PERCENT_ESCAPE_RE
RESERVED_RE

Public Class Methods

urinorm(uri) click to toggle source
# File lib/openid/urinorm.rb, line 7
def URINorm.urinorm(uri)
  uri = URI.parse(uri)

  raise URI::InvalidURIError.new('no scheme') unless uri.scheme
  uri.scheme = uri.scheme.downcase
  unless ['http','https'].member?(uri.scheme)
    raise URI::InvalidURIError.new('Not an HTTP or HTTPS URI')
  end

  raise URI::InvalidURIError.new('no host') unless uri.host
  uri.host = uri.host.downcase

  uri.path = remove_dot_segments(uri.path)
  uri.path = '/' if uri.path.length == 0

  uri = uri.normalize.to_s
  uri = uri.gsub(PERCENT_ESCAPE_RE) {
    sub = $&[1..2].to_i(16).chr
    reserved(sub) ? $&.upcase : sub
  }

  return uri
end

Private Class Methods

remove_dot_segments(path) click to toggle source
# File lib/openid/urinorm.rb, line 39
def URINorm.remove_dot_segments(path)
  result_segments = []

  while path.length > 0
    if path.start_with?('../')
      path = path[3..-1]
    elsif path.start_with?('./')
      path = path[2..-1]
    elsif path.start_with?('/./')
      path = path[2..-1]
    elsif path == '/.'
      path = '/'
    elsif path.start_with?('/../')
      path = path[3..-1]
      result_segments.pop if result_segments.length > 0
    elsif path == '/..'
      path = '/'
      result_segments.pop if result_segments.length > 0
    elsif path == '..' or path == '.'
      path = ''
    else
      i = 0
      i = 1 if path[0].chr == '/'
      i = path.index('/', i)
      i = path.length if i.nil?
      result_segments << path[0...i]
      path = path[i..-1]
    end
  end

  return result_segments.join('')
end
reserved(chr) click to toggle source
# File lib/openid/urinorm.rb, line 35
def URINorm.reserved(chr)
  not RESERVED_RE =~ chr
end