uri 0.10.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of uri might be problematic. Click here for more details.

@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0e36cfa261a79542a5591ce20bc085a0f622baf08fd2492083187ccce7d892a7
4
+ data.tar.gz: d3164253ba35cc1c531bc730d66fcda4e9731a7f086cf9a4e45d89005e50ab7c
5
+ SHA512:
6
+ metadata.gz: 58e1fe3612ceca21b12a36ca05aae94b5aabbb83b5f8949d5a1e059cb272aaeaa9383ae0dbc876fbd0a32db059a939d3f56462c70b07c9d622075f0c5d28309d
7
+ data.tar.gz: bcbb9f2611ffd627d5ab13555bd5054c55536a2aff664022de31631ad8e825298bdcc9c06cf3d6c7cac1ef7c439d71b5e5f0c33e5e6fa8a287b2143cc145a756
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ Gemfile.lock
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.3
7
+ before_install: gem install bundler -v 2.0.2
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem "bundler"
7
+ gem "rake"
8
+ gem "test-unit"
9
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
@@ -0,0 +1,53 @@
1
+ # URI
2
+
3
+ URI is a module providing classes to handle Uniform Resource Identifiers
4
+ (RFC2396[http://tools.ietf.org/html/rfc2396]).
5
+
6
+ ## Features
7
+
8
+ * Uniform way of handling URIs.
9
+ * Flexibility to introduce custom URI schemes.
10
+ * Flexibility to have an alternate URI::Parser (or just different patterns and regexp's).
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'uri'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install uri
27
+
28
+ ## Usage
29
+
30
+ ```ruby
31
+ require 'uri'
32
+
33
+ uri = URI("http://foo.com/posts?id=30&limit=5#time=1305298413")
34
+ #=> #<URI::HTTP http://foo.com/posts?id=30&limit=5#time=1305298413>
35
+
36
+ uri.scheme #=> "http"
37
+ uri.host #=> "foo.com"
38
+ uri.path #=> "/posts"
39
+ uri.query #=> "id=30&limit=5"
40
+ uri.fragment #=> "time=1305298413"
41
+
42
+ uri.to_s #=> "http://foo.com/posts?id=30&limit=5#time=1305298413"
43
+ ```
44
+
45
+ ## Development
46
+
47
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
48
+
49
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
50
+
51
+ ## Contributing
52
+
53
+ Bug reports and pull requests are welcome on GitHub at https://github.com/hsbt/uri.
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test" << "test/lib"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "uri"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: false
2
+ # URI is a module providing classes to handle Uniform Resource Identifiers
3
+ # (RFC2396[http://tools.ietf.org/html/rfc2396]).
4
+ #
5
+ # == Features
6
+ #
7
+ # * Uniform way of handling URIs.
8
+ # * Flexibility to introduce custom URI schemes.
9
+ # * Flexibility to have an alternate URI::Parser (or just different patterns
10
+ # and regexp's).
11
+ #
12
+ # == Basic example
13
+ #
14
+ # require 'uri'
15
+ #
16
+ # uri = URI("http://foo.com/posts?id=30&limit=5#time=1305298413")
17
+ # #=> #<URI::HTTP http://foo.com/posts?id=30&limit=5#time=1305298413>
18
+ #
19
+ # uri.scheme #=> "http"
20
+ # uri.host #=> "foo.com"
21
+ # uri.path #=> "/posts"
22
+ # uri.query #=> "id=30&limit=5"
23
+ # uri.fragment #=> "time=1305298413"
24
+ #
25
+ # uri.to_s #=> "http://foo.com/posts?id=30&limit=5#time=1305298413"
26
+ #
27
+ # == Adding custom URIs
28
+ #
29
+ # module URI
30
+ # class RSYNC < Generic
31
+ # DEFAULT_PORT = 873
32
+ # end
33
+ # @@schemes['RSYNC'] = RSYNC
34
+ # end
35
+ # #=> URI::RSYNC
36
+ #
37
+ # URI.scheme_list
38
+ # #=> {"FILE"=>URI::File, "FTP"=>URI::FTP, "HTTP"=>URI::HTTP,
39
+ # # "HTTPS"=>URI::HTTPS, "LDAP"=>URI::LDAP, "LDAPS"=>URI::LDAPS,
40
+ # # "MAILTO"=>URI::MailTo, "RSYNC"=>URI::RSYNC}
41
+ #
42
+ # uri = URI("rsync://rsync.foo.com")
43
+ # #=> #<URI::RSYNC rsync://rsync.foo.com>
44
+ #
45
+ # == RFC References
46
+ #
47
+ # A good place to view an RFC spec is http://www.ietf.org/rfc.html.
48
+ #
49
+ # Here is a list of all related RFC's:
50
+ # - RFC822[http://tools.ietf.org/html/rfc822]
51
+ # - RFC1738[http://tools.ietf.org/html/rfc1738]
52
+ # - RFC2255[http://tools.ietf.org/html/rfc2255]
53
+ # - RFC2368[http://tools.ietf.org/html/rfc2368]
54
+ # - RFC2373[http://tools.ietf.org/html/rfc2373]
55
+ # - RFC2396[http://tools.ietf.org/html/rfc2396]
56
+ # - RFC2732[http://tools.ietf.org/html/rfc2732]
57
+ # - RFC3986[http://tools.ietf.org/html/rfc3986]
58
+ #
59
+ # == Class tree
60
+ #
61
+ # - URI::Generic (in uri/generic.rb)
62
+ # - URI::File - (in uri/file.rb)
63
+ # - URI::FTP - (in uri/ftp.rb)
64
+ # - URI::HTTP - (in uri/http.rb)
65
+ # - URI::HTTPS - (in uri/https.rb)
66
+ # - URI::LDAP - (in uri/ldap.rb)
67
+ # - URI::LDAPS - (in uri/ldaps.rb)
68
+ # - URI::MailTo - (in uri/mailto.rb)
69
+ # - URI::Parser - (in uri/common.rb)
70
+ # - URI::REGEXP - (in uri/common.rb)
71
+ # - URI::REGEXP::PATTERN - (in uri/common.rb)
72
+ # - URI::Util - (in uri/common.rb)
73
+ # - URI::Escape - (in uri/common.rb)
74
+ # - URI::Error - (in uri/common.rb)
75
+ # - URI::InvalidURIError - (in uri/common.rb)
76
+ # - URI::InvalidComponentError - (in uri/common.rb)
77
+ # - URI::BadURIError - (in uri/common.rb)
78
+ #
79
+ # == Copyright Info
80
+ #
81
+ # Author:: Akira Yamada <akira@ruby-lang.org>
82
+ # Documentation::
83
+ # Akira Yamada <akira@ruby-lang.org>
84
+ # Dmitry V. Sabanin <sdmitry@lrn.ru>
85
+ # Vincent Batts <vbatts@hashbangbash.com>
86
+ # License::
87
+ # Copyright (c) 2001 akira yamada <akira@ruby-lang.org>
88
+ # You can redistribute it and/or modify it under the same term as Ruby.
89
+ # Revision:: $Id$
90
+ #
91
+
92
+ module URI
93
+ end
94
+
95
+ require_relative 'uri/version'
96
+ require_relative 'uri/common'
97
+ require_relative 'uri/generic'
98
+ require_relative 'uri/file'
99
+ require_relative 'uri/ftp'
100
+ require_relative 'uri/http'
101
+ require_relative 'uri/https'
102
+ require_relative 'uri/ldap'
103
+ require_relative 'uri/ldaps'
104
+ require_relative 'uri/mailto'
@@ -0,0 +1,744 @@
1
+ # frozen_string_literal: true
2
+ #--
3
+ # = uri/common.rb
4
+ #
5
+ # Author:: Akira Yamada <akira@ruby-lang.org>
6
+ # Revision:: $Id$
7
+ # License::
8
+ # You can redistribute it and/or modify it under the same term as Ruby.
9
+ #
10
+ # See URI for general documentation
11
+ #
12
+
13
+ require_relative "rfc2396_parser"
14
+ require_relative "rfc3986_parser"
15
+
16
+ module URI
17
+ REGEXP = RFC2396_REGEXP
18
+ Parser = RFC2396_Parser
19
+ RFC3986_PARSER = RFC3986_Parser.new
20
+
21
+ # URI::Parser.new
22
+ DEFAULT_PARSER = Parser.new
23
+ DEFAULT_PARSER.pattern.each_pair do |sym, str|
24
+ unless REGEXP::PATTERN.const_defined?(sym)
25
+ REGEXP::PATTERN.const_set(sym, str)
26
+ end
27
+ end
28
+ DEFAULT_PARSER.regexp.each_pair do |sym, str|
29
+ const_set(sym, str)
30
+ end
31
+
32
+ module Util # :nodoc:
33
+ def make_components_hash(klass, array_hash)
34
+ tmp = {}
35
+ if array_hash.kind_of?(Array) &&
36
+ array_hash.size == klass.component.size - 1
37
+ klass.component[1..-1].each_index do |i|
38
+ begin
39
+ tmp[klass.component[i + 1]] = array_hash[i].clone
40
+ rescue TypeError
41
+ tmp[klass.component[i + 1]] = array_hash[i]
42
+ end
43
+ end
44
+
45
+ elsif array_hash.kind_of?(Hash)
46
+ array_hash.each do |key, value|
47
+ begin
48
+ tmp[key] = value.clone
49
+ rescue TypeError
50
+ tmp[key] = value
51
+ end
52
+ end
53
+ else
54
+ raise ArgumentError,
55
+ "expected Array of or Hash of components of #{klass} (#{klass.component[1..-1].join(', ')})"
56
+ end
57
+ tmp[:scheme] = klass.to_s.sub(/\A.*::/, '').downcase
58
+
59
+ return tmp
60
+ end
61
+ module_function :make_components_hash
62
+ end
63
+
64
+ # Module for escaping unsafe characters with codes.
65
+ module Escape
66
+ #
67
+ # == Synopsis
68
+ #
69
+ # URI.escape(str [, unsafe])
70
+ #
71
+ # == Args
72
+ #
73
+ # +str+::
74
+ # String to replaces in.
75
+ # +unsafe+::
76
+ # Regexp that matches all symbols that must be replaced with codes.
77
+ # By default uses <tt>UNSAFE</tt>.
78
+ # When this argument is a String, it represents a character set.
79
+ #
80
+ # == Description
81
+ #
82
+ # Escapes the string, replacing all unsafe characters with codes.
83
+ #
84
+ # This method is obsolete and should not be used. Instead, use
85
+ # CGI.escape, URI.encode_www_form or URI.encode_www_form_component
86
+ # depending on your specific use case.
87
+ #
88
+ # == Usage
89
+ #
90
+ # require 'uri'
91
+ #
92
+ # enc_uri = URI.escape("http://example.com/?a=\11\15")
93
+ # # => "http://example.com/?a=%09%0D"
94
+ #
95
+ # URI.unescape(enc_uri)
96
+ # # => "http://example.com/?a=\t\r"
97
+ #
98
+ # URI.escape("@?@!", "!?")
99
+ # # => "@%3F@%21"
100
+ #
101
+ def escape(*arg)
102
+ warn "URI.escape is obsolete", uplevel: 1
103
+ DEFAULT_PARSER.escape(*arg)
104
+ end
105
+ alias encode escape
106
+ #
107
+ # == Synopsis
108
+ #
109
+ # URI.unescape(str)
110
+ #
111
+ # == Args
112
+ #
113
+ # +str+::
114
+ # String to unescape.
115
+ #
116
+ # == Description
117
+ #
118
+ # This method is obsolete and should not be used. Instead, use
119
+ # CGI.unescape, URI.decode_www_form or URI.decode_www_form_component
120
+ # depending on your specific use case.
121
+ #
122
+ # == Usage
123
+ #
124
+ # require 'uri'
125
+ #
126
+ # enc_uri = URI.escape("http://example.com/?a=\11\15")
127
+ # # => "http://example.com/?a=%09%0D"
128
+ #
129
+ # URI.unescape(enc_uri)
130
+ # # => "http://example.com/?a=\t\r"
131
+ #
132
+ def unescape(*arg)
133
+ warn "URI.unescape is obsolete", uplevel: 1
134
+ DEFAULT_PARSER.unescape(*arg)
135
+ end
136
+ alias decode unescape
137
+ end # module Escape
138
+
139
+ extend Escape
140
+ include REGEXP
141
+
142
+ @@schemes = {}
143
+ # Returns a Hash of the defined schemes.
144
+ def self.scheme_list
145
+ @@schemes
146
+ end
147
+
148
+ #
149
+ # Base class for all URI exceptions.
150
+ #
151
+ class Error < StandardError; end
152
+ #
153
+ # Not a URI.
154
+ #
155
+ class InvalidURIError < Error; end
156
+ #
157
+ # Not a URI component.
158
+ #
159
+ class InvalidComponentError < Error; end
160
+ #
161
+ # URI is valid, bad usage is not.
162
+ #
163
+ class BadURIError < Error; end
164
+
165
+ #
166
+ # == Synopsis
167
+ #
168
+ # URI::split(uri)
169
+ #
170
+ # == Args
171
+ #
172
+ # +uri+::
173
+ # String with URI.
174
+ #
175
+ # == Description
176
+ #
177
+ # Splits the string on following parts and returns array with result:
178
+ #
179
+ # * Scheme
180
+ # * Userinfo
181
+ # * Host
182
+ # * Port
183
+ # * Registry
184
+ # * Path
185
+ # * Opaque
186
+ # * Query
187
+ # * Fragment
188
+ #
189
+ # == Usage
190
+ #
191
+ # require 'uri'
192
+ #
193
+ # URI.split("http://www.ruby-lang.org/")
194
+ # # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil]
195
+ #
196
+ def self.split(uri)
197
+ RFC3986_PARSER.split(uri)
198
+ end
199
+
200
+ #
201
+ # == Synopsis
202
+ #
203
+ # URI::parse(uri_str)
204
+ #
205
+ # == Args
206
+ #
207
+ # +uri_str+::
208
+ # String with URI.
209
+ #
210
+ # == Description
211
+ #
212
+ # Creates one of the URI's subclasses instance from the string.
213
+ #
214
+ # == Raises
215
+ #
216
+ # URI::InvalidURIError::
217
+ # Raised if URI given is not a correct one.
218
+ #
219
+ # == Usage
220
+ #
221
+ # require 'uri'
222
+ #
223
+ # uri = URI.parse("http://www.ruby-lang.org/")
224
+ # # => #<URI::HTTP http://www.ruby-lang.org/>
225
+ # uri.scheme
226
+ # # => "http"
227
+ # uri.host
228
+ # # => "www.ruby-lang.org"
229
+ #
230
+ # It's recommended to first ::escape the provided +uri_str+ if there are any
231
+ # invalid URI characters.
232
+ #
233
+ def self.parse(uri)
234
+ RFC3986_PARSER.parse(uri)
235
+ end
236
+
237
+ #
238
+ # == Synopsis
239
+ #
240
+ # URI::join(str[, str, ...])
241
+ #
242
+ # == Args
243
+ #
244
+ # +str+::
245
+ # String(s) to work with, will be converted to RFC3986 URIs before merging.
246
+ #
247
+ # == Description
248
+ #
249
+ # Joins URIs.
250
+ #
251
+ # == Usage
252
+ #
253
+ # require 'uri'
254
+ #
255
+ # URI.join("http://example.com/","main.rbx")
256
+ # # => #<URI::HTTP http://example.com/main.rbx>
257
+ #
258
+ # URI.join('http://example.com', 'foo')
259
+ # # => #<URI::HTTP http://example.com/foo>
260
+ #
261
+ # URI.join('http://example.com', '/foo', '/bar')
262
+ # # => #<URI::HTTP http://example.com/bar>
263
+ #
264
+ # URI.join('http://example.com', '/foo', 'bar')
265
+ # # => #<URI::HTTP http://example.com/bar>
266
+ #
267
+ # URI.join('http://example.com', '/foo/', 'bar')
268
+ # # => #<URI::HTTP http://example.com/foo/bar>
269
+ #
270
+ def self.join(*str)
271
+ RFC3986_PARSER.join(*str)
272
+ end
273
+
274
+ #
275
+ # == Synopsis
276
+ #
277
+ # URI::extract(str[, schemes][,&blk])
278
+ #
279
+ # == Args
280
+ #
281
+ # +str+::
282
+ # String to extract URIs from.
283
+ # +schemes+::
284
+ # Limit URI matching to specific schemes.
285
+ #
286
+ # == Description
287
+ #
288
+ # Extracts URIs from a string. If block given, iterates through all matched URIs.
289
+ # Returns nil if block given or array with matches.
290
+ #
291
+ # == Usage
292
+ #
293
+ # require "uri"
294
+ #
295
+ # URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.")
296
+ # # => ["http://foo.example.com/bla", "mailto:test@example.com"]
297
+ #
298
+ def self.extract(str, schemes = nil, &block)
299
+ warn "URI.extract is obsolete", uplevel: 1 if $VERBOSE
300
+ DEFAULT_PARSER.extract(str, schemes, &block)
301
+ end
302
+
303
+ #
304
+ # == Synopsis
305
+ #
306
+ # URI::regexp([match_schemes])
307
+ #
308
+ # == Args
309
+ #
310
+ # +match_schemes+::
311
+ # Array of schemes. If given, resulting regexp matches to URIs
312
+ # whose scheme is one of the match_schemes.
313
+ #
314
+ # == Description
315
+ #
316
+ # Returns a Regexp object which matches to URI-like strings.
317
+ # The Regexp object returned by this method includes arbitrary
318
+ # number of capture group (parentheses). Never rely on it's number.
319
+ #
320
+ # == Usage
321
+ #
322
+ # require 'uri'
323
+ #
324
+ # # extract first URI from html_string
325
+ # html_string.slice(URI.regexp)
326
+ #
327
+ # # remove ftp URIs
328
+ # html_string.sub(URI.regexp(['ftp']), '')
329
+ #
330
+ # # You should not rely on the number of parentheses
331
+ # html_string.scan(URI.regexp) do |*matches|
332
+ # p $&
333
+ # end
334
+ #
335
+ def self.regexp(schemes = nil)
336
+ warn "URI.regexp is obsolete", uplevel: 1 if $VERBOSE
337
+ DEFAULT_PARSER.make_regexp(schemes)
338
+ end
339
+
340
+ TBLENCWWWCOMP_ = {} # :nodoc:
341
+ 256.times do |i|
342
+ TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i)
343
+ end
344
+ TBLENCWWWCOMP_[' '] = '+'
345
+ TBLENCWWWCOMP_.freeze
346
+ TBLDECWWWCOMP_ = {} # :nodoc:
347
+ 256.times do |i|
348
+ h, l = i>>4, i&15
349
+ TBLDECWWWCOMP_[-('%%%X%X' % [h, l])] = -i.chr
350
+ TBLDECWWWCOMP_[-('%%%x%X' % [h, l])] = -i.chr
351
+ TBLDECWWWCOMP_[-('%%%X%x' % [h, l])] = -i.chr
352
+ TBLDECWWWCOMP_[-('%%%x%x' % [h, l])] = -i.chr
353
+ end
354
+ TBLDECWWWCOMP_['+'] = ' '
355
+ TBLDECWWWCOMP_.freeze
356
+
357
+ # Encodes given +str+ to URL-encoded form data.
358
+ #
359
+ # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
360
+ # (ASCII space) to + and converts others to %XX.
361
+ #
362
+ # If +enc+ is given, convert +str+ to the encoding before percent encoding.
363
+ #
364
+ # This is an implementation of
365
+ # http://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data.
366
+ #
367
+ # See URI.decode_www_form_component, URI.encode_www_form.
368
+ def self.encode_www_form_component(str, enc=nil)
369
+ str = str.to_s.dup
370
+ if str.encoding != Encoding::ASCII_8BIT
371
+ if enc && enc != Encoding::ASCII_8BIT
372
+ str.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace)
373
+ str.encode!(enc, fallback: ->(x){"&##{x.ord};"})
374
+ end
375
+ str.force_encoding(Encoding::ASCII_8BIT)
376
+ end
377
+ str.gsub!(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_)
378
+ str.force_encoding(Encoding::US_ASCII)
379
+ end
380
+
381
+ # Decodes given +str+ of URL-encoded form data.
382
+ #
383
+ # This decodes + to SP.
384
+ #
385
+ # See URI.encode_www_form_component, URI.decode_www_form.
386
+ def self.decode_www_form_component(str, enc=Encoding::UTF_8)
387
+ raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/ =~ str
388
+ str.b.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc)
389
+ end
390
+
391
+ # Generates URL-encoded form data from given +enum+.
392
+ #
393
+ # This generates application/x-www-form-urlencoded data defined in HTML5
394
+ # from given an Enumerable object.
395
+ #
396
+ # This internally uses URI.encode_www_form_component(str).
397
+ #
398
+ # This method doesn't convert the encoding of given items, so convert them
399
+ # before calling this method if you want to send data as other than original
400
+ # encoding or mixed encoding data. (Strings which are encoded in an HTML5
401
+ # ASCII incompatible encoding are converted to UTF-8.)
402
+ #
403
+ # This method doesn't handle files. When you send a file, use
404
+ # multipart/form-data.
405
+ #
406
+ # This refers http://url.spec.whatwg.org/#concept-urlencoded-serializer
407
+ #
408
+ # URI.encode_www_form([["q", "ruby"], ["lang", "en"]])
409
+ # #=> "q=ruby&lang=en"
410
+ # URI.encode_www_form("q" => "ruby", "lang" => "en")
411
+ # #=> "q=ruby&lang=en"
412
+ # URI.encode_www_form("q" => ["ruby", "perl"], "lang" => "en")
413
+ # #=> "q=ruby&q=perl&lang=en"
414
+ # URI.encode_www_form([["q", "ruby"], ["q", "perl"], ["lang", "en"]])
415
+ # #=> "q=ruby&q=perl&lang=en"
416
+ #
417
+ # See URI.encode_www_form_component, URI.decode_www_form.
418
+ def self.encode_www_form(enum, enc=nil)
419
+ enum.map do |k,v|
420
+ if v.nil?
421
+ encode_www_form_component(k, enc)
422
+ elsif v.respond_to?(:to_ary)
423
+ v.to_ary.map do |w|
424
+ str = encode_www_form_component(k, enc)
425
+ unless w.nil?
426
+ str << '='
427
+ str << encode_www_form_component(w, enc)
428
+ end
429
+ end.join('&')
430
+ else
431
+ str = encode_www_form_component(k, enc)
432
+ str << '='
433
+ str << encode_www_form_component(v, enc)
434
+ end
435
+ end.join('&')
436
+ end
437
+
438
+ # Decodes URL-encoded form data from given +str+.
439
+ #
440
+ # This decodes application/x-www-form-urlencoded data
441
+ # and returns an array of key-value arrays.
442
+ #
443
+ # This refers http://url.spec.whatwg.org/#concept-urlencoded-parser,
444
+ # so this supports only &-separator, and doesn't support ;-separator.
445
+ #
446
+ # ary = URI.decode_www_form("a=1&a=2&b=3")
447
+ # ary #=> [['a', '1'], ['a', '2'], ['b', '3']]
448
+ # ary.assoc('a').last #=> '1'
449
+ # ary.assoc('b').last #=> '3'
450
+ # ary.rassoc('a').last #=> '2'
451
+ # Hash[ary] #=> {"a"=>"2", "b"=>"3"}
452
+ #
453
+ # See URI.decode_www_form_component, URI.encode_www_form.
454
+ def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false)
455
+ raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only?
456
+ ary = []
457
+ return ary if str.empty?
458
+ enc = Encoding.find(enc)
459
+ str.b.each_line(separator) do |string|
460
+ string.chomp!(separator)
461
+ key, sep, val = string.partition('=')
462
+ if isindex
463
+ if sep.empty?
464
+ val = key
465
+ key = +''
466
+ end
467
+ isindex = false
468
+ end
469
+
470
+ if use__charset_ and key == '_charset_' and e = get_encoding(val)
471
+ enc = e
472
+ use__charset_ = false
473
+ end
474
+
475
+ key.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_)
476
+ if val
477
+ val.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_)
478
+ else
479
+ val = +''
480
+ end
481
+
482
+ ary << [key, val]
483
+ end
484
+ ary.each do |k, v|
485
+ k.force_encoding(enc)
486
+ k.scrub!
487
+ v.force_encoding(enc)
488
+ v.scrub!
489
+ end
490
+ ary
491
+ end
492
+
493
+ private
494
+ =begin command for WEB_ENCODINGS_
495
+ curl https://encoding.spec.whatwg.org/encodings.json|
496
+ ruby -rjson -e 'H={}
497
+ h={
498
+ "shift_jis"=>"Windows-31J",
499
+ "euc-jp"=>"cp51932",
500
+ "iso-2022-jp"=>"cp50221",
501
+ "x-mac-cyrillic"=>"macCyrillic",
502
+ }
503
+ JSON($<.read).map{|x|x["encodings"]}.flatten.each{|x|
504
+ Encoding.find(n=h.fetch(n=x["name"].downcase,n))rescue next
505
+ x["labels"].each{|y|H[y]=n}
506
+ }
507
+ puts "{"
508
+ H.each{|k,v|puts %[ #{k.dump}=>#{v.dump},]}
509
+ puts "}"
510
+ '
511
+ =end
512
+ WEB_ENCODINGS_ = {
513
+ "unicode-1-1-utf-8"=>"utf-8",
514
+ "utf-8"=>"utf-8",
515
+ "utf8"=>"utf-8",
516
+ "866"=>"ibm866",
517
+ "cp866"=>"ibm866",
518
+ "csibm866"=>"ibm866",
519
+ "ibm866"=>"ibm866",
520
+ "csisolatin2"=>"iso-8859-2",
521
+ "iso-8859-2"=>"iso-8859-2",
522
+ "iso-ir-101"=>"iso-8859-2",
523
+ "iso8859-2"=>"iso-8859-2",
524
+ "iso88592"=>"iso-8859-2",
525
+ "iso_8859-2"=>"iso-8859-2",
526
+ "iso_8859-2:1987"=>"iso-8859-2",
527
+ "l2"=>"iso-8859-2",
528
+ "latin2"=>"iso-8859-2",
529
+ "csisolatin3"=>"iso-8859-3",
530
+ "iso-8859-3"=>"iso-8859-3",
531
+ "iso-ir-109"=>"iso-8859-3",
532
+ "iso8859-3"=>"iso-8859-3",
533
+ "iso88593"=>"iso-8859-3",
534
+ "iso_8859-3"=>"iso-8859-3",
535
+ "iso_8859-3:1988"=>"iso-8859-3",
536
+ "l3"=>"iso-8859-3",
537
+ "latin3"=>"iso-8859-3",
538
+ "csisolatin4"=>"iso-8859-4",
539
+ "iso-8859-4"=>"iso-8859-4",
540
+ "iso-ir-110"=>"iso-8859-4",
541
+ "iso8859-4"=>"iso-8859-4",
542
+ "iso88594"=>"iso-8859-4",
543
+ "iso_8859-4"=>"iso-8859-4",
544
+ "iso_8859-4:1988"=>"iso-8859-4",
545
+ "l4"=>"iso-8859-4",
546
+ "latin4"=>"iso-8859-4",
547
+ "csisolatincyrillic"=>"iso-8859-5",
548
+ "cyrillic"=>"iso-8859-5",
549
+ "iso-8859-5"=>"iso-8859-5",
550
+ "iso-ir-144"=>"iso-8859-5",
551
+ "iso8859-5"=>"iso-8859-5",
552
+ "iso88595"=>"iso-8859-5",
553
+ "iso_8859-5"=>"iso-8859-5",
554
+ "iso_8859-5:1988"=>"iso-8859-5",
555
+ "arabic"=>"iso-8859-6",
556
+ "asmo-708"=>"iso-8859-6",
557
+ "csiso88596e"=>"iso-8859-6",
558
+ "csiso88596i"=>"iso-8859-6",
559
+ "csisolatinarabic"=>"iso-8859-6",
560
+ "ecma-114"=>"iso-8859-6",
561
+ "iso-8859-6"=>"iso-8859-6",
562
+ "iso-8859-6-e"=>"iso-8859-6",
563
+ "iso-8859-6-i"=>"iso-8859-6",
564
+ "iso-ir-127"=>"iso-8859-6",
565
+ "iso8859-6"=>"iso-8859-6",
566
+ "iso88596"=>"iso-8859-6",
567
+ "iso_8859-6"=>"iso-8859-6",
568
+ "iso_8859-6:1987"=>"iso-8859-6",
569
+ "csisolatingreek"=>"iso-8859-7",
570
+ "ecma-118"=>"iso-8859-7",
571
+ "elot_928"=>"iso-8859-7",
572
+ "greek"=>"iso-8859-7",
573
+ "greek8"=>"iso-8859-7",
574
+ "iso-8859-7"=>"iso-8859-7",
575
+ "iso-ir-126"=>"iso-8859-7",
576
+ "iso8859-7"=>"iso-8859-7",
577
+ "iso88597"=>"iso-8859-7",
578
+ "iso_8859-7"=>"iso-8859-7",
579
+ "iso_8859-7:1987"=>"iso-8859-7",
580
+ "sun_eu_greek"=>"iso-8859-7",
581
+ "csiso88598e"=>"iso-8859-8",
582
+ "csisolatinhebrew"=>"iso-8859-8",
583
+ "hebrew"=>"iso-8859-8",
584
+ "iso-8859-8"=>"iso-8859-8",
585
+ "iso-8859-8-e"=>"iso-8859-8",
586
+ "iso-ir-138"=>"iso-8859-8",
587
+ "iso8859-8"=>"iso-8859-8",
588
+ "iso88598"=>"iso-8859-8",
589
+ "iso_8859-8"=>"iso-8859-8",
590
+ "iso_8859-8:1988"=>"iso-8859-8",
591
+ "visual"=>"iso-8859-8",
592
+ "csisolatin6"=>"iso-8859-10",
593
+ "iso-8859-10"=>"iso-8859-10",
594
+ "iso-ir-157"=>"iso-8859-10",
595
+ "iso8859-10"=>"iso-8859-10",
596
+ "iso885910"=>"iso-8859-10",
597
+ "l6"=>"iso-8859-10",
598
+ "latin6"=>"iso-8859-10",
599
+ "iso-8859-13"=>"iso-8859-13",
600
+ "iso8859-13"=>"iso-8859-13",
601
+ "iso885913"=>"iso-8859-13",
602
+ "iso-8859-14"=>"iso-8859-14",
603
+ "iso8859-14"=>"iso-8859-14",
604
+ "iso885914"=>"iso-8859-14",
605
+ "csisolatin9"=>"iso-8859-15",
606
+ "iso-8859-15"=>"iso-8859-15",
607
+ "iso8859-15"=>"iso-8859-15",
608
+ "iso885915"=>"iso-8859-15",
609
+ "iso_8859-15"=>"iso-8859-15",
610
+ "l9"=>"iso-8859-15",
611
+ "iso-8859-16"=>"iso-8859-16",
612
+ "cskoi8r"=>"koi8-r",
613
+ "koi"=>"koi8-r",
614
+ "koi8"=>"koi8-r",
615
+ "koi8-r"=>"koi8-r",
616
+ "koi8_r"=>"koi8-r",
617
+ "koi8-ru"=>"koi8-u",
618
+ "koi8-u"=>"koi8-u",
619
+ "dos-874"=>"windows-874",
620
+ "iso-8859-11"=>"windows-874",
621
+ "iso8859-11"=>"windows-874",
622
+ "iso885911"=>"windows-874",
623
+ "tis-620"=>"windows-874",
624
+ "windows-874"=>"windows-874",
625
+ "cp1250"=>"windows-1250",
626
+ "windows-1250"=>"windows-1250",
627
+ "x-cp1250"=>"windows-1250",
628
+ "cp1251"=>"windows-1251",
629
+ "windows-1251"=>"windows-1251",
630
+ "x-cp1251"=>"windows-1251",
631
+ "ansi_x3.4-1968"=>"windows-1252",
632
+ "ascii"=>"windows-1252",
633
+ "cp1252"=>"windows-1252",
634
+ "cp819"=>"windows-1252",
635
+ "csisolatin1"=>"windows-1252",
636
+ "ibm819"=>"windows-1252",
637
+ "iso-8859-1"=>"windows-1252",
638
+ "iso-ir-100"=>"windows-1252",
639
+ "iso8859-1"=>"windows-1252",
640
+ "iso88591"=>"windows-1252",
641
+ "iso_8859-1"=>"windows-1252",
642
+ "iso_8859-1:1987"=>"windows-1252",
643
+ "l1"=>"windows-1252",
644
+ "latin1"=>"windows-1252",
645
+ "us-ascii"=>"windows-1252",
646
+ "windows-1252"=>"windows-1252",
647
+ "x-cp1252"=>"windows-1252",
648
+ "cp1253"=>"windows-1253",
649
+ "windows-1253"=>"windows-1253",
650
+ "x-cp1253"=>"windows-1253",
651
+ "cp1254"=>"windows-1254",
652
+ "csisolatin5"=>"windows-1254",
653
+ "iso-8859-9"=>"windows-1254",
654
+ "iso-ir-148"=>"windows-1254",
655
+ "iso8859-9"=>"windows-1254",
656
+ "iso88599"=>"windows-1254",
657
+ "iso_8859-9"=>"windows-1254",
658
+ "iso_8859-9:1989"=>"windows-1254",
659
+ "l5"=>"windows-1254",
660
+ "latin5"=>"windows-1254",
661
+ "windows-1254"=>"windows-1254",
662
+ "x-cp1254"=>"windows-1254",
663
+ "cp1255"=>"windows-1255",
664
+ "windows-1255"=>"windows-1255",
665
+ "x-cp1255"=>"windows-1255",
666
+ "cp1256"=>"windows-1256",
667
+ "windows-1256"=>"windows-1256",
668
+ "x-cp1256"=>"windows-1256",
669
+ "cp1257"=>"windows-1257",
670
+ "windows-1257"=>"windows-1257",
671
+ "x-cp1257"=>"windows-1257",
672
+ "cp1258"=>"windows-1258",
673
+ "windows-1258"=>"windows-1258",
674
+ "x-cp1258"=>"windows-1258",
675
+ "x-mac-cyrillic"=>"macCyrillic",
676
+ "x-mac-ukrainian"=>"macCyrillic",
677
+ "chinese"=>"gbk",
678
+ "csgb2312"=>"gbk",
679
+ "csiso58gb231280"=>"gbk",
680
+ "gb2312"=>"gbk",
681
+ "gb_2312"=>"gbk",
682
+ "gb_2312-80"=>"gbk",
683
+ "gbk"=>"gbk",
684
+ "iso-ir-58"=>"gbk",
685
+ "x-gbk"=>"gbk",
686
+ "gb18030"=>"gb18030",
687
+ "big5"=>"big5",
688
+ "big5-hkscs"=>"big5",
689
+ "cn-big5"=>"big5",
690
+ "csbig5"=>"big5",
691
+ "x-x-big5"=>"big5",
692
+ "cseucpkdfmtjapanese"=>"cp51932",
693
+ "euc-jp"=>"cp51932",
694
+ "x-euc-jp"=>"cp51932",
695
+ "csiso2022jp"=>"cp50221",
696
+ "iso-2022-jp"=>"cp50221",
697
+ "csshiftjis"=>"Windows-31J",
698
+ "ms932"=>"Windows-31J",
699
+ "ms_kanji"=>"Windows-31J",
700
+ "shift-jis"=>"Windows-31J",
701
+ "shift_jis"=>"Windows-31J",
702
+ "sjis"=>"Windows-31J",
703
+ "windows-31j"=>"Windows-31J",
704
+ "x-sjis"=>"Windows-31J",
705
+ "cseuckr"=>"euc-kr",
706
+ "csksc56011987"=>"euc-kr",
707
+ "euc-kr"=>"euc-kr",
708
+ "iso-ir-149"=>"euc-kr",
709
+ "korean"=>"euc-kr",
710
+ "ks_c_5601-1987"=>"euc-kr",
711
+ "ks_c_5601-1989"=>"euc-kr",
712
+ "ksc5601"=>"euc-kr",
713
+ "ksc_5601"=>"euc-kr",
714
+ "windows-949"=>"euc-kr",
715
+ "utf-16be"=>"utf-16be",
716
+ "utf-16"=>"utf-16le",
717
+ "utf-16le"=>"utf-16le",
718
+ } # :nodoc:
719
+
720
+ # :nodoc:
721
+ # return encoding or nil
722
+ # http://encoding.spec.whatwg.org/#concept-encoding-get
723
+ def self.get_encoding(label)
724
+ Encoding.find(WEB_ENCODINGS_[label.to_str.strip.downcase]) rescue nil
725
+ end
726
+ end # module URI
727
+
728
+ module Kernel
729
+
730
+ #
731
+ # Returns +uri+ converted to an URI object.
732
+ #
733
+ def URI(uri)
734
+ if uri.is_a?(URI::Generic)
735
+ uri
736
+ elsif uri = String.try_convert(uri)
737
+ URI.parse(uri)
738
+ else
739
+ raise ArgumentError,
740
+ "bad argument (expected URI object or URI string)"
741
+ end
742
+ end
743
+ module_function :URI
744
+ end