OpenCATS icon indicating copy to clipboard operation
OpenCATS copied to clipboard

Upgrade php to newer version

Open skrchnavy opened this issue 9 years ago • 4 comments

OpenCATS uses PHP 5.X. PHP 7 is available, so it would be nice to upgrade code to be compliant to this version.

skrchnavy avatar Jul 08 '16 06:07 skrchnavy

Yep, we are running php7, just need to change the DB class to use mysqli or something like that.

I think that is the only major issue

scottunderhill avatar Oct 30 '16 11:10 scottunderhill

Managed to get it working in version 7,

Maybe still some issues. This is the databaseconnection.php file. That needs updating.

Although, If your installing new, I would recommend you install in version 5 (because of the eval functions and direct calls to the db in the install process) then move to version 7.

connect(); self::$_instance->setInTransaction(false); } // FIXME: Remove Session tight-coupling here. if (isset($_SESSION['CATS']) && $_SESSION['CATS']->isLoggedIn()) { self::$_instance->_timeZone = $_SESSION['CATS']->getTimeZoneOffset(); self::$_instance->_dateDMY = $_SESSION['CATS']->isDateDMY(); } else { self::$_instance->_timeZone = OFFSET_GMT \* -1; self::$_instance->_dateDMY = false; } return self::$_instance; } /\* Prevent this class from being instantiated by any means other - than getInstance(). */ private function __construct() {} private function __clone() {} public function setInTransaction($tf) { return ($this->_inTransaction = $tf); } /** - Returns this instance's connection resource, or null if nonexistant. * - @return resource This instance's connection resource, or null if - nonexistant. */ public function getConnection() { return $this->_connection; } /** - Initiate a connection with the MySQL database. This is called by the - constructor. * - @param string MySQL query or null to operate on the last executed query - for this instance. - @return boolean Was the connection successful? */ public function connect() { $this->_connection = @mysqli_connect( DATABASE_HOST, DATABASE_USER, DATABASE_PASS ); if (!$this->_connection) { $error = mysqli_error(); ``` die( '

Error Connecting ' . "to Database

\n\n" . $error . "
\n\n" ); return false; ``` } mysqli_set_charset(SQL_CHARACTER_SET, $this->_connection); $isDBSelected = @mysqli_select_db($this->_connection,DATABASE_NAME); if (!$isDBSelected) { $error = mysqli_error($this->_connection); ``` die( '

Error Selecting ' . "Database

\n\n" . $error . "
\n\n" ); return false; ``` } return true; } /** - Executes a MySQL query against the current connection. Unless - $ignoreErrors is true, any failed queies will result in a die(). * - @param string MySQL query or null to operate on the last executed query - for this instance. - @return resource MySQL query result. For non-SELECT queries, this will - return a boolean value indicating whether or not the - query's execution was successful. SELECT queries can - also return false indicating a permission error or - ``` other failure. ``` _/ public function query($query, $ignoreErrors = false) { /_ Does our current configuration allow the execution of this query? */ if (!$this->allowQuery($query)) { return false; } /\* Fix formatted dates and time zones for localization. */ // FIXME: I don't like rewriting queries.... $query = $this->_localizationFilter($query); /\* Don't limit the execution time of queries. */ set_time_limit(0); $this->_queryResult = mysqli_query($this->_connection,$query); if (!$this->_queryResult && !$ignoreErrors) { $error = mysqli_error($this->_connection); ``` echo ( '

Query Error -- Report to System' . " Administrator ASAP

\n\nMySQL Query Failed: "
          . $error . "\n\n" . $query . "
\n\n" ); echo(''); die(); } return $this->_queryResult; ``` } /** - Executes multiple queries from a string. Each query in the specified - string must be terminated with a semicolon (;). * - @param string MySQL query or null to operate on the last executed query - for this instance. - @param string Delimiter to use to split the SQL commands (usually ';') - @return void */ public function queryMultiple($string, $delimiter = ';') { $SQLStatments = explode($delimiter, str_replace("\r\n", "\n", $string)); foreach ($SQLStatments as $SQL) { $SQL = trim($SQL); ``` if (empty($SQL)) { continue; } $this->query($SQL); ``` } } /** - Returns a single field from a result set, based on the field's row and - column number. If a query is not specified, this method will operate on the - last executed query for this instance. * - @param string MySQL query or null to operate on the last executed query - for this instance. - @param integer Row number. - @param integer Column number. - @return array Multi-dimensional associative result set array, or array() */ public function getColumn($query = null, $row, $column) { if ($query != null) { $this->query($query); } $numRows = mysqli_num_rows($this->_queryResult); if ($numRows === false) { return false; } else if ($row >= $numRows) { return false; } else if ($row mysqli_result($this->_queryResult, $row, $column); } public function mysqli_result($res,$row=0,$col=0){ $numrows = mysqli_num_rows($res); if ($numrows && $row =0){ mysqli_data_seek($res,$row); $resrow = (is_numeric($col)) ? mysqli_fetch_row($res) : mysqli_fetch_assoc($res); if (isset($resrow[$col])){ return $resrow[$col]; } } return false; } /** - Returns one row from a query's result set in an associative array, - starting at the current row pointer. After the call, the row pointer - will be incemented by 1 (this is how the mysqli_fetch_*() functions - work). If a query is not specified, this method will operate on the - last executed query for this instance. Specifing a query always resets - the row pointer to 0. * - Example (first call): - array( - 'firstName' => 'Will', - 'lastName' => 'Buckner', - 'dateCreated' => '05/05/07 4:32 PM' - ); * - Example (second call): - array( - 'firstName' => 'Asim', - 'lastName' => 'Baig', - 'dateCreated' => '05/06/07 3:30 PM' - ); * - @param string MySQL query or null to operate on the last executed query - for this instance. - @return array Associative result set array, or array() if no records - ``` were returned. ``` */ public function getAssoc($query = null) { if ($query != null) { $this->query($query); } $recordSet = mysqli_fetch_assoc($this->_queryResult); if (empty($recordSet)) { $recordSet = array(); } return $recordSet; } /** - Returns all rows from a query's result set in a multi-dimensional - associative array. If a query is not specified, this method will operate - on the last executed query for this instance. * - Example: - array( - 0 => array( - 'firstName' => 'Will', - 'lastName' => 'Buckner', - 'dateCreated' => '05/05/07 4:32 PM' - ), - 1 => array( - 'firstName' => 'Asim', - 'lastName' => 'Baig', - 'dateCreated' => '05/06/07 3:30 PM' - ), - ... - ); * - @param string MySQL query or null to operate on the last executed query - for this instance. - @return array Multi-dimensional associative result set array, or array() - ``` if no records were returned. ``` */ public function getAllAssoc($query = null) { if ($query != null) { $this->query($query); } /\* Make sure we always return an array. */ $recordSetArray = array(); /\* Store all rows in $recordSetArray; */ while (($recordSet = mysqli_fetch_assoc($this->_queryResult))) { $recordSetArray[] = $recordSet; } /\* Return the multi-dimensional record set array. */ return $recordSetArray; } /** - Returns the number of rows in a query's result set (regardless of where - the current row pointer is). * - @return integer Total rows in a query's result set. */ public function getNumRows($query = null) { if ($query != null) { $this->query($query); } return mysqli_num_rows($this->_queryResult); } /** - Returns true if there are no (more) records in the result set for the - last query. * - @return boolean Are we at the end of the MySQL result set? */ public function isEOF() { $rowCount = mysqli_num_rows($this->_queryResult); if (!$rowCount) { return true; } return false; } /** - Creates a blocking advisory lock with the specified name. Subsequent - calls to this method will block until the previous lock with the same - name has been released. THIS DOES NOT ACTUALLY PREVENT READS OR WRITES - TO THE DATABASE! This currently only works with MySQL. * - @param string Name to assign to the lock. - @param integer Lock timeout. - @return void */ public function getAdvisoryLock($lockName, $timeout = 120) { $sql = sprintf( "SELECT GET_LOCK(%s, %s)", $this->makeQueryString($lockName), $this->makeQueryInteger($timeout) ); $this->query($sql); } /** - Returns true if the blocking advisory lock is free. * - @param string Name assigned to the lock. - @return boolean Has the lock been freed? */ public function isAdvisoryLockFree($lockName) { $sql = sprintf( "SELECT IS_FREE_LOCK(%s) AS isFreeLock", $this->makeQueryString($lockName) ); $rs = $this->getAssoc($sql); if ($rs['isFreeLock'] == 1) { return true; } return false; } /** - Releases a blocking advisory lock with the specified name (created with - $this->getAdvisoryLock(). This currently only works with MySQL. * - @param string Name of lock to be released. - @return void */ public function releaseAdvisoryLock($lockName) { $sql = sprintf( "SELECT RELEASE_LOCK(%s)", $this->makeQueryString($lockName) ); $this->query($sql); } /** - Returns the original string escaped for query use. * - @param string String to process. - @return string Original string, escaped for query use. */ public function escapeString($string) { // FIXME: Security issue, this function is not enough for sanitizing // user input. For instance see: // https://johnroach.info/2011/02/17/why-mysqli_real_escape_string-isnt-enough-to-stop-sql-injection-attacks/ // To be replaced with Symfony's stack return mysqli_real_escape_string($this->_connection, $string); } /** - Returns the original string quoted / escaped for query use. * - @param string String to process. - @return string Original string, escaped / quoted for query use. */ public function makeQueryString($string) { $st = "'" . $this->escapeString($string) . "'"; return $st; } /** - Returns 'NULL' if $string is empty; otherwise, the original string - quoted / escaped for query use. * - @param string String to process. - @return string Original string, escaped / quoted for query use, or NULL - ``` for an empty string. ``` */ public function makeQueryStringOrNULL($string) { $string = trim($string); if (empty($string)) { return 'NULL'; } return $this->makeQueryString($string); } /** - Returns 'NULL' if the specified value is equal to -1; otherwise the - original value as an integer safe for MySQL. This follows PHP5's integer - casting rules. Doubles will be rounded using truncation (1.9999 => 1). * - @param mixed Value to process. - @return integer Value converted to an integer, or 'NULL'. */ public function makeQueryIntegerOrNULL($value) { if ($value == '-1') { return 'NULL'; } return (integer) $value; } /** - Returns the original value as an integer safe for MySQL. This follows - PHP5's integer casting rules. Doubles will be rounded using truncation - (1.9999 => 1). * - @param mixed Value to process. - @return integer Value converted to an integer. */ public function makeQueryInteger($value) { return (integer) $value; } /** - Returns the original value as a safe MySQL double, rounded to the - specified precision. 0.00 is returned for bad values. * - @param string Double / string value to process. - @return string Safe MySQL double, rounded to the specified precision. */ public function makeQueryDouble($value, $precision = false) { $value = trim($value); if (empty($value) || !preg_match('/^-?[0-9]+(?:.[0-9]+)?$/', $value)) { return '0.0'; } if ($precision !== false) { $valueAsDouble = round($value, $precision); $isAWholeNumber = fmod($valueAsDouble, 1) == 0; return number_format($valueAsDouble, $isAWholeNumber ? 0 : 2); } return (string) $value; } /** - Returns the last error message (value of mysqli_error()) for the current - MySQL connection. * - @return string Error message, or '' if no error occurred. */ public function getError() { return mysqli_error($this->_connection); } /** - Returns the last insert's AUTO_INCREMENT key's value for the current - database connection connection. * - @return integer ID generated for an AUTO_INCREMENT column by the - previous INSERT query on success, 0 if the previous query does - not generate an AUTO_INCREMENT value, or false if no database - connection was established. */ public function getLastInsertID() { return @mysqli_insert_id($this->_connection); } /** - Returns the number of rows in the database that were affected by the - last query (INSERT / UPDATE / DELETE / etc.). * - @return integer Number of affected rows by the last executed MySQL - operation (INSERT / UPDATE / DELETE / etc.). */ public function getAffectedRows() { return @mysqli_affected_rows($this->_connection); } /** - Returns the current RDBMS version, as reported by the RDBMS. - The string 'MySQL ' is prepended for MySQL. * - @return string RDBMS version. */ public function getRDBMSVersion() { $rs = $this->getAssoc('SELECT VERSION() AS version'); return 'MySQL ' . $rs['version']; } /** - Returns true if the specified query is allowed by the filter. Currently - this is only used to prevent database writes when CATS_SLAVE is enabled. * - @param string Query to check. - @return boolean Is this query allowed by the current configuration? _/ public function allowQuery($query) { if (CATS_SLAVE && preg_match('/^\s_(?:UPDATE|INSERT|DELETE)\s/i', trim($query))) { return false; } return true; } // FIXME: Document me. private function _localizationFilter($query) { /\* Fix query to allow time results to be offset by $_timeZone. */ if (strpos($query , 'SELECT') !== 0) { return $query; } ``` // FIXME: This could probably be done better with regexes. // FIXME: D M Y support. // FIXME: Document this. Any string-manipulation things like this can // get fairly confusing if not documented. $newQuery = ''; while ($query != '') { /* Does the query contain a DATE_FORMAT()? */ $dateFormatPosition = strpos($query, 'DATE_FORMAT('); if ($dateFormatPosition === false) { $newQuery .= $query; $query = ''; continue; } if ($dateFormatPosition > 0) { $newQuery .= substr($query, 0, strpos($query, 'DATE_FORMAT(')); $query = substr($query, strpos($query, 'DATE_FORMAT(')); } $working = substr($query, 0, strpos($query, ',')); $query = substr($query, strpos($query, ',')); if (strpos(substr($working, 13), '(') === false) { /* Add or subtract time before the date format depeidng on the * time zone offset. We don't have to do any replacement if the * offset is 0. */ if ($this->_timeZone > 0) { $working = str_replace('DATE_FORMAT(', 'DATE_FORMAT(DATE_ADD(', $working); $working .= ', INTERVAL ' . $this->_timeZone . ' HOUR)'; } else if ($this->_timeZone _timeZone * -1) . ' HOUR)'; } } $newQuery .= $working; } $query = $newQuery; /* Replace m-d-y dates with d-m-y dates if we're in dmy mode. */ if ($this->_dateDMY) { $query = str_replace('%m-%d-%y', '%d-%m-%y', $query); $query = str_replace('%m-%d-%Y', '%d-%m-%Y', $query); $query = str_replace('%m/%d/%Y', '%d/%m/%Y', $query); $query = str_replace('%m/%d/%y', '%d/%m/%y', $query); } return $query; ``` } /** - Transaction functions for InnoDB tables. */ public function beginTransaction() { if (!$this->_inTransaction) { // Ignore errors (if called for MyISAM, for example) $this->query('BEGIN', true); return ($this->_inTransaction = true); } else { // Already in a transaction return false; } } public function commitTransaction() { if ($this->_inTransaction) { $this->query('COMMIT', true); $this->_inTransaction = false; return true; } else { // We're not in a transaction return false; } } public function rollbackTransaction() { if ($this->_inTransaction) { $this->query('ROLLBACK', true); $this->_inTransaction = false; return true; } else { // We're not in a transaction return false; } } } ?>

scottunderhill avatar Oct 30 '16 19:10 scottunderhill

duplicate of #171

RussH avatar Dec 02 '16 12:12 RussH

Will be resolved once #362 is accepted.

RussH avatar Sep 21 '18 12:09 RussH