hanami-utils 2.0.3 → 2.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b652af87ed75992d9e11acdfe997b8c8037ac034bdce97cb555904789b337844
4
- data.tar.gz: 179a36a649aadeb552c550ef104154ec64834bc89c0af25868184e6df89821c6
3
+ metadata.gz: 7d8408f6dcbf5d2b7a701c70130fe840c313114ce78f73ff5591f624b0fec635
4
+ data.tar.gz: 46423746a2dc76982974f54cd7c542f705aaf9ae36c3549056ec92136acb4f50
5
5
  SHA512:
6
- metadata.gz: d1a6db92d34b26615a48bf79f922bf214ca8517a9d84d7b255ade523a35df878fec93ebc33a1a923bb0026dc815cbf0da95bd608032cae3986dce75222bd0bdd
7
- data.tar.gz: d80d611dd33a3a4d897bd53e7db05617d363ab7f629a5ac4d10f58892ef546e9cad03710c114c796642b40f95bc43299fde88b5a32edef758dd35450f1940a24
6
+ metadata.gz: 5110f56db1184e39c4e741bb313f7aaff5ab8ff6a703b8bd8e3eaaf8608663ca88eec0ffa83054ac9ffbb961c9f4158b0ee56e1eea20031f539d74bf5470c30f
7
+ data.tar.gz: 58ce8d880d76a662f47e9ee19e96eaec06e02242b90ac456716c76aac7089a4b73db7a7630095227a08037ab26a040a05b7711554c471293c98d5b30ebb5c261
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  Ruby core extensions and class utilities for Hanami
4
4
 
