url_escape 2009.06.24

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile "ext/url_escape"
@@ -0,0 +1,47 @@
1
+ # Copyright © 2009 Evan Phoenix and The Rubyists, LLC
2
+ # Distributed under the terms of the MIT license.
3
+ # See the LICENSE file which accompanies this software for the full text
4
+ require File.expand_path("../helper", __FILE__)
5
+ require 'benchmark'
6
+ require 'rack'
7
+ require 'cgi'
8
+
9
+
10
+ describe "URLEscape benchmark" do
11
+ def benchit(obj, meth, s = nil)
12
+ n = 100
13
+ s ||= "%03a" * 10000
14
+ bm = Benchmark.bmbm { |b|
15
+ b.report("#{obj.name}::#{meth}") { n.times{ obj.send(meth, s) } }
16
+ }
17
+ end
18
+
19
+ def multiplier
20
+ /java/i === RUBY_PLATFORM ? [4,2] : [25,15]
21
+ end
22
+
23
+ it "runs faster than standard CGI.unescape" do
24
+ one = benchit(URLEscape, :unescape).first
25
+ two = benchit(CGI, :unescape).first
26
+ two.real.should > multiplier.first * one.real
27
+ end
28
+
29
+ it "runs faster than Rack::Utils.unescape" do
30
+ one = benchit(URLEscape, :unescape).first
31
+ two = benchit(Rack::Utils, :unescape).first
32
+ two.real.should > multiplier.first * one.real
33
+ end
34
+
35
+ it "runs faster than standard CGI.escape" do
36
+ one = benchit(URLEscape, :escape).first
37
+ two = benchit(CGI, :escape).first
38
+ two.real.should > multiplier.last * one.real
39
+ end
40
+
41
+ it "runs faster than Rack::Utils.escape" do
42
+ one = benchit(URLEscape, :escape).first
43
+ two = benchit(Rack::Utils, :escape).first
44
+ two.real.should > multiplier.last * one.real
45
+ end
46
+
47
+ end
@@ -0,0 +1,76 @@
1
+ # Copyright © 2009 Evan Phoenix and The Rubyists, LLC
2
+ # Distributed under the terms of the MIT license.
3
+ # See the LICENSE file which accompanies this software for the full text
4
+ require File.expand_path("../helper", __FILE__)
5
+ require 'benchmark'
6
+ require 'rack'
7
+ require 'cgi'
8
+
9
+ describe "Long running benchmarks" do
10
+ def benchit(obj, meth, s)
11
+ n = 100
12
+ s = s * 10000
13
+ bm = Benchmark.bmbm { |b|
14
+ b.report("#{obj.name}::#{meth}") { n.times{ obj.send(meth, s) } }
15
+ }
16
+ end
17
+
18
+ def multiplier
19
+ /java/i === RUBY_PLATFORM ? [3,2] : [7,4]
20
+ end
21
+
22
+ it "is efficient on larger encoded sets" do
23
+ hex_table = [
24
+ "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
25
+ "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f",
26
+ "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
27
+ "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f",
28
+ "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27",
29
+ "%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f",
30
+ "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37",
31
+ "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f",
32
+ "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47",
33
+ "%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f",
34
+ "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57",
35
+ "%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f",
36
+ "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67",
37
+ "%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f",
38
+ "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77",
39
+ "%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f",
40
+ "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",
41
+ "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f",
42
+ "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",
43
+ "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f",
44
+ "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
45
+ "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af",
46
+ "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7",
47
+ "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf",
48
+ "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7",
49
+ "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf",
50
+ "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
51
+ "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df",
52
+ "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7",
53
+ "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef",
54
+ "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
55
+ "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff"
56
+ ]
57
+
58
+ s = URLEscape.unescape(hex_table.join)
59
+ one = benchit(URLEscape, :escape, s).first
60
+ two = benchit(Rack::Utils, :escape, s).first
61
+ two.real.should > multiplier.first * one.real
62
+
63
+ three = benchit(CGI, :escape, s).first
64
+ three.real.should > multiplier.first * one.real
65
+
66
+ s = hex_table.join
67
+ one = benchit(URLEscape, :unescape, s).first
68
+ two = benchit(Rack::Utils, :unescape, s).first
69
+ two.real.should > multiplier.last * one.real
70
+
71
+ three = benchit(CGI, :unescape, s).first
72
+ three.real.should > multiplier.last * one.real
73
+ end
74
+ end
75
+
76
+
@@ -0,0 +1,21 @@
1
+ # Copyright © 2009 Evan Phoenix and The Rubyists, LLC
2
+ # Distributed under the terms of the MIT license.
3
+ # See the LICENSE file which accompanies this software for the full text
4
+ require 'rbconfig'
5
+
6
+ unless RUBY_PLATFORM.match(/java/)
7
+ ext = File.expand_path("../../ext", __FILE__)
8
+ exec_format = RbConfig::CONFIG['ruby_install_name'].sub(/^ruby.*$/, '%s') rescue '%s'
9
+
10
+ system(exec_format % 'rake', 'build')
11
+
12
+ require File.join(ext, "url_escape")
13
+ else
14
+ lib = File.expand_path("../../lib", __FILE__)
15
+ require File.join(lib, "url_escape")
16
+ end
17
+
18
+ require "rubygems"
19
+ require "bacon"
20
+
21
+ Bacon.summary_at_exit
@@ -0,0 +1,108 @@
1
+ # * Encoding: UTF-8
2
+ # Copyright © 2009 Evan Phoenix and The Rubyists, LLC
3
+ # Distributed under the terms of the MIT license.
4
+ # See the LICENSE file which accompanies this software for the full text
5
+
6
+ require File.expand_path("../helper", __FILE__)
7
+ require "rack"
8
+ require "cgi"
9
+
10
+ describe "URLEscape" do
11
+ describe '#escape' do
12
+ def escape(input)
13
+ URLEscape.escape input
14
+ end
15
+
16
+ it "should escape a standard ascii string" do
17
+ s = "A standard ascii string."
18
+ escape(s).should == Rack::Utils.escape(s) # This should have spaces escaped
19
+ escape(s).should == CGI.escape(s) # This should have spaces escaped
20
+ escape(s).should == 'A+standard+ascii+string.' # This should have spaces escaped
21
+ s1 = 'a & b'
22
+ escape(s1).should == Rack::Utils.escape(s1) # This should have spaces escaped and the amp encoded
23
+ escape(s1).should == CGI.escape(s1) # This should have spaces escaped and the amp encoded
24
+ escape(s1).should == 'a+%26+b' # This should have spaces escaped and the amp encoded
25
+ end
26
+
27
+ it "should escape a very hairy ascii string" do
28
+ s = %q{oi&%$#@!;laksdf\"';:<>?\\}
29
+ escape(s).should == "oi%26%25%24%23%40%21%3Blaksdf%5C%22%27%3B%3A%3C%3E%3F%5C" # This should have lots of escapes
30
+ escape(s).should == CGI.escape(s)
31
+ escape(s).should == Rack::Utils.escape(s)
32
+ end
33
+
34
+ it 'escapes an escaped uri fragment' do
35
+ escape(s = "%C3%87").should == '%25C3%2587'
36
+ escape(s).should == CGI.escape(s)
37
+ escape(s).should == Rack::Utils.escape(s)
38
+ end
39
+
40
+ it 'escapes unicode' do
41
+ escape(s = 'ルビイスと').should == '%E3%83%AB%E3%83%93%E3%82%A4%E3%82%B9%E3%81%A8'
42
+ escape(s).should == CGI.escape(s)
43
+ escape(s).should == Rack::Utils.escape(s) unless /^1\.9/ === RUBY_VERSION
44
+ end
45
+
46
+ it 'escapes mixed ascii and unicode' do
47
+ escape(s = "oidfu㈤").should == "oidfu%E3%88%A4"
48
+ escape(s).should == CGI.escape(s)
49
+ escape(s).should == Rack::Utils.escape(s) unless /^1\.9/ === RUBY_VERSION
50
+ end
51
+
52
+ it 'handles high bit ascii strings' do
53
+ s = "\xA1oidfu\xB5"
54
+ if /java/i === RUBY_PLATFORM
55
+ escape(s).should == "%EF%BF%BDoidfu%EF%BF%BD"
56
+ else
57
+ escape(s).should == CGI.escape(s) unless /^1\.9/ === RUBY_VERSION
58
+ escape(s).should == Rack::Utils.escape(s) unless /^1\.9/ === RUBY_VERSION
59
+ escape(s).should == "%A1oidfu%B5"
60
+ end
61
+ end
62
+
63
+ it 'treats strings ending in a unicode starting byte as high bit ascii' do
64
+ s = "oidfu\xD5"
65
+ s1 = "\xE1\xB1"
66
+ if /java/i === RUBY_PLATFORM
67
+ escape(s).should == "oidfu%EF%BF%BD"
68
+ escape(s1).should == "%EF%BF%BD"
69
+ else
70
+ escape(s).should == CGI.escape(s) unless /^1\.9/ === RUBY_VERSION
71
+ escape(s).should == Rack::Utils.escape(s) unless /^1\.9/ === RUBY_VERSION
72
+ escape(s).should == "oidfu%D5"
73
+
74
+ escape(s1).should == CGI.escape(s1) unless /^1\.9/ === RUBY_VERSION
75
+ escape(s1).should == Rack::Utils.escape(s1) unless /^1\.9/ === RUBY_VERSION
76
+ escape(s1).should == "%E1%B1"
77
+ end
78
+ end
79
+ end
80
+
81
+ describe '#unescape' do
82
+ def unescape(input)
83
+ URLEscape.unescape input
84
+ end
85
+
86
+ it "should unescape a url" do
87
+ s = "http://a.simple.url/foo_bar.php?hey=you%20me"
88
+ unescape(s).should == "http://a.simple.url/foo_bar.php?hey=you me" # This should have spaces expanded
89
+ unescape(s).should == CGI.unescape(s)
90
+ unescape(s).should == Rack::Utils.unescape(s)
91
+ end
92
+
93
+ it 'should unescape unicode' do
94
+ s = 'ルビイスと'
95
+ if s.respond_to?(:force_encoding)
96
+ unescape('%E3%83%AB%E3%83%93%E3%82%A4%E3%82%B9%E3%81%A8').
97
+ should == s.force_encoding("ASCII-8BIT")
98
+ unescape(s).should == CGI.unescape(s)
99
+ unescape(s).should == Rack::Utils.unescape(s)
100
+ else
101
+ unescape('%E3%83%AB%E3%83%93%E3%82%A4%E3%82%B9%E3%81%A8').
102
+ should == s
103
+ unescape(s).should == CGI.unescape(s)
104
+ unescape(s).should == Rack::Utils.unescape(s)
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,33 @@
1
+ # Once git has a fix for the glibc in handling .mailmap and another fix for
2
+ # allowing empty mail address to be mapped in .mailmap we won't have to handle
3
+ # them manually.
4
+
5
+ desc 'Update AUTHORS'
6
+ task :authors do
7
+ authors = Hash.new(0)
8
+
9
+ `git shortlog -nse`.scan(/(\d+)\s(.+)\s<(.*)>$/) do |count, name, email|
10
+ # Examples of mappping, replace with your own or comment this out/delete it
11
+ case name
12
+ when /^(?:bougyman$|TJ Vanderpoel)/
13
+ name, email = "TJ Vanderpoel", "tj@rubyists.com"
14
+ when /^(?:manveru$|Michael Fellinger)/
15
+ name, email = "Michael Fellinger", "mf@rubyists.com"
16
+ when /^(?:deathsyn$|Kevin Berry)/
17
+ name, email = "Kevin Berry", "kb@rubyists.com"
18
+ when /^(?:Admin)/
19
+ name, email = "Trey Dempsey", "trey.dempsey@gmail.com"
20
+ end
21
+
22
+ authors[[name, email]] += count.to_i
23
+ end
24
+
25
+ File.open('AUTHORS', 'w+') do |io|
26
+ io.puts "Following persons have contributed to #{GEMSPEC.name}."
27
+ io.puts '(Sorted by number of submitted patches, then alphabetically)'
28
+ io.puts ''
29
+ authors.sort_by{|(n,e),c| [-c, n.downcase] }.each do |(name, email), count|
30
+ io.puts("%6d %s <%s>" % [count, name, email])
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,77 @@
1
+ desc 'Run all bacon specs with pretty output'
2
+ task :bacon => :setup do
3
+ require 'open3'
4
+ require 'scanf'
5
+ require 'matrix'
6
+
7
+ specs = PROJECT_SPECS
8
+
9
+ some_failed = false
10
+ specs_size = specs.size
11
+ if specs.size == 0
12
+ $stderr.puts "You have no specs! Put a spec in spec/ before running this task"
13
+ exit 1
14
+ end
15
+ len = specs.map{|s| s.size }.sort.last
16
+ total_tests = total_assertions = total_failures = total_errors = 0
17
+ totals = Vector[0, 0, 0, 0]
18
+
19
+ red, yellow, green = "\e[31m%s\e[0m", "\e[33m%s\e[0m", "\e[32m%s\e[0m"
20
+ left_format = "%4d/%d: %-#{len + 11}s"
21
+ spec_format = "%d specifications (%d requirements), %d failures, %d errors"
22
+
23
+ $stderr.puts "Executing on windows. Colors won't work and errors won't be separated.\n" if(RUBY_PLATFORM.match(/mswin/))
24
+
25
+ specs.each_with_index do |spec, idx|
26
+ print(left_format % [idx + 1, specs_size, spec])
27
+
28
+ if(RUBY_PLATFORM.match(/mswin/))
29
+ running_spec = IO.popen("#{RUBY} #{spec}")
30
+ out = running_spec.read.strip
31
+ err = ""
32
+ else
33
+ sin, sout, serr = Open3.popen3(RUBY, spec)
34
+ out = sout.read.strip
35
+ err = serr.read.strip
36
+ end
37
+
38
+ # this is conventional, see spec/innate/state/fiber.rb for usage
39
+ if out =~ /^Bacon::Error: (needed .*)/
40
+ puts(yellow % ("%6s %s" % ['', $1]))
41
+ else
42
+ total = nil
43
+
44
+ out.each_line do |line|
45
+ scanned = line.scanf(spec_format)
46
+
47
+ next unless scanned.size == 4
48
+
49
+ total = Vector[*scanned]
50
+ break
51
+ end
52
+
53
+ if total
54
+ totals += total
55
+ tests, assertions, failures, errors = total_array = total.to_a
56
+
57
+ if tests > 0 && failures + errors == 0
58
+ puts((green % "%6d passed") % tests)
59
+ else
60
+ some_failed = true
61
+ puts(red % " failed")
62
+ puts out unless out.empty?
63
+ puts err unless err.empty?
64
+ end
65
+ else
66
+ some_failed = true
67
+ puts(red % " failed")
68
+ puts out unless out.empty?
69
+ puts err unless err.empty?
70
+ end
71
+ end
72
+ end
73
+
74
+ total_color = some_failed ? red : green
75
+ puts(total_color % (spec_format % totals.to_a))
76
+ exit 1 if some_failed
77
+ end
@@ -0,0 +1,56 @@
1
+ require 'rbconfig'
2
+
3
+ task :build do
4
+ if(RUBY_PLATFORM.match(/mswin/))
5
+ build_mswin
6
+ else
7
+ build_unix
8
+ end
9
+ end
10
+
11
+ def build_unix
12
+ Dir.chdir 'ext' do
13
+ sh 'make distclean' rescue nil
14
+ ruby 'extconf.rb'
15
+ sh 'make'
16
+ end
17
+ end
18
+
19
+ def build_mswin
20
+ mswin_gotchas
21
+ Dir.chdir 'ext' do
22
+ sh 'nmake distclean' rescue nil
23
+ File.unlink('url_escape.so.manifest') rescue nil
24
+ ruby 'extconf.rb'
25
+ sh 'nmake'
26
+ sh 'mt -manifest url_escape.so.manifest -outputresource:url_escape.so;#2'
27
+ end
28
+ end
29
+
30
+ def mswin_gotchas
31
+ if(ENV['VCINSTALLDIR'].nil?)
32
+ puts "\nWARNING: Your development environment may not be correctly configured. Run vcvars32 first to setup the environment\n\n"
33
+ sleep 5
34
+ end
35
+
36
+ config_h = [
37
+ File.join(RbConfig::CONFIG["archdir"], "config.h"),
38
+ File.join(RbConfig::CONFIG["rubyhdrdir"], RbConfig::CONFIG["arch"], "ruby", "config.h")
39
+ ].detect { |file| File.exists?(file) }
40
+
41
+ if(config_h)
42
+ File.open(config_h, "r") do |f|
43
+ f.each do |l|
44
+ if(l.match(/_MSC_VER/))
45
+ puts "\nWARNING: Windows Ruby config.h checks for Microsoft VC 6.0. Remove the following lines to allow compiling on later editions."
46
+ puts "Remove #if _MSC_VER != 1200"
47
+ puts " #error MSC version unmatch"
48
+ puts " #endif"
49
+ puts "From #{config_h}\n\n"
50
+ sleep 5
51
+ break
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,18 @@
1
+ desc 'update changelog'
2
+ task :changelog do
3
+ File.open('CHANGELOG', 'w+') do |changelog|
4
+ `git log -z --abbrev-commit`.split("\0").each do |commit|
5
+ next if commit =~ /^Merge: \d*/
6
+ ref, author, time, _, title, _, message = commit.split("\n", 7)
7
+ ref = ref[/commit ([0-9a-f]+)/, 1]
8
+ author = author[/Author: (.*)/, 1].strip
9
+ time = Time.parse(time[/Date: (.*)/, 1]).utc
10
+ title.strip!
11
+
12
+ changelog.puts "[#{ref} | #{time}] #{author}"
13
+ changelog.puts '', " * #{title}"
14
+ changelog.puts '', message.rstrip if message
15
+ changelog.puts
16
+ end
17
+ end
18
+ end