idnx 0.1.0 → 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 +35 -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 +93 -0
- metadata +8 -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
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
## [0.1.2] - 2026-11-11
|
|
4
|
+
|
|
5
|
+
* added missing license file.
|
|
6
|
+
* skip warnings when falling back to pure ruby version.
|
|
7
|
+
* remove pure ruby dead code for decoding.
|
|
8
|
+
|
|
9
|
+
## [0.1.1] - 2021-10-03
|
|
10
|
+
|
|
11
|
+
Added missing RBS sig files to the gemspec.
|
|
12
|
+
|
|
13
|
+
## [0.1.0] - 2021-09-04
|
|
14
|
+
|
|
15
|
+
### improvements
|
|
16
|
+
|
|
17
|
+
It ships RBS signatures for the main public API.
|
|
18
|
+
|
|
19
|
+
### compliance
|
|
20
|
+
|
|
21
|
+
`idnx` ships with a pure ruby punycode implementation (IDNA 2003), which will get loaded when `libidn2` isn't installed in the system. This was necessary for license compatibility, given that Apache 2.0 projects can rely on GPL dependencies (such as `libidn2`) but nnot exclusively.
|
|
22
|
+
|
|
23
|
+
## [0.0.1] - 2021-06-11
|
|
24
|
+
|
|
25
|
+
This is the initial release.
|
|
26
|
+
|
|
27
|
+
### Features
|
|
28
|
+
|
|
29
|
+
`idnx` ships with a single function, which translate Innternational domain names into Punycode names, which can be used for DNS requests:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
require "idnx"
|
|
33
|
+
|
|
34
|
+
Idnx.to_punycode("bücher.de") #=> "xn--bcher-kva.de"
|
|
35
|
+
```
|
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
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
module Idnx
|
|
2
|
+
VERSION: String
|
|
3
|
+
|
|
4
|
+
class Error < StandardError
|
|
5
|
+
end
|
|
6
|
+
|
|
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
|
|
45
|
+
|
|
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
|
|
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
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def self?.to_punycode: (String hostname) -> String
|
|
91
|
+
|
|
92
|
+
LIB: singleton(Idn2) | singleton(Windows) | singleton(Ruby)
|
|
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
|
|
@@ -35,6 +34,7 @@ extra_rdoc_files:
|
|
|
35
34
|
- LICENSE.txt
|
|
36
35
|
- README.md
|
|
37
36
|
files:
|
|
37
|
+
- CHANGELOG.md
|
|
38
38
|
- LICENSE.txt
|
|
39
39
|
- README.md
|
|
40
40
|
- lib/idnx.rb
|
|
@@ -42,13 +42,15 @@ files:
|
|
|
42
42
|
- lib/idnx/ruby.rb
|
|
43
43
|
- lib/idnx/version.rb
|
|
44
44
|
- lib/idnx/windows.rb
|
|
45
|
+
- sig/idnx.rbs
|
|
45
46
|
homepage: https://github.com/honeyryderchuck/idnx
|
|
46
|
-
licenses:
|
|
47
|
+
licenses:
|
|
48
|
+
- Apache 2.0
|
|
47
49
|
metadata:
|
|
48
50
|
homepage_uri: https://github.com/honeyryderchuck/idnx
|
|
49
51
|
source_code_uri: https://github.com/honeyryderchuck/idnx
|
|
50
52
|
changelog_uri: https://github.com/honeyryderchuck/idnx/-/blob/master/CHANGELOG.md
|
|
51
|
-
|
|
53
|
+
rubygems_mfa_required: 'true'
|
|
52
54
|
rdoc_options: []
|
|
53
55
|
require_paths:
|
|
54
56
|
- lib
|
|
@@ -63,8 +65,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
63
65
|
- !ruby/object:Gem::Version
|
|
64
66
|
version: '0'
|
|
65
67
|
requirements: []
|
|
66
|
-
rubygems_version:
|
|
67
|
-
signing_key:
|
|
68
|
+
rubygems_version: 4.0.20
|
|
68
69
|
specification_version: 4
|
|
69
70
|
summary: Converts International Domain Names into Punycode. It uses (via FFI) 'libidn2'
|
|
70
71
|
for Mac and Linux; for Windows, it uses native APIs.
|