twitter-status-bot/.gems/gems/http-0.6.2/lib/http/backports/uri.rb

132 lines
4.4 KiB
Ruby

# Taken from Ruby 1.9's uri/common.rb
# By Akira Yamada <akira@ruby-lang.org>
# License:
# You can redistribute it and/or modify it under the same term as Ruby.
require 'uri'
# Backport Ruby 1.9's form encoding/decoding functionality
module URI
TBLENCWWWCOMP_ = {} # :nodoc:
256.times do |i|
TBLENCWWWCOMP_[i.chr] = format('%%%02X', i)
end
TBLENCWWWCOMP_[' '] = '+'
TBLENCWWWCOMP_.freeze
TBLDECWWWCOMP_ = {} # :nodoc:
256.times do |i|
h, l = i >> 4, i & 15
TBLDECWWWCOMP_[format('%%%X%X', h, l)] = i.chr
TBLDECWWWCOMP_[format('%%%x%X', h, l)] = i.chr
TBLDECWWWCOMP_[format('%%%X%x', h, l)] = i.chr
TBLDECWWWCOMP_[format('%%%x%x', h, l)] = i.chr
end
TBLDECWWWCOMP_['+'] = ' '
TBLDECWWWCOMP_.freeze
# Encode given +str+ to URL-encoded form data.
#
# This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
# (ASCII space) to + and converts others to %XX.
#
# This is an implementation of
# http://www.w3.org/TR/html5/association-of-controls-and-forms.html#url-encoded-form-data
#
# See URI.decode_www_form_component, URI.encode_www_form
def self.encode_www_form_component(str)
str.to_s.gsub(/[^*\-.0-9A-Z_a-z]/) { |chr| TBLENCWWWCOMP_[chr] }
end
# Decode given +str+ of URL-encoded form data.
#
# This decods + to SP.
#
# See URI.encode_www_form_component, URI.decode_www_form
def self.decode_www_form_component(str)
fail(ArgumentError, "invalid %-encoding (#{str})") unless /\A[^%]*(?:%\h\h[^%]*)*\z/ =~ str
str.gsub(/\+|%\h\h/) { |chr| TBLDECWWWCOMP_[chr] }
end
# Generate URL-encoded form data from given +enum+.
#
# This generates application/x-www-form-urlencoded data defined in HTML5
# from given an Enumerable object.
#
# This internally uses URI.encode_www_form_component(str).
#
# This method doesn't convert the encoding of given items, so convert them
# before call this method if you want to send data as other than original
# encoding or mixed encoding data. (Strings which are encoded in an HTML5
# ASCII incompatible encoding are converted to UTF-8.)
#
# This method doesn't handle files. When you send a file, use
# multipart/form-data.
#
# This is an implementation of
# http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
#
# URI.encode_www_form([["q", "ruby"], ["lang", "en"]])
# #=> "q=ruby&lang=en"
# URI.encode_www_form("q" => "ruby", "lang" => "en")
# #=> "q=ruby&lang=en"
# URI.encode_www_form("q" => ["ruby", "perl"], "lang" => "en")
# #=> "q=ruby&q=perl&lang=en"
# URI.encode_www_form([["q", "ruby"], ["q", "perl"], ["lang", "en"]])
# #=> "q=ruby&q=perl&lang=en"
#
# See URI.encode_www_form_component, URI.decode_www_form
def self.encode_www_form(enum)
enum.map do |k, v|
if v.nil?
encode_www_form_component(k)
elsif v.respond_to?(:to_ary)
v.to_ary.map do |w|
next unless w
str = encode_www_form_component(k)
str << '='
str << encode_www_form_component(w)
end.join('&')
else
str = encode_www_form_component(k)
str << '='
str << encode_www_form_component(v)
end
end.join('&')
end
WFKV_ = '(?:[^%#=;&]*(?:%\h\h[^%#=;&]*)*)' # :nodoc:
# Decode URL-encoded form data from given +str+.
#
# This decodes application/x-www-form-urlencoded data
# and returns array of key-value array.
# This internally uses URI.decode_www_form_component.
#
# _charset_ hack is not supported now because the mapping from given charset
# to Ruby's encoding is not clear yet.
# see also http://www.w3.org/TR/html5/syntax.html#character-encodings-0
#
# This refers http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
#
# ary = URI.decode_www_form("a=1&a=2&b=3")
# p ary #=> [['a', '1'], ['a', '2'], ['b', '3']]
# p ary.assoc('a').last #=> '1'
# p ary.assoc('b').last #=> '3'
# p ary.rassoc('a').last #=> '2'
# p Hash[ary] # => {"a"=>"2", "b"=>"3"}
#
# See URI.decode_www_form_component, URI.encode_www_form
def self.decode_www_form(str)
return [] if str.empty?
unless /\A#{WFKV_}=#{WFKV_}(?:[;&]#{WFKV_}=#{WFKV_})*\z/o =~ str
fail(ArgumentError, "invalid data of application/x-www-form-urlencoded (#{str})")
end
ary = []
$&.scan(/([^=;&]+)=([^;&]*)/) do
ary << [decode_www_form_component(Regexp.last_match[1]), decode_www_form_component(Regexp.last_match[2])]
end
ary
end
end