Hey all,
I ran into a problem in the way RoundCube handles mail messages with "Date:" headers that aren't 100% compliant with RFC 2822's date format. The header in question is:
Date: Tue, 21 Oct 2008 00:13:54 0600
Notice that the time zone offset specifier is missing the "+/-" prefix. Thunderbird seems to drop the zone offset in this case and assume it's a local date. RoundCube, on the other hand, passes it into PHP's handy "strtotime" function which interprets 0600 as the year. This leads at the very least to display problems (in the message list and the message display), and worst case to invalid dates in the database if caching is enabled.
I'd like to make RoundCube a little more tolerant, so I was wondering what everyone else thought about possible solutions. The options I'm considering are:
What do you all think?
Eric Stadtherr wrote:
Date: Tue, 21 Oct 2008 00:13:54 0600
Notice that the time zone offset specifier is missing the "+/-" prefix. Thunderbird seems to drop the zone offset in this case and assume it's a local date. RoundCube, on the other hand, passes it into PHP's handy "strtotime" function which interprets 0600 as the year. This leads at the very least to display problems (in the message list and the message display), and worst case to invalid dates in the database if caching is enabled.
I'd like to make RoundCube a little more tolerant, so I was wondering what everyone else thought about possible solutions. The options I'm considering are:
- Parse the date using a fixed format string (e.g. "D, d M Y H:i:s O") and one of PHP's other date functions. This would prevent misinterpretation but might be even less tolerant.
- Analyze the string before passing to strtotime() to identify and work around known issues (of which there would be exactly one at this point). This is a single special case kind of solution, but strtotime might be reliable enough that this is the only case we'll hit.
So, now we have (function format_date()):
while (($ts = @strtotime($date))===false)
I think it will be enough to change that to:
while (($ts = @strtotime($date))===false || $ts < 0)
Time zone offset will be lost. 0 here is for 1970-01-01, to be more strict such value could be greater ;) As you see there's one work around yet in function format_date():
if (is_numeric($date)) $ts = $date;
so, we can add another one for your issue.
ps. isn't it a bug in strtotime?
On Fri, Oct 24, 2008 at 8:38 AM, A.L.E.C alec@alec.pl wrote:
Eric Stadtherr wrote:
Date: Tue, 21 Oct 2008 00:13:54 0600
Notice that the time zone offset specifier is missing the "+/-" prefix. Thunderbird seems to drop the zone offset in this case and assume it's a local date. RoundCube, on the other hand, passes it into PHP's handy "strtotime" function which interprets 0600 as the year. This leads at the very least to display problems (in the message list and the message display), and worst case to invalid dates in the database if caching is enabled.
I'd like to make RoundCube a little more tolerant, so I was wondering what everyone else thought about possible solutions. The options I'm considering are:
- Parse the date using a fixed format string (e.g. "D, d M Y H:i:s O") and one of PHP's other date functions. This would prevent misinterpretation but might be even less tolerant.
- Analyze the string before passing to strtotime() to identify and work around known issues (of which there would be exactly one at this point). This is a single special case kind of solution, but strtotime might be reliable enough that this is the only case we'll hit.
So, now we have (function format_date()):
while (($ts = @strtotime($date))===false)
I think it will be enough to change that to:
while (($ts = @strtotime($date))===false || $ts < 0)
Time zone offset will be lost. 0 here is for 1970-01-01, to be more strict such value could be greater ;) As you see there's one work around yet in function format_date():
if (is_numeric($date)) $ts = $date;
so, we can add another one for your issue.
ps. isn't it a bug in strtotime?
I've personally ran into at least two issues with strtotime() and they both won't be fixed on PHP5.2.x. They appear to be fine/working in the 5.3 and 6 branches.
On top of that, the documentation is also pretty unclear. According to the author, PHP does not have a straight implementation of the GNU syntax which the docs link to. ;-) He's got a book in the works, which I probably need to buy and maybe someone gets around to updating the manual as well. :-(
Till _______________________________________________ List info: http://lists.roundcube.net/dev/
On Fri, 24 Oct 2008 08:38:17 +0200, "A.L.E.C" alec@alec.pl wrote:
Eric Stadtherr wrote:
Date: Tue, 21 Oct 2008 00:13:54 0600
Notice that the time zone offset specifier is missing the "+/-" prefix. Thunderbird seems to drop the zone offset in this case and assume it's a local date. RoundCube, on the other hand, passes it into PHP's handy "strtotime" function which interprets 0600 as the year. This leads at the very least to display problems (in the message list and the message display), and worst case to invalid dates in the database if caching is enabled.
I'd like to make RoundCube a little more tolerant, so I was wondering what everyone else thought about possible solutions. The options I'm considering are:
- Parse the date using a fixed format string (e.g. "D, d M Y H:i:s O") and one of PHP's other date functions. This would prevent misinterpretation but might be even less tolerant.
- Analyze the string before passing to strtotime() to identify and work around known issues (of which there would be exactly one at this point). This is a single special case kind of solution, but strtotime might be reliable enough that this is the only case we'll hit.
So, now we have (function format_date()):
while (($ts = @strtotime($date))===false)
I think it will be enough to change that to:
while (($ts = @strtotime($date))===false || $ts < 0)
Time zone offset will be lost. 0 here is for 1970-01-01, to be more strict such value could be greater ;) As you see there's one work around yet in function format_date():
if (is_numeric($date)) $ts = $date;
so, we can add another one for your issue.
ps. isn't it a bug in strtotime?
I don't know that we can call it a bug, since it's actually working as advertised. The documentation says that a 4-digit number that appears after other non-4-digit numbers (e.g. days and months) will be interpreted as a year. So, I'm guessing it reads the 2008 as the year, but then sees the 0600 and happily interprets that as a year. That seems wrong, but consistent with the documentation.
That workaround sounds reasonable, and should match Thunderbird's parsing. I'll test it out and commit if it looks good.