* add uri encoding as a text modifier

* add multibyte hex encoding.  useful for %u


git-svn-id: file:///home/svn/incoming/trunk@3544 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
bmc 2006-02-27 19:51:17 +00:00
parent 940ad36f22
commit 64c7a2063f
2 changed files with 56 additions and 9 deletions

View File

@ -110,8 +110,14 @@ module Text
#
# Returns the hex version of the supplied string
#
def self.to_hex(str, prefix = "\\x")
return str.gsub(/./) { |s| prefix + s.unpack('H*')[0] }
def self.to_hex(str, prefix = "\\x", count = 1)
raise RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
# XXX: Regexp.new is used here since using /.{#{count}}/o would compile
# the regex the first time it is used and never check again. Since we
# want to know how many to capture on every instance, we do it this
# way.
return str.gsub(Regexp.new(".{#{count}}")) { |s| prefix + s.unpack('H*')[0] }
end
#
@ -257,7 +263,30 @@ module Text
raise TypeError, 'invalid utf type'
end
end
#
# Encode a string in a manor useful for HTTP URIs and URI Parameters.
#
def self.uri_encode(str, mode = 'hex-normal')
return str if mode == 'none' # fast track no encoding
all = /[^\/\\]+/
normal = /[^a-zA-Z1-9]+/
case mode
when 'hex-normal'
return str.gsub(normal) { |s| Rex::Text.to_hex(s, '%') }
when 'hex-all'
return str.gsub(all) { |s| Rex::Text.to_hex(s, '%') }
when 'u-normal'
return str.gsub(normal) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
when 'u-all'
return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
else
raise TypeError, 'invalid mode'
end
end
#
# Converts a hex string to a raw string
#

View File

@ -7,6 +7,19 @@ require 'rex/text'
class Rex::Text::UnitTest < Test::Unit::TestCase
def test_uri_encode
srand(0)
assert_equal('A1%21', Rex::Text.uri_encode('A1!'), 'uri encode')
assert_equal('A1%21', Rex::Text.uri_encode('A1!', 'hex-normal'), 'uri encode: hex-normal')
assert_equal('%41%31%21', Rex::Text.uri_encode('A1!', 'hex-all'), 'uri encode: hex-all')
assert_equal('A1%u01c3', Rex::Text.uri_encode('A1!', 'u-normal'), 'uri encode: u-normal')
assert_equal('%uff21%u2081%uff01', Rex::Text.uri_encode('A1!', 'u-all'), 'uri encode: u-all')
assert_raises(TypeError) {
Rex::Text.uri_encode('a', 'umpa lumpa')
}
end
def test_rand_text
srand(0)
assert_equal("\254/u\300C\373\303g\t\323", Rex::Text.rand_text(10), 'rand text 1')
@ -95,13 +108,18 @@ class Rex::Text::UnitTest < Test::Unit::TestCase
end
def test_hexify
str = "\x01\x02\xff"
str = "\x01\x02\xff\x00"
assert_equal("\\x01\\x02\\xff", Rex::Text.to_hex(str), 'to_hex')
assert_equal("ABC01ABC02ABCff", Rex::Text.to_hex(str, 'ABC'), 'to_hex with prefix')
assert_equal("\"\\x01\\x02\\xff\"\n", Rex::Text.to_ruby(str), 'to_ruby')
assert_equal("\"\\x01\\x02\\xff\";\n", Rex::Text.to_perl(str), 'to_perl')
assert_equal("unsigned char buf[] = \n\"\\x01\\x02\\xff\";\n", Rex::Text.to_c(str), 'to_c')
assert_equal("\\x01\\x02\\xff\\x00", Rex::Text.to_hex(str), 'to_hex')
assert_equal("ABC01ABC02ABCffABC00", Rex::Text.to_hex(str, 'ABC'), 'to_hex with prefix')
assert_equal('%u0102%uff00', Rex::Text.to_hex(str, '%u', 2), 'to_hex with chunk size of 2')
# to_hex, without providing enouigh data to chunk on a given size
assert_raises(RuntimeError){ Rex::Text.to_hex('a', '', 2) }
assert_equal("\"\\x01\\x02\\xff\\x00\"\n", Rex::Text.to_ruby(str), 'to_ruby')
assert_equal("\"\\x01\\x02\\xff\\x00\";\n", Rex::Text.to_perl(str), 'to_perl')
assert_equal("unsigned char buf[] = \n\"\\x01\\x02\\xff\\x00\";\n", Rex::Text.to_c(str), 'to_c')
# 0 -> 20
str = "\000\001\002\003\004\005\006\a\010\t\n\v\f\r\016\017\020\021\022\023"