escape_utils 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a15665f9653635141dfb582e5748299d6f31359f
4
- data.tar.gz: 8ed831486f3292a3dd31f20e2b460218bf50cfe5
3
+ metadata.gz: a359a0da23b56ac37301e4ae73060dcfc4870d14
4
+ data.tar.gz: 2a3c9ed36204fc638605f012c3ca5a87ccc756b3
5
5
  SHA512:
6
- metadata.gz: 587f6c30123a5478c3d1775b305cca518342e1d7b1ed0e882a6aeb225e1858812e4d0107b5b00ae8bd3f78a27ecf729217a02660ae58a099d044b634a64d05ec
7
- data.tar.gz: 1dc21ebae6acdef6bacea70b303ed8fc251c5ba479b729ad2bb2670396a9a423342fe136fc255d7fe4f8bb808ef4fa4baebb8962db9abd5f5323bd585372bdfa
6
+ metadata.gz: f862189c73f7858184a61a0e2ae78b2d344ac162022bd41ec77eb18eba6ae52a62e188d29b2b7ed2931ae47a4d6a33b2f8d6ecf82ef85e46ce1457e016897403
7
+ data.tar.gz: 8f4a4643def62dfd8fdb27d9d631aa452bca3e63e1672a70bcf95594f98040ccee00276d6c0abd8e90c11126b7932b6e0efcce9e7d0b2881523b6faed62cad1b
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Brian Lopez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,9 +1,8 @@
1
1
  # encoding: utf-8
2
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
2
 
5
3
  require 'rubygems'
6
- require 'benchmark'
4
+ require 'bundler/setup'
5
+ require 'benchmark/ips'
7
6
 
8
7
  require 'rack'
9
8
  require 'erb'
@@ -16,53 +15,54 @@ module HamlBench
16
15
  extend Haml::Helpers
17
16
  end
18
17
 
19
- times = 100
20
18
  url = "http://en.wikipedia.org/wiki/Line_of_succession_to_the_British_throne"
21
19
  html = `curl -s #{url}`
22
20
  html = html.force_encoding('utf-8') if html.respond_to?(:force_encoding)
23
- puts "Escaping #{html.bytesize} bytes of html #{times} times, from #{url}"
21
+ puts "Escaping #{html.bytesize} bytes of html from #{url}"
24
22
 
25
- Benchmark.bmbm do |x|
26
- x.report "Rack::Utils.escape_html" do
23
+ Benchmark.ips do |x|
24
+ x.report "Rack::Utils.escape_html" do |times|
27
25
  times.times do
28
26
  Rack::Utils.escape_html(html)
29
27
  end
30
28
  end
31
29
 
32
- x.report "Haml::Helpers.html_escape" do
30
+ x.report "Haml::Helpers.html_escape" do |times|
33
31
  times.times do
34
32
  HamlBench.html_escape(html)
35
33
  end
36
34
  end
37
35
 
38
- x.report "ERB::Util.html_escape" do
36
+ x.report "ERB::Util.html_escape" do |times|
39
37
  times.times do
40
38
  ERB::Util.html_escape(html)
41
39
  end
42
40
  end
43
41
 
44
- x.report "CGI.escapeHTML" do
42
+ x.report "CGI.escapeHTML" do |times|
45
43
  times.times do
46
44
  CGI.escapeHTML(html)
47
45
  end
48
46
  end
49
47
 
50
- x.report "String#gsub" do
48
+ x.report "String#gsub" do |times|
51
49
  html_escape = { '&' => '&amp;', '>' => '&gt;', '<' => '&lt;', '"' => '&quot;', "'" => '&#39;' }
52
50
  times.times do
53
51
  html.gsub(/[&"'><]/, html_escape)
54
52
  end
55
53
  end
56
54
 
57
- x.report "fast_xs_extra#fast_xs_html" do
55
+ x.report "fast_xs_extra#fast_xs_html" do |times|
58
56
  times.times do
59
57
  html.fast_xs_html
60
58
  end
61
59
  end
62
60
 
63
- x.report "EscapeUtils.escape_html" do
61
+ x.report "EscapeUtils.escape_html" do |times|
64
62
  times.times do
65
63
  EscapeUtils.escape_html(html)
66
64
  end
67
65
  end
66
+
67
+ x.compare!
68
68
  end
@@ -1,9 +1,8 @@
1
1
  # encoding: utf-8
2
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
2
 
5
3
  require 'rubygems'
6
- require 'benchmark'
4
+ require 'bundler/setup'
5
+ require 'benchmark/ips'
7
6
 
8
7
  require 'cgi'
9
8
  require 'haml'
@@ -13,23 +12,24 @@ module HamlBench
13
12
  extend Haml::Helpers
14
13
  end
15
14
 
16
- times = 100
17
15
  url = "http://en.wikipedia.org/wiki/Line_of_succession_to_the_British_throne"
18
16
  html = `curl -s #{url}`
19
17
  html = html.force_encoding('binary') if html.respond_to?(:force_encoding)
20
18
  escaped_html = EscapeUtils.escape_html(html)
21
- puts "Unescaping #{escaped_html.bytesize} bytes of escaped html #{times} times, from #{url}"
19
+ puts "Unescaping #{escaped_html.bytesize} bytes of escaped html, from #{url}"
22
20
 
23
- Benchmark.bmbm do |x|
24
- x.report "CGI.unescapeHTML" do
21
+ Benchmark.ips do |x|
22
+ x.report "CGI.unescapeHTML" do |times|
25
23
  times.times do
26
24
  CGI.unescapeHTML(escaped_html)
27
25
  end
28
26
  end
29
27
 
30
- x.report "EscapeUtils.unescape_html" do
28
+ x.report "EscapeUtils.unescape_html" do |times|
31
29
  times.times do
32
30
  EscapeUtils.unescape_html(escaped_html)
33
31
  end
34
32
  end
35
- end
33
+
34
+ x.compare!
35
+ end
@@ -1,9 +1,8 @@
1
1
  # encoding: utf-8
2
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
2
 
5
3
  require 'rubygems'
6
- require 'benchmark'
4
+ require 'bundler/setup'
5
+ require 'benchmark/ips'
7
6
 
8
7
  require 'action_view'
9
8
  require 'escape_utils'
@@ -12,22 +11,23 @@ class ActionPackBench
12
11
  extend ActionView::Helpers::JavaScriptHelper
13
12
  end
14
13
 
15
- times = 100
16
14
  url = "http://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dojo/dojo.xd.js.uncompressed.js"
17
15
  javascript = `curl -s #{url}`
18
16
  javascript = javascript.force_encoding('utf-8') if javascript.respond_to?(:force_encoding)
19
- puts "Escaping #{javascript.bytesize} bytes of javascript #{times} times, from #{url}"
17
+ puts "Escaping #{javascript.bytesize} bytes of javascript, from #{url}"
20
18
 
21
- Benchmark.bmbm do |x|
22
- x.report "ActionView::Helpers::JavaScriptHelper#escape_javascript" do
19
+ Benchmark.ips do |x|
20
+ x.report "ActionView::Helpers::JavaScriptHelper#escape_javascript" do |times|
23
21
  times.times do
24
22
  ActionPackBench.escape_javascript(javascript)
25
23
  end
26
24
  end
27
25
 
28
- x.report "EscapeUtils.escape_javascript" do
26
+ x.report "EscapeUtils.escape_javascript" do |times|
29
27
  times.times do
30
28
  EscapeUtils.escape_javascript(javascript)
31
29
  end
32
30
  end
33
- end
31
+
32
+ x.compare!
33
+ end
@@ -1,23 +1,21 @@
1
1
  # encoding: utf-8
2
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
2
 
5
3
  require 'rubygems'
6
- require 'benchmark'
4
+ require 'bundler/setup'
5
+ require 'benchmark/ips'
7
6
 
8
7
  require 'escape_utils'
9
8
 
10
- times = 100
11
9
  url = "http://ajax.googleapis.com/ajax/libs/dojo/1.4.3/dojo/dojo.xd.js.uncompressed.js"
12
10
  javascript = `curl -s #{url}`
13
11
  javascript = javascript.force_encoding('utf-8') if javascript.respond_to?(:force_encoding)
14
12
  escaped_javascript = EscapeUtils.escape_javascript(javascript)
15
- puts "Escaping #{escaped_javascript.bytesize} bytes of javascript #{times} times, from #{url}"
13
+ puts "Escaping #{escaped_javascript.bytesize} bytes of javascript, from #{url}"
16
14
 
17
- Benchmark.bmbm do |x|
18
- x.report "EscapeUtils.escape_javascript" do
15
+ Benchmark.ips do |x|
16
+ x.report "EscapeUtils.escape_javascript" do |times|
19
17
  times.times do
20
18
  EscapeUtils.unescape_javascript(escaped_javascript)
21
19
  end
22
20
  end
23
- end
21
+ end
@@ -1,9 +1,8 @@
1
1
  # encoding: utf-8
2
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
2
 
5
3
  require 'rubygems'
6
- require 'benchmark'
4
+ require 'bundler/setup'
5
+ require 'benchmark/ips'
7
6
 
8
7
  require 'rack'
9
8
  require 'erb'
@@ -12,45 +11,46 @@ require 'url_escape'
12
11
  require 'fast_xs_extra'
13
12
  require 'escape_utils'
14
13
 
15
- times = 10_000
16
14
  url = "https://www.yourmom.com/cgi-bin/session.cgi?sess_args=mYHcEA dh435dqUs0moGHeeAJTSLLbdbcbd9ef----,574b95600e9ab7d27eb0bf524ac68c27----"
17
15
  url = url.force_encoding('us-ascii') if url.respond_to?(:force_encoding)
18
- puts "Escaping a #{url.bytesize} byte URL #{times} times"
16
+ puts "Escaping a #{url.bytesize} byte URL times"
19
17
 
20
- Benchmark.bmbm do |x|
21
- x.report "ERB::Util.url_encode" do
18
+ Benchmark.ips do |x|
19
+ x.report "ERB::Util.url_encode" do |times|
22
20
  times.times do
23
21
  ERB::Util.url_encode(url)
24
22
  end
25
23
  end
26
24
 
27
- x.report "Rack::Utils.escape" do
25
+ x.report "Rack::Utils.escape" do |times|
28
26
  times.times do
29
27
  Rack::Utils.escape(url)
30
28
  end
31
29
  end
32
30
 
33
- x.report "CGI.escape" do
31
+ x.report "CGI.escape" do |times|
34
32
  times.times do
35
33
  CGI.escape(url)
36
34
  end
37
35
  end
38
36
 
39
- x.report "URLEscape#escape" do
37
+ x.report "URLEscape#escape" do |times|
40
38
  times.times do
41
39
  URLEscape.escape(url)
42
40
  end
43
41
  end
44
42
 
45
- x.report "fast_xs_extra#fast_xs_url" do
43
+ x.report "fast_xs_extra#fast_xs_url" do |times|
46
44
  times.times do
47
45
  url.fast_xs_url
48
46
  end
49
47
  end
50
48
 
51
- x.report "EscapeUtils.escape_url" do
49
+ x.report "EscapeUtils.escape_url" do |times|
52
50
  times.times do
53
51
  EscapeUtils.escape_url(url)
54
52
  end
55
53
  end
56
- end
54
+
55
+ x.compare!
56
+ end
@@ -1,9 +1,8 @@
1
1
  # encoding: utf-8
2
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
2
 
5
3
  require 'rubygems'
6
- require 'benchmark'
4
+ require 'bundler/setup'
5
+ require 'benchmark/ips'
7
6
 
8
7
  require 'rack'
9
8
  require 'cgi'
@@ -11,40 +10,41 @@ require 'url_escape'
11
10
  require 'fast_xs_extra'
12
11
  require 'escape_utils'
13
12
 
14
- times = 10_000
15
13
  url = "https://www.yourmom.com/cgi-bin/session.cgi?sess_args=mYHcEA dh435dqUs0moGHeeAJTSLLbdbcbd9ef----,574b95600e9ab7d27eb0bf524ac68c27----"
16
14
  url = url.force_encoding('us-ascii') if url.respond_to?(:force_encoding)
17
15
  escaped_url = EscapeUtils.escape_url(url)
18
- puts "Escaping a #{url.bytesize} byte URL #{times} times"
16
+ puts "Escaping a #{url.bytesize} byte URL"
19
17
 
20
- Benchmark.bmbm do |x|
21
- x.report "Rack::Utils.unescape" do
18
+ Benchmark.ips do |x|
19
+ x.report "Rack::Utils.unescape" do |times|
22
20
  times.times do
23
21
  Rack::Utils.unescape(escaped_url)
24
22
  end
25
23
  end
26
-
27
- x.report "CGI.unescape" do
24
+
25
+ x.report "CGI.unescape" do |times|
28
26
  times.times do
29
27
  CGI.unescape(escaped_url)
30
28
  end
31
29
  end
32
-
33
- x.report "URLEscape#unescape" do
30
+
31
+ x.report "URLEscape#unescape" do |times|
34
32
  times.times do
35
33
  URLEscape.unescape(escaped_url)
36
34
  end
37
35
  end
38
36
 
39
- x.report "fast_xs_extra#fast_uxs_cgi" do
37
+ x.report "fast_xs_extra#fast_uxs_cgi" do |times|
40
38
  times.times do
41
39
  url.fast_uxs_cgi
42
40
  end
43
41
  end
44
42
 
45
- x.report "EscapeUtils.unescape_url" do
43
+ x.report "EscapeUtils.unescape_url" do |times|
46
44
  times.times do
47
45
  EscapeUtils.unescape_url(escaped_url)
48
46
  end
49
47
  end
50
- end
48
+
49
+ x.compare!
50
+ end
@@ -1,29 +1,29 @@
1
1
  # encoding: utf-8
2
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
3
- $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
2
 
5
3
  require 'rubygems'
6
- require 'benchmark'
4
+ require 'bundler/setup'
5
+ require 'benchmark/ips'
7
6
 
8
- require 'builder'
7
+ require 'fast_xs'
9
8
  require 'escape_utils'
10
9
 
11
- times = 100
12
10
  url = "http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml"
13
11
  xml = `curl -s #{url}`
14
12
  xml = xml.force_encoding('binary') if xml.respond_to?(:force_encoding)
15
- puts "Escaping #{xml.bytesize} bytes of xml #{times} times, from #{url}"
13
+ puts "Escaping #{xml.bytesize} bytes of xml, from #{url}"
16
14
 
17
- Benchmark.bmbm do |x|
18
- x.report "Builder::String.to_xs" do
15
+ Benchmark.ips do |x|
16
+ x.report "fast_xs" do |times|
19
17
  times.times do
20
- xml.to_xs
18
+ xml.fast_xs
21
19
  end
22
20
  end
23
21
 
24
- x.report "EscapeUtils.escape_xml" do
22
+ x.report "EscapeUtils.escape_xml" do |times|
25
23
  times.times do
26
24
  EscapeUtils.escape_xml(xml)
27
25
  end
28
26
  end
27
+
28
+ x.compare!
29
29
  end
@@ -22,10 +22,10 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency 'rake-compiler', ">= 0.7.5"
23
23
  s.add_development_dependency 'minitest', ">= 5.0.0"
24
24
  # benchmarks
25
+ s.add_development_dependency 'benchmark-ips'
25
26
  s.add_development_dependency 'rack'
26
27
  s.add_development_dependency 'haml'
27
28
  s.add_development_dependency 'fast_xs'
28
29
  s.add_development_dependency 'actionpack'
29
30
  s.add_development_dependency 'url_escape'
30
31
  end
31
-
@@ -242,7 +242,7 @@ void gh_buf_attach(gh_buf *buf, char *ptr, size_t asize)
242
242
 
243
243
  int gh_buf_cmp(const gh_buf *a, const gh_buf *b)
244
244
  {
245
- int result = memcmp(a->ptr, b->ptr, (a->size < b->size) ? a->size : b->size);
245
+ int result = memcmp(a->ptr, b->ptr, MIN(a->size, b->size));
246
246
  return (result != 0) ? result :
247
247
  (a->size < b->size) ? -1 : (a->size > b->size) ? 1 : 0;
248
248
  }
@@ -202,6 +202,19 @@ static VALUE rb_eu_unescape_uri(VALUE self, VALUE str)
202
202
  return rb_eu__generic(str, &houdini_unescape_uri);
203
203
  }
204
204
 
205
+ /**
206
+ * URI component methods
207
+ */
208
+ static VALUE rb_eu_escape_uri_component(VALUE self, VALUE str)
209
+ {
210
+ return rb_eu__generic(str, &houdini_escape_uri_component);
211
+ }
212
+
213
+ static VALUE rb_eu_unescape_uri_component(VALUE self, VALUE str)
214
+ {
215
+ return rb_eu__generic(str, &houdini_unescape_uri_component);
216
+ }
217
+
205
218
 
206
219
  /**
207
220
  * Ruby Extension initializer
@@ -227,6 +240,8 @@ void Init_escape_utils()
227
240
  rb_define_method(rb_mEscapeUtils, "unescape_url", rb_eu_unescape_url, 1);
228
241
  rb_define_method(rb_mEscapeUtils, "escape_uri", rb_eu_escape_uri, 1);
229
242
  rb_define_method(rb_mEscapeUtils, "unescape_uri", rb_eu_unescape_uri, 1);
243
+ rb_define_method(rb_mEscapeUtils, "escape_uri_component", rb_eu_escape_uri_component, 1);
244
+ rb_define_method(rb_mEscapeUtils, "unescape_uri_component", rb_eu_unescape_uri_component, 1);
230
245
 
231
246
  rb_define_singleton_method(rb_mEscapeUtils, "html_secure=", rb_eu_set_html_secure, 1);
232
247
  rb_define_singleton_method(rb_mEscapeUtils, "html_safe_string_class=", rb_eu_set_html_safe_string_class, 1);
@@ -30,9 +30,11 @@ extern int houdini_escape_html0(gh_buf *ob, const uint8_t *src, size_t size, int
30
30
  extern int houdini_unescape_html(gh_buf *ob, const uint8_t *src, size_t size);
31
31
  extern int houdini_escape_xml(gh_buf *ob, const uint8_t *src, size_t size);
32
32
  extern int houdini_escape_uri(gh_buf *ob, const uint8_t *src, size_t size);
33
+ extern int houdini_escape_uri_component(gh_buf *ob, const uint8_t *src, size_t size);
33
34
  extern int houdini_escape_url(gh_buf *ob, const uint8_t *src, size_t size);
34
35
  extern int houdini_escape_href(gh_buf *ob, const uint8_t *src, size_t size);
35
36
  extern int houdini_unescape_uri(gh_buf *ob, const uint8_t *src, size_t size);
37
+ extern int houdini_unescape_uri_component(gh_buf *ob, const uint8_t *src, size_t size);
36
38
  extern int houdini_unescape_url(gh_buf *ob, const uint8_t *src, size_t size);
37
39
  extern int houdini_escape_js(gh_buf *ob, const uint8_t *src, size_t size);
38
40
  extern int houdini_unescape_js(gh_buf *ob, const uint8_t *src, size_t size);
@@ -57,7 +57,7 @@ unescape_ent(gh_buf *ob, const uint8_t *src, size_t size)
57
57
  codepoint = (codepoint * 16) + ((src[i] | 32) % 39 - 9);
58
58
  }
59
59
 
60
- if (i < size && src[i] == ';') {
60
+ if (i < size && src[i] == ';' && codepoint) {
61
61
  gh_buf_put_utf8(ob, codepoint);
62
62
  return i + 1;
63
63
  }
@@ -43,10 +43,10 @@ static const char URI_SAFE[] = {
43
43
  };
44
44
 
45
45
  static int
46
- escape(gh_buf *ob, const uint8_t *src, size_t size, int is_url)
46
+ escape(gh_buf *ob, const uint8_t *src, size_t size,
47
+ const char *safe_table, bool escape_plus)
47
48
  {
48
49
  static const uint8_t hex_chars[] = "0123456789ABCDEF";
49
- const char *safe_table = is_url ? URL_SAFE : URI_SAFE;
50
50
 
51
51
  size_t i = 0, org;
52
52
  uint8_t hex_str[3];
@@ -73,7 +73,7 @@ escape(gh_buf *ob, const uint8_t *src, size_t size, int is_url)
73
73
  if (i >= size)
74
74
  break;
75
75
 
76
- if (src[i] == ' ' && is_url) {
76
+ if (src[i] == ' ' && escape_plus) {
77
77
  gh_buf_putc(ob, '+');
78
78
  } else {
79
79
  hex_str[1] = hex_chars[(src[i] >> 4) & 0xF];
@@ -90,12 +90,18 @@ escape(gh_buf *ob, const uint8_t *src, size_t size, int is_url)
90
90
  int
91
91
  houdini_escape_uri(gh_buf *ob, const uint8_t *src, size_t size)
92
92
  {
93
- return escape(ob, src, size, 0);
93
+ return escape(ob, src, size, URI_SAFE, false);
94
+ }
95
+
96
+ int
97
+ houdini_escape_uri_component(gh_buf *ob, const uint8_t *src, size_t size)
98
+ {
99
+ return escape(ob, src, size, URL_SAFE, false);
94
100
  }
95
101
 
96
102
  int
97
103
  houdini_escape_url(gh_buf *ob, const uint8_t *src, size_t size)
98
104
  {
99
- return escape(ob, src, size, 1);
105
+ return escape(ob, src, size, URL_SAFE, true);
100
106
  }
101
107
 
@@ -7,18 +7,18 @@
7
7
  #define hex2c(c) ((c | 32) % 39 - 9)
8
8
 
9
9
  static int
10
- unescape(gh_buf *ob, const uint8_t *src, size_t size, int is_url)
10
+ unescape(gh_buf *ob, const uint8_t *src, size_t size, bool unescape_plus)
11
11
  {
12
12
  size_t i = 0, org;
13
13
 
14
14
  while (i < size) {
15
15
  org = i;
16
- while (i < size && src[i] != '%')
16
+ while (i < size && src[i] != '%' && src[i] != '+')
17
17
  i++;
18
18
 
19
19
  if (likely(i > org)) {
20
20
  if (unlikely(org == 0)) {
21
- if (i >= size && !is_url)
21
+ if (i >= size)
22
22
  return 0;
23
23
 
24
24
  gh_buf_grow(ob, HOUDINI_UNESCAPED_SIZE(size));
@@ -31,7 +31,10 @@ unescape(gh_buf *ob, const uint8_t *src, size_t size, int is_url)
31
31
  if (i >= size)
32
32
  break;
33
33
 
34
- i++;
34
+ if (src[i++] == '+') {
35
+ gh_buf_putc(ob, unescape_plus ? ' ' : '+');
36
+ continue;
37
+ }
35
38
 
36
39
  if (i + 1 < size && _isxdigit(src[i]) && _isxdigit(src[i + 1])) {
37
40
  unsigned char new_char = (hex2c(src[i]) << 4) + hex2c(src[i + 1]);
@@ -42,24 +45,24 @@ unescape(gh_buf *ob, const uint8_t *src, size_t size, int is_url)
42
45
  }
43
46
  }
44
47
 
45
- if (is_url) {
46
- char *find = (char *)gh_buf_cstr(ob);
47
- while ((find = strchr(find, '+')) != NULL)
48
- *find = ' ';
49
- }
50
-
51
48
  return 1;
52
49
  }
53
50
 
54
51
  int
55
52
  houdini_unescape_uri(gh_buf *ob, const uint8_t *src, size_t size)
56
53
  {
57
- return unescape(ob, src, size, 0);
54
+ return unescape(ob, src, size, false);
55
+ }
56
+
57
+ int
58
+ houdini_unescape_uri_component(gh_buf *ob, const uint8_t *src, size_t size)
59
+ {
60
+ return unescape(ob, src, size, false);
58
61
  }
59
62
 
60
63
  int
61
64
  houdini_unescape_url(gh_buf *ob, const uint8_t *src, size_t size)
62
65
  {
63
- return unescape(ob, src, size, 1);
66
+ return unescape(ob, src, size, true);
64
67
  }
65
68
 
@@ -1,3 +1,3 @@
1
1
  module EscapeUtils
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -25,6 +25,14 @@ class UriEscapeTest < Minitest::Test
25
25
  assert_equal '%E3%81%BE%E3%81%A4%20%E3%82%82%E3%81%A8', EscapeUtils.escape_uri(matz_name_sep)
26
26
  end
27
27
 
28
+ def test_uri_containing_pluses
29
+ assert_equal "a+plus", EscapeUtils.escape_uri("a+plus")
30
+ end
31
+
32
+ def test_uri_containing_slashes
33
+ assert_equal "a/slash", EscapeUtils.escape_uri("a/slash")
34
+ end
35
+
28
36
  if RUBY_VERSION =~ /^1.9/
29
37
  def test_input_must_be_utf8_or_ascii
30
38
  str = "fo<o>bar"
@@ -30,18 +30,29 @@ class UriUnescapeTest < Minitest::Test
30
30
  assert_equal matz_name_sep, EscapeUtils.unescape_uri('%E3%81%BE%E3%81%A4%20%E3%82%82%E3%81%A8')
31
31
  end
32
32
 
33
+ def test_uri_containing_pluses
34
+ assert_equal "a+plus", EscapeUtils.unescape_uri("a%2Bplus")
35
+ end
36
+
37
+ def test_escape_unescape_roundtrip
38
+ (0..127).each do |index|
39
+ char = index.chr
40
+ assert_equal char, EscapeUtils.unescape_uri(EscapeUtils.escape_uri(char))
41
+ end
42
+ end
43
+
33
44
  if RUBY_VERSION =~ /^1.9/
34
45
  def test_input_must_be_valid_utf8_or_ascii
35
46
  escaped = EscapeUtils.escape_uri("fo<o>bar")
36
47
 
37
48
  escaped.force_encoding 'ISO-8859-1'
38
49
  assert_raises Encoding::CompatibilityError do
39
- EscapeUtils.unescape_url(escaped)
50
+ EscapeUtils.unescape_uri(escaped)
40
51
  end
41
52
 
42
53
  escaped.force_encoding 'UTF-8'
43
54
  begin
44
- EscapeUtils.unescape_url(escaped)
55
+ EscapeUtils.unescape_uri(escaped)
45
56
  rescue Encoding::CompatibilityError => e
46
57
  assert_nil e, "#{e.class.name} raised, expected not to"
47
58
  end
@@ -49,7 +60,7 @@ class UriUnescapeTest < Minitest::Test
49
60
 
50
61
  def test_return_value_is_tagged_as_utf8
51
62
  escaped = EscapeUtils.escape_uri("a space")
52
- assert_equal Encoding.find('UTF-8'), EscapeUtils.unescape_url(escaped).encoding
63
+ assert_equal Encoding.find('UTF-8'), EscapeUtils.unescape_uri(escaped).encoding
53
64
  end
54
65
  end
55
66
  end
@@ -0,0 +1,68 @@
1
+ require File.expand_path("../../helper", __FILE__)
2
+ require 'cgi'
3
+
4
+ class UriComponentEscapeTest < Minitest::Test
5
+ def test_basic_url
6
+ assert_equal "http%3A%2F%2Fwww.homerun.com%2F", EscapeUtils.escape_uri_component("http://www.homerun.com/")
7
+ end
8
+
9
+ def test_cgi_equivalence
10
+ (0..127).each do |i|
11
+ c = i.chr
12
+ # Escaping URI path components should match CGI parameter escaping, except
13
+ # spaces should be escaped as "%20" instead of "+"
14
+ assert_equal CGI.escape(c).sub("+", "%20"), EscapeUtils.escape_uri_component(c)
15
+ end
16
+ end
17
+
18
+ def test_uri_component_containing_tags
19
+ assert_equal "fo%3Co%3Ebar", EscapeUtils.escape_uri_component("fo<o>bar")
20
+ end
21
+
22
+ def test_uri_component_containing_tags_containing_spaces
23
+ assert_equal "a%20space", EscapeUtils.escape_uri_component("a space")
24
+ assert_equal "a%20%20%20sp%20ace%20", EscapeUtils.escape_uri_component("a sp ace ")
25
+ end
26
+
27
+ def test_uri_component_containing_mixed_characters
28
+ assert_equal "q1%212%22%27w%245%267%2Fz8%29%3F%5C", EscapeUtils.escape_uri_component("q1!2\"'w$5&7/z8)?\\")
29
+ end
30
+
31
+ def test_multibyte_characters
32
+ matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8" # Matsumoto
33
+ assert_equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8', EscapeUtils.escape_uri_component(matz_name)
34
+ matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8" # Matsu moto
35
+ assert_equal '%E3%81%BE%E3%81%A4%20%E3%82%82%E3%81%A8', EscapeUtils.escape_uri_component(matz_name_sep)
36
+ end
37
+
38
+ def test_uri_component_containing_pluses
39
+ assert_equal "a%2Bplus", EscapeUtils.escape_uri_component("a+plus")
40
+ end
41
+
42
+ def test_uri_component_containing_slashes
43
+ assert_equal "a%2Fslash", EscapeUtils.escape_uri_component("a/slash")
44
+ end
45
+
46
+ if RUBY_VERSION =~ /^1.9/
47
+ def test_input_must_be_utf8_or_ascii
48
+ str = "fo<o>bar"
49
+
50
+ str.force_encoding 'ISO-8859-1'
51
+ assert_raises Encoding::CompatibilityError do
52
+ EscapeUtils.escape_uri_component(str)
53
+ end
54
+
55
+ str.force_encoding 'UTF-8'
56
+ begin
57
+ EscapeUtils.escape_uri_component(str)
58
+ rescue Encoding::CompatibilityError => e
59
+ assert_nil e, "#{e.class.name} raised, expected not to"
60
+ end
61
+ end
62
+
63
+ def test_return_value_is_tagged_as_utf8
64
+ str = "fo<o>bar"
65
+ assert_equal Encoding.find('UTF-8'), EscapeUtils.escape_uri_component(str).encoding
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,71 @@
1
+ require File.expand_path("../../helper", __FILE__)
2
+
3
+ class UriComponentUnescapeTest < Minitest::Test
4
+ def test_basic_url
5
+ assert_equal "http://www.homerun.com/", EscapeUtils.unescape_uri_component("http%3A%2F%2Fwww.homerun.com%2F")
6
+ assert_equal "http://www.homerun.com/", EscapeUtils.unescape_uri_component("http://www.homerun.com/")
7
+ end
8
+
9
+ def test_doesnt_unescape_an_incomplete_escape
10
+ assert_equal "%", EscapeUtils.unescape_uri_component("%")
11
+ assert_equal "http%", EscapeUtils.unescape_uri_component("http%")
12
+ end
13
+
14
+ def test_uri_component_containing_tags
15
+ assert_equal "fo<o>bar", EscapeUtils.unescape_uri_component("fo%3Co%3Ebar")
16
+ end
17
+
18
+ def test_uri_component_containing_spaces
19
+ assert_equal "a space", EscapeUtils.unescape_uri_component("a%20space")
20
+ assert_equal "a sp ace ", EscapeUtils.unescape_uri_component("a%20%20%20sp%20ace%20")
21
+ end
22
+
23
+ def test_uri_component_containing_pluses
24
+ assert_equal "a+plus", EscapeUtils.unescape_uri_component("a%2Bplus")
25
+ assert_equal "a+plus", EscapeUtils.unescape_uri_component("a+plus")
26
+ end
27
+
28
+ def test_escape_unescape_roundtrip
29
+ (0..127).each do |index|
30
+ char = index.chr
31
+ assert_equal char, EscapeUtils.unescape_uri_component(EscapeUtils.escape_uri_component(char))
32
+ end
33
+ end
34
+
35
+ def test_uri_component_containing_mixed_characters
36
+ assert_equal "q1!2\"'w$5&7/z8)?\\", EscapeUtils.unescape_uri_component("q1%212%22%27w%245%267%2Fz8%29%3F%5C")
37
+ assert_equal "q1!2\"'w$5&7/z8)?\\", EscapeUtils.unescape_uri_component("q1!2%22'w$5&7/z8)?%5C")
38
+ end
39
+
40
+ def test_multibyte_characters
41
+ matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8" # Matsumoto
42
+ matz_name.force_encoding('UTF-8') if matz_name.respond_to?(:force_encoding)
43
+ assert_equal matz_name, EscapeUtils.unescape_uri_component('%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8')
44
+ matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8" # Matsu moto
45
+ matz_name_sep.force_encoding('UTF-8') if matz_name_sep.respond_to?(:force_encoding)
46
+ assert_equal matz_name_sep, EscapeUtils.unescape_uri_component('%E3%81%BE%E3%81%A4%20%E3%82%82%E3%81%A8')
47
+ end
48
+
49
+ if RUBY_VERSION =~ /^1.9/
50
+ def test_input_must_be_valid_utf8_or_ascii
51
+ escaped = EscapeUtils.escape_uri_component("fo<o>bar")
52
+
53
+ escaped.force_encoding 'ISO-8859-1'
54
+ assert_raises Encoding::CompatibilityError do
55
+ EscapeUtils.unescape_uri_component(escaped)
56
+ end
57
+
58
+ escaped.force_encoding 'UTF-8'
59
+ begin
60
+ EscapeUtils.unescape_uri_component(escaped)
61
+ rescue Encoding::CompatibilityError => e
62
+ assert_nil e, "#{e.class.name} raised, expected not to"
63
+ end
64
+ end
65
+
66
+ def test_return_value_is_tagged_as_utf8
67
+ escaped = EscapeUtils.escape_uri_component("fo<o>bar")
68
+ assert_equal Encoding.find('UTF-8'), EscapeUtils.unescape_uri_component(escaped).encoding
69
+ end
70
+ end
71
+ end
@@ -1,7 +1,7 @@
1
1
  require File.expand_path("../../helper", __FILE__)
2
2
  require 'cgi'
3
3
 
4
- class UriEscapeTest < Minitest::Test
4
+ class UrlEscapeTest < Minitest::Test
5
5
  def test_basic_url
6
6
  assert_equal "http%3A%2F%2Fwww.homerun.com%2F", EscapeUtils.escape_url("http://www.homerun.com/")
7
7
  end
@@ -33,6 +33,14 @@ class UriEscapeTest < Minitest::Test
33
33
  assert_equal '%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8', EscapeUtils.escape_url(matz_name_sep)
34
34
  end
35
35
 
36
+ def test_url_containing_pluses
37
+ assert_equal "a%2Bplus", EscapeUtils.escape_url("a+plus")
38
+ end
39
+
40
+ def test_url_containing_slashes
41
+ assert_equal "a%2Fslash", EscapeUtils.escape_url("a/slash")
42
+ end
43
+
36
44
  if RUBY_VERSION =~ /^1.9/
37
45
  def test_input_must_be_utf8_or_ascii
38
46
  str = "fo<o>bar"
@@ -1,6 +1,6 @@
1
1
  require File.expand_path("../../helper", __FILE__)
2
2
 
3
- class UriUnescapeTest < Minitest::Test
3
+ class UrlUnescapeTest < Minitest::Test
4
4
  def test_basic_url
5
5
  assert_equal "http://www.homerun.com/", EscapeUtils.unescape_url("http%3A%2F%2Fwww.homerun.com%2F")
6
6
  assert_equal "http://www.homerun.com/", EscapeUtils.unescape_url("http://www.homerun.com/")
@@ -35,9 +35,20 @@ class UriUnescapeTest < Minitest::Test
35
35
  assert_equal matz_name_sep, EscapeUtils.unescape_url('%E3%81%BE%E3%81%A4%20%E3%82%82%E3%81%A8')
36
36
  end
37
37
 
38
+ def test_url_containing_pluses
39
+ assert_equal "a+plus", EscapeUtils.unescape_url("a%2Bplus")
40
+ end
41
+
42
+ def test_escape_unescape_roundtrip
43
+ (0..127).each do |index|
44
+ char = index.chr
45
+ assert_equal char, EscapeUtils.unescape_url(EscapeUtils.escape_url(char))
46
+ end
47
+ end
48
+
38
49
  if RUBY_VERSION =~ /^1.9/
39
50
  def test_input_must_be_valid_utf8_or_ascii
40
- escaped = EscapeUtils.escape_uri("fo<o>bar")
51
+ escaped = EscapeUtils.escape_url("fo<o>bar")
41
52
 
42
53
  escaped.force_encoding 'ISO-8859-1'
43
54
  assert_raises Encoding::CompatibilityError do
@@ -53,7 +64,7 @@ class UriUnescapeTest < Minitest::Test
53
64
  end
54
65
 
55
66
  def test_return_value_is_tagged_as_utf8
56
- escaped = EscapeUtils.escape_uri("fo<o>bar")
67
+ escaped = EscapeUtils.escape_url("fo<o>bar")
57
68
  assert_equal Encoding.find('UTF-8'), EscapeUtils.unescape_url(escaped).encoding
58
69
  end
59
70
  end
metadata CHANGED
@@ -1,111 +1,125 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: escape_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Lopez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-10 00:00:00.000000000 Z
11
+ date: 2015-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.7.5
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.7.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 5.0.0
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 5.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: benchmark-ips
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rack
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - '>='
59
+ - - ">="
46
60
  - !ruby/object:Gem::Version
47
61
  version: '0'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - '>='
66
+ - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: haml
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - '>='
73
+ - - ">="
60
74
  - !ruby/object:Gem::Version
61
75
  version: '0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - '>='
80
+ - - ">="
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: fast_xs
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - '>='
87
+ - - ">="
74
88
  - !ruby/object:Gem::Version
75
89
  version: '0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - '>='
94
+ - - ">="
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: actionpack
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - '>='
101
+ - - ">="
88
102
  - !ruby/object:Gem::Version
89
103
  version: '0'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
- - - '>='
108
+ - - ">="
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: url_escape
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
- - - '>='
115
+ - - ">="
102
116
  - !ruby/object:Gem::Version
103
117
  version: '0'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
- - - '>='
122
+ - - ">="
109
123
  - !ruby/object:Gem::Version
110
124
  version: '0'
111
125
  description: Quickly perform HTML, URL, URI and Javascript escaping/unescaping
@@ -115,10 +129,10 @@ extensions:
115
129
  - ext/escape_utils/extconf.rb
116
130
  extra_rdoc_files: []
117
131
  files:
118
- - .gitignore
119
- - .travis.yml
132
+ - ".gitignore"
133
+ - ".travis.yml"
120
134
  - Gemfile
121
- - MIT-LICENSE
135
+ - LICENSE
122
136
  - README.md
123
137
  - Rakefile
124
138
  - benchmark/html_escape.rb
@@ -167,6 +181,8 @@ files:
167
181
  - test/query/unescape_test.rb
168
182
  - test/uri/escape_test.rb
169
183
  - test/uri/unescape_test.rb
184
+ - test/uri_component/escape_test.rb
185
+ - test/uri_component/unescape_test.rb
170
186
  - test/url/escape_test.rb
171
187
  - test/url/unescape_test.rb
172
188
  - test/xml/escape_test.rb
@@ -176,22 +192,22 @@ licenses:
176
192
  metadata: {}
177
193
  post_install_message:
178
194
  rdoc_options:
179
- - --charset=UTF-8
195
+ - "--charset=UTF-8"
180
196
  require_paths:
181
197
  - lib
182
198
  required_ruby_version: !ruby/object:Gem::Requirement
183
199
  requirements:
184
- - - '>='
200
+ - - ">="
185
201
  - !ruby/object:Gem::Version
186
202
  version: 1.9.3
187
203
  required_rubygems_version: !ruby/object:Gem::Requirement
188
204
  requirements:
189
- - - '>='
205
+ - - ">="
190
206
  - !ruby/object:Gem::Version
191
207
  version: '0'
192
208
  requirements: []
193
209
  rubyforge_project:
194
- rubygems_version: 2.0.3
210
+ rubygems_version: 2.2.2
195
211
  signing_key:
196
212
  specification_version: 4
197
213
  summary: Faster string escaping routines for your web apps
@@ -206,6 +222,8 @@ test_files:
206
222
  - test/query/unescape_test.rb
207
223
  - test/uri/escape_test.rb
208
224
  - test/uri/unescape_test.rb
225
+ - test/uri_component/escape_test.rb
226
+ - test/uri_component/unescape_test.rb
209
227
  - test/url/escape_test.rb
210
228
  - test/url/unescape_test.rb
211
229
  - test/xml/escape_test.rb
@@ -1,20 +0,0 @@
1
- Copyright (c) 2010-2013 Brian Lopez - http://github.com/brianmario
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.