From 09c58d1adde92a60a3e7cd67f4e66c8b1a56be6a Mon Sep 17 00:00:00 2001
From: Thomas Bruederli <bruederli@kolabsys.com>
Date: Sun, 28 Dec 2014 09:41:47 -0500
Subject: [PATCH] Make rcube_utils::strtotime() timezone aware (#1490163)

---
 tests/Framework/Utils.php |  274 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 274 insertions(+), 0 deletions(-)

diff --git a/tests/Framework/Utils.php b/tests/Framework/Utils.php
index b6cc5d5..1cd9e74 100644
--- a/tests/Framework/Utils.php
+++ b/tests/Framework/Utils.php
@@ -29,6 +29,7 @@
             array('email@domain.name', '.name is valid Top Level Domain name'),
             array('email@domain.co.jp', 'Dot in Top Level Domain name also considered valid (use co.jp as example here)'),
             array('firstname-lastname@domain.com', 'Dash in address field is valid'),
+            array('test@xn--e1aaa0cbbbcacac.xn--p1ai', 'IDNA domain'),
         );
     }
 
@@ -83,6 +84,83 @@
     }
 
     /**
+     * Valid IP addresses for test_valid_ip()
+     */
+    function data_valid_ip()
+    {
+        return array(
+            array('0.0.0.0'),
+            array('123.123.123.123'),
+            array('::'),
+            array('::1'),
+            array('::1.2.3.4'),
+            array('2001:2d12:c4fe:5afe::1'),
+        );
+    }
+
+    /**
+     * Valid IP addresses for test_invalid_ip()
+     */
+    function data_invalid_ip()
+    {
+        return array(
+            array(''),
+            array(0),
+            array('123.123.123.1234'),
+            array('1.1.1.1.1'),
+            array('::1.2.3.260'),
+            array('::1.0'),
+            array('2001::c4fe:5afe::1'),
+        );
+    }
+
+    /**
+     * @dataProvider data_valid_ip
+     */
+    function test_valid_ip($ip)
+    {
+        $this->assertTrue(rcube_utils::check_ip($ip));
+    }
+
+    /**
+     * @dataProvider data_invalid_ip
+     */
+    function test_invalid_ip($ip)
+    {
+        $this->assertFalse(rcube_utils::check_ip($ip));
+    }
+
+    /**
+     * Data for test_rep_specialchars_output()
+     */
+    function data_rep_specialchars_output()
+    {
+        return array(
+            array('', '', 'abc', 'abc'),
+            array('', '', '?', '?'),
+            array('', '', '"', '&quot;'),
+            array('', '', '<', '&lt;'),
+            array('', '', '>', '&gt;'),
+            array('', '', '&', '&amp;'),
+            array('', '', '&amp;', '&amp;amp;'),
+            array('', '', '<a>', '&lt;a&gt;'),
+            array('', 'remove', '<a>', ''),
+        );
+    }
+
+    /**
+     * Test for rep_specialchars_output
+     * @dataProvider data_rep_specialchars_output
+     */
+    function test_rep_specialchars_output($type, $mode, $str, $res)
+    {
+        $result = rcube_utils::rep_specialchars_output(
+            $str, $type ? $type : 'html', $mode ? $mode : 'strict');
+
+        $this->assertEquals($result, $res);
+    }
+
+    /**
      * rcube_utils::mod_css_styles()
      */
     function test_mod_css_styles()
@@ -94,6 +172,12 @@
         $this->assertRegExp('/#rcmbody h1\s\{/', $mod, "Prefix tag styles (single)");
         $this->assertRegExp('/#rcmbody h1, #rcmbody h2, #rcmbody h3, #rcmbody textarea\s+\{/', $mod, "Prefix tag styles (multiple)");
         $this->assertRegExp('/#rcmbody \.noscript\s+\{/', $mod, "Prefix class styles");
+
+        $css = file_get_contents(TESTS_DIR . 'src/media.css');
+        $mod = rcube_utils::mod_css_styles($css, 'rcmbody');
+
+        $this->assertContains('#rcmbody table[class=w600]', $mod, 'Replace styles nested in @media block');
+        $this->assertContains('#rcmbody {width:600px', $mod, 'Replace body selector nested in @media block');
     }
 
     /**
@@ -116,4 +200,194 @@
         $mod = rcube_utils::mod_css_styles("background:\\0075\\0072\\006c( javascript:alert(&#039;xss&#039;) )", 'rcmbody');
         $this->assertEquals("/* evil! */", $mod, "Don't allow encoding quirks (2)");
     }
+
+    /**
+     * Check rcube_utils::explode_quoted_string()
+     */
+    function test_explode_quoted_string()
+    {
+        $data = array(
+            '"a,b"' => array('"a,b"'),
+            '"a,b","c,d"' => array('"a,b"','"c,d"'),
+            '"a,\\"b",d' => array('"a,\\"b"', 'd'),
+        );
+
+        foreach ($data as $text => $res) {
+            $result = rcube_utils::explode_quoted_string(',', $text);
+            $this->assertSame($res, $result);
+        }
+    }
+
+    /**
+     * Check rcube_utils::explode_quoted_string() compat. with explode()
+     */
+    function test_explode_quoted_string_compat()
+    {
+        $data = array('', 'a,b,c', 'a', ',', ',a');
+
+        foreach ($data as $text) {
+            $result = rcube_utils::explode_quoted_string(',', $text);
+            $this->assertSame(explode(',', $text), $result);
+        }
+    }
+
+    /**
+     * rcube_utils::get_boolean()
+     */
+    function test_get_boolean()
+    {
+        $input = array(
+            false, 'false', '0', 'no', 'off', 'nein', 'FALSE', '', null,
+        );
+
+        foreach ($input as $idx => $value) {
+            $this->assertFalse(rcube_utils::get_boolean($value), "Invalid result for $idx test item");
+        }
+
+        $input = array(
+            true, 'true', '1', 1, 'yes', 'anything', 1000,
+        );
+
+        foreach ($input as $idx => $value) {
+            $this->assertTrue(rcube_utils::get_boolean($value), "Invalid result for $idx test item");
+        }
+    }
+
+    /**
+     * rcube:utils::file2class()
+     */
+    function test_file2class()
+    {
+        $test = array(
+            array('', '', 'unknown'),
+            array('text', 'text', 'text'),
+            array('image/png', 'image.png', 'image png'),
+        );
+
+        foreach ($test as $v) {
+            $result = rcube_utils::file2class($v[0], $v[1]);
+            $this->assertSame($v[2], $result);
+        }
+    }
+
+    /**
+     * rcube:utils::strtotime()
+     */
+    function test_strtotime()
+    {
+        $test = array(
+            '1' => 1,
+            '' => 0,
+            'abc-555' => 0,
+            '2013-04-22' => 1366581600,
+            '2013/04/22' => 1366581600,
+            '2013.04.22' => 1366581600,
+            '22-04-2013' => 1366581600,
+            '22/04/2013' => 1366581600,
+            '22.04.2013' => 1366581600,
+            '22.4.2013'  => 1366581600,
+            '20130422'   => 1366581600,
+            '2013/06/21 12:00:00 UTC' => 1371816000,
+            '2013/06/21 12:00:00 Europe/Berlin' => 1371808800,
+        );
+
+        foreach ($test as $datetime => $ts) {
+            $result = rcube_utils::strtotime($datetime);
+            $this->assertSame($ts, $result, "Error parsing date: $datetime");
+        }
+    }
+
+    /**
+     * rcube:utils::anytodatetime()
+     */
+    function test_anytodatetime()
+    {
+        $test = array(
+            '2013-04-22' => '2013-04-22',
+            '2013/04/22' => '2013-04-22',
+            '2013.04.22' => '2013-04-22',
+            '22-04-2013' => '2013-04-22',
+            '22/04/2013' => '2013-04-22',
+            '22.04.2013' => '2013-04-22',
+            '04/22/2013' => '2013-04-22',
+            '22.4.2013'  => '2013-04-22',
+            '20130422'   => '2013-04-22',
+            '1900-10-10' => '1900-10-10',
+            '01-01-1900' => '1900-01-01',
+            '01/30/1960' => '1960-01-30'
+        );
+
+        foreach ($test as $datetime => $ts) {
+            $result = rcube_utils::anytodatetime($datetime);
+            $this->assertSame($ts, $result ? $result->format('Y-m-d') : false, "Error parsing date: $datetime");
+        }
+    }
+
+    /**
+     * rcube:utils::anytodatetime()
+     */
+    function test_anytodatetime_timezone()
+    {
+        $tz = new DateTimeZone('Europe/Helsinki');
+        $test = array(
+            'Jan 1st 2014 +0800' => '2013-12-31 18:00',  // result in target timezone
+            'Jan 1st 14 45:42'   => '2014-01-01 00:00',  // force fallback to rcube_utils::strtotime()
+            'Jan 1st 2014 UK'    => '2014-01-01 00:00',
+            'Invalid date'       => false,
+        );
+
+        foreach ($test as $datetime => $ts) {
+            $result = rcube_utils::anytodatetime($datetime, $tz);
+            if ($result) $result->setTimezone($tz);  // move to target timezone for comparison
+            $this->assertSame($ts, $result ? $result->format('Y-m-d H:i') : false, "Error parsing date: $datetime");
+        }
+    }
+
+    /**
+     * rcube:utils::normalize_string()
+     */
+    function test_normalize_string()
+    {
+        $test = array(
+            ''        => '',
+            'abc def' => 'abc def',
+            'ÇçäâàåæéêëèïîìÅÉöôòüûùÿøØáíóúñÑÁÂÀãÃÊËÈÍÎÏÓÔõÕÚÛÙýÝ' => 'ccaaaaaeeeeiiiaeooouuuyooaiounnaaaaaeeeiiioooouuuyy',
+            'ąáâäćçčéęëěíîłľĺńňóôöŕřśšşťţůúűüźžżýĄŚŻŹĆ' => 'aaaaccceeeeiilllnnooorrsssttuuuuzzzyaszzc',
+            'ß'  => 'ss',
+            'ae' => 'a',
+            'oe' => 'o',
+            'ue' => 'u',
+        );
+
+        foreach ($test as $input => $output) {
+            $result = rcube_utils::normalize_string($input);
+            $this->assertSame($output, $result);
+        }
+    }
+
+    /**
+     * rcube:utils::is_absolute_path()
+     */
+    function test_is_absolute_path()
+    {
+        if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
+            $test = array(
+                '' => false,
+                "C:\\" => true,
+                'some/path' => false,
+            );
+        }
+        else {
+            $test = array(
+                '' => false,
+                '/path' => true,
+                'some/path' => false,
+            );
+        }
+
+        foreach ($test as $input => $output) {
+            $result = rcube_utils::is_absolute_path($input);
+            $this->assertSame($output, $result);
+        }
+    }
 }

--
Gitblit v1.9.1