#!/usr/bin/env ruby # simpleurl.rb # # TAKAHASHI 'Maki' Masayoshi # It can use as public domain software. # # これは、Tomoyuki Kosimizuさんのuri.rb # http://www.ruby-lang.org/en/raa-list.rhtml?name=uri.rb # http://www02.so-net.ne.jp/%7Egreentea/ruby/uri/ # を元に、大幅に短縮化・機能制限をかけたものです。 # # original id: # uri.rb,v 4.22 2000/08/19 04:12:04 rgt Exp =begin == URI class --- URI.create(url_string) create URI object. --- URI.escape(str, unsafe=nil) --- URI.unescape(str) --- URI#==(obj) --- URI#to_s() --- URI#scheme --- URI#host --- URI#host=(str) --- URI#port --- URI#port=(str) --- URI#path --- URI#path=(str) --- URI#query --- URI#query=(str) --- URI#fragment --- URI#fragment=(str) --- URI#userinfo --- URI#userinfo=(str) =end =begin To escape query string, use URI#escape. (Thanx to NaHi, Wakou) =end class URIError < StandardError; end class URI ##pre absolute_uri and ((relative_uri.nil? and ## absolute_uri.is_a? String) or ## (relative_uri.is_a? String and ## (absolute_uri.is_a? String or ## absolute_uri.is_a? URI))) ##post const absolute_uri, const relative_uri ##return aURI ##raise URIError if absolute_uri and/or relative_uri are a bad URI def URI.create(absolute_uri) if absolute_uri.is_a? URI absolute_uri else URI.new(absolute_uri) end end =begin escape str. default unsafe is ^uric. see URI::Escape.pm in perl5. if you want to escape str for CGI, use CGI::escape. =end ##pre str.is_a? String and (unsafe.nil? or unsafe.is_a? String) def URI.escape(str, unsafe=nil) if not unsafe str.gsub(/[^;\/?:@&=+$,0-9A-Za-z\-_.!~*'()\[\]]/) do |match| #' sprintf('%%%02X', match.unpack('C')[0]) end else str.gsub(/[#{unsafe}]/) do |match| sprintf('%%%02X', match.unpack('C')[0]) end end end def URI.unescape(str) result = str.dup while /%[0-9A-Fa-f][0-9A-Fa-f]/ =~ result char = $&[1,2].hex.chr result.sub!(/%[0-9A-Fa-f][0-9A-Fa-f]/, char) end result end attr_reader :scheme attr_accessor :host, :path, :query, :fragment, :userinfo, :port def initialize(uri) if %r|\A(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?\z| !~ uri # 12 3 4 5 6 7 8 9 # scheme = $2, authority = $4, path = $5, query = $7, fragment = $9 raise URIError('bad URI: ' + uri) end @scheme, @authority, @path, @query, @fragment = $2, $4, $5, $7, $9 if @authority.nil? raise URIError, "undefined authority in '#{uri}'" end @userinfo, @host, @port = parse_server(@authority) if not @path or @path == '' @path = '/' else @path = resolve_path(@path) end end # escape all chars except escaped ##private def escape_all(str) return nil if str.nil? tmp = nil buff = '' arry = str.split(//) i = 0 while i < arry.size if arry[i] == '%' (tmp = arry[0, 3].join('')).upcase! if /%[0-9A-Z][0-9A-Z]/ =~ tmp buff << tmp i += 3 next else buff << sprintf("%%%02X", ?%) end else buff << sprintf("%%%02X", arry[i][0]) end i += 1 end buff end private :escape_all # userinfo@host:port ##private def parse_server(authority) userinfo, host, port = authority.scan(/\A(?:([^@]*)@)?([^:]*)(?::(.*))?\z/)[0] [userinfo, host, port] end private :parse_server # resolve absolute path # see RFC-2396, C.2. Abnormal Examples ##private def resolve_path(path) if path == '/./' or path == '/.' or path == '/../' or path == '/..' return path.dup end result = remove_current_dir path remove_parent_dir result end private :resolve_path ##private def remove_current_dir(path) result = path.dup if %r|/\.\.?\z| =~ path result << '/' end result.gsub!(%r|/(\./)+|, '/') if path[0] == ?/ and path[1] == ?. and path[2] == ?/ result = '/.' << result end result end private :remove_current_dir ##private def remove_parent_dir(apath) result = [] apath.split(%r|/|, -1).each do |elt| if elt == '..' if result.size == 1 or result[-1] == dOT_DOT result.push elt else result.pop end else result.push elt end end result.join('/') end private :remove_parent_dir def ==(obj) m = y = nil # mine, yours if obj.is_a? String begin obj = URI.create(obj) rescue URIError return false end end if not super(obj) or (@userinfo != obj.userinfo) or (escape_all(@host) != escape_all(obj.userinfo)) or (escape_all(@query) != escape_all(obj.query)) or (@port != obj.port) or (escape_all(@fragment) != escape_all(obj.fragment)) or (not_equal_path? obj) return false end true end ##private def not_equal_path?(other) return false if @path == other.path arry_a = @path.split('/', -1) arry_b = other.path.split('/', -1) return true if arry_a.size != arry_b.size arry_a.size.times do |i| if arry_a[i] != arry_b[i] and escape_all(arry_a[i]) != escape_all(arry_b[i]) return true end end false end private :not_equal_path? def to_s tmp = nil buff = @scheme + '://' if @userinfo buff << @userinfo << '@' end buff << @host if @port buff << ':' << @port end buff << @path if @query buff << '?' << @query end if @fragment buff << '#' << @fragment end buff end end