Package: release.debian.org Severity: normal Tags: jessie User: release.debian....@packages.debian.org Usertags: pu
I want to fix bug #798348 in stable. Due to this bug ruby-tzinfo is broken in non-utf8 locales. Please consider uploading fixed version. -- System Information: Debian Release: 8.2 APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'stable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 3.16.0-4-amd64 (SMP w/4 CPU cores) Locale: LANG=be_BY.utf8, LC_CTYPE=be_BY.utf8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: sysvinit (via /sbin/init)
From: Hleb Valoshka <hleb_valos...@epam.com> Date: Tue, 8 Sep 2015 14:56:01 +0300 Subject: Load iso3166.tab and zone.tab files as UTF-8 Backported from upstream commit 61fdd4359117e9a406c546bdc044a3e41faaa5d7 Author: Phil Ross <phil.r...@gmail.com> --- lib/tzinfo/ruby_core_support.rb | 13 ++++++++ lib/tzinfo/zoneinfo_data_source.rb | 16 ++++++++-- test/tc_ruby_core_support.rb | 62 ++++++++++++++++++++++++++++++++++++++ test/tc_zoneinfo_data_source.rb | 30 ++++++++++++++++-- 4 files changed, 115 insertions(+), 6 deletions(-) diff --git a/lib/tzinfo/ruby_core_support.rb b/lib/tzinfo/ruby_core_support.rb index eb81e2c..b76c0ed 100644 --- a/lib/tzinfo/ruby_core_support.rb +++ b/lib/tzinfo/ruby_core_support.rb @@ -150,5 +150,18 @@ module TZInfo str end end + + # Wrapper for File.open that supports passing hash options for specifying + # encodings on Ruby 1.9+. The options are ignored on earlier versions of + # Ruby. + if RUBY_VERSION =~ /\A1\.[0-8]\./ + def self.open_file(file_name, mode, opts, &block) + File.open(file_name, mode, &block) + end + else + def self.open_file(file_name, mode, opts, &block) + File.open(file_name, mode, opts, &block) + end + end end end diff --git a/lib/tzinfo/zoneinfo_data_source.rb b/lib/tzinfo/zoneinfo_data_source.rb index 9d1aaf5..88c8a7b 100644 --- a/lib/tzinfo/zoneinfo_data_source.rb +++ b/lib/tzinfo/zoneinfo_data_source.rb @@ -290,8 +290,13 @@ module TZInfo # available countries and their timezones. def load_country_index zones = {} - - File.open(File.join(@zoneinfo_dir, 'zone.tab')) do |file| + + RubyCoreSupport.open_file( + File.join(@zoneinfo_dir, 'zone.tab'), + 'r', + :external_encoding => 'UTF-8', + :internal_encoding => 'UTF-8' + ) do |file| file.each_line do |line| line.chomp! @@ -318,7 +323,12 @@ module TZInfo countries = {} - File.open(File.join(@zoneinfo_dir, 'iso3166.tab')) do |file| + RubyCoreSupport.open_file( + File.join(@zoneinfo_dir, 'iso3166.tab'), + 'r', + :external_encoding => 'UTF-8', + :internal_encoding => 'UTF-8' + ) do |file| file.each_line do |line| line.chomp! diff --git a/test/tc_ruby_core_support.rb b/test/tc_ruby_core_support.rb index e59608f..cde46f5 100644 --- a/test/tc_ruby_core_support.rb +++ b/test/tc_ruby_core_support.rb @@ -114,4 +114,66 @@ class TCRubyCoreSupport < Test::Unit::TestCase assert_equal('©', s) end end + + begin + SUPPORTS_ENCODING = !!Encoding + rescue NameError + SUPPORTS_ENCODING = false + end + + def test_open_file + Dir.mktmpdir('tzinfo_test') do |dir| + test_file = File.join(dir, 'test.txt') + + file = RubyCoreSupport.open_file(test_file, 'w', :external_encoding => 'UTF-8') + begin + file.puts(SUPPORTS_ENCODING ? '©' : 'x') + ensure + file.close + end + + file = RubyCoreSupport.open_file(test_file, 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') + begin + data = file.gets + refute_nil(data) + data.chomp! + + if SUPPORTS_ENCODING + assert_equal('UTF-8', data.encoding.name) + assert_equal(1, data.length) + assert_equal(2, data.bytesize) + assert_equal('©', data) + else + assert_equal('x', data) + end + ensure + file.close + end + end + end + + def test_open_file_block + Dir.mktmpdir('tzinfo_test') do |dir| + test_file = File.join(dir, 'test.txt') + + RubyCoreSupport.open_file(test_file, 'w', :external_encoding => 'UTF-8') do |file| + file.puts(SUPPORTS_ENCODING ? '©' : 'x') + end + + RubyCoreSupport.open_file(test_file, 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file| + data = file.gets + refute_nil(data) + data.chomp! + + if SUPPORTS_ENCODING + assert_equal('UTF-8', data.encoding.name) + assert_equal(1, data.length) + assert_equal(2, data.bytesize) + assert_equal('©', data) + else + assert_equal('x', data) + end + end + end + end end diff --git a/test/tc_zoneinfo_data_source.rb b/test/tc_zoneinfo_data_source.rb index e74bd9c..6764cd2 100644 --- a/test/tc_zoneinfo_data_source.rb +++ b/test/tc_zoneinfo_data_source.rb @@ -19,6 +19,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. #++ +# encoding: UTF-8 require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils') require 'fileutils' @@ -611,12 +612,12 @@ class TCZoneinfoDataSource < Test::Unit::TestCase def test_load_country_info_check_zones Dir.mktmpdir('tzinfo_test') do |dir| - File.open(File.join(dir, 'iso3166.tab'), 'w') do |iso3166| + RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166| iso3166.puts("FC\tFake Country") iso3166.puts("OC\tOther Country") end - File.open(File.join(dir, 'zone.tab'), 'w') do |zone| + RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone| zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one") zone.puts("FC\t+353916+1394441\tFake/Two\tAnother description") zone.puts("FC\t-2332-04637\tFake/Three\tThis is Three") @@ -643,11 +644,34 @@ class TCZoneinfoDataSource < Test::Unit::TestCase assert_equal(true, info.zones.frozen?) end end + + def test_load_country_info_utf8 + # Files are in ASCII, but may change to UTF-8 (a superset of ASCII) in + # the future. + + Dir.mktmpdir('tzinfo_test') do |dir| + RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166| + iso3166.puts("UT\tUnicode Test ✓") + end + + RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone| + zone.puts("UT\t+513030-0000731\tUnicode✓/One\tUnicode Description ✓") + end + + data_source = ZoneinfoDataSource.new(dir) + + info = data_source.load_country_info('UT') + assert_equal('UT', info.code) + assert_equal('Unicode Test ✓', info.name) + assert_equal(['Unicode✓/One'], info.zone_identifiers) + assert_equal([CountryTimezone.new('Unicode✓/One', 6181, 120, -451, 3600, 'Unicode Description ✓')], info.zones) + end + end def test_country_codes file_codes = [] - File.open(File.join(@data_source.zoneinfo_dir, 'iso3166.tab')) do |file| + RubyCoreSupport.open_file(File.join(@data_source.zoneinfo_dir, 'iso3166.tab'), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file| file.each_line do |line| line.chomp! file_codes << $1 if line =~ /\A([A-Z]{2})\t/