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/

Reply via email to