idn_ffi 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in idn_ffi.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 'Konstantin Makarchev'
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,13 @@
1
+ #LibIdn FFI ruby binding
2
+
3
+ ```ruby
4
+ gem 'idn_ffi'
5
+ ```
6
+
7
+ ```ruby
8
+ IDNFFI.to_ascii "топ-site.рф"
9
+ => "xn---site-iyehw.xn--p1ai"
10
+
11
+ IDNFFI.to_unicode "xn---site-iyehw.xn--p1ai"
12
+ => "топ-site.рф"
13
+ ```
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rspec/core/rake_task'
5
+ task :default => :spec
6
+ RSpec::Core::RakeTask.new(:spec)
data/idn_ffi.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/idn_ffi/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Konstantin Makarchev"]
6
+ gem.email = ["kostya27@gmail.com"]
7
+ gem.description = %q{LibIdn FFI ruby binding}
8
+ gem.summary = %q{LibIdn FFI ruby binding}
9
+ gem.homepage = "https://github.com/kostya/idn_ffi"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "idn_ffi"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = IDNFFI::VERSION
17
+
18
+ gem.add_dependency "ffi"
19
+ gem.add_development_dependency "rake"
20
+ gem.add_development_dependency "rspec"
21
+ end
data/lib/idn_ffi.rb ADDED
@@ -0,0 +1,9 @@
1
+ require File.join(File.dirname(__FILE__), %w{ idn_ffi version } )
2
+ require File.join(File.dirname(__FILE__), %w{ idn_ffi idn_lib } )
3
+ require File.join(File.dirname(__FILE__), %w{ idn_ffi methods } )
4
+
5
+ module IDNFFI
6
+ extend IDNFFI::Methods
7
+
8
+ class Error < Exception; end
9
+ end
@@ -0,0 +1,10 @@
1
+ require 'ffi'
2
+
3
+ module IDNFFI::Lib
4
+ extend FFI::Library
5
+ ffi_lib 'idn'
6
+
7
+ attach_function :idna_to_ascii_8z, [:string, :pointer, :int], :int
8
+ attach_function :idna_to_unicode_8z8z, [:string, :pointer, :int], :int
9
+ end
10
+
@@ -0,0 +1,44 @@
1
+ module IDNFFI::Methods
2
+
3
+ # flags
4
+ IDNA_ALLOW_UNASSIGNED = 0x0001 # Don't reject strings containing unassigned Unicode code points.
5
+ IDNA_USE_STD3_ASCII_RULES = 0x0002 # Validate strings according to STD3 rules (i.e., normal host name rules).
6
+
7
+ def to_ascii(str, flags = IDNA_ALLOW_UNASSIGNED)
8
+ transform(:idna_to_ascii_8z, str, flags)
9
+ end
10
+
11
+ def to_unicode(str, flags = IDNA_ALLOW_UNASSIGNED)
12
+ transform(:idna_to_unicode_8z8z, str, flags)
13
+ end
14
+
15
+ private
16
+
17
+ UTF8 = "UTF-8"
18
+
19
+ if RUBY_VERSION >= "1.9"
20
+ def transform(method, str, flags)
21
+ return unless str
22
+ pointer = FFI::MemoryPointer.new :pointer
23
+ int = IDNFFI::Lib.send(method, str, pointer, flags)
24
+ raise Error, "bad answer from libidn #{ind}, http://www.gnu.org/software/libidn/reference/libidn-idna.html#IDNA-SUCCESS:CAPS" if int != 0
25
+ strptr = pointer.read_pointer()
26
+ result = strptr.read_string()
27
+ pointer.free
28
+ result.force_encoding(UTF8)
29
+ result
30
+ end
31
+ else
32
+ def transform(method, str, flags)
33
+ return unless str
34
+ pointer = FFI::MemoryPointer.new :pointer
35
+ int = IDNFFI::Lib.send(method, str, pointer, flags)
36
+ raise Error, "bad answer from libidn #{ind}, http://www.gnu.org/software/libidn/reference/libidn-idna.html#IDNA-SUCCESS:CAPS" if int != 0
37
+ strptr = pointer.read_pointer()
38
+ result = strptr.read_string()
39
+ pointer.free
40
+ result
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,3 @@
1
+ module IDNFFI
2
+ VERSION = "0.1"
3
+ end
data/spec/idn_spec.rb ADDED
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+ require 'rspec'
3
+ require 'idn_ffi'
4
+ require 'test_vectors'
5
+
6
+ describe "IDNFFI" do
7
+ describe "to_unicode" do
8
+ it "should pass all test cases" do
9
+ TESTCASES_JOSEFSSON.sort.each do |testcase, vector|
10
+ IDNFFI.to_unicode(vector[1]).should == vector[0]
11
+ end
12
+ end
13
+
14
+ it "should respect * and not try to decode it" do
15
+ IDNFFI.to_unicode("*.xn--mllerriis-l8a.com").should == "*.møllerriis.com"
16
+ end
17
+
18
+ it "should respect leading _ and not try to encode it" do
19
+ IDNFFI.to_unicode("_something.xn--mllerriis-l8a.com").should == "_something.møllerriis.com"
20
+ end
21
+
22
+ it "should return nil for nil" do
23
+ IDNFFI.to_unicode(nil).should be_nil
24
+ end
25
+
26
+ end
27
+
28
+ describe "to_ascii" do
29
+ it "should pass all test cases" do
30
+ TESTCASES_JOSEFSSON.sort.each do |testcase, vector|
31
+ IDNFFI.to_ascii(vector[0]).should == vector[1].downcase
32
+ end
33
+ end
34
+
35
+ it "should respect * and not try to encode it" do
36
+ IDNFFI.to_ascii("*.hello.com").should == "*.hello.com"
37
+ end
38
+
39
+ it "should respect leading _ and not try to encode it" do
40
+ IDNFFI.to_ascii("_something.example.org").should == "_something.example.org"
41
+ end
42
+
43
+ it "should return nil for nil" do
44
+ IDNFFI.to_ascii(nil).should be_nil
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,139 @@
1
+ # encoding: utf-8
2
+ # JOSEFSSON test vectors, taken from DRAFT-JOSEFSSON-IDN-TEST-VECTORS-00:
3
+ # http://www.gnu.org/software/libidn/draft-josefsson-idn-test-vectors.html
4
+ #
5
+ # Modifications:
6
+ # - omission of 5.20 since it is identical with 5.8 (case H below)
7
+
8
+ TESTCASES_JOSEFSSON = {
9
+ 'A' => [
10
+ [ 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643,
11
+ 0x0644, 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A,
12
+ 0x061F ].pack('U*'),
13
+ 'xn--egbpdaj6bu4bxfgehfvwxn'
14
+ ],
15
+
16
+ 'B' => [
17
+ [ 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D,
18
+ 0x6587 ].pack('U*'),
19
+ 'xn--ihqwcrb4cv8a8dqg056pqjye'
20
+ ],
21
+
22
+ 'C' => [
23
+ [ 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D,
24
+ 0x6587 ].pack('U*'),
25
+ 'xn--ihqwctvzc91f659drss3x8bo0yb'
26
+ ],
27
+
28
+ 'D' => [
29
+ [ 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073,
30
+ 0x0074, 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076,
31
+ 0x00ED, 0x010D, 0x0065, 0x0073, 0x006B, 0x0079 ].pack('U*'),
32
+ 'xn--Proprostnemluvesky-uyb24dma41a'
33
+ ],
34
+
35
+ 'E' => [
36
+ [ 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5,
37
+ 0x05D8, 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9,
38
+ 0x05DD, 0x05E2, 0x05D1, 0x05E8, 0x05D9, 0x05EA ].pack('U*'),
39
+ 'xn--4dbcagdahymbxekheh6e0a7fei0b'
40
+ ],
41
+
42
+ 'F' => [
43
+ [ 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928,
44
+ 0x094D, 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902,
45
+ 0x0928, 0x0939, 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938,
46
+ 0x0915, 0x0924, 0x0947, 0x0939, 0x0948, 0x0902 ].pack('U*'),
47
+ 'xn--i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd'
48
+ ],
49
+
50
+ 'G' => [
51
+ [ 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E,
52
+ 0x3092, 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044,
53
+ 0x306E, 0x304B ].pack('U*'),
54
+ 'xn--n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa'
55
+ ],
56
+
57
+ 'H' => [
58
+ [ 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435,
59
+ 0x043E, 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432,
60
+ 0x043E, 0x0440, 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443,
61
+ 0x0441, 0x0441, 0x043A, 0x0438 ].pack('U*'),
62
+ 'xn--b1abfaaepdrnnbgefbadotcwatmq2g4l'
63
+ ],
64
+
65
+ 'I' => [
66
+ [ 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F,
67
+ 0x0070, 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069,
68
+ 0x006D, 0x0070, 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074,
69
+ 0x0065, 0x0068, 0x0061, 0x0062, 0x006C, 0x0061, 0x0072, 0x0065,
70
+ 0x006E, 0x0045, 0x0073, 0x0070, 0x0061, 0x00F1, 0x006F,
71
+ 0x006C ].pack('U*'),
72
+ 'xn--PorqunopuedensimplementehablarenEspaol-fmd56a'
73
+ ],
74
+
75
+ 'J' => [
76
+ [ 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD,
77
+ 0x006B, 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3,
78
+ 0x0063, 0x0068, 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069,
79
+ 0x1EBF, 0x006E, 0x0067, 0x0056, 0x0069, 0x1EC7, 0x0074 ].pack('U*'),
80
+ 'xn--TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g'
81
+ ],
82
+
83
+ 'K' => [
84
+ [ 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148,
85
+ 0x751F ].pack('U*'),
86
+ 'xn--3B-ww4c5e180e575a65lsy2b'
87
+ ],
88
+
89
+ 'L' => [
90
+ [ 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069,
91
+ 0x0074, 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052,
92
+ 0x002D, 0x004D, 0x004F, 0x004E, 0x004B, 0x0045, 0x0059,
93
+ 0x0053 ].pack('U*'),
94
+ 'xn---with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n'
95
+ ],
96
+
97
+ 'M' => [
98
+ [ 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E,
99
+ 0x006F, 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061,
100
+ 0x0079, 0x002D, 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834,
101
+ 0x6240 ].pack('U*'),
102
+ 'xn--Hello-Another-Way--fc4qua05auwb3674vfr0b'
103
+ ],
104
+
105
+ 'N' => [
106
+ [ 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B,
107
+ 0x0032 ].pack('U*'),
108
+ 'xn--2-u9tlzr9756bt3uc0v'
109
+ ],
110
+
111
+ 'O' => [
112
+ [ 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069,
113
+ 0x3059, 0x308B, 0x0035, 0x79D2, 0x524D ].pack('U*'),
114
+ 'xn--MajiKoi5-783gue6qz075azm5e'
115
+ ],
116
+
117
+ 'P' => [
118
+ [ 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3,
119
+ 0x30D0 ].pack('U*'),
120
+ 'xn--de-jg4avhby1noc0d'
121
+ ],
122
+
123
+ 'Q' => [
124
+ [ 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067 ].pack('U*'),
125
+ 'xn--d9juau41awczczp'
126
+ ],
127
+
128
+ 'R' => [
129
+ [ 0x03B5, 0x03BB, 0x03BB, 0x03B7, 0x03BD, 0x03B9, 0x03BA,
130
+ 0x03AC ].pack('U*'),
131
+ 'xn--hxargifdar'
132
+ ],
133
+
134
+ 'S' => [
135
+ [ 0x0062, 0x006F, 0x006E, 0x0121, 0x0075, 0x0073, 0x0061, 0x0127,
136
+ 0x0127, 0x0061 ].pack('U*'),
137
+ 'xn--bonusaa-5bb1da'
138
+ ]
139
+ }
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: idn_ffi
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Konstantin Makarchev
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ffi
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: LibIdn FFI ruby binding
63
+ email:
64
+ - kostya27@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE
72
+ - README.md
73
+ - Rakefile
74
+ - idn_ffi.gemspec
75
+ - lib/idn_ffi.rb
76
+ - lib/idn_ffi/idn_lib.rb
77
+ - lib/idn_ffi/methods.rb
78
+ - lib/idn_ffi/version.rb
79
+ - spec/idn_spec.rb
80
+ - spec/test_vectors.rb
81
+ homepage: https://github.com/kostya/idn_ffi
82
+ licenses: []
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 1.8.24
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: LibIdn FFI ruby binding
105
+ test_files:
106
+ - spec/idn_spec.rb
107
+ - spec/test_vectors.rb
108
+ has_rdoc: