idn-ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,60 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/rdoctask'
6
+ require 'rake/extensiontask'
7
+
8
+ CLEAN << FileList[ 'ext/Makefile', 'ext/*.so', 'ext/*.o' ]
9
+
10
+ begin
11
+ require 'jeweler'
12
+ rescue LoadError
13
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
14
+ end
15
+
16
+ Jeweler::Tasks.new do |gem|
17
+ gem.name = 'idn-ruby'
18
+ gem.summary = 'LibIDN Ruby Bindings.'
19
+ gem.description = %q{
20
+ Ruby Bindings for the GNU LibIDN library, an implementation of the
21
+ Stringprep, Punycode and IDNA specifications defined by the IETF
22
+ Internationalized Domain Names (IDN) working group.
23
+
24
+ Included are the most important parts of the Stringprep, Punycode
25
+ and IDNA APIs like performing Stringprep processings, encoding to
26
+ and decoding from Punycode strings and converting entire domain names
27
+ to and from the ACE encoded form.
28
+ }
29
+ gem.email = 'deepfryed@gmail.com'
30
+ gem.homepage = 'http://github.com/deepfryed/idn-ruby'
31
+ gem.authors = ['Erik Abele', 'Bharanee Rathna']
32
+ gem.files = FileList['CHANGES', 'LICENSE', 'NOTICE', 'Rakefile', 'README', 'ext/*.{c,h}']
33
+ gem.extensions = FileList[ 'ext/**/extconf.rb' ]
34
+ gem.test_files = FileList[ 'test/*.rb' ]
35
+ end
36
+
37
+ Jeweler::GemcutterTasks.new
38
+
39
+ Rake::ExtensionTask.new do |ext|
40
+ ext.name = 'idn'
41
+ ext.ext_dir = 'ext'
42
+ ext.lib_dir = 'ext'
43
+ end
44
+
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "idn-ruby #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
52
+
53
+ Rake::TestTask.new(:test) do |test|
54
+ test.libs << 'ext'
55
+ test.pattern = 'test/*.rb'
56
+ test.verbose = true
57
+ end
58
+
59
+ task :test => [ :compile, :check_dependencies ]
60
+ task :default => :test
@@ -0,0 +1,56 @@
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
+ @libs = ['idn']
25
+ @headers = ['idna.h', 'punycode.h', 'stringprep.h']
26
+
27
+ INFO_NOTE = <<EOL
28
+ Please install the GNU IDN library or alternatively specify at least one
29
+ of the following options if the library can only be found in a non-standard
30
+ location:
31
+ --with-idn-dir=/path/to/non/standard/location
32
+ or
33
+ --with-idn-lib=/path/to/non/standard/location/lib
34
+ --with-idn-include=/path/to/non/standard/location/include
35
+ EOL
36
+
37
+ dir_config('idn')
38
+
39
+ @libs.each do |lib|
40
+ unless have_library(lib)
41
+ STDERR.puts "ERROR: could not find #{lib} library!\n" +
42
+ "\n#{INFO_NOTE}\n"
43
+ exit 1
44
+ end
45
+ end
46
+
47
+ @headers.each do |header|
48
+ unless have_header(header)
49
+ STDERR.puts "ERROR: could not find #{header} header file!\n" +
50
+ "\n#{INFO_NOTE}\n"
51
+ exit 1
52
+ end
53
+ end
54
+
55
+ $CFLAGS += ' -Wall' unless $CFLAGS.split.include? '-Wall'
56
+ create_makefile('idn')
@@ -0,0 +1,59 @@
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 <ruby.h>
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
+ }
@@ -0,0 +1,59 @@
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 <ruby.h>
27
+ #include <ruby/encoding.h>
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_ */
@@ -0,0 +1,164 @@
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 <stdlib.h>
23
+ #include <ruby.h>
24
+ #include <idna.h>
25
+ #include "idn.h"
26
+
27
+ /*
28
+ * Document-class: IDN::Idna
29
+ * The Idna module of LibIDN Ruby Bindings.
30
+ *
31
+ * === Example usage
32
+ *
33
+ * require 'idn'
34
+ * include IDN
35
+ *
36
+ * puts 'ACE-Prefix: ' + Idna::ACE_PREFIX
37
+ *
38
+ * domain = Idna.toUnicode('xn--rksmrgs-5wao1o.josefsson.org',
39
+ * Idna::USE_STD3_ASCII_RULES | Idna::ALLOW_UNASSIGNED)
40
+ *
41
+ * === Constants
42
+ *
43
+ * <b>ACE_PREFIX</b>
44
+ * - The ACE prefix: 'xn--'.
45
+ *
46
+ * <b>ALLOW_UNASSIGNED</b>
47
+ * - Used as flag for toASCII/toUnicode.
48
+ *
49
+ * <b>USE_STD3_ASCII_RULES</b>
50
+ * - Used as flag for toASCII/toUnicode.
51
+ */
52
+
53
+ VALUE mIdna;
54
+
55
+ /*
56
+ * Document-class: IDN::Idna::IdnaError
57
+ * The base class for all exceptions raised by the IDN::Idna module.
58
+ */
59
+
60
+ VALUE eIdnaError;
61
+
62
+ /*
63
+ * call-seq:
64
+ * IDN::Idna.toASCII(string, flags=nil) => string
65
+ *
66
+ * Converts a domain name in UTF-8 format into an ASCII string. The domain
67
+ * name may contain several labels, separated by dots.
68
+ *
69
+ * Raises IDN::Idna::IdnaError on failure.
70
+ */
71
+
72
+ static VALUE toASCII(int argc, VALUE argv[], VALUE self)
73
+ {
74
+ int rc;
75
+ char *buf;
76
+ VALUE str, flags, retv;
77
+
78
+ rb_scan_args(argc, argv, "11", &str, &flags);
79
+ str = rb_check_convert_type(str, T_STRING, "String", "to_s");
80
+
81
+ if (flags != Qnil) {
82
+ Check_Type(flags, T_FIXNUM);
83
+ flags = FIX2INT(flags);
84
+ } else {
85
+ flags = 0x0000;
86
+ }
87
+
88
+ rc = idna_to_ascii_8z(RSTRING_PTR(str), &buf, flags);
89
+
90
+ if (rc != IDNA_SUCCESS) {
91
+ xfree(buf);
92
+ rb_raise(eIdnaError, "%s (%d)", idna_strerror(rc), rc);
93
+ return Qnil;
94
+ }
95
+
96
+ retv = rb_str_new2(buf);
97
+ xfree(buf);
98
+ return retv;
99
+ }
100
+
101
+ /*
102
+ * call-seq:
103
+ * IDN::Idna.toUnicode(string, flags=nil) => string
104
+ *
105
+ * Converts a possibly ACE encoded domain name in UTF-8 format into an
106
+ * UTF-8 string. The domain name may contain several labels, separated
107
+ * by dots.
108
+ *
109
+ * Raises IDN::Idna::IdnaError on failure.
110
+ */
111
+
112
+ static VALUE toUnicode(int argc, VALUE argv[], VALUE self)
113
+ {
114
+ int rc;
115
+ char *buf;
116
+ VALUE str, flags, retv;
117
+
118
+ rb_scan_args(argc, argv, "11", &str, &flags);
119
+ str = rb_check_convert_type(str, T_STRING, "String", "to_s");
120
+
121
+ if (flags != Qnil) {
122
+ Check_Type(flags, T_FIXNUM);
123
+ flags = FIX2INT(flags);
124
+ } else {
125
+ flags = 0x0000;
126
+ }
127
+
128
+ rc = idna_to_unicode_8z8z(RSTRING_PTR(str), &buf, flags);
129
+
130
+ if (rc != IDNA_SUCCESS) {
131
+ xfree(buf);
132
+ rb_raise(eIdnaError, "%s (%d)", idna_strerror(rc), rc);
133
+ return Qnil;
134
+ }
135
+
136
+ retv = rb_enc_str_new(buf, strlen(buf), rb_utf8_encoding());
137
+ xfree(buf);
138
+ return retv;
139
+ }
140
+
141
+ /*
142
+ * Module Initialization.
143
+ */
144
+
145
+ void init_idna(void)
146
+ {
147
+ #ifdef mIDN_RDOC_HACK
148
+ mIDN = rb_define_module("IDN");
149
+ eIDNError = rb_define_class_under(mIDN, "IDNError", rb_eStandardError);
150
+ #endif
151
+
152
+ mIdna = rb_define_module_under(mIDN, "Idna");
153
+ eIdnaError = rb_define_class_under(mIdna, "IdnaError", eIDNError);
154
+
155
+ rb_define_const(mIdna, "ACE_PREFIX",
156
+ rb_str_new2(IDNA_ACE_PREFIX));
157
+ rb_define_const(mIdna, "ALLOW_UNASSIGNED",
158
+ INT2FIX(IDNA_ALLOW_UNASSIGNED));
159
+ rb_define_const(mIdna, "USE_STD3_ASCII_RULES",
160
+ INT2FIX(IDNA_USE_STD3_ASCII_RULES));
161
+
162
+ rb_define_singleton_method(mIdna, "toASCII", toASCII, -1);
163
+ rb_define_singleton_method(mIdna, "toUnicode", toUnicode, -1);
164
+ }
@@ -0,0 +1,160 @@
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 <stdlib.h>
24
+ #include <ruby.h>
25
+ #include <stringprep.h>
26
+ #include <punycode.h>
27
+ #include "idn.h"
28
+
29
+ /*
30
+ * Document-class: IDN::Punycode
31
+ * The Punycode module of LibIDN Ruby Bindings.
32
+ *
33
+ * === Example usage
34
+ *
35
+ * require 'idn'
36
+ * include IDN
37
+ *
38
+ * str = Punycode.decode('egbpdaj6bu4bxfgehfvwxn')
39
+ */
40
+
41
+ VALUE mPunycode;
42
+
43
+ /*
44
+ * Document-class: IDN::Punycode::PunycodeError
45
+ * The base class for all exceptions raised by the IDN::Punycode module.
46
+ */
47
+
48
+ VALUE ePunycodeError;
49
+
50
+ /*
51
+ * call-seq:
52
+ * IDN::Punycode.encode(string) => string
53
+ *
54
+ * Converts a string in UTF-8 format to Punycode.
55
+ *
56
+ * Raises IDN::Punycode::PunycodeError on failure.
57
+ */
58
+
59
+ static VALUE encode(VALUE self, VALUE str)
60
+ {
61
+ int rc;
62
+ punycode_uint *ustr;
63
+ size_t len;
64
+ size_t buflen = 0x100;
65
+ char *buf = NULL;
66
+ VALUE retv;
67
+
68
+ str = rb_check_convert_type(str, T_STRING, "String", "to_s");
69
+ ustr = stringprep_utf8_to_ucs4(RSTRING_PTR(str), RSTRING_LEN(str), &len);
70
+
71
+ while (1) {
72
+ buf = realloc(buf, buflen);
73
+
74
+ if (buf == NULL) {
75
+ xfree(ustr);
76
+ rb_raise(rb_eNoMemError, "cannot allocate memory (%d bytes)", (uint32_t)buflen);
77
+ return Qnil;
78
+ }
79
+
80
+ rc = punycode_encode(len, ustr, NULL, &buflen, buf);
81
+
82
+ if (rc == PUNYCODE_SUCCESS) {
83
+ break;
84
+ } else if (rc == PUNYCODE_BIG_OUTPUT) {
85
+ buflen += 0x100;
86
+ } else {
87
+ xfree(ustr);
88
+ xfree(buf);
89
+ rb_raise(ePunycodeError, "%s (%d)", punycode_strerror(rc), rc);
90
+ return Qnil;
91
+ }
92
+ }
93
+
94
+ retv = rb_str_new(buf, buflen);
95
+ xfree(ustr);
96
+ xfree(buf);
97
+ return retv;
98
+ }
99
+
100
+ /*
101
+ * call-seq:
102
+ * IDN::Punycode.decode(string) => string
103
+ *
104
+ * Converts Punycode to a string in UTF-8 format.
105
+ *
106
+ * Raises IDN::Punycode::PunycodeError on failure.
107
+ */
108
+
109
+ static VALUE decode(VALUE self, VALUE str)
110
+ {
111
+ int rc;
112
+ punycode_uint *ustr;
113
+ size_t len;
114
+ char *buf = NULL;
115
+ VALUE retv;
116
+
117
+ str = rb_check_convert_type(str, T_STRING, "String", "to_s");
118
+
119
+ len = RSTRING_LEN(str);
120
+ ustr = malloc(len * sizeof(punycode_uint));
121
+
122
+ if (ustr == NULL) {
123
+ rb_raise(rb_eNoMemError, "cannot allocate memory (%d bytes)", (uint32_t)len);
124
+ return Qnil;
125
+ }
126
+
127
+ rc = punycode_decode(RSTRING_LEN(str), RSTRING_PTR(str),
128
+ &len, ustr, NULL);
129
+
130
+ if (rc != PUNYCODE_SUCCESS) {
131
+ xfree(ustr);
132
+ rb_raise(ePunycodeError, "%s (%d)", punycode_strerror(rc), rc);
133
+ return Qnil;
134
+ }
135
+
136
+ buf = stringprep_ucs4_to_utf8(ustr, len, NULL, &len);
137
+ retv = rb_enc_str_new(buf, len, rb_utf8_encoding());
138
+ xfree(ustr);
139
+ xfree(buf);
140
+ return retv;
141
+ }
142
+
143
+ /*
144
+ * Module Initialization.
145
+ */
146
+
147
+ void init_punycode(void)
148
+ {
149
+ #ifdef mIDN_RDOC_HACK
150
+ mIDN = rb_define_module("IDN");
151
+ eIDNError = rb_define_class_under(mIDN, "IDNError", rb_eStandardError);
152
+ #endif
153
+
154
+ mPunycode = rb_define_module_under(mIDN, "Punycode");
155
+ ePunycodeError = rb_define_class_under(mPunycode, "PunycodeError",
156
+ eIDNError);
157
+
158
+ rb_define_singleton_method(mPunycode, "encode", encode, 1);
159
+ rb_define_singleton_method(mPunycode, "decode", decode, 1);
160
+ }