@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator

Remove support for PHP mysql extension

Summary:
This extension was deprecated in PHP 5.5.0 and removed in PHP 7.0.0.
Given the requirement of PHP 7.2, it makes no sense to support this
extension.

Closes T16024

Test Plan: Grep for both `mysql` and `mysqli` and look for outdated references.

Reviewers: O1 Blessed Committers, aklapper

Reviewed By: O1 Blessed Committers, aklapper

Subscribers: aklapper, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno

Maniphest Tasks: T16024

Differential Revision: https://we.phorge.it/D25946

+12 -207
-2
src/__phutil_library_map__.php
··· 252 252 'AphrontMultipartParser' => 'aphront/multipartparser/AphrontMultipartParser.php', 253 253 'AphrontMultipartParserTestCase' => 'aphront/multipartparser/__tests__/AphrontMultipartParserTestCase.php', 254 254 'AphrontMultipartPart' => 'aphront/multipartparser/AphrontMultipartPart.php', 255 - 'AphrontMySQLDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php', 256 255 'AphrontMySQLDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontMySQLDatabaseConnectionTestCase.php', 257 256 'AphrontMySQLiDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php', 258 257 'AphrontNotSupportedQueryException' => 'infrastructure/storage/exception/AphrontNotSupportedQueryException.php', ··· 6263 6262 'AphrontMultipartParser' => 'Phobject', 6264 6263 'AphrontMultipartParserTestCase' => 'PhutilTestCase', 6265 6264 'AphrontMultipartPart' => 'Phobject', 6266 - 'AphrontMySQLDatabaseConnection' => 'AphrontBaseMySQLDatabaseConnection', 6267 6265 'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase', 6268 6266 'AphrontMySQLiDatabaseConnection' => 'AphrontBaseMySQLDatabaseConnection', 6269 6267 'AphrontNotSupportedQueryException' => 'AphrontQueryException',
+1 -4
src/applications/config/check/PhabricatorExtensionsSetupCheck.php
··· 19 19 'openssl', 20 20 'mbstring', 21 21 'ctype', 22 + 'mysqli', 22 23 23 24 // There is a tiny chance we might not need this, but a significant 24 25 // number of applications require it and it's widely available. ··· 30 31 if (!extension_loaded($extension)) { 31 32 $need[] = $extension; 32 33 } 33 - } 34 - 35 - if (!extension_loaded('mysqli') && !extension_loaded('mysql')) { 36 - $need[] = 'mysqli or mysql'; 37 34 } 38 35 39 36 if (!$need) {
+9 -35
src/applications/config/check/PhabricatorPHPConfigSetupCheck.php
··· 67 67 ->addPHPConfig('always_populate_raw_post_data'); 68 68 } 69 69 70 - if (!extension_loaded('mysqli')) { 71 - $summary = pht( 72 - 'Install the MySQLi extension to improve database behavior.'); 73 - 74 - $message = pht( 75 - 'PHP is currently using the very old "mysql" extension to interact '. 76 - 'with the database. You should install the newer "mysqli" extension '. 77 - 'to improve behaviors (like error handling and query timeouts).'. 78 - "\n\n". 79 - 'This software will work with the older extension, but upgrading to '. 80 - 'the newer extension is recommended.'. 81 - "\n\n". 82 - 'You may be able to install the extension with a command like: %s', 83 - 84 - // NOTE: We're intentionally telling you to install "mysqlnd" here; on 85 - // Ubuntu, there's no separate "mysqli" package. 86 - phutil_tag('tt', array(), 'sudo apt-get install php-mysqlnd')); 87 - 88 - $this->newIssue('php.mysqli') 89 - ->setName(pht('MySQLi Extension Not Available')) 90 - ->setSummary($summary) 91 - ->setMessage($message); 92 - } else if (!defined('MYSQLI_ASYNC')) { 70 + if (!defined('MYSQLI_ASYNC')) { 93 71 $summary = pht( 94 72 'Configure the MySQL Native Driver to improve database behavior.'); 95 73 ··· 112 90 ->setMessage($message); 113 91 } 114 92 115 - 116 - if (extension_loaded('mysqli')) { 117 - $infile_key = 'mysqli.allow_local_infile'; 118 - } else { 119 - $infile_key = 'mysql.allow_local_infile'; 120 - } 121 - 122 - if (ini_get($infile_key)) { 93 + if (ini_get('mysqli.allow_local_infile')) { 123 94 $summary = pht( 124 95 'Disable unsafe option "%s" in PHP configuration.', 125 - $infile_key); 96 + 'mysqli.allow_local_infile'); 126 97 127 98 $message = pht( 128 99 'PHP is currently configured to honor requests from any MySQL server '. ··· 139 110 'dangerous.'. 140 111 "\n\n". 141 112 'To disable this option, set: %s', 142 - phutil_tag('tt', array(), pht('%s = 0', $infile_key))); 113 + phutil_tag( 114 + 'tt', 115 + array(), 116 + pht('%s = 0', 'mysqli.allow_local_infile'))); 143 117 144 - $this->newIssue('php.'.$infile_key) 118 + $this->newIssue('php.mysqli.allow_local_infile') 145 119 ->setName(pht('Unsafe PHP "Local Infile" Configuration')) 146 120 ->setSummary($summary) 147 121 ->setMessage($message) 148 - ->addPHPConfig($infile_key); 122 + ->addPHPConfig('mysqli.allow_local_infile'); 149 123 } 150 124 151 125 }
+1 -1
src/docs/user/installation_guide.diviner
··· 120 120 - Apache (usually "httpd" or "apache2") (or nginx) 121 121 - MySQL Server (usually "mysqld" or "mysql-server" or "mariadb-server") 122 122 - PHP (usually "php") 123 - - Required PHP extensions: mbstring, iconv, mysql (or mysqli), curl, pcntl 123 + - Required PHP extensions: mbstring, iconv, mysqli, curl, pcntl 124 124 (these might be something like "php-mysql" or "php-mysqlnd") 125 125 - Optional PHP extensions: gd, zip 126 126
+1 -5
src/infrastructure/cluster/PhabricatorDatabaseRef.php
··· 738 738 } 739 739 740 740 public static function newRawConnection(array $options) { 741 - if (extension_loaded('mysqli')) { 742 - return new AphrontMySQLiDatabaseConnection($options); 743 - } else { 744 - return new AphrontMySQLDatabaseConnection($options); 745 - } 741 + return new AphrontMySQLiDatabaseConnection($options); 746 742 } 747 743 748 744 }
-160
src/infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php
··· 1 - <?php 2 - 3 - final class AphrontMySQLDatabaseConnection 4 - extends AphrontBaseMySQLDatabaseConnection { 5 - 6 - public function escapeUTF8String($string) { 7 - $this->validateUTF8String($string); 8 - return $this->escapeBinaryString($string); 9 - } 10 - 11 - public function escapeBinaryString($string) { 12 - return mysql_real_escape_string($string, $this->requireConnection()); 13 - } 14 - 15 - public function getInsertID() { 16 - return mysql_insert_id($this->requireConnection()); 17 - } 18 - 19 - public function getAffectedRows() { 20 - return mysql_affected_rows($this->requireConnection()); 21 - } 22 - 23 - protected function closeConnection() { 24 - mysql_close($this->requireConnection()); 25 - } 26 - 27 - protected function connect() { 28 - if (!function_exists('mysql_connect')) { 29 - // We have to '@' the actual call since it can spew all sorts of silly 30 - // noise, but it will also silence fatals caused by not having MySQL 31 - // installed, which has bitten me on three separate occasions. Make sure 32 - // such failures are explicit and loud. 33 - throw new Exception( 34 - pht( 35 - 'About to call %s, but the PHP MySQL extension is not available!', 36 - 'mysql_connect()')); 37 - } 38 - 39 - $user = $this->getConfiguration('user'); 40 - $host = $this->getConfiguration('host'); 41 - $port = $this->getConfiguration('port'); 42 - 43 - if ($port) { 44 - $host .= ':'.$port; 45 - } 46 - 47 - $database = $this->getConfiguration('database'); 48 - 49 - $pass = $this->getConfiguration('pass'); 50 - if ($pass instanceof PhutilOpaqueEnvelope) { 51 - $pass = $pass->openEnvelope(); 52 - } 53 - 54 - $timeout = $this->getConfiguration('timeout'); 55 - $timeout_ini = 'mysql.connect_timeout'; 56 - if ($timeout) { 57 - $old_timeout = ini_get($timeout_ini); 58 - ini_set($timeout_ini, $timeout); 59 - } 60 - 61 - try { 62 - $conn = @mysql_connect( 63 - $host, 64 - $user, 65 - $pass, 66 - $new_link = true, 67 - $flags = 0); 68 - } catch (Exception $ex) { 69 - if ($timeout) { 70 - ini_set($timeout_ini, $old_timeout); 71 - } 72 - throw $ex; 73 - } 74 - 75 - if ($timeout) { 76 - ini_set($timeout_ini, $old_timeout); 77 - } 78 - 79 - if (!$conn) { 80 - $errno = mysql_errno(); 81 - $error = mysql_error(); 82 - $this->throwConnectionException($errno, $error, $user, $host); 83 - } 84 - 85 - if ($database !== null) { 86 - $ret = @mysql_select_db($database, $conn); 87 - if (!$ret) { 88 - $this->throwQueryException($conn); 89 - } 90 - } 91 - 92 - $ok = @mysql_set_charset('utf8mb4', $conn); 93 - if (!$ok) { 94 - mysql_set_charset('binary', $conn); 95 - } 96 - 97 - return $conn; 98 - } 99 - 100 - protected function rawQuery($raw_query) { 101 - return @mysql_query($raw_query, $this->requireConnection()); 102 - } 103 - 104 - /** 105 - * @phutil-external-symbol function mysql_multi_query 106 - * @phutil-external-symbol function mysql_fetch_result 107 - * @phutil-external-symbol function mysql_more_results 108 - * @phutil-external-symbol function mysql_next_result 109 - */ 110 - protected function rawQueries(array $raw_queries) { 111 - $conn = $this->requireConnection(); 112 - $results = array(); 113 - 114 - if (!function_exists('mysql_multi_query')) { 115 - foreach ($raw_queries as $key => $raw_query) { 116 - $results[$key] = $this->processResult($this->rawQuery($raw_query)); 117 - } 118 - return $results; 119 - } 120 - 121 - if (!mysql_multi_query(implode("\n;\n\n", $raw_queries), $conn)) { 122 - $ex = $this->processResult(false); 123 - return array_fill_keys(array_keys($raw_queries), $ex); 124 - } 125 - 126 - $processed_all = false; 127 - foreach ($raw_queries as $key => $raw_query) { 128 - $results[$key] = $this->processResult(@mysql_fetch_result($conn)); 129 - if (!mysql_more_results($conn)) { 130 - $processed_all = true; 131 - break; 132 - } 133 - mysql_next_result($conn); 134 - } 135 - 136 - if (!$processed_all) { 137 - throw new Exception( 138 - pht('There are some results left in the result set.')); 139 - } 140 - 141 - return $results; 142 - } 143 - 144 - protected function freeResult($result) { 145 - mysql_free_result($result); 146 - } 147 - 148 - protected function fetchAssoc($result) { 149 - return mysql_fetch_assoc($result); 150 - } 151 - 152 - protected function getErrorCode($connection) { 153 - return mysql_errno($connection); 154 - } 155 - 156 - protected function getErrorDescription($connection) { 157 - return mysql_error($connection); 158 - } 159 - 160 - }