operasoftware / dns-ui

Opera's LDAP-authenticated PowerDNS user interface
Apache License 2.0
282 stars 57 forks source link

Don't raise and exception when trying to parse date without microseconds #187

Closed uedvt359 closed 2 years ago

uedvt359 commented 2 years ago

I wasn't sure where a good place would be to add utility functions like this, so i added it inline in user.php and as a function in zone.php -- suggestions welcome!

(and yes: we actually hit this bug in production ;) )

commit message:

When SELECTing a date from the postgres database, and that date's microsecond part is exactly zero, it will be omitted from the string representation. This causes DateTime::createFromFormat to return false instead of the date.

To reproduce this bug, create and then edit a zone (so a changeset entry exists), then set its change_date like so:

update changeset set change_date = '2021-11-23 10:37:38.000000' where id = 1;

note that when issuing a SELECT, the '.000000' will be automatically stripped.

[23-Nov-2021 09:40:03 UTC] 1637660403: Error: Call to a member function format() on bool in /var/www/dns-ui/templates/zone.php:687
[23-Nov-2021 09:40:03 UTC] 1637660403: Stack trace:
[23-Nov-2021 09:40:03 UTC] 1637660403: #0 /var/www/dns-ui/pagesection.php(69): include()
[23-Nov-2021 09:40:03 UTC] 1637660403: #1 /var/www/dns-ui/pagesection.php(57): PageSection->generate()
[23-Nov-2021 09:40:03 UTC] 1637660403: #2 /var/www/dns-ui/templates/base.php(81): PageSection->get()
[23-Nov-2021 09:40:03 UTC] 1637660403: #3 /var/www/dns-ui/pagesection.php(69): include('/var/www/dns-ui...')
[23-Nov-2021 09:40:03 UTC] 1637660403: #4 /var/www/dns-ui/views/zone.php(321): PageSection->generate()
[23-Nov-2021 09:40:03 UTC] 1637660403: #5 /var/www/dns-ui/requesthandler.php(62): require('/var/www/dns-ui...')
[23-Nov-2021 09:40:03 UTC] 1637660403: #6 /var/www/dns-ui/public_html/init.php(18): require('/var/www/dns-ui...')
[23-Nov-2021 09:40:03 UTC] 1637660403: #7 {main}
thomas-pike commented 2 years ago

I'm curious which PHP version you are encountering this in. At least running this code manually in PHP 8.0 gives the expected result:

$ php -r 'var_dump(DateTime::createFromFormat("Y-m-d H:i:s.u", "2021-11-23 10:37:38.000000"));'
object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2021-11-23 10:37:38.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}

same result also with PHP 7.4

thomas-pike commented 2 years ago

Ah, I see, it's because the database layer is stripping the .000000. I should learn to read better :)

thomas-pike commented 2 years ago

I see that the popular Doctrine database abstraction library has also had to make mention of this problem: https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/known-vendor-issues.html

uedvt359 commented 2 years ago

Ah, I see, it's because the database layer is stripping the .000000. I should learn to read better :)

No worries; I didn't explain it well either.

Moved the function to core.php; used it in model/user.php.

thomas-pike commented 2 years ago

Thank you very much for finding and fixing this bug!