Categories > TinyButStrong general >

TinyButString date formatting bug, operator frm

The forum is closed. Please use Stack Overflow for submitting new questions. Use tags: tinybutstrong , opentbs
By: sempasha
Date: 2012-05-22
Time: 07:53

TinyButString date formatting bug, operator frm

There is a bug in formatting of dates using 'frm' modifier.
How to reproduce.

Platform:
CentOS 5.6 64bit, PHP 5.3.10

Steps:
1. Assign to template date field with value 1337544000 (integer, unix timestamp format).
2. Add to template format for this field "year [field;frm=yyyy]"
3. Generate document from template
4. Expected result: in document we see "year 2012". Real result: in document we see "year 4000"

I found this error caused by clsTinyButString::meth_Misc_Format method.
On lines 2893-2898 there is code
$x = strtotime($Value);
if (($x===-1) or ($x===false)) {
    if (!is_numeric($Value)) $Value = 0;
} else {
    $Value = &$x;
}
In my case $Value is equivalent to string '1337544000', so execution of previous code provides a logic error:
$Value = '1337544000';
// $x will an integer with value of 64072895874
$x = strtotime($Value);
// so ($x===-1) or ($x===false) is not true
if (($x===-1) or ($x===false)) {
    if (!is_numeric($Value)) $Value = 0;
} else {
    // $Value will have value of $x (int 64072895874),
    // and we become very very sad in this fact,
    // because we expects $Value kept its own original value
    $Value = &$x;
}

That's all.
By: Skrol29
Date: 2012-05-22
Time: 22:42

Re: TinyButString date formatting bug, operator frm

Hi sempasha,

I must say, I cannot reproduce this bug.

PHP:
$dt1 = '1337544000';
$dt2 = 1337544000;

HTML:
{[onload.dt1;frm=yyyy]}
{[onload.dt2;frm=yyyy]}

Result:
{2012}
{2012}

I'm with PHP 5.3.10 & 5.4.0, Win7, TBS 3.7.0 & 3.8.0
By: sempasha
Date: 2012-05-23
Time: 09:16

Re: TinyButString date formatting bug, operator frm

Hi Skrol29!

You should understand, that bug not in TinyButStrong at all, but in php:strtotime function, and it appears only in 64bit servers with 64bit PHP builds.
Function strtotime returns int(64072895874) if we pass string('1337544000') as first (ans single) argument.
$time = strtotime('1337544000');
echo ($time === 64072895874 ? 'there is a bug' : 'there is no bug');

I mean TinyButStrong use $Value to time conversion to test, if $Value is valid date string (such as '2012-05-21 12:00:00' or '2001-09-11 12:00:00'), but it should not do this. It's enough to perform is_numeric($Value) (or some other test to check is $Value is real numeric string) first.
// clsTinyButString::meth_Misc_Format method
// lines 2893-2898
// replace with next code
if (!preg_match('/^[0-9]$/+', $Value))
{
    $x = strtotime($Value);
    $Value = $x !== -1 && $x !== false
            ? $x
            : 0;
}
By: Skrol29
Date: 2012-05-23
Time: 12:04

Re: TinyButString date formatting bug, operator frm

Hi Sempasha,

I understand better now.

Your fix with preg_match() is unfortunately not compatible with some other cases.
Some databases can return date values with the format 'yyyyddmm'. And this format is also supported by strtotime().

What do you think of the following patch ?
  if (is_string($Value)) {
    if ($Value==='') return '';
    if ( (!is_numeric($Value)) || (strlen($Value)<=8) ) {
      $x = strtotime($Value);
      if (($x===-1) or ($x===false)) {
        if (!is_numeric($Value)) $Value = 0;
      } else {
        $Value = &$x;
      }
    }
  } else {
    if (!is_numeric($Value)) return ''.$Value;
  }
By: sempasha
Date: 2012-05-24
Time: 08:21

Re: TinyButString date formatting bug, operator frm

I think you should use much clear logic.
In my experience of executing clsTinyButString::meth_Misc_Format method in debugger I can say I've never saw $Value was a number (float or int), it's always a string, even you had attached it to template as number.
You told "Some databases can return date values with the format 'yyyyddmm'.", it very sad fact for us, but I can suppose that these databases can return datetime value as 20001023235959 (year month date hours minutes seconds). And if it's true, we in big trouble.

First way is to correct code, which converts $Value to string, before it comes to clsTinyButString::meth_Misc_Format method, in this case we can easely use is_int() or is_float() test to detect unixtimestamp. This way can be very hard, but is single right way.

Second way is use strtotime check only in case $Value is string length of 8 or 12 (12 only in case 20001023235959 year month date hours minutes seconds happens). But we should remember strtotime can give us unexpected result, such in my case strtotime('1337544000') returned 64072895874 which corresponds to datetime 4000-05-22 13:37:45, where "05-22" is always equivalent to the current month-date.
strtotime is very buggy, it works fine only with formatted strings, so do not use strtotime('20010911') but use strtotime('2001-09-11').

As for date format, I think you should set limits on the possible date formats (for example 2001-12-31 23:59:59), if the date passed as formated date string (no unixtimestamp)
By: Peter
Date: 2012-05-30
Time: 21:01

Re: TinyButString date formatting bug, operator frm

skrol29, this is working on here on my hoster.
Please add this to the next release.

Thanks,
Peter