├── VERSION ├── .gitignore ├── NOTICE ├── CHANGES ├── test ├── ts_IDN.rb ├── tc_Stringprep.rb ├── tc_Punycode.rb └── tc_Idna.rb ├── ext ├── idn.h ├── idn.c ├── extconf.rb ├── punycode.c ├── idna.c └── stringprep.c ├── Rakefile ├── idn-ruby.gemspec ├── README.md └── LICENSE /VERSION: -------------------------------------------------------------------------------- 1 | 0.1.5 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ext/*.so 2 | ext/*.o 3 | ext/Makefile 4 | tmp/ 5 | ext/mkmf.log 6 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | This product includes software developed by Erik Abele 2 | (http://www.codefaktor.de/). 3 | 4 | This software contains code derived from the Net::XMPP for Ruby 5 | project by Yuki Mitsui (http://netxmpp-ruby.jabberstudio.org/). 6 | -------------------------------------------------------------------------------- /CHANGES: -------------------------------------------------------------------------------- 1 | Changes with IDN 0.1.5 (2022-11-16) 2 | 3 | * Minor updates to support compilation of M1 silicon. 4 | 5 | Changes with IDN 0.1.4 (2021-11-02) 6 | 7 | * nfkc_normalize raises ArgumentError instead of returning nil for 8 | invalid utf-8 strings. 9 | 10 | Changes with IDN 0.1.3 (2021-11-01) 11 | 12 | * Fixed segv in latest ruby-head with bad utf-8 13 | 14 | Changes with IDN 0.1.2 (2021-06-10) 15 | 16 | * add missing includes 17 | * fix default encoding to use utf8 18 | 19 | Changes with IDN 0.1.1 [yanked] (2021-06-09) 20 | 21 | * Use xfree() only with memory allocated with xmalloc()/xrealloc(). Free 22 | IDN-allocated memory with idn_free() 23 | 24 | Changes with IDN 0.1.0 (2011-03-31) 25 | 26 | * Fix compilation errors in ruby 1.9.2p0 (2010-08-18 revision 29036). 27 | 28 | Changes with IDN 0.0.2 (2006-02-11) 29 | 30 | * Remove excessive xfree() if a call to stringprep_profile() returns an 31 | error. Fixes crash reported in PR #3088. 32 | 33 | * Add tests for invalid Stringprep strings and adjust names of already 34 | existing test methods. 35 | 36 | * Improve existing tests for IDN::Idna. 37 | 38 | Changes with IDN 0.0.1 (2005-09-26) 39 | 40 | * First release. 41 | -------------------------------------------------------------------------------- /test/ts_IDN.rb: -------------------------------------------------------------------------------- 1 | # Test suite for LibIDN Ruby Bindings. 2 | # 3 | # Copyright (c) 2005 Erik Abele. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # Please see the file called LICENSE for further details. 8 | # 9 | # You may also obtain a copy of the License at 10 | # 11 | # * http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | # This software is OSI Certified Open Source Software. 20 | # OSI Certified is a certification mark of the Open Source Initiative. 21 | 22 | require 'test/unit' 23 | 24 | # Construct absolute project path. 25 | #project_path = File.join(File.dirname(__FILE__), '..') 26 | 27 | # Add project directories to global LOAD_PATH ($:). 28 | #$:.unshift File.join(project_path, 'ext'), File.join(project_path, 'lib') 29 | 30 | # Require all testcase files. 31 | #Dir[File.join(project_path, 'test', 'tc_*.rb')].each { |tc| require tc } 32 | -------------------------------------------------------------------------------- /ext/idn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Erik Abele. All rights reserved. 3 | * Portions Copyright (c) 2005 Yuki Mitsui. All rights reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * Please see the file called LICENSE for further details. 8 | * 9 | * You may also obtain a copy of the License at 10 | * 11 | * * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * 19 | * This software is OSI Certified Open Source Software. 20 | * OSI Certified is a certification mark of the Open Source Initiative. 21 | */ 22 | 23 | #ifndef ___IDN_IDN_H_ 24 | #define ___IDN_IDN_H_ 25 | 26 | #include 27 | #include 28 | 29 | /* 30 | * idn.c 31 | */ 32 | extern VALUE mIDN; 33 | extern VALUE eIDNError; 34 | 35 | /* 36 | * idna.c 37 | */ 38 | extern VALUE mIdna; 39 | extern VALUE eIdnaError; 40 | 41 | void init_idna(void); 42 | 43 | /* 44 | * punycode.c 45 | */ 46 | extern VALUE mPunycode; 47 | extern VALUE ePunycodeError; 48 | 49 | void init_punycode(void); 50 | 51 | /* 52 | * stringprep.c 53 | */ 54 | extern VALUE mStringprep; 55 | extern VALUE eStringprepError; 56 | 57 | void init_stringprep(void); 58 | 59 | #endif /* ___IDN_IDN_H_ */ 60 | -------------------------------------------------------------------------------- /ext/idn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Erik Abele. All rights reserved. 3 | * Portions Copyright (c) 2005 Yuki Mitsui. All rights reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * Please see the file called LICENSE for further details. 8 | * 9 | * You may also obtain a copy of the License at 10 | * 11 | * * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * 19 | * This software is OSI Certified Open Source Software. 20 | * OSI Certified is a certification mark of the Open Source Initiative. 21 | */ 22 | 23 | #include 24 | #include "idn.h" 25 | 26 | /* 27 | * Document-class: IDN 28 | * The main module of LibIDN Ruby Bindings. 29 | * 30 | * === Example usage 31 | * 32 | * require 'idn' 33 | * include IDN 34 | * 35 | * ... 36 | */ 37 | 38 | VALUE mIDN; 39 | 40 | /* 41 | * Document-class: IDN::IDNError 42 | * The superclass for all exceptions raised by the IDN extension. 43 | */ 44 | 45 | VALUE eIDNError; 46 | 47 | /* 48 | * Module Initialization. 49 | */ 50 | 51 | void Init_idn(void) 52 | { 53 | mIDN = rb_define_module("IDN"); 54 | eIDNError = rb_define_class_under(mIDN, "IDNError", rb_eStandardError); 55 | 56 | init_idna(); 57 | init_punycode(); 58 | init_stringprep(); 59 | } 60 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'rake' 3 | require 'rake/clean' 4 | require 'rake/testtask' 5 | 6 | CLEAN << FileList[ 'ext/Makefile', 'ext/*.so', 'ext/*.o' ] 7 | 8 | begin 9 | require 'jeweler' 10 | rescue LoadError 11 | puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler" 12 | end 13 | 14 | Jeweler::Tasks.new do |gem| 15 | gem.name = 'idn-ruby' 16 | gem.summary = 'LibIDN Ruby Bindings.' 17 | gem.description = %q{ 18 | Ruby Bindings for the GNU LibIDN library, an implementation of the 19 | Stringprep, Punycode and IDNA specifications defined by the IETF 20 | Internationalized Domain Names (IDN) working group. 21 | 22 | Included are the most important parts of the Stringprep, Punycode 23 | and IDNA APIs like performing Stringprep processings, encoding to 24 | and decoding from Punycode strings and converting entire domain names 25 | to and from the ACE encoded form. 26 | } 27 | gem.email = 'deepfryed@gmail.com' 28 | gem.homepage = 'http://github.com/deepfryed/idn-ruby' 29 | gem.authors = ['Erik Abele', 'Bharanee Rathna'] 30 | gem.files = FileList['CHANGES', 'LICENSE', 'NOTICE', 'Rakefile', 'README', 'ext/*.{c,h}'] 31 | gem.extensions = FileList[ 'ext/**/extconf.rb' ] 32 | gem.test_files = FileList[ 'test/*.rb' ] 33 | end 34 | 35 | Jeweler::GemcutterTasks.new 36 | 37 | task :compile do 38 | Dir.chdir('ext') do 39 | system('ruby extconf.rb && make') or raise 'failed to compile extension' 40 | end 41 | end 42 | 43 | Rake::TestTask.new(:test) do |test| 44 | test.libs << 'ext' 45 | test.pattern = 'test/*.rb' 46 | test.verbose = true 47 | end 48 | 49 | task :test => [ :compile ] 50 | task :default => :test 51 | -------------------------------------------------------------------------------- /idn-ruby.gemspec: -------------------------------------------------------------------------------- 1 | # Generated by jeweler 2 | # DO NOT EDIT THIS FILE DIRECTLY 3 | # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' 4 | # -*- encoding: utf-8 -*- 5 | 6 | Gem::Specification.new do |s| 7 | s.name = %q{idn-ruby} 8 | s.version = "0.1.5" 9 | 10 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= 11 | s.authors = ["Erik Abele", "Bharanee Rathna"] 12 | s.date = %q{2021-11-01} 13 | s.description = %q{ 14 | Ruby Bindings for the GNU LibIDN library, an implementation of the 15 | Stringprep, Punycode and IDNA specifications defined by the IETF 16 | Internationalized Domain Names (IDN) working group. 17 | 18 | Included are the most important parts of the Stringprep, Punycode 19 | and IDNA APIs like performing Stringprep processings, encoding to 20 | and decoding from Punycode strings and converting entire domain names 21 | to and from the ACE encoded form. 22 | } 23 | s.email = %q{deepfryed@gmail.com} 24 | s.extensions = ["ext/extconf.rb"] 25 | s.extra_rdoc_files = [ 26 | "LICENSE", 27 | "README.md" 28 | ] 29 | s.files = [ 30 | "CHANGES", 31 | "LICENSE", 32 | "NOTICE", 33 | "README.md", 34 | "Rakefile", 35 | "ext/idn.c", 36 | "ext/idn.h", 37 | "ext/idna.c", 38 | "ext/punycode.c", 39 | "ext/stringprep.c" 40 | ] 41 | s.homepage = %q{http://github.com/deepfryed/idn-ruby} 42 | s.require_paths = ["lib"] 43 | s.rubygems_version = %q{1.3.7} 44 | s.summary = %q{LibIDN Ruby Bindings.} 45 | s.test_files = ["test/ts_IDN.rb", "test/tc_Punycode.rb", "test/tc_Stringprep.rb", "test/tc_Idna.rb"] 46 | 47 | if s.respond_to? :specification_version then 48 | current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION 49 | s.specification_version = 3 50 | 51 | if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then 52 | else 53 | end 54 | else 55 | end 56 | end 57 | 58 | -------------------------------------------------------------------------------- /ext/extconf.rb: -------------------------------------------------------------------------------- 1 | # Makefile configuration for LibIDN Ruby Bindings. 2 | # 3 | # Copyright (c) 2005 Erik Abele. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # Please see the file called LICENSE for further details. 8 | # 9 | # You may also obtain a copy of the License at 10 | # 11 | # * http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | # This software is OSI Certified Open Source Software. 20 | # OSI Certified is a certification mark of the Open Source Initiative. 21 | 22 | require 'mkmf' 23 | 24 | pkg_config 'libidn' 25 | 26 | @libs = ['idn'] 27 | @headers = ['idna.h', 'punycode.h', 'stringprep.h'] 28 | 29 | INFO_NOTE = < [ "Nameprep", "\xC5\x83\xCD\xBA", "\xC5\x84 \xCE\xB9" ], 33 | 'B' => [ "Nodeprep", "\xE1\xBE\xB7", "\xE1\xBE\xB6\xCE\xB9" ], 34 | 'C' => [ "Resourceprep", "foo@bar", "foo@bar" ], 35 | 'D' => [ "ISCSIprep", "Example-Name", "example-name" ], 36 | 'E' => [ "SASLprep", "Example\xC2\xA0Name", "Example Name" ] 37 | } 38 | 39 | # STRINGPREP_INVALID test vectors: invalid input strings and their 40 | # corresponding profile. 41 | 42 | TESTCASES_STRINGPREP_INVALID = { 43 | 'A' => [ "Nodeprep", "toto@a/a" ] 44 | } 45 | 46 | # NFKC test vectors: UTF-8 encoded strings and the corresponding 47 | # normalized form, according to NFKC normalization mode. 48 | 49 | TESTCASES_NFKC = { 50 | 'A' => [ "\xC2\xB5", "\xCE\xBC" ], 51 | 'B' => [ "\xC2\xAA", "\x61" ] 52 | } 53 | 54 | def setup 55 | end 56 | 57 | def teardown 58 | end 59 | 60 | def test_with_profile_STRINGPREP 61 | TESTCASES_STRINGPREP.each do |key, val| 62 | rc = Stringprep.with_profile(val[1], val[0]) 63 | assert_equal(val[2], rc, "TestCase #{key} failed") 64 | end 65 | end 66 | 67 | def test_with_profile_STRINGPREP_INVALID 68 | TESTCASES_STRINGPREP_INVALID.each do |key, val| 69 | assert_raise(Stringprep::StringprepError, "TestCase #{key} failed") do 70 | Stringprep.with_profile(val[0], val[1]) 71 | end 72 | end 73 | end 74 | 75 | def test_nfkc_normalize_NFKC 76 | TESTCASES_NFKC.each do |key, val| 77 | rc = Stringprep.nfkc_normalize(val[0]) 78 | assert_equal(val[1], rc, "TestCase #{key} failed") 79 | end 80 | 81 | assert_raise(ArgumentError, "TestCase \xE8 failed") do 82 | Stringprep.nfkc_normalize("\xE8") 83 | end 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /ext/punycode.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Erik Abele. All rights reserved. 3 | * Portions Copyright (c) 2005 Yuki Mitsui. All rights reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * Please see the file called LICENSE for further details. 8 | * 9 | * You may also obtain a copy of the License at 10 | * 11 | * * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * 19 | * This software is OSI Certified Open Source Software. 20 | * OSI Certified is a certification mark of the Open Source Initiative. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "idn.h" 28 | #include "idn-free.h" 29 | 30 | /* 31 | * Document-class: IDN::Punycode 32 | * The Punycode module of LibIDN Ruby Bindings. 33 | * 34 | * === Example usage 35 | * 36 | * require 'idn' 37 | * include IDN 38 | * 39 | * str = Punycode.decode('egbpdaj6bu4bxfgehfvwxn') 40 | */ 41 | 42 | VALUE mPunycode; 43 | 44 | /* 45 | * Document-class: IDN::Punycode::PunycodeError 46 | * The base class for all exceptions raised by the IDN::Punycode module. 47 | */ 48 | 49 | VALUE ePunycodeError; 50 | 51 | /* 52 | * call-seq: 53 | * IDN::Punycode.encode(string) => string 54 | * 55 | * Converts a string in UTF-8 format to Punycode. 56 | * 57 | * Raises IDN::Punycode::PunycodeError on failure. 58 | */ 59 | 60 | static VALUE encode(VALUE self, VALUE str) 61 | { 62 | int rc; 63 | punycode_uint *ustr; 64 | size_t len; 65 | size_t buflen = 0x100; 66 | char *buf = NULL; 67 | VALUE retv; 68 | 69 | str = rb_check_convert_type(str, T_STRING, "String", "to_s"); 70 | ustr = stringprep_utf8_to_ucs4(RSTRING_PTR(str), RSTRING_LEN(str), &len); 71 | 72 | while (1) { 73 | buf = xrealloc(buf, buflen); 74 | 75 | if (buf == NULL) { 76 | idn_free(ustr); 77 | rb_raise(rb_eNoMemError, "cannot allocate memory (%d bytes)", (uint32_t)buflen); 78 | return Qnil; 79 | } 80 | 81 | rc = punycode_encode(len, ustr, NULL, &buflen, buf); 82 | 83 | if (rc == PUNYCODE_SUCCESS) { 84 | break; 85 | } else if (rc == PUNYCODE_BIG_OUTPUT) { 86 | buflen += 0x100; 87 | } else { 88 | idn_free(ustr); 89 | xfree(buf); 90 | rb_raise(ePunycodeError, "%s (%d)", punycode_strerror(rc), rc); 91 | return Qnil; 92 | } 93 | } 94 | 95 | retv = rb_str_new(buf, buflen); 96 | idn_free(ustr); 97 | xfree(buf); 98 | return retv; 99 | } 100 | 101 | /* 102 | * call-seq: 103 | * IDN::Punycode.decode(string) => string 104 | * 105 | * Converts Punycode to a string in UTF-8 format. 106 | * 107 | * Raises IDN::Punycode::PunycodeError on failure. 108 | */ 109 | 110 | static VALUE decode(VALUE self, VALUE str) 111 | { 112 | int rc; 113 | punycode_uint *ustr; 114 | size_t len; 115 | char *buf = NULL; 116 | VALUE retv; 117 | 118 | str = rb_check_convert_type(str, T_STRING, "String", "to_s"); 119 | 120 | len = RSTRING_LEN(str); 121 | ustr = xmalloc(len * sizeof(punycode_uint)); 122 | 123 | if (ustr == NULL) { 124 | rb_raise(rb_eNoMemError, "cannot allocate memory (%d bytes)", (uint32_t)len); 125 | return Qnil; 126 | } 127 | 128 | rc = punycode_decode(RSTRING_LEN(str), RSTRING_PTR(str), 129 | &len, ustr, NULL); 130 | 131 | if (rc != PUNYCODE_SUCCESS) { 132 | xfree(ustr); 133 | rb_raise(ePunycodeError, "%s (%d)", punycode_strerror(rc), rc); 134 | return Qnil; 135 | } 136 | 137 | buf = stringprep_ucs4_to_utf8(ustr, len, NULL, &len); 138 | retv = rb_enc_str_new(buf, len, rb_utf8_encoding()); 139 | xfree(ustr); 140 | idn_free(buf); 141 | return retv; 142 | } 143 | 144 | /* 145 | * Module Initialization. 146 | */ 147 | 148 | void init_punycode(void) 149 | { 150 | #ifdef mIDN_RDOC_HACK 151 | mIDN = rb_define_module("IDN"); 152 | eIDNError = rb_define_class_under(mIDN, "IDNError", rb_eStandardError); 153 | #endif 154 | 155 | mPunycode = rb_define_module_under(mIDN, "Punycode"); 156 | ePunycodeError = rb_define_class_under(mPunycode, "PunycodeError", 157 | eIDNError); 158 | 159 | rb_define_singleton_method(mPunycode, "encode", encode, 1); 160 | rb_define_singleton_method(mPunycode, "decode", decode, 1); 161 | } 162 | -------------------------------------------------------------------------------- /ext/idna.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005 Erik Abele. All rights reserved. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * Please see the file called LICENSE for further details. 7 | * 8 | * You may also obtain a copy of the License at 9 | * 10 | * * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * This software is OSI Certified Open Source Software. 19 | * OSI Certified is a certification mark of the Open Source Initiative. 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include "idn.h" 26 | #include "idn-free.h" 27 | 28 | /* 29 | * Document-class: IDN::Idna 30 | * The Idna module of LibIDN Ruby Bindings. 31 | * 32 | * === Example usage 33 | * 34 | * require 'idn' 35 | * include IDN 36 | * 37 | * puts 'ACE-Prefix: ' + Idna::ACE_PREFIX 38 | * 39 | * domain = Idna.toUnicode('xn--rksmrgs-5wao1o.josefsson.org', 40 | * Idna::USE_STD3_ASCII_RULES | Idna::ALLOW_UNASSIGNED) 41 | * 42 | * === Constants 43 | * 44 | * ACE_PREFIX 45 | * - The ACE prefix: 'xn--'. 46 | * 47 | * ALLOW_UNASSIGNED 48 | * - Used as flag for toASCII/toUnicode. 49 | * 50 | * USE_STD3_ASCII_RULES 51 | * - Used as flag for toASCII/toUnicode. 52 | */ 53 | 54 | VALUE mIdna; 55 | 56 | /* 57 | * Document-class: IDN::Idna::IdnaError 58 | * The base class for all exceptions raised by the IDN::Idna module. 59 | */ 60 | 61 | VALUE eIdnaError; 62 | 63 | /* 64 | * call-seq: 65 | * IDN::Idna.toASCII(string, flags=nil) => string 66 | * 67 | * Converts a domain name in UTF-8 format into an ASCII string. The domain 68 | * name may contain several labels, separated by dots. 69 | * 70 | * Raises IDN::Idna::IdnaError on failure. 71 | */ 72 | 73 | static VALUE toASCII(int argc, VALUE argv[], VALUE self) 74 | { 75 | int rc; 76 | char *buf; 77 | VALUE str, flags, retv; 78 | 79 | rb_scan_args(argc, argv, "11", &str, &flags); 80 | str = rb_check_convert_type(str, T_STRING, "String", "to_s"); 81 | 82 | if (flags != Qnil) { 83 | Check_Type(flags, T_FIXNUM); 84 | flags = FIX2INT(flags); 85 | } else { 86 | flags = 0x0000; 87 | } 88 | 89 | rc = idna_to_ascii_8z(RSTRING_PTR(str), &buf, flags); 90 | 91 | if (rc != IDNA_SUCCESS) { 92 | idn_free(buf); 93 | rb_raise(eIdnaError, "%s (%d)", idna_strerror(rc), rc); 94 | return Qnil; 95 | } 96 | 97 | retv = rb_utf8_str_new_cstr(buf); 98 | idn_free(buf); 99 | return retv; 100 | } 101 | 102 | /* 103 | * call-seq: 104 | * IDN::Idna.toUnicode(string, flags=nil) => string 105 | * 106 | * Converts a possibly ACE encoded domain name in UTF-8 format into an 107 | * UTF-8 string. The domain name may contain several labels, separated 108 | * by dots. 109 | * 110 | * Raises IDN::Idna::IdnaError on failure. 111 | */ 112 | 113 | static VALUE toUnicode(int argc, VALUE argv[], VALUE self) 114 | { 115 | int rc; 116 | char *buf; 117 | VALUE str, flags, retv; 118 | 119 | rb_scan_args(argc, argv, "11", &str, &flags); 120 | str = rb_check_convert_type(str, T_STRING, "String", "to_s"); 121 | 122 | if (flags != Qnil) { 123 | Check_Type(flags, T_FIXNUM); 124 | flags = FIX2INT(flags); 125 | } else { 126 | flags = 0x0000; 127 | } 128 | 129 | rc = idna_to_unicode_8z8z(RSTRING_PTR(str), &buf, flags); 130 | 131 | if (rc != IDNA_SUCCESS) { 132 | idn_free(buf); 133 | rb_raise(eIdnaError, "%s (%d)", idna_strerror(rc), rc); 134 | return Qnil; 135 | } 136 | 137 | retv = rb_enc_str_new(buf, strlen(buf), rb_utf8_encoding()); 138 | idn_free(buf); 139 | return retv; 140 | } 141 | 142 | /* 143 | * Module Initialization. 144 | */ 145 | 146 | void init_idna(void) 147 | { 148 | #ifdef mIDN_RDOC_HACK 149 | mIDN = rb_define_module("IDN"); 150 | eIDNError = rb_define_class_under(mIDN, "IDNError", rb_eStandardError); 151 | #endif 152 | 153 | mIdna = rb_define_module_under(mIDN, "Idna"); 154 | eIdnaError = rb_define_class_under(mIdna, "IdnaError", eIDNError); 155 | 156 | rb_define_const(mIdna, "ACE_PREFIX", 157 | rb_utf8_str_new_cstr(IDNA_ACE_PREFIX)); 158 | rb_define_const(mIdna, "ALLOW_UNASSIGNED", 159 | INT2FIX(IDNA_ALLOW_UNASSIGNED)); 160 | rb_define_const(mIdna, "USE_STD3_ASCII_RULES", 161 | INT2FIX(IDNA_USE_STD3_ASCII_RULES)); 162 | 163 | rb_define_singleton_method(mIdna, "toASCII", toASCII, -1); 164 | rb_define_singleton_method(mIdna, "toUnicode", toUnicode, -1); 165 | } 166 | -------------------------------------------------------------------------------- /ext/stringprep.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2005-2006 Erik Abele. All rights reserved. 3 | * Portions Copyright (c) 2005 Yuki Mitsui. All rights reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * Please see the file called LICENSE for further details. 8 | * 9 | * You may also obtain a copy of the License at 10 | * 11 | * * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * 19 | * This software is OSI Certified Open Source Software. 20 | * OSI Certified is a certification mark of the Open Source Initiative. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include "idn.h" 27 | #include "idn-free.h" 28 | 29 | /* 30 | * Document-class: IDN::Stringprep 31 | * The Stringprep module of LibIDN Ruby Bindings. 32 | * 33 | * === Example usage 34 | * 35 | * require 'idn' 36 | * include IDN 37 | * 38 | * str = Stringprep.with_profile('FOO', 'Nameprep') 39 | */ 40 | 41 | VALUE mStringprep; 42 | 43 | /* 44 | * Document-class: IDN::Stringprep::StringprepError 45 | * The base class for all exceptions raised by the IDN::Stringprep module. 46 | */ 47 | 48 | VALUE eStringprepError; 49 | 50 | /* 51 | * Internal helper function: 52 | * stringprep_internal 53 | * 54 | * Prepares the given string in UTF-8 format according to the given 55 | * stringprep profile name. See the various public wrapper functions 56 | * below for details. 57 | * 58 | * Raises IDN::Stringprep::StringprepError on failure. 59 | */ 60 | 61 | static VALUE stringprep_internal(VALUE str, const char *profile) 62 | { 63 | int rc; 64 | char *buf; 65 | VALUE retv; 66 | 67 | str = rb_check_convert_type(str, T_STRING, "String", "to_s"); 68 | rc = stringprep_profile(RSTRING_PTR(str), &buf, profile, 0); 69 | 70 | if (rc != STRINGPREP_OK) { 71 | rb_raise(eStringprepError, "%s (%d)", stringprep_strerror(rc), rc); 72 | return Qnil; 73 | } 74 | 75 | retv = rb_utf8_str_new_cstr(buf); 76 | idn_free(buf); 77 | return retv; 78 | } 79 | 80 | /* 81 | * call-seq: 82 | * IDN::Stringprep.nameprep(string) => string 83 | * 84 | * Prepares a string in UTF-8 format according to the 'Nameprep' 85 | * profile. 86 | * 87 | * Raises IDN::Stringprep::StringprepError on failure. 88 | */ 89 | 90 | static VALUE nameprep(VALUE self, VALUE str) 91 | { 92 | return stringprep_internal(str, "Nameprep"); 93 | } 94 | 95 | /* 96 | * call-seq: 97 | * IDN::Stringprep.nodeprep(string) => string 98 | * 99 | * Prepares a string in UTF-8 format according to the 'Nodeprep' 100 | * profile. 101 | * 102 | * Raises IDN::Stringprep::StringprepError on failure. 103 | */ 104 | 105 | static VALUE nodeprep(VALUE self, VALUE str) 106 | { 107 | return stringprep_internal(str, "Nodeprep"); 108 | } 109 | 110 | /* 111 | * call-seq: 112 | * IDN::Stringprep.resourceprep(string) => string 113 | * 114 | * Prepares a string in UTF-8 format according to the 'Resourceprep' 115 | * profile. 116 | * 117 | * Raises IDN::Stringprep::StringprepError on failure. 118 | */ 119 | 120 | static VALUE resourceprep(VALUE self, VALUE str) 121 | { 122 | return stringprep_internal(str, "Resourceprep"); 123 | } 124 | 125 | /* 126 | * call-seq: 127 | * IDN::Stringprep.with_profile(string, profile) => string 128 | * 129 | * Prepares a string in UTF-8 format according to the given stringprep 130 | * profile name which must be one of the internally supported stringprep 131 | * profiles (for details see IANA's Profile Names in RFC3454). 132 | * 133 | * Raises IDN::Stringprep::StringprepError on failure. 134 | */ 135 | 136 | static VALUE with_profile(VALUE self, VALUE str, VALUE profile) 137 | { 138 | profile = rb_check_convert_type(profile, T_STRING, "String", "to_s"); 139 | return stringprep_internal(str, RSTRING_PTR(profile)); 140 | } 141 | 142 | /* 143 | * call-seq: 144 | * IDN::Stringprep.nfkc_normalize(string) => string 145 | * 146 | * Converts a string in UTF-8 format into canonical form, standardizing 147 | * such issues as whether a character with an accent is represented as a 148 | * base character and combining accent or as a single precomposed character. 149 | */ 150 | 151 | static VALUE nfkc_normalize(VALUE self, VALUE str) 152 | { 153 | char *buf; 154 | VALUE retv; 155 | 156 | str = rb_check_convert_type(str, T_STRING, "String", "to_s"); 157 | buf = stringprep_utf8_nfkc_normalize(RSTRING_PTR(str), RSTRING_LEN(str)); 158 | if (!buf) { 159 | rb_raise(rb_eArgError, "Invalid string or encoding, normalize failed"); 160 | return Qnil; 161 | } 162 | retv = rb_utf8_str_new_cstr(buf); 163 | idn_free(buf); 164 | return retv; 165 | } 166 | 167 | /* 168 | * Module Initialization. 169 | */ 170 | 171 | void init_stringprep(void) 172 | { 173 | #ifdef mIDN_RDOC_HACK 174 | mIDN = rb_define_module("IDN"); 175 | eIDNError = rb_define_class_under(mIDN, "IDNError", rb_eStandardError); 176 | #endif 177 | 178 | mStringprep = rb_define_module_under(mIDN, "Stringprep"); 179 | eStringprepError = rb_define_class_under(mStringprep, "StringprepError", 180 | eIDNError); 181 | 182 | rb_define_singleton_method(mStringprep, "nameprep", nameprep, 1); 183 | rb_define_singleton_method(mStringprep, "nodeprep", nodeprep, 1); 184 | rb_define_singleton_method(mStringprep, "resourceprep", resourceprep, 1); 185 | rb_define_singleton_method(mStringprep, "with_profile", with_profile, 2); 186 | rb_define_singleton_method(mStringprep, "nfkc_normalize", nfkc_normalize, 1); 187 | } 188 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LibIDN Ruby Bindings 2 | 3 | Version 0.1.2 4 | 5 | Ruby Bindings for the GNU LibIDN library, an implementation of the 6 | Stringprep, Punycode and IDNA specifications defined by the IETF 7 | Internationalized Domain Names (IDN) working group. 8 | 9 | Included are the most important parts of the Stringprep, Punycode 10 | and IDNA APIs like performing Stringprep processings, encoding to 11 | and decoding from Punycode strings and converting entire domain names 12 | to and from the ACE encoded form. 13 | 14 | The latest version of the LibIDN Ruby Bindings project and its 15 | documentation can always be found at 16 | 17 | * https://github.com/deepfryed/idn-ruby 18 | 19 | The original version can be found at, 20 | 21 | * http://rubyforge.org/projects/idn 22 | 23 | See the CHANGES file for detailed information on the changes of every 24 | released version. 25 | 26 | 27 | ### Requirements 28 | 29 | * [GNU LibIDN](http://www.gnu.org/software/libidn/) Library 30 | 31 | * [Rake](http://rubyforge.org/projects/rake) to run the tests and generate 32 | the documentation 33 | 34 | * [RubyGems](http://docs.rubygems.org/) to produce a Gem package 35 | 36 | * Ruby 1.9.1 or above. Patches welcome to make this work in 1.8.7 37 | 38 | 39 | ### Installation 40 | 41 | You need GNU LibIDN installed first. 42 | 43 | * On MacOS you can install it with `brew install libidn` 44 | * On Debian flavours of Linux `apt-get install libidn11-dev` 45 | 46 | You can easily install the LibIDN Ruby Bindings by following one of the 47 | ways outlined below: 48 | 49 | #### Automatic installation and management with RubyGems 50 | 51 | Simply invoke the standard RubyGems commands (install, update, ...), 52 | for example: 53 | 54 | ```bash 55 | gem install --remote idn-ruby 56 | ``` 57 | 58 | or if the GNU LibIDN library can only be found in a non-standard location 59 | 60 | ```bash 61 | gem install --remote idn-ruby \ 62 | --with-idn-dir=/path/to/non/standard/location 63 | ``` 64 | 65 | or in an even more complex setup 66 | 67 | ```bash 68 | gem install --remote idn-ruby -- \ 69 | --with-idn-lib=/path/to/non/standard/location/lib \ 70 | --with-idn-include=/path/to/non/standard/location/include 71 | ``` 72 | 73 | #### Apple silicon 74 | ``` 75 | gem install idn-ruby -- --with-idn-dir=$(brew --prefix libidn) 76 | ``` 77 | 78 | #### Semi-automatic installation with Rake 79 | 80 | If you are not able to or don't want to use RubyGems you can simply 81 | download the latest release and install it with the help of Rake: 82 | 83 | ```bash 84 | tar -xvzf idn-x.x.x.tar.gz 85 | cd idn-x.x.x 86 | 87 | rake install 88 | ``` 89 | 90 | or if the GNU LibIDN library can only be found in a non-standard location 91 | 92 | ```bash 93 | rake install IDN_DIR=/path/to/non/standard/location 94 | ``` 95 | 96 | You can also run the tests or generate the documentation; just call Rake 97 | with the '--tasks' parameter to get an overview of the available tasks: 98 | 99 | ```bash 100 | rake --tasks 101 | ``` 102 | 103 | #### Manual installation with extconf.rb 104 | 105 | If you are not able to or don't want to use even Rake then you will have to 106 | do a little bit more work by yourself: 107 | 108 | ```bash 109 | tar -xvzf idn-x.x.x.tar.gz 110 | cd idn-x.x.x/ext 111 | 112 | ruby extconf.rb 113 | ``` 114 | 115 | or if the GNU LibIDN library can only be found in a non-standard location 116 | 117 | ```bash 118 | ruby extconf.rb \ 119 | --with-idn-dir=/path/to/non/standard/location 120 | ``` 121 | 122 | or in an even more complex setup 123 | 124 | ```bash 125 | ruby extconf.rb \ 126 | --with-idn-lib=/path/to/non/standard/location/lib \ 127 | --with-idn-include=/path/to/non/standard/location/include 128 | ``` 129 | 130 | and finally 131 | 132 | ```bash 133 | make 134 | sudo make install 135 | ``` 136 | 137 | 138 | ### Documentation 139 | 140 | The complete documentation is available online at 141 | 142 | * http://rubydoc.info/github/deepfryed/idn-ruby/master/frames 143 | 144 | #### Example usage 145 | 146 | ```ruby 147 | require 'idn' 148 | include IDN 149 | 150 | puts 'Idna.toUnicode: ' + Idna.toUnicode('xn--rksmrgs-5wao1o.josefsson.org') 151 | puts 'Punycode.decode: ' + Punycode.decode('egbpdaj6bu4bxfgehfvwxn') 152 | puts 'Stringprep.with_profile: ' + Stringprep.with_profile('FOO', 'Nameprep') 153 | ``` 154 | 155 | 156 | ### References 157 | 158 | [GNU LibIDN] 159 | An implementation of the Stringprep, Punycode and IDNA specifications 160 | defined by the IETF Internationalized Domain Names (IDN) working group, 161 | used for internationalized domain names. The package is available under 162 | the GNU Lesser General Public License. 163 | 164 | * http://www.gnu.org/software/libidn 165 | 166 | [RFC3454] 167 | P. Hoffman, M. Blanchet, "Preparation of Internationalized Strings 168 | ('stringprep')", IETF RFC3454, December 2002. 169 | 170 | * http://www.ietf.org/rfc/rfc3454.txt 171 | 172 | [RFC3490] 173 | P. Faltstrom, P. Hoffman, A. Costello, "Internationalizing Domain 174 | Names in Applications (IDNA)", IETF RFC3490, March 2003. 175 | 176 | * http://www.ietf.org/rfc/rfc3490.txt 177 | 178 | [RFC3491] 179 | P. Hoffman, M. Blanchet, "Nameprep: A Stringprep Profile for 180 | Internationalized Domain Names (IDN)", IETF RFC3491, March 2003. 181 | 182 | * http://www.ietf.org/rfc/rfc3491.txt 183 | 184 | [RFC3492] 185 | A. Costello, "Punycode: A Bootstring encoding of Unicode for 186 | Internationalized Domain Names in Applications (IDNA)", IETF 187 | RFC3492, March 2003. 188 | 189 | * http://www.ietf.org/rfc/rfc3492.txt 190 | 191 | 192 | ### Questions, comments, patches? 193 | 194 | If you have any questions, comments or feature requests or if you want 195 | to submit a bug report or provide a patch, then have a look at the project 196 | website at 197 | 198 | * https://github.com/deepfryed/idn-ruby 199 | * http://rubyforge.org/projects/idn (original) 200 | 201 | For other information, feel free to ask on the idn-discuss at rubyforge.org 202 | mailing list. 203 | 204 | 205 | ### Copyright & License 206 | 207 | Copyright (c) 2005-2006 Erik Abele. 2011 Bharanee Rathna. All rights reserved. 208 | 209 | This documentation and the software itself are licensed under the Apache 210 | License, Version 2.0 (the "License"). 211 | 212 | Some portions of the software come with separate copyright notices and are 213 | subject to additional license terms. Please see the file called LICENSE for 214 | further details on these subcomponents of the software. 215 | 216 | You may also obtain a copy of the License at 217 | 218 | * http://www.apache.org/licenses/LICENSE-2.0 219 | 220 | Unless required by applicable law or agreed to in writing, software 221 | distributed under the License is distributed on an "AS IS" BASIS, 222 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 223 | See the License for the specific language governing permissions and 224 | limitations under the License. 225 | 226 | This software is OSI Certified Open Source Software. 227 | OSI Certified is a certification mark of the Open Source Initiative. 228 | -------------------------------------------------------------------------------- /test/tc_Punycode.rb: -------------------------------------------------------------------------------- 1 | # Unit tests for IDN::Punycode. 2 | # 3 | # Copyright (c) 2005 Erik Abele. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # Please see the file called LICENSE for further details. 8 | # 9 | # You may also obtain a copy of the License at 10 | # 11 | # * http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | # This software is OSI Certified Open Source Software. 20 | # OSI Certified is a certification mark of the Open Source Initiative. 21 | 22 | require 'test/unit' 23 | require 'idn' 24 | 25 | class Test_Punycode < Test::Unit::TestCase 26 | include IDN 27 | 28 | # RFC3492 test vectors, taken from RFC3492 (7.1 Sample Strings): 29 | # http://www.ietf.org/rfc/rfc3492.txt 30 | # 31 | # Modifications: 32 | # - correction of an obviously wrong uppercase character in case I 33 | 34 | TESTCASES_RFC3492 = { 35 | 'A' => [ 36 | [ 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643, 37 | 0x0644, 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A, 38 | 0x061F ].pack('U*'), 39 | 'egbpdaj6bu4bxfgehfvwxn' 40 | ], 41 | 42 | 'B' => [ 43 | [ 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D, 44 | 0x6587 ].pack('U*'), 45 | 'ihqwcrb4cv8a8dqg056pqjye' 46 | ], 47 | 48 | 'C' => [ 49 | [ 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D, 50 | 0x6587 ].pack('U*'), 51 | 'ihqwctvzc91f659drss3x8bo0yb' 52 | ], 53 | 54 | 'D' => [ 55 | [ 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073, 56 | 0x0074, 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076, 57 | 0x00ED, 0x010D, 0x0065, 0x0073, 0x006B, 0x0079 ].pack('U*'), 58 | 'Proprostnemluvesky-uyb24dma41a' 59 | ], 60 | 61 | 'E' => [ 62 | [ 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5, 63 | 0x05D8, 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9, 64 | 0x05DD, 0x05E2, 0x05D1, 0x05E8, 0x05D9, 0x05EA ].pack('U*'), 65 | '4dbcagdahymbxekheh6e0a7fei0b' 66 | ], 67 | 68 | 'F' => [ 69 | [ 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928, 70 | 0x094D, 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902, 71 | 0x0928, 0x0939, 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938, 72 | 0x0915, 0x0924, 0x0947, 0x0939, 0x0948, 0x0902 ].pack('U*'), 73 | 'i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd' 74 | ], 75 | 76 | 'G' => [ 77 | [ 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E, 78 | 0x3092, 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044, 79 | 0x306E, 0x304B ].pack('U*'), 80 | 'n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa' 81 | ], 82 | 83 | 'H' => [ 84 | [ 0xC138, 0xACC4, 0xC758, 0xBAA8, 0xB4E0, 0xC0AC, 0xB78C, 0xB4E4, 85 | 0xC774, 0xD55C, 0xAD6D, 0xC5B4, 0xB97C, 0xC774, 0xD574, 0xD55C, 86 | 0xB2E4, 0xBA74, 0xC5BC, 0xB9C8, 0xB098, 0xC88B, 0xC744, 87 | 0xAE4C ].pack('U*'), 88 | '989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5jpsd879ccm6fea98c' 89 | ], 90 | 91 | 'I' => [ 92 | [ 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435, 93 | 0x043E, 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432, 94 | 0x043E, 0x0440, 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443, 95 | 0x0441, 0x0441, 0x043A, 0x0438 ].pack('U*'), 96 | 'b1abfaaepdrnnbgefbadotcwatmq2g4l' 97 | ], 98 | 99 | 'J' => [ 100 | [ 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F, 101 | 0x0070, 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069, 102 | 0x006D, 0x0070, 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074, 103 | 0x0065, 0x0068, 0x0061, 0x0062, 0x006C, 0x0061, 0x0072, 0x0065, 104 | 0x006E, 0x0045, 0x0073, 0x0070, 0x0061, 0x00F1, 0x006F, 105 | 0x006C ].pack('U*'), 106 | 'PorqunopuedensimplementehablarenEspaol-fmd56a' 107 | ], 108 | 109 | 'K' => [ 110 | [ 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD, 111 | 0x006B, 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3, 112 | 0x0063, 0x0068, 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069, 113 | 0x1EBF, 0x006E, 0x0067, 0x0056, 0x0069, 0x1EC7, 0x0074 ].pack('U*'), 114 | 'TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g' 115 | ], 116 | 117 | 'L' => [ 118 | [ 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 119 | 0x751F ].pack('U*'), 120 | '3B-ww4c5e180e575a65lsy2b' 121 | ], 122 | 123 | 'M' => [ 124 | [ 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069, 125 | 0x0074, 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052, 126 | 0x002D, 0x004D, 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 127 | 0x0053 ].pack('U*'), 128 | '-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n' 129 | ], 130 | 131 | 'N' => [ 132 | [ 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E, 133 | 0x006F, 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061, 134 | 0x0079, 0x002D, 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834, 135 | 0x6240 ].pack('U*'), 136 | 'Hello-Another-Way--fc4qua05auwb3674vfr0b' 137 | ], 138 | 139 | 'O' => [ 140 | [ 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 141 | 0x0032 ].pack('U*'), 142 | '2-u9tlzr9756bt3uc0v' 143 | ], 144 | 145 | 'P' => [ 146 | [ 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069, 147 | 0x3059, 0x308B, 0x0035, 0x79D2, 0x524D ].pack('U*'), 148 | 'MajiKoi5-783gue6qz075azm5e' 149 | ], 150 | 151 | 'Q' => [ 152 | [ 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 153 | 0x30D0 ].pack('U*'), 154 | 'de-jg4avhby1noc0d' 155 | ], 156 | 157 | 'R' => [ 158 | [ 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067 ].pack('U*'), 159 | 'd9juau41awczczp' 160 | ], 161 | 162 | 'S' => [ 163 | [ 0x002D, 0x003E, 0x0020, 0x0024, 0x0031, 0x002E, 0x0030, 0x0030, 164 | 0x0020, 0x003C, 0x002D ].pack('U*'), 165 | '-> $1.00 <--' 166 | ] 167 | } 168 | 169 | def setup 170 | end 171 | 172 | def teardown 173 | end 174 | 175 | def test_encode_RFC3492 176 | TESTCASES_RFC3492.each do |key, val| 177 | rc = Punycode.encode(val[0]) 178 | assert_equal(val[1], rc, "TestCase #{key} failed") 179 | end 180 | end 181 | 182 | def test_decode_RFC3492 183 | TESTCASES_RFC3492.each do |key, val| 184 | rc = Punycode.decode(val[1]) 185 | assert_equal(val[0], rc, "TestCase #{key} failed") 186 | end 187 | end 188 | end 189 | -------------------------------------------------------------------------------- /test/tc_Idna.rb: -------------------------------------------------------------------------------- 1 | # Unit tests for IDN::Idna. 2 | # 3 | # Copyright (c) 2005-2006 Erik Abele. All rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # Please see the file called LICENSE for further details. 8 | # 9 | # You may also obtain a copy of the License at 10 | # 11 | # * http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | # 19 | # This software is OSI Certified Open Source Software. 20 | # OSI Certified is a certification mark of the Open Source Initiative. 21 | 22 | require 'test/unit' 23 | require 'idn' 24 | 25 | class Test_Idna < Test::Unit::TestCase 26 | include IDN 27 | 28 | # JOSEFSSON test vectors, taken from DRAFT-JOSEFSSON-IDN-TEST-VECTORS-00: 29 | # http://www.gnu.org/software/libidn/draft-josefsson-idn-test-vectors.html 30 | # 31 | # Modifications: 32 | # - omission of 5.20 since it is identical with 5.8 (case H below) 33 | 34 | TESTCASES_JOSEFSSON = { 35 | 'A' => [ 36 | [ 0x0644, 0x064A, 0x0647, 0x0645, 0x0627, 0x0628, 0x062A, 0x0643, 37 | 0x0644, 0x0645, 0x0648, 0x0634, 0x0639, 0x0631, 0x0628, 0x064A, 38 | 0x061F ].pack('U*'), 39 | Idna::ACE_PREFIX + 'egbpdaj6bu4bxfgehfvwxn' 40 | ], 41 | 42 | 'B' => [ 43 | [ 0x4ED6, 0x4EEC, 0x4E3A, 0x4EC0, 0x4E48, 0x4E0D, 0x8BF4, 0x4E2D, 44 | 0x6587 ].pack('U*'), 45 | Idna::ACE_PREFIX + 'ihqwcrb4cv8a8dqg056pqjye' 46 | ], 47 | 48 | 'C' => [ 49 | [ 0x4ED6, 0x5011, 0x7232, 0x4EC0, 0x9EBD, 0x4E0D, 0x8AAA, 0x4E2D, 50 | 0x6587 ].pack('U*'), 51 | Idna::ACE_PREFIX + 'ihqwctvzc91f659drss3x8bo0yb' 52 | ], 53 | 54 | 'D' => [ 55 | [ 0x0050, 0x0072, 0x006F, 0x010D, 0x0070, 0x0072, 0x006F, 0x0073, 56 | 0x0074, 0x011B, 0x006E, 0x0065, 0x006D, 0x006C, 0x0075, 0x0076, 57 | 0x00ED, 0x010D, 0x0065, 0x0073, 0x006B, 0x0079 ].pack('U*'), 58 | Idna::ACE_PREFIX + 'Proprostnemluvesky-uyb24dma41a' 59 | ], 60 | 61 | 'E' => [ 62 | [ 0x05DC, 0x05DE, 0x05D4, 0x05D4, 0x05DD, 0x05E4, 0x05E9, 0x05D5, 63 | 0x05D8, 0x05DC, 0x05D0, 0x05DE, 0x05D3, 0x05D1, 0x05E8, 0x05D9, 64 | 0x05DD, 0x05E2, 0x05D1, 0x05E8, 0x05D9, 0x05EA ].pack('U*'), 65 | Idna::ACE_PREFIX + '4dbcagdahymbxekheh6e0a7fei0b' 66 | ], 67 | 68 | 'F' => [ 69 | [ 0x092F, 0x0939, 0x0932, 0x094B, 0x0917, 0x0939, 0x093F, 0x0928, 70 | 0x094D, 0x0926, 0x0940, 0x0915, 0x094D, 0x092F, 0x094B, 0x0902, 71 | 0x0928, 0x0939, 0x0940, 0x0902, 0x092C, 0x094B, 0x0932, 0x0938, 72 | 0x0915, 0x0924, 0x0947, 0x0939, 0x0948, 0x0902 ].pack('U*'), 73 | Idna::ACE_PREFIX + 'i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd' 74 | ], 75 | 76 | 'G' => [ 77 | [ 0x306A, 0x305C, 0x307F, 0x3093, 0x306A, 0x65E5, 0x672C, 0x8A9E, 78 | 0x3092, 0x8A71, 0x3057, 0x3066, 0x304F, 0x308C, 0x306A, 0x3044, 79 | 0x306E, 0x304B ].pack('U*'), 80 | Idna::ACE_PREFIX + 'n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa' 81 | ], 82 | 83 | 'H' => [ 84 | [ 0x043F, 0x043E, 0x0447, 0x0435, 0x043C, 0x0443, 0x0436, 0x0435, 85 | 0x043E, 0x043D, 0x0438, 0x043D, 0x0435, 0x0433, 0x043E, 0x0432, 86 | 0x043E, 0x0440, 0x044F, 0x0442, 0x043F, 0x043E, 0x0440, 0x0443, 87 | 0x0441, 0x0441, 0x043A, 0x0438 ].pack('U*'), 88 | Idna::ACE_PREFIX + 'b1abfaaepdrnnbgefbadotcwatmq2g4l' 89 | ], 90 | 91 | 'I' => [ 92 | [ 0x0050, 0x006F, 0x0072, 0x0071, 0x0075, 0x00E9, 0x006E, 0x006F, 93 | 0x0070, 0x0075, 0x0065, 0x0064, 0x0065, 0x006E, 0x0073, 0x0069, 94 | 0x006D, 0x0070, 0x006C, 0x0065, 0x006D, 0x0065, 0x006E, 0x0074, 95 | 0x0065, 0x0068, 0x0061, 0x0062, 0x006C, 0x0061, 0x0072, 0x0065, 96 | 0x006E, 0x0045, 0x0073, 0x0070, 0x0061, 0x00F1, 0x006F, 97 | 0x006C ].pack('U*'), 98 | Idna::ACE_PREFIX + 'PorqunopuedensimplementehablarenEspaol-fmd56a' 99 | ], 100 | 101 | 'J' => [ 102 | [ 0x0054, 0x1EA1, 0x0069, 0x0073, 0x0061, 0x006F, 0x0068, 0x1ECD, 103 | 0x006B, 0x0068, 0x00F4, 0x006E, 0x0067, 0x0074, 0x0068, 0x1EC3, 104 | 0x0063, 0x0068, 0x1EC9, 0x006E, 0x00F3, 0x0069, 0x0074, 0x0069, 105 | 0x1EBF, 0x006E, 0x0067, 0x0056, 0x0069, 0x1EC7, 0x0074 ].pack('U*'), 106 | Idna::ACE_PREFIX + 'TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g' 107 | ], 108 | 109 | 'K' => [ 110 | [ 0x0033, 0x5E74, 0x0042, 0x7D44, 0x91D1, 0x516B, 0x5148, 111 | 0x751F ].pack('U*'), 112 | Idna::ACE_PREFIX + '3B-ww4c5e180e575a65lsy2b' 113 | ], 114 | 115 | 'L' => [ 116 | [ 0x5B89, 0x5BA4, 0x5948, 0x7F8E, 0x6075, 0x002D, 0x0077, 0x0069, 117 | 0x0074, 0x0068, 0x002D, 0x0053, 0x0055, 0x0050, 0x0045, 0x0052, 118 | 0x002D, 0x004D, 0x004F, 0x004E, 0x004B, 0x0045, 0x0059, 119 | 0x0053 ].pack('U*'), 120 | Idna::ACE_PREFIX + '-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n' 121 | ], 122 | 123 | 'M' => [ 124 | [ 0x0048, 0x0065, 0x006C, 0x006C, 0x006F, 0x002D, 0x0041, 0x006E, 125 | 0x006F, 0x0074, 0x0068, 0x0065, 0x0072, 0x002D, 0x0057, 0x0061, 126 | 0x0079, 0x002D, 0x305D, 0x308C, 0x305E, 0x308C, 0x306E, 0x5834, 127 | 0x6240 ].pack('U*'), 128 | Idna::ACE_PREFIX + 'Hello-Another-Way--fc4qua05auwb3674vfr0b' 129 | ], 130 | 131 | 'N' => [ 132 | [ 0x3072, 0x3068, 0x3064, 0x5C4B, 0x6839, 0x306E, 0x4E0B, 133 | 0x0032 ].pack('U*'), 134 | Idna::ACE_PREFIX + '2-u9tlzr9756bt3uc0v' 135 | ], 136 | 137 | 'O' => [ 138 | [ 0x004D, 0x0061, 0x006A, 0x0069, 0x3067, 0x004B, 0x006F, 0x0069, 139 | 0x3059, 0x308B, 0x0035, 0x79D2, 0x524D ].pack('U*'), 140 | Idna::ACE_PREFIX + 'MajiKoi5-783gue6qz075azm5e' 141 | ], 142 | 143 | 'P' => [ 144 | [ 0x30D1, 0x30D5, 0x30A3, 0x30FC, 0x0064, 0x0065, 0x30EB, 0x30F3, 145 | 0x30D0 ].pack('U*'), 146 | Idna::ACE_PREFIX + 'de-jg4avhby1noc0d' 147 | ], 148 | 149 | 'Q' => [ 150 | [ 0x305D, 0x306E, 0x30B9, 0x30D4, 0x30FC, 0x30C9, 0x3067 ].pack('U*'), 151 | Idna::ACE_PREFIX + 'd9juau41awczczp' 152 | ], 153 | 154 | 'R' => [ 155 | [ 0x03B5, 0x03BB, 0x03BB, 0x03B7, 0x03BD, 0x03B9, 0x03BA, 156 | 0x03AC ].pack('U*'), 157 | Idna::ACE_PREFIX + 'hxargifdar' 158 | ], 159 | 160 | 'S' => [ 161 | [ 0x0062, 0x006F, 0x006E, 0x0121, 0x0075, 0x0073, 0x0061, 0x0127, 162 | 0x0127, 0x0061 ].pack('U*'), 163 | Idna::ACE_PREFIX + 'bonusaa-5bb1da' 164 | ] 165 | } 166 | 167 | # UNASSIGNED test vectors: unassigned code points U+0221 and U+0236. 168 | 169 | TESTCASES_UNASSIGNED = { 170 | 'A' => [ 171 | [ 0x0221 ].pack('U*'), 172 | Idna::ACE_PREFIX + '6la' 173 | ], 174 | 175 | 'B' => [ 176 | [ 0x0236 ].pack('U*'), 177 | Idna::ACE_PREFIX + 'sma' 178 | ] 179 | } 180 | 181 | # STD3 test vectors: labels not conforming to the STD3 ASCII rules (see 182 | # RFC1122 and RFC1123 for details). 183 | 184 | TESTCASES_STD3 = { 185 | 'A' => [ 186 | [ 0x0115, 0x0073, 0x0074, 0x0065, 0x002D ].pack('U*'), 187 | Idna::ACE_PREFIX + 'ste--kva' 188 | ], 189 | 190 | 'B' => [ 191 | [ 0x006F, 0x003A, 0x006C, 0x006B, 0x01EB, 0x0065 ].pack('U*'), 192 | Idna::ACE_PREFIX + 'o:lke-m1b' 193 | ] 194 | } 195 | 196 | def setup 197 | end 198 | 199 | def teardown 200 | end 201 | 202 | def test_toASCII_JOSEFSSON 203 | TESTCASES_JOSEFSSON.each do |key, val| 204 | rc = Idna.toASCII(val[0]) 205 | assert_equal(val[1].downcase, rc, "TestCase #{key} failed") 206 | end 207 | end 208 | 209 | def test_toASCII_UNASSIGNED_ALLOWED 210 | TESTCASES_UNASSIGNED.each do |key, val| 211 | rc = Idna.toASCII(val[0], IDN::Idna::ALLOW_UNASSIGNED) 212 | assert_equal(val[1], rc, "TestCase #{key} failed") 213 | end 214 | end 215 | 216 | def test_toASCII_UNASSIGNED_NOT_ALLOWED 217 | TESTCASES_UNASSIGNED.each do |key, val| 218 | assert_raise(Idna::IdnaError, "TestCase #{key} failed") do 219 | Idna.toASCII(val[0]) 220 | end 221 | end 222 | end 223 | 224 | def test_toASCII_STD3_USED 225 | TESTCASES_STD3.each do |key, val| 226 | assert_raise(Idna::IdnaError, "TestCase #{key} failed") do 227 | Idna.toASCII(val[0], IDN::Idna::USE_STD3_ASCII_RULES) 228 | end 229 | end 230 | end 231 | 232 | def test_toASCII_STD3_NOT_USED 233 | TESTCASES_STD3.each do |key, val| 234 | rc = Idna.toASCII(val[0]) 235 | assert_equal(val[1], rc, "TestCase #{key} failed") 236 | end 237 | end 238 | 239 | def test_toUnicode_JOSEFSSON 240 | TESTCASES_JOSEFSSON.each do |key, val| 241 | rc = Idna.toUnicode(val[1]) 242 | assert_equal(val[0], rc, "TestCase #{key} failed") 243 | end 244 | end 245 | 246 | def test_toUnicode_UNASSIGNED_ALLOWED 247 | TESTCASES_UNASSIGNED.each do |key, val| 248 | rc = Idna.toUnicode(val[1], IDN::Idna::ALLOW_UNASSIGNED) 249 | assert_equal(val[0], rc, "TestCase #{key} failed") 250 | end 251 | end 252 | 253 | def test_toUnicode_UNASSIGNED_NOT_ALLOWED 254 | TESTCASES_UNASSIGNED.each do |key, val| 255 | rc = Idna.toUnicode(val[1]) 256 | assert_equal(val[1], rc, "TestCase #{key} failed") 257 | end 258 | end 259 | 260 | def test_toUnicode_STD3_USED 261 | TESTCASES_STD3.each do |key, val| 262 | rc = Idna.toUnicode(val[1], IDN::Idna::USE_STD3_ASCII_RULES) 263 | assert_equal(val[1], rc, "TestCase #{key} failed") 264 | end 265 | end 266 | 267 | def test_toUnicode_STD3_NOT_USED 268 | TESTCASES_STD3.each do |key, val| 269 | rc = Idna.toUnicode(val[1]) 270 | assert_equal(val[0], rc, "TestCase #{key} failed") 271 | end 272 | end 273 | end 274 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- 204 | 205 | SUBCOMPONENT LICENSES 206 | 207 | This software includes a number of subcomponents with separate copyright 208 | notices and additional license terms. Your use of the source code for 209 | these components is subject to the terms and conditions of the following 210 | licenses: 211 | 212 | -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- 213 | 214 | = ext/idn.c 215 | = ext/idn.h 216 | = ext/punycode.c 217 | = ext/stringprep.c 218 | 219 | Portions Copyright (c) 2005 Yuki Mitsui. All rights reserved. 220 | 221 | Redistribution and use in source and binary forms, with or without 222 | modification, are permitted provided that the following conditions 223 | are met: 224 | 225 | * Redistributions of source code must retain the above copyright 226 | notice, this list of conditions and the following disclaimer. 227 | 228 | * Redistributions in binary form must reproduce the above copyright 229 | notice, this list of conditions and the following disclaimer in 230 | the documentation and/or other materials provided with the 231 | distribution. 232 | 233 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 234 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 235 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 236 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 237 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 238 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 239 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 240 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 242 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 243 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 244 | 245 | -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- + -- 246 | 247 | + END OF ALL TERMS AND CONDITIONS + 248 | --------------------------------------------------------------------------------