From 126bab81467b7401ca89e46a794aa5c5d64d31d1 Mon Sep 17 00:00:00 2001 From: ralf Date: Tue, 10 May 2022 12:36:25 +0200 Subject: [PATCH] fix PHP 8.1 throws \mysqli_sql_exception or \PDOException for SQL errors - change them to our regular Api\Db\Exception - for prop(find|patch) explicitly catch PDOException to deal more graceful with non-ascii prop-names --- api/src/Db.php | 17 +++++-- api/src/Db/Exception.php | 6 +-- api/src/Vfs/Sqlfs/StreamWrapper.php | 78 +++++++++++++++++------------ 3 files changed, 61 insertions(+), 40 deletions(-) diff --git a/api/src/Db.php b/api/src/Db.php index 40ec01c406..dd37d940ec 100644 --- a/api/src/Db.php +++ b/api/src/Db.php @@ -776,13 +776,20 @@ class Db return 0; } } - if ($num_rows > 0) + try { - $rs = $this->Link_ID->SelectLimit($Query_String,$num_rows,(int)$offset,$inputarr); + if ($num_rows > 0) + { + $rs = $this->Link_ID->SelectLimit($Query_String, $num_rows, (int)$offset, $inputarr); + } + else + { + $rs = $this->Link_ID->Execute($Query_String, $inputarr); + } } - else - { - $rs = $this->Link_ID->Execute($Query_String,$inputarr); + // PHP 8.1 mysqli throws its own exception + catch(\mysqli_sql_exception $e) { + throw new Db\Exception($e->getMessage(), $e->getCode(), $e); } $this->Row = 0; $this->Errno = $this->Link_ID->ErrorNo(); diff --git a/api/src/Db/Exception.php b/api/src/Db/Exception.php index 3d3e906af9..991a72d68b 100644 --- a/api/src/Db/Exception.php +++ b/api/src/Db/Exception.php @@ -27,10 +27,10 @@ class Exception extends \egw_exception_db * @param string $msg =null message, default "Database error!" * @param int $code =100 */ - function __construct($msg=null,$code=100) + function __construct($msg=null, $code=100, \Exception $previous=null) { if (is_null($msg)) $msg = lang('Database error!'); - parent::__construct($msg,$code); + parent::__construct($msg, $code, $previous); } -} +} \ No newline at end of file diff --git a/api/src/Vfs/Sqlfs/StreamWrapper.php b/api/src/Vfs/Sqlfs/StreamWrapper.php index c9b8a9c979..c13c4fc53a 100644 --- a/api/src/Vfs/Sqlfs/StreamWrapper.php +++ b/api/src/Vfs/Sqlfs/StreamWrapper.php @@ -1875,44 +1875,52 @@ GROUP BY A.fs_id'; return false; // permission denied } $ins_stmt = $del_stmt = null; - foreach($props as &$prop) - { - if(!array_key_exists('name', $prop)) - { - return false; // Name is missing - } - if (!isset($prop['ns'])) $prop['ns'] = Vfs::DEFAULT_PROP_NAMESPACE; - if (!isset($prop['val']) || self::$pdo_type != 'mysql') // for non mysql, we have to delete the prop anyway, as there's no REPLACE! + try { + foreach ($props as &$prop) { - if (!isset($del_stmt)) + if (!array_key_exists('name', $prop)) { - $del_stmt = self::$pdo->prepare('DELETE FROM '.self::PROPS_TABLE.' WHERE fs_id=:fs_id AND prop_namespace=:prop_namespace AND prop_name=:prop_name'); + return false; // Name is missing } - $del_stmt->execute(array( - 'fs_id' => $id, - 'prop_namespace' => $prop['ns'], - 'prop_name' => $prop['name'], - )); - } - if (isset($prop['val'])) - { - if (!isset($ins_stmt)) + if (!isset($prop['ns'])) $prop['ns'] = Vfs::DEFAULT_PROP_NAMESPACE; + + if (!isset($prop['val']) || self::$pdo_type != 'mysql') // for non mysql, we have to delete the prop anyway, as there's no REPLACE! { - $ins_stmt = self::$pdo->prepare((self::$pdo_type == 'mysql' ? 'REPLACE' : 'INSERT'). - ' INTO '.self::PROPS_TABLE.' (fs_id,prop_namespace,prop_name,prop_value) VALUES (:fs_id,:prop_namespace,:prop_name,:prop_value)'); + if (!isset($del_stmt)) + { + $del_stmt = self::$pdo->prepare('DELETE FROM ' . self::PROPS_TABLE . ' WHERE fs_id=:fs_id AND prop_namespace=:prop_namespace AND prop_name=:prop_name'); + } + $del_stmt->execute(array( + 'fs_id' => $id, + 'prop_namespace' => $prop['ns'], + 'prop_name' => $prop['name'], + )); } - if (!$ins_stmt->execute(array( - 'fs_id' => $id, - 'prop_namespace' => $prop['ns'], - 'prop_name' => $prop['name'], - 'prop_value' => $prop['val'], - ))) + if (isset($prop['val'])) { - return false; + if (!isset($ins_stmt)) + { + $ins_stmt = self::$pdo->prepare((self::$pdo_type == 'mysql' ? 'REPLACE' : 'INSERT') . + ' INTO ' . self::PROPS_TABLE . ' (fs_id,prop_namespace,prop_name,prop_value) VALUES (:fs_id,:prop_namespace,:prop_name,:prop_value)'); + } + if (!$ins_stmt->execute(array( + 'fs_id' => $id, + 'prop_namespace' => $prop['ns'], + 'prop_name' => $prop['name'], + 'prop_value' => $prop['val'], + ))) + { + return false; + } } } } + // catch exception for inserting or deleting non-ascii prop_names + catch (\PDOException $e) { + _egw_log_exception($e); + return false; + } return true; } @@ -1945,10 +1953,16 @@ GROUP BY A.fs_id'; (!is_null($ns) ? ' AND prop_namespace=?' : ''); if (self::LOG_LEVEL > 2) $query = '/* '.__METHOD__.': '.__LINE__.' */ '.$query; - $stmt = self::$pdo->prepare($query); - $stmt->setFetchMode(\PDO::FETCH_ASSOC); - $stmt->execute(!is_null($ns) ? array($ns) : array()); - + try { + $stmt = self::$pdo->prepare($query); + $stmt->setFetchMode(\PDO::FETCH_ASSOC); + $stmt->execute(!is_null($ns) ? array($ns) : array()); + } + // cat exception trying to search for non-ascii prop_name + catch (\PDOException $e) { + _egw_log_exception($e); + return []; + } $props = array(); foreach($stmt as $row) {