5
+ ## v2.1.0.beta1 - 2023-06-29
6
+
7
+ ### Changed
8
+
9
+ - [Tim Riley] Remove `Hanami::Utils::Escape` (which was not public as of 2.0.0) (#410)
10
+
5
11
  ## v2.0.3 - 2023-02-01
6
12
 
7
13
  ### Fixed
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2014-2017 Luca Guidi
1
+ Copyright © 2014 Hanami Team
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -50,10 +50,6 @@ Or install it yourself as:
50
50
 
51
51
  ## Features
52
52
 
53
- ### Hanami::Logger
54
-
55
- Enhanced version of Ruby's `Logger`. [[API doc](http://www.rubydoc.info/gems/hanami-utils/Hanami/Logger)]
56
-
57
53
  ### Hanami::Utils::Blank
58
54
 
59
55
  Checks for blank. [[API doc](http://www.rubydoc.info/gems/hanami-utils/Hanami/Utils/Blank)]
@@ -74,10 +70,6 @@ Inheritable class attributes. [[API doc](http://www.rubydoc.info/gems/hanami-uti
74
70
 
75
71
  Deprecate Hanami features. [[API doc](http://www.rubydoc.info/gems/hanami-utils/Hanami/Utils/Deprecation)]
76
72
 
77
- ### Hanami::Utils::Escape
78
-
79
- Safe and fast escape for URLs, HTML content and attributes. Based on OWASP/ESAPI code. [[API doc](http://www.rubydoc.info/gems/hanami-utils/Hanami/Utils/Escape)]
80
-
81
73
  ### Hanami::Utils::FileList
82
74
 
83
75
  Recursive, cross-platform ordered list of files. [[API doc](http://www.rubydoc.info/gems/hanami-utils/Hanami/Utils/FileList)]
@@ -136,4 +128,4 @@ Enhanced version of Ruby's `String`. [[API doc](http://www.rubydoc.info/gems/han
136
128
 
137
129
  ## Copyright
138
130
 
139
- Copyright © 2014-2022 Hanami Team – Released under MIT License
131
+ Copyright © 2014 Hanami Team – Released under MIT License
@@ -6,6 +6,6 @@ module Hanami
6
6
  #
7
7
  # @since 0.1.0
8
8
  # @api public
9
- VERSION = "2.0.3"
9
+ VERSION = "2.1.0.beta1"
10
10
  end
11
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.1.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-01 00:00:00.000000000 Z
11
+ date: 2023-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-core
@@ -146,7 +146,6 @@ files:
146
146
  - lib/hanami/utils/class_attribute.rb
147
147
  - lib/hanami/utils/class_attribute/attributes.rb
148
148
  - lib/hanami/utils/deprecation.rb
149
- - lib/hanami/utils/escape.rb
150
149
  - lib/hanami/utils/file_list.rb
151
150
  - lib/hanami/utils/files.rb
152
151
  - lib/hanami/utils/hash.rb
@@ -175,11 +174,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
175
174
  version: '3.0'
176
175
  required_rubygems_version: !ruby/object:Gem::Requirement
177
176
  requirements:
178
- - - ">="
177
+ - - ">"
179
178
  - !ruby/object:Gem::Version
180
- version: '0'
179
+ version: 1.3.1
181
180
  requirements: []
182
- rubygems_version: 3.4.5
181
+ rubygems_version: 3.4.13
183
182
  signing_key:
184
183
  specification_version: 4
185
184
  summary: Ruby core extentions and Hanami utilities
@@ -1,583 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hanami
4
- module Utils
5
- # HTML escape utilities
6
- #
7
- # Based on OWASP research and OWASP ESAPI code
8
- #
9
- # @since 0.4.0
10
- #
11
- # @see https://www.owasp.org
12
- # @see https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29
13
- # @see https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
14
- # @see https://www.owasp.org/index.php/ESAPI
15
- # @see https://github.com/ESAPI/esapi-java-legacy
16
- module Escape # rubocop:disable Metrics/ModuleLength
17
- # Hex base for base 10 integer conversion
18
- #
19
- # @since 0.4.0
20
- # @api private
21
- #
22
- # @see http://www.ruby-doc.org/core/Fixnum.html#method-i-to_s
23
- HEX_BASE = 16
24
-
25
- # Limit for non printable chars
26
- #
27
- # @since 0.4.0
28
- # @api private
29
- LOW_HEX_CODE_LIMIT = 0xff
30
-
31
- # Replacement hex for non printable characters
32
- #
33
- # @since 0.4.0
34
- # @api private
35
- REPLACEMENT_HEX = "fffd"
36
-
37
- # Low hex codes lookup table
38
- #
39
- # @since 0.4.0
40
- # @api private
41
- HEX_CODES = (0..255).each_with_object({}) do |c, codes|
42
- if (c >= 0x30 && c <= 0x39) || (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A)
43
- codes[c] = nil
44
- else
45
- codes[c] = c.to_s(HEX_BASE)
46
- end
47
- end.freeze
48
-
49
- # Non printable chars
50
- #
51
- # This is a Hash instead of a Set, to make lookup faster.
52
- #
53
- # @since 0.4.0
54
- # @api private
55
- #
56
- # @see https://gist.github.com/jodosha/ac5dd54416de744b9600
57
- NON_PRINTABLE_CHARS = {
58
- 0x0 => true, 0x1 => true, 0x2 => true, 0x3 => true, 0x4 => true,
59
- 0x5 => true, 0x6 => true, 0x7 => true, 0x8 => true, 0x11 => true,
60
- 0x12 => true, 0x14 => true, 0x15 => true, 0x16 => true, 0x17 => true,
61
- 0x18 => true, 0x19 => true, 0x1a => true, 0x1b => true, 0x1c => true,
62
- 0x1d => true, 0x1e => true, 0x1f => true, 0x7f => true, 0x80 => true,
63
- 0x81 => true, 0x82 => true, 0x83 => true, 0x84 => true, 0x85 => true,
64
- 0x86 => true, 0x87 => true, 0x88 => true, 0x89 => true, 0x8a => true,
65
- 0x8b => true, 0x8c => true, 0x8d => true, 0x8e => true, 0x8f => true,
66
- 0x90 => true, 0x91 => true, 0x92 => true, 0x93 => true, 0x94 => true,
67
- 0x95 => true, 0x96 => true, 0x97 => true, 0x98 => true, 0x99 => true,
68
- 0x9a => true, 0x9b => true, 0x9c => true, 0x9d => true, 0x9e => true,
69
- 0x9f => true
70
- }.freeze
71
-
72
- # Lookup table for HTML escape
73
- #
74
- # @since 0.4.0
75
- # @api private
76
- #
77
- # @see Hanami::Utils::Escape.html
78
- HTML_CHARS = {
79
- "&" => "&amp;",
80
- "<" => "&lt;",
81
- ">" => "&gt;",
82
- '"' => "&quot;",
83
- "'" => "&apos;",
84
- "/" => "&#x2F;"
85
- }.freeze
86
-
87
- # Lookup table for safe chars for HTML attributes.
88
- #
89
- # This is a Hash instead of a Set, to make lookup faster.
90
- #
91
- # @since 0.4.0
92
- # @api private
93
- #
94
- # @see Lookup::Utils::Escape.html_attribute
95
- # @see https://gist.github.com/jodosha/ac5dd54416de744b9600
96
- HTML_ATTRIBUTE_SAFE_CHARS = {
97
- "," => true, "." => true, "-" => true, "_" => true
98
- }.freeze
99
-
100
- # Lookup table for HTML attribute escape
101
- #
102
- # @since 0.4.0
103
- # @api private
104
- #
105
- # @see Hanami::Utils::Escape.html_attribute
106
- HTML_ENTITIES = {
107
- 34 => "quot", # quotation mark
108
- 38 => "amp", # ampersand
109
- 60 => "lt", # less-than sign
110
- 62 => "gt", # greater-than sign
111
- 160 => "nbsp", # no-break space
112
- 161 => "iexcl", # inverted exclamation mark
113
- 162 => "cent", # cent sign
114
- 163 => "pound", # pound sign
115
- 164 => "curren", # currency sign
116
- 165 => "yen", # yen sign
117
- 166 => "brvbar", # broken bar
118
- 167 => "sect", # section sign
119
- 168 => "uml", # diaeresis
120
- 169 => "copy", # copyright sign
121
- 170 => "ordf", # feminine ordinal indicator
122
- 171 => "laquo", # left-pointing double angle quotation mark
123
- 172 => "not", # not sign
124
- 173 => "shy", # soft hyphen
125
- 174 => "reg", # registered sign
126
- 175 => "macr", # macron
127
- 176 => "deg", # degree sign
128
- 177 => "plusmn", # plus-minus sign
129
- 178 => "sup2", # superscript two
130
- 179 => "sup3", # superscript three
131
- 180 => "acute", # acute accent
132
- 181 => "micro", # micro sign
133
- 182 => "para", # pilcrow sign
134
- 183 => "middot", # middle dot
135
- 184 => "cedil", # cedilla
136
- 185 => "sup1", # superscript one
137
- 186 => "ordm", # masculine ordinal indicator
138
- 187 => "raquo", # right-pointing double angle quotation mark
139
- 188 => "frac14", # vulgar fraction one quarter
140
- 189 => "frac12", # vulgar fraction one half
141
- 190 => "frac34", # vulgar fraction three quarters
142
- 191 => "iquest", # inverted question mark
143
- 192 => "Agrave", # Latin capital letter a with grave
144
- 193 => "Aacute", # Latin capital letter a with acute
145
- 194 => "Acirc", # Latin capital letter a with circumflex
146
- 195 => "Atilde", # Latin capital letter a with tilde
147
- 196 => "Auml", # Latin capital letter a with diaeresis
148
- 197 => "Aring", # Latin capital letter a with ring above
149
- 198 => "AElig", # Latin capital letter ae
150
- 199 => "Ccedil", # Latin capital letter c with cedilla
151
- 200 => "Egrave", # Latin capital letter e with grave
152
- 201 => "Eacute", # Latin capital letter e with acute
153
- 202 => "Ecirc", # Latin capital letter e with circumflex
154
- 203 => "Euml", # Latin capital letter e with diaeresis
155
- 204 => "Igrave", # Latin capital letter i with grave
156
- 205 => "Iacute", # Latin capital letter i with acute
157
- 206 => "Icirc", # Latin capital letter i with circumflex
158
- 207 => "Iuml", # Latin capital letter i with diaeresis
159
- 208 => "ETH", # Latin capital letter eth
160
- 209 => "Ntilde", # Latin capital letter n with tilde
161
- 210 => "Ograve", # Latin capital letter o with grave
162
- 211 => "Oacute", # Latin capital letter o with acute
163
- 212 => "Ocirc", # Latin capital letter o with circumflex
164
- 213 => "Otilde", # Latin capital letter o with tilde
165
- 214 => "Ouml", # Latin capital letter o with diaeresis
166
- 215 => "times", # multiplication sign
167
- 216 => "Oslash", # Latin capital letter o with stroke
168
- 217 => "Ugrave", # Latin capital letter u with grave
169
- 218 => "Uacute", # Latin capital letter u with acute
170
- 219 => "Ucirc", # Latin capital letter u with circumflex
171
- 220 => "Uuml", # Latin capital letter u with diaeresis
172
- 221 => "Yacute", # Latin capital letter y with acute
173
- 222 => "THORN", # Latin capital letter thorn
174
- 223 => "szlig", # Latin small letter sharp sXCOMMAX German Eszett
175
- 224 => "agrave", # Latin small letter a with grave
176
- 225 => "aacute", # Latin small letter a with acute
177
- 226 => "acirc", # Latin small letter a with circumflex
178
- 227 => "atilde", # Latin small letter a with tilde
179
- 228 => "auml", # Latin small letter a with diaeresis
180
- 229 => "aring", # Latin small letter a with ring above
181
- 230 => "aelig", # Latin lowercase ligature ae
182
- 231 => "ccedil", # Latin small letter c with cedilla
183
- 232 => "egrave", # Latin small letter e with grave
184
- 233 => "eacute", # Latin small letter e with acute
185
- 234 => "ecirc", # Latin small letter e with circumflex
186
- 235 => "euml", # Latin small letter e with diaeresis
187
- 236 => "igrave", # Latin small letter i with grave
188
- 237 => "iacute", # Latin small letter i with acute
189
- 238 => "icirc", # Latin small letter i with circumflex
190
- 239 => "iuml", # Latin small letter i with diaeresis
191
- 240 => "eth", # Latin small letter eth
192
- 241 => "ntilde", # Latin small letter n with tilde
193
- 242 => "ograve", # Latin small letter o with grave
194
- 243 => "oacute", # Latin small letter o with acute
195
- 244 => "ocirc", # Latin small letter o with circumflex
196
- 245 => "otilde", # Latin small letter o with tilde
197
- 246 => "ouml", # Latin small letter o with diaeresis
198
- 247 => "divide", # division sign
199
- 248 => "oslash", # Latin small letter o with stroke
200
- 249 => "ugrave", # Latin small letter u with grave
201
- 250 => "uacute", # Latin small letter u with acute
202
- 251 => "ucirc", # Latin small letter u with circumflex
203
- 252 => "uuml", # Latin small letter u with diaeresis
204
- 253 => "yacute", # Latin small letter y with acute
205
- 254 => "thorn", # Latin small letter thorn
206
- 255 => "yuml", # Latin small letter y with diaeresis
207
- 338 => "OElig", # Latin capital ligature oe
208
- 339 => "oelig", # Latin small ligature oe
209
- 352 => "Scaron", # Latin capital letter s with caron
210
- 353 => "scaron", # Latin small letter s with caron
211
- 376 => "Yuml", # Latin capital letter y with diaeresis
212
- 402 => "fnof", # Latin small letter f with hook
213
- 710 => "circ", # modifier letter circumflex accent
214
- 732 => "tilde", # small tilde
215
- 913 => "Alpha", # Greek capital letter alpha
216
- 914 => "Beta", # Greek capital letter beta
217
- 915 => "Gamma", # Greek capital letter gamma
218
- 916 => "Delta", # Greek capital letter delta
219
- 917 => "Epsilon", # Greek capital letter epsilon
220
- 918 => "Zeta", # Greek capital letter zeta
221
- 919 => "Eta", # Greek capital letter eta
222
- 920 => "Theta", # Greek capital letter theta
223
- 921 => "Iota", # Greek capital letter iota
224
- 922 => "Kappa", # Greek capital letter kappa
225
- 923 => "Lambda", # Greek capital letter lambda
226
- 924 => "Mu", # Greek capital letter mu
227
- 925 => "Nu", # Greek capital letter nu
228
- 926 => "Xi", # Greek capital letter xi
229
- 927 => "Omicron", # Greek capital letter omicron
230
- 928 => "Pi", # Greek capital letter pi
231
- 929 => "Rho", # Greek capital letter rho
232
- 931 => "Sigma", # Greek capital letter sigma
233
- 932 => "Tau", # Greek capital letter tau
234
- 933 => "Upsilon", # Greek capital letter upsilon
235
- 934 => "Phi", # Greek capital letter phi
236
- 935 => "Chi", # Greek capital letter chi
237
- 936 => "Psi", # Greek capital letter psi
238
- 937 => "Omega", # Greek capital letter omega
239
- 945 => "alpha", # Greek small letter alpha
240
- 946 => "beta", # Greek small letter beta
241
- 947 => "gamma", # Greek small letter gamma
242
- 948 => "delta", # Greek small letter delta
243
- 949 => "epsilon", # Greek small letter epsilon
244
- 950 => "zeta", # Greek small letter zeta
245
- 951 => "eta", # Greek small letter eta
246
- 952 => "theta", # Greek small letter theta
247
- 953 => "iota", # Greek small letter iota
248
- 954 => "kappa", # Greek small letter kappa
249
- 955 => "lambda", # Greek small letter lambda
250
- 956 => "mu", # Greek small letter mu
251
- 957 => "nu", # Greek small letter nu
252
- 958 => "xi", # Greek small letter xi
253
- 959 => "omicron", # Greek small letter omicron
254
- 960 => "pi", # Greek small letter pi
255
- 961 => "rho", # Greek small letter rho
256
- 962 => "sigmaf", # Greek small letter final sigma
257
- 963 => "sigma", # Greek small letter sigma
258
- 964 => "tau", # Greek small letter tau
259
- 965 => "upsilon", # Greek small letter upsilon
260
- 966 => "phi", # Greek small letter phi
261
- 967 => "chi", # Greek small letter chi
262
- 968 => "psi", # Greek small letter psi
263
- 969 => "omega", # Greek small letter omega
264
- 977 => "thetasym", # Greek theta symbol
265
- 978 => "upsih", # Greek upsilon with hook symbol
266
- 982 => "piv", # Greek pi symbol
267
- 8194 => "ensp", # en space
268
- 8195 => "emsp", # em space
269
- 8201 => "thinsp", # thin space
270
- 8204 => "zwnj", # zero width non-joiner
271
- 8205 => "zwj", # zero width joiner
272
- 8206 => "lrm", # left-to-right mark
273
- 8207 => "rlm", # right-to-left mark
274
- 8211 => "ndash", # en dash
275
- 8212 => "mdash", # em dash
276
- 8216 => "lsquo", # left single quotation mark
277
- 8217 => "rsquo", # right single quotation mark
278
- 8218 => "sbquo", # single low-9 quotation mark
279
- 8220 => "ldquo", # left double quotation mark
280
- 8221 => "rdquo", # right double quotation mark
281
- 8222 => "bdquo", # double low-9 quotation mark
282
- 8224 => "dagger", # dagger
283
- 8225 => "Dagger", # double dagger
284
- 8226 => "bull", # bullet
285
- 8230 => "hellip", # horizontal ellipsis
286
- 8240 => "permil", # per mille sign
287
- 8242 => "prime", # prime
288
- 8243 => "Prime", # double prime
289
- 8249 => "lsaquo", # single left-pointing angle quotation mark
290
- 8250 => "rsaquo", # single right-pointing angle quotation mark
291
- 8254 => "oline", # overline
292
- 8260 => "frasl", # fraction slash
293
- 8364 => "euro", # euro sign
294
- 8465 => "image", # black-letter capital i
295
- 8472 => "weierp", # script capital pXCOMMAX Weierstrass p
296
- 8476 => "real", # black-letter capital r
297
- 8482 => "trade", # trademark sign
298
- 8501 => "alefsym", # alef symbol
299
- 8592 => "larr", # leftwards arrow
300
- 8593 => "uarr", # upwards arrow
301
- 8594 => "rarr", # rightwards arrow
302
- 8595 => "darr", # downwards arrow
303
- 8596 => "harr", # left right arrow
304
- 8629 => "crarr", # downwards arrow with corner leftwards
305
- 8656 => "lArr", # leftwards double arrow
306
- 8657 => "uArr", # upwards double arrow
307
- 8658 => "rArr", # rightwards double arrow
308
- 8659 => "dArr", # downwards double arrow
309
- 8660 => "hArr", # left right double arrow
310
- 8704 => "forall", # for all
311
- 8706 => "part", # partial differential
312
- 8707 => "exist", # there exists
313
- 8709 => "empty", # empty set
314
- 8711 => "nabla", # nabla
315
- 8712 => "isin", # element of
316
- 8713 => "notin", # not an element of
317
- 8715 => "ni", # contains as member
318
- 8719 => "prod", # n-ary product
319
- 8721 => "sum", # n-ary summation
320
- 8722 => "minus", # minus sign
321
- 8727 => "lowast", # asterisk operator
322
- 8730 => "radic", # square root
323
- 8733 => "prop", # proportional to
324
- 8734 => "infin", # infinity
325
- 8736 => "ang", # angle
326
- 8743 => "and", # logical and
327
- 8744 => "or", # logical or
328
- 8745 => "cap", # intersection
329
- 8746 => "cup", # union
330
- 8747 => "int", # integral
331
- 8756 => "there4", # therefore
332
- 8764 => "sim", # tilde operator
333
- 8773 => "cong", # congruent to
334
- 8776 => "asymp", # almost equal to
335
- 8800 => "ne", # not equal to
336
- 8801 => "equiv", # identical toXCOMMAX equivalent to
337
- 8804 => "le", # less-than or equal to
338
- 8805 => "ge", # greater-than or equal to
339
- 8834 => "sub", # subset of
340
- 8835 => "sup", # superset of
341
- 8836 => "nsub", # not a subset of
342
- 8838 => "sube", # subset of or equal to
343
- 8839 => "supe", # superset of or equal to
344
- 8853 => "oplus", # circled plus
345
- 8855 => "otimes", # circled times
346
- 8869 => "perp", # up tack
347
- 8901 => "sdot", # dot operator
348
- 8968 => "lceil", # left ceiling
349
- 8969 => "rceil", # right ceiling
350
- 8970 => "lfloor", # left floor
351
- 8971 => "rfloor", # right floor
352
- 9001 => "lang", # left-pointing angle bracket
353
- 9002 => "rang", # right-pointing angle bracket
354
- 9674 => "loz", # lozenge
355
- 9824 => "spades", # black spade suit
356
- 9827 => "clubs", # black club suit
357
- 9829 => "hearts", # black heart suit
358
- 9830 => "diams" # black diamond suit
359
- }.freeze
360
-
361
- # Allowed URL schemes
362
- #
363
- # @since 0.4.0
364
- # @api private
365
- #
366
- # @see Hanami::Utils::Escape.url
367
- DEFAULT_URL_SCHEMES = %w[http https mailto].freeze
368
-
369
- # The output of an escape.
370
- #
371
- # It's marked with this special class for two reasons:
372
- #
373
- # * Don't double escape the same string (this is for `Hanami::Helpers`
374
- # compatibility)
375
- # * Leave open the possibility to developers to mark a string as safe
376
- # with an higher API (eg. `#raw` in `Hanami::View` or `Hanami::Helpers`)
377
- #
378
- # @since 0.4.0
379
- # @api private
380
- class SafeString < ::String
381
- # @return [SafeString] the duped string
382
- #
383
- # @since 0.4.0
384
- # @api private
385
- #
386
- # @see http://www.ruby-doc.org/core/String.html#method-i-to_s
387
- def to_s
388
- dup
389
- end
390
-
391
- # Encode the string the given encoding
392
- #
393
- # @return [SafeString] an encoded SafeString
394
- #
395
- # @since 0.4.0
396
- # @api private
397
- #
398
- # @see http://www.ruby-doc.org/core/String.html#method-i-encode
399
- def encode(*args)
400
- self.class.new super
401
- end
402
- end
403
-
404
- # Escapes HTML contents
405
- #
406
- # This MUST be used only for tag contents.
407
- # Please use `html_attribute` for escaping HTML attributes.
408
- #
409
- # @param input [String] the input
410
- #
411
- # @return [String] the escaped string
412
- #
413
- # @since 0.4.0
414
- #
415
- # @see https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet OWASP XSS Cheat Sheet Rule #1
416
- #
417
- # @example Good practice
418
- # <div><%= Hanami::Utils::Escape.html('<script>alert(1);</script>') %></div>
419
- # <div>&lt;script&gt;alert(1);&lt;&#x2F;script&gt;</div>
420
- #
421
- # @example Bad practice
422
- # # WRONG Use Escape.html_attribute instead
423
- # <a title="<%= Hanami::Utils::Escape.html('...') %>">link</a>
424
- def self.html(input)
425
- input = encode(input)
426
- return input if input.is_a?(SafeString)
427
-
428
- result = SafeString.new
429
-
430
- input.each_char do |chr|
431
- result << HTML_CHARS.fetch(chr, chr)
432
- end
433
-
434
- result
435
- end
436
-
437
- # Escapes HTML attributes
438
- #
439
- # This can be used both for HTML attributes and contents.
440
- # Please note that this is more computational expensive.
441
- # If you need to escape only HTML contents, please use `.html`.
442
- #
443
- # @param input [String] the input
444
- #
445
- # @return [String] the escaped string
446
- #
447
- # @since 0.4.0
448
- #
449
- # @see https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet OWASP XSS Cheat Sheet Rule #2
450
- #
451
- # @example Good practice
452
- # <a title="<%= Hanami::Utils::Escape.html_attribute('...') %>">link</a>
453
- #
454
- # @example Good but expensive practice
455
- # # Alternatively you can use Escape.html
456
- # <p><%= Hanami::Utils::Escape.html_attribute('...') %></p>
457
- def self.html_attribute(input)
458
- input = encode(input)
459
- return input if input.is_a?(SafeString)
460
-
461
- result = SafeString.new
462
-
463
- input.each_char do |chr|
464
- result << encode_char(chr, HTML_ATTRIBUTE_SAFE_CHARS)
465
- end
466
-
467
- result
468
- end
469
-
470
- # Escapes URL for HTML attributes (href, src, etc..).
471
- #
472
- # It extracts from the given input the first valid URL that matches the
473
- # whitelisted schemes (default: http, https and mailto).
474
- #
475
- # It's possible to pass a second optional argument to specify different
476
- # schemes.
477
- #
478
- # @param input [String] the input
479
- # @param schemes [Array<String>] an array of whitelisted schemes
480
- #
481
- # @return [String] the escaped string
482
- #
483
- # @since 0.4.0
484
- #
485
- # @see Hanami::Utils::Escape::DEFAULT_URL_SCHEMES
486
- # @see http://www.ruby-doc.org/stdlib/libdoc/uri/rdoc/URI.html#method-c-extract
487
- #
488
- # @example Basic usage
489
- # <%
490
- # good_input = "http://hanamirb.org"
491
- # evil_input = "javascript:alert('xss')"
492
- #
493
- # escaped_good_input = Hanami::Utils::Escape.url(good_input) # => "http://hanamirb.org"
494
- # escaped_evil_input = Hanami::Utils::Escape.url(evil_input) # => ""
495
- # %>
496
- #
497
- # <a href="<%= escaped_good_input %>">personal website</a>
498
- # <a href="<%= escaped_evil_input %>">personal website</a>
499
- #
500
- # @example Custom scheme
501
- # <%
502
- # schemes = ['ftp', 'ftps']
503
- #
504
- # accepted = "ftps://ftp.example.org"
505
- # rejected = "http://www.example.org"
506
- #
507
- # escaped_accepted = Hanami::Utils::Escape.url(accepted) # => "ftps://ftp.example.org"
508
- # escaped_rejected = Hanami::Utils::Escape.url(rejected) # => ""
509
- # %>
510
- #
511
- # <a href="<%= escaped_accepted %>">FTP</a>
512
- # <a href="<%= escaped_rejected %>">FTP</a>
513
- def self.url(input, schemes = DEFAULT_URL_SCHEMES)
514
- input = encode(input)
515
- return input if input.is_a?(SafeString)
516
-
517
- SafeString.new(
518
- URI::DEFAULT_PARSER.extract(
519
- URI.decode_www_form_component(input),
520
- schemes
521
- ).first.to_s
522
- )
523
- end
524
-
525
- class << self
526
- private
527
-
528
- # Encodes the given string into UTF-8
529
- #
530
- # @param input [String] the input
531
- #
532
- # @return [String] an UTF-8 encoded string
533
- #
534
- # @since 0.4.0
535
- # @api private
536
- def encode(input)
537
- return "" if input.nil?
538
-
539
- input.to_s.encode(Encoding::UTF_8)
540
- rescue Encoding::UndefinedConversionError
541
- input.dup.force_encoding(Encoding::UTF_8)
542
- end
543
-
544
- # Encode the given UTF-8 char.
545
- #
546
- # @param char [String] an UTF-8 char
547
- # @param safe_chars [Hash] a table of safe chars
548
- #
549
- # @return [String] an HTML encoded string
550
- #
551
- # @since 0.4.0
552
- # @api private
553
- def encode_char(char, safe_chars = {})
554
- return char if safe_chars[char]
555
-
556
- code = char.ord
557
- hex = hex_for_non_alphanumeric_code(code)
558
- return char if hex.nil?
559
-
560
- hex = REPLACEMENT_HEX if NON_PRINTABLE_CHARS[code]
561
-
562
- if entity = HTML_ENTITIES[code]
563
- "&#{entity};"
564
- else
565
- "&#x#{hex};"
566
- end
567
- end
568
-
569
- # Transforms the given char code
570
- #
571
- # @since 0.4.0
572
- # @api private
573
- def hex_for_non_alphanumeric_code(input)
574
- if input < LOW_HEX_CODE_LIMIT
575
- HEX_CODES[input]
576
- else
577
- input.to_s(HEX_BASE)
578
- end
579
- end
580
- end
581
- end
582
- end
583
- end