zendframework / zf1

This project reached its end-of-life on 2016-09-28. Contains conversion of ZF1 subversion repo to git, from version 15234 forward, and only containing master and release-1.12 branches and 1.12 tags.
https://framework.zend.com/blog/2016-06-28-zf1-eol.html
BSD 3-Clause "New" or "Revised" License
357 stars 800 forks source link

Cannot validate Date if end-user uses custom HTTP_ACCEPT_LANGUAGE #10

Open zfbot opened 11 years ago

zfbot commented 11 years ago

Jira Information

Original Issue:ZF-12403
Issue Type:Bug
Reporter:PowerKiKi
Created:09/04/12
Assignee:Thomas Weidner
Components:Zend_Date Zend_Locale Zend_Validate

Description

Date validation throw exception if the end-user enter custom values for HTTP_ACCEPT_LANGUAGE which are used internally in Zend_Locale. Those values are 'root', 'auto' and 'browser'.

I believe those internal values should never be accepted from end-user. However I can't wrap my mind around Zend_Locale well enough to provide a patch for that.

Here is a test script to be used via CLI (so we can manually set HTTP_ACCEPT_LANGUAGE):

require_once('Zend/Version.php');
require_once('Zend/Locale.php');
require_once('Zend/Registry.php');
require_once('Zend/Validate/Date.php');

if (php_sapi_name() != 'cli')
    die('must run as CLI script');

// Extends Zend_Locale, so we can reset its state between tests
class Zend_LocaleReset extends Zend_Locale {
    public static function reset() {
        self::$_auto = null;
        self::$_browser = null;
        self::$_environment = null;
    }
}

function test($accept) 
{
    Zend_LocaleReset::reset();
    $_SERVER['HTTP_ACCEPT_LANGUAGE'] = $accept;

    $locale = new Zend_Locale();
    Zend_Registry::set('Zend_Locale', $locale);

    echo $accept . "\t=>\t" . $locale->getLanguage() . ': ';
    try {
        $validator = new Zend_Validate_Date(array('format' => 'Y-m-d'));
        $validator->isValid('2012-08-08');
        echo 'OK';
    } catch (Exception $exc) {
        echo $exc->getMessage();
    }
    echo PHP_EOL;

}

echo 'Zend Version: ' . Zend_Version::VERSION . PHP_EOL . PHP_EOL;
test(null);
test('');
test('en');
test('en-US,en;q=0.8,ko;q=0.6');
test('fr');
test('non valid string');
test('root');
test('auto');
test('browser');
test('environment');

It will output the following:

Zend Version: 1.11.0dev

=> en: OK => en: OK


en  =>  en: OK
en-US,en;q=0.8,ko;q=0.6 =>  en: OK
fr  =>  fr: OK
non valid string    =>  en: OK
root    =>  root: The locale '' is no known locale
auto    =>  root: The locale '' is no known locale
browser =>  root: The locale '' is no known locale
environment =>  en: OK
zfbot commented 11 years ago

(Originally posted by: fgibaux on 10/22/12)

In fact if the value of HTTP_ACCEPT_LANGUAGE is any word of letter up to 8 chars that is not a language or a country, it fails :

test('null');
test('top');

will output

null    =>      root: The locale '' is no known locale
top     =>      root: The locale '' is no known locale

A solution could be to validate input in static function getBrowser() of Zend_Locale :

something like this ??

if (!isset(self::$_localeData[$region]) && !isset(self::$_territoryData[$region])) {
    continue;
}
foreach ($countrys as $country) {
zfbot commented 11 years ago

This issue was ported from the ZF2 Jira Issue Tracker at http://framework.zend.com/issues/browse/ZF-12403

Known GitHub users mentioned in the original message or comment: @PowerKiKi

jusfeel commented 8 years ago

Is this issue having any solution now? I tested ZF 1.12.17. "root" locale breaks the site. I have to use "auto" or "en" in bootstrap as suggest on ZF1 documentation but I don't feel very content without knowing why.

try {
      $locale = new Zend_Locale('auto');
} catch (Zend_Locale_Exception $e) {
      $locale = new Zend_Locale('en');
}

I can't see any error or exception either with php error report turned on. Very strange. I think my accept language is "zh-xx" and this might be the reason this issue appears.

i also tried earlier version, this issue will throw Zend_Date date parsing error. Somewhere in my code when I create a Zend_Date($locale), this issue will kick in and throw exception " No region found within the locale 'root' . I tried even more earlier version, the error is "unable to parse date 2016-03-27 using DATE_FULL . (M <> d)" in Locale/Format.php file. But I can't make a sense out of it after trying to echo here and there.

Just wondering why 'root' will break the site?

PowerKiKi commented 8 years ago

I am not aware of any patch for this issue, since I reported it in 2012. And I wouldn't expect to be fixed anytime soon, since ZF3 is on the way.

The workaround I use now is similar to:

self::$locale = new Zend_Locale(); // autodetect language from browser or OS environment

// Trick: If the user entered a custom local value in his browser such as 'root' it will confuse Zend
// and it will ultimately throw exceptions (when validating Date amongst other thing). So we need to
// double check that Zend actually is able to findLocale() with the locale Zend itself detected.
if (!Zend_Locale::findLocale(self::$locale->getLanguage())) {
    // Force to revert to default language if Zend is confused
    self::$locale->setLocale("en");
}
jusfeel commented 8 years ago

My previous try/catch code somehow didn't completely work. Strangely, I redirect back from a payment gateway and the site breaks again with the root issue. I thought the try/catch in bootstrap can stop this bug. Will try to use your "findLocale" and test again.