idnx 0.1.1 → 0.1.2
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +2 -1
- data/lib/idnx/idn2.rb +3 -1
- data/lib/idnx/ruby.rb +4 -96
- data/lib/idnx/version.rb +1 -1
- data/lib/idnx/windows.rb +4 -1
- data/lib/idnx.rb +2 -2
- data/sig/idnx.rbs +83 -2
- metadata +6 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f0b5da39f881e947e1c29b5fbe5eb3647071e30316c817e6b87eeeba1c34af90
|
|
4
|
+
data.tar.gz: 3d5afd606ab46635d3db135952efae893963c460d87487302e83f3925b49143c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a4c2583fc53027a4b37a6727f6ea0b40fe49ac84db9f1e35f687a79ff6924831e23d2bc259dc6fb86b0e6e89796fc05cf1a0b2901dbe9f8cfac02f7fb2a95bef
|
|
7
|
+
data.tar.gz: c28933fb3ae97ee2fe8c1eb9f80df6dff5fb66a063767db604f9ee7e9c49ff6ee5ac803f57c23488a6d3cc538f9d70c9bd5dabd9538df9a7a38545c5ddda33e8
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Idnx
|
|
2
2
|
|
|
3
|
+
[](http://rubygems.org/gems/idnx)
|
|
3
4
|
[](https://github.com/HoneyryderChuck/idnx/actions/workflows/test.yml)
|
|
4
|
-
|
|
5
|
+
[](https://honeyryderchuck.github.io/idnx/merged/#_AllFiles)
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
`idnx` provides a Ruby API for decoding Internationalized domain names into Punycode.
|
data/lib/idnx/idn2.rb
CHANGED
data/lib/idnx/ruby.rb
CHANGED
|
@@ -8,7 +8,6 @@ module Idnx
|
|
|
8
8
|
Punycode.encode_hostname(hostname)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
# :nocov:
|
|
12
11
|
# -*- coding: utf-8 -*-
|
|
13
12
|
#--
|
|
14
13
|
# punycode.rb - PunyCode encoder for the Domain Name library
|
|
@@ -78,12 +77,14 @@ module Idnx
|
|
|
78
77
|
# Returns the numeric value of a basic code point (for use in
|
|
79
78
|
# representing integers) in the range 0 to base-1, or nil if cp
|
|
80
79
|
# is does not represent a value.
|
|
81
|
-
DECODE_DIGIT =
|
|
80
|
+
DECODE_DIGIT = begin
|
|
81
|
+
map = {} #: Hash[Integer, Integer]
|
|
82
82
|
# ASCII A..Z map to 0..25
|
|
83
83
|
# ASCII a..z map to 0..25
|
|
84
84
|
(0..25).each { |i| map[65 + i] = map[97 + i] = i }
|
|
85
85
|
# ASCII 0..9 map to 26..35
|
|
86
86
|
(26..35).each { |i| map[22 + i] = i }
|
|
87
|
+
map
|
|
87
88
|
end
|
|
88
89
|
|
|
89
90
|
# Returns the basic code point whose value (when used for
|
|
@@ -109,7 +110,7 @@ module Idnx
|
|
|
109
110
|
|
|
110
111
|
# Encode a +string+ in Punycode
|
|
111
112
|
def encode(string)
|
|
112
|
-
input = string.unpack("U*")
|
|
113
|
+
input = string.unpack("U*") #: Array[Integer]
|
|
113
114
|
output = +""
|
|
114
115
|
|
|
115
116
|
# Initialize the state
|
|
@@ -201,99 +202,6 @@ module Idnx
|
|
|
201
202
|
end
|
|
202
203
|
end.join(DOT)
|
|
203
204
|
end
|
|
204
|
-
|
|
205
|
-
# Decode a +string+ encoded in Punycode
|
|
206
|
-
def decode(string)
|
|
207
|
-
# Initialize the state
|
|
208
|
-
n = INITIAL_N
|
|
209
|
-
i = 0
|
|
210
|
-
bias = INITIAL_BIAS
|
|
211
|
-
|
|
212
|
-
if j = string.rindex(DELIMITER)
|
|
213
|
-
b = string[0...j]
|
|
214
|
-
|
|
215
|
-
b.match(RE_NONBASIC) &&
|
|
216
|
-
raise(ArgumentError, "Illegal character is found in basic part: #{string.inspect}")
|
|
217
|
-
|
|
218
|
-
# Handle the basic code points
|
|
219
|
-
|
|
220
|
-
output = b.unpack("U*")
|
|
221
|
-
u = string[(j + 1)..-1]
|
|
222
|
-
else
|
|
223
|
-
output = []
|
|
224
|
-
u = string
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
# Main decoding loop: Start just after the last delimiter if any
|
|
228
|
-
# basic code points were copied; start at the beginning
|
|
229
|
-
# otherwise.
|
|
230
|
-
|
|
231
|
-
input = u.unpack("C*")
|
|
232
|
-
input_length = input.length
|
|
233
|
-
h = 0
|
|
234
|
-
out = output.length
|
|
235
|
-
|
|
236
|
-
while h < input_length
|
|
237
|
-
# Decode a generalized variable-length integer into delta,
|
|
238
|
-
# which gets added to i. The overflow checking is easier
|
|
239
|
-
# if we increase i as we go, then subtract off its starting
|
|
240
|
-
# value at the end to obtain delta.
|
|
241
|
-
|
|
242
|
-
oldi = i
|
|
243
|
-
w = 1
|
|
244
|
-
k = BASE
|
|
245
|
-
|
|
246
|
-
loop do
|
|
247
|
-
(digit = DECODE_DIGIT[input[h]]) ||
|
|
248
|
-
raise(ArgumentError, "Illegal character is found in non-basic part: #{string.inspect}")
|
|
249
|
-
h += 1
|
|
250
|
-
i += digit * w
|
|
251
|
-
raise BufferOverflowError if i > MAXINT
|
|
252
|
-
|
|
253
|
-
t = k <= bias ? TMIN : k - bias >= TMAX ? TMAX : k - bias
|
|
254
|
-
break if digit < t
|
|
255
|
-
|
|
256
|
-
w *= BASE - t
|
|
257
|
-
raise BufferOverflowError if w > MAXINT
|
|
258
|
-
|
|
259
|
-
k += BASE
|
|
260
|
-
(h < input_length) || raise(ArgumentError, "Malformed input given: #{string.inspect}")
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
# Adapt the bias
|
|
264
|
-
delta = oldi == 0 ? i / DAMP : (i - oldi) >> 1
|
|
265
|
-
delta += delta / (out + 1)
|
|
266
|
-
bias = 0
|
|
267
|
-
while delta > CUTOFF
|
|
268
|
-
delta /= LOBASE
|
|
269
|
-
bias += BASE
|
|
270
|
-
end
|
|
271
|
-
bias += (LOBASE + 1) * delta / (delta + SKEW)
|
|
272
|
-
|
|
273
|
-
# i was supposed to wrap around from out+1 to 0, incrementing
|
|
274
|
-
# n each time, so we'll fix that now:
|
|
275
|
-
|
|
276
|
-
q, i = i.divmod(out + 1)
|
|
277
|
-
n += q
|
|
278
|
-
raise BufferOverflowError if n > MAXINT
|
|
279
|
-
|
|
280
|
-
# Insert n at position i of the output:
|
|
281
|
-
|
|
282
|
-
output[i, 0] = n
|
|
283
|
-
|
|
284
|
-
out += 1
|
|
285
|
-
i += 1
|
|
286
|
-
end
|
|
287
|
-
output.pack("U*")
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
# Decode a hostname using IDN/Punycode algorithms
|
|
291
|
-
def decode_hostname(hostname)
|
|
292
|
-
hostname.gsub(/(\A|#{Regexp.quote(DOT)})#{Regexp.quote(PREFIX)}([^#{Regexp.quote(DOT)}]*)/o) do
|
|
293
|
-
Regexp.last_match(1) << decode(Regexp.last_match(2))
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
205
|
end
|
|
297
|
-
# :nocov:
|
|
298
206
|
end
|
|
299
207
|
end
|
data/lib/idnx/version.rb
CHANGED
data/lib/idnx/windows.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require "win32ole"
|
|
4
4
|
|
|
5
5
|
module Idnx
|
|
6
|
-
module
|
|
6
|
+
module Windows
|
|
7
7
|
extend FFI::Library
|
|
8
8
|
|
|
9
9
|
ffi_lib "Normaliz.dll"
|
|
@@ -100,6 +100,9 @@ module Idnx
|
|
|
100
100
|
|
|
101
101
|
unicode = utf8_ptr.read_string(utf8_ptr.size)
|
|
102
102
|
unicode.strip! # remove null-byte
|
|
103
|
+
unicode
|
|
103
104
|
end
|
|
104
105
|
end
|
|
106
|
+
|
|
107
|
+
LIB = Windows
|
|
105
108
|
end
|
data/lib/idnx.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Idnx
|
|
|
9
9
|
module_function
|
|
10
10
|
|
|
11
11
|
def to_punycode(hostname)
|
|
12
|
-
|
|
12
|
+
LIB.lookup(hostname)
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -21,6 +21,6 @@ else
|
|
|
21
21
|
rescue LoadError
|
|
22
22
|
# fallback to pure ruby punycode 2003 implementation
|
|
23
23
|
require "idnx/ruby"
|
|
24
|
-
|
|
24
|
+
LIB = Idnx::Ruby
|
|
25
25
|
end
|
|
26
26
|
end
|
data/sig/idnx.rbs
CHANGED
|
@@ -4,9 +4,90 @@ module Idnx
|
|
|
4
4
|
class Error < StandardError
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
module Idn2
|
|
8
|
+
extend FFI::Library
|
|
9
|
+
|
|
10
|
+
VERSION: String
|
|
11
|
+
IDN2_OK: Integer
|
|
12
|
+
IDN2_NFC_INPUT: Integer
|
|
13
|
+
IDN2_TRANSITIONAL: Integer
|
|
14
|
+
IDN2_NONTRANSITIONAL: Integer
|
|
15
|
+
|
|
16
|
+
FLAGS: Integer
|
|
17
|
+
|
|
18
|
+
def self?.lookup: (String hostname) -> String
|
|
19
|
+
|
|
20
|
+
def self?.idn2_lookup_ul: (String hostname, FFI::Pointer?, Integer flags) -> Integer
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def self?.idn2_strerror: (Integer code) -> String
|
|
24
|
+
|
|
25
|
+
def self?.idn2_free: (FFI::Pointer?) -> void
|
|
26
|
+
|
|
27
|
+
def self?.idn2_check_version: (FFI::Pointer?) -> void
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
module Windows
|
|
31
|
+
extend FFI::Library
|
|
32
|
+
|
|
33
|
+
IDN_MAX_LENGTH: Integer
|
|
34
|
+
MB_ERR_INVALID_CHARS: Integer
|
|
35
|
+
|
|
36
|
+
ERROR_INSUFFICIENT_BUFFER: Integer
|
|
37
|
+
ERROR_INVALID_FLAGS: Integer
|
|
38
|
+
ERROR_INVALID_NAME: Integer
|
|
39
|
+
ERROR_INVALID_PARAMETER: Integer
|
|
40
|
+
ERROR_NO_UNICODE_TRANSLATION: Integer
|
|
41
|
+
|
|
42
|
+
def self?.lookup: (String hostname) -> String
|
|
43
|
+
|
|
44
|
+
def self?.IdnToAscii: (Integer, FFI::Pointer?, Integer, FFI::Pointer?, Integer) -> Integer
|
|
8
45
|
|
|
9
|
-
|
|
46
|
+
def self?.MultiByteToWideChar: (Integer, Integer, String, Integer, FFI::Pointer?, Integer) -> Integer
|
|
47
|
+
|
|
48
|
+
def self?.WideCharToMultiByte: (Integer, Integer, FFI::Pointer?, Integer, FFI::Pointer?, Integer, FFI::Pointer?, FFI::Pointer?) -> Integer
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
module Ruby
|
|
10
52
|
def self?.lookup: (String hostname) -> String
|
|
53
|
+
|
|
54
|
+
module Punycode
|
|
55
|
+
BASE: Integer
|
|
56
|
+
TMIN: Integer
|
|
57
|
+
TMAX: Integer
|
|
58
|
+
SKEW: Integer
|
|
59
|
+
DAMP: Integer
|
|
60
|
+
INITIAL_BIAS: Integer
|
|
61
|
+
INITIAL_N: Integer
|
|
62
|
+
DELIMITER: String
|
|
63
|
+
|
|
64
|
+
MAXINT: Integer
|
|
65
|
+
|
|
66
|
+
LOBASE: Integer
|
|
67
|
+
CUTOFF: Integer
|
|
68
|
+
|
|
69
|
+
RE_NONBASIC: Regexp
|
|
70
|
+
|
|
71
|
+
DECODE_DIGIT: Hash[Integer, Integer]
|
|
72
|
+
|
|
73
|
+
ENCODE_DIGIT: ^(Integer d, bool flag) -> String
|
|
74
|
+
|
|
75
|
+
DOT: String
|
|
76
|
+
PREFIX: String
|
|
77
|
+
|
|
78
|
+
class ArgumentError < ::ArgumentError
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
class BufferOverflowError < ArgumentError
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def self?.encode: (String string) -> String
|
|
85
|
+
|
|
86
|
+
def self?.encode_hostname: (String hostname) -> String
|
|
87
|
+
end
|
|
11
88
|
end
|
|
89
|
+
|
|
90
|
+
def self?.to_punycode: (String hostname) -> String
|
|
91
|
+
|
|
92
|
+
LIB: singleton(Idn2) | singleton(Windows) | singleton(Ruby)
|
|
12
93
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: idnx
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- HoneyryderChuck
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: ffi
|
|
@@ -45,12 +44,13 @@ files:
|
|
|
45
44
|
- lib/idnx/windows.rb
|
|
46
45
|
- sig/idnx.rbs
|
|
47
46
|
homepage: https://github.com/honeyryderchuck/idnx
|
|
48
|
-
licenses:
|
|
47
|
+
licenses:
|
|
48
|
+
- Apache 2.0
|
|
49
49
|
metadata:
|
|
50
50
|
homepage_uri: https://github.com/honeyryderchuck/idnx
|
|
51
51
|
source_code_uri: https://github.com/honeyryderchuck/idnx
|
|
52
52
|
changelog_uri: https://github.com/honeyryderchuck/idnx/-/blob/master/CHANGELOG.md
|
|
53
|
-
|
|
53
|
+
rubygems_mfa_required: 'true'
|
|
54
54
|
rdoc_options: []
|
|
55
55
|
require_paths:
|
|
56
56
|
- lib
|
|
@@ -65,8 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
65
65
|
- !ruby/object:Gem::Version
|
|
66
66
|
version: '0'
|
|
67
67
|
requirements: []
|
|
68
|
-
rubygems_version:
|
|
69
|
-
signing_key:
|
|
68
|
+
rubygems_version: 4.0.20
|
|
70
69
|
specification_version: 4
|
|
71
70
|
summary: Converts International Domain Names into Punycode. It uses (via FFI) 'libidn2'
|
|
72
71
|
for Mac and Linux; for Windows, it uses native APIs.
|