diff --git a/scripts/sql/manage_storage.php b/scripts/sql/manage_storage.php index ab547c38b5..4661fc9f1f 100755 --- a/scripts/sql/manage_storage.php +++ b/scripts/sql/manage_storage.php @@ -1,123 +1,129 @@ #!/usr/bin/env php setTagline('manage Phabricator storage and schemata'); $args->setSynopsis(<<parseStandardArguments(); $conf = PhabricatorEnv::newObjectFromConfig('mysql.configuration-provider'); $default_user = $conf->getUser(); -$default_password = $conf->getPassword(); $default_host = $conf->getHost(); $default_namespace = PhabricatorLiskDAO::getDefaultStorageNamespace(); try { $args->parsePartial( array( array( 'name' => 'force', 'short' => 'f', 'help' => 'Do not prompt before performing dangerous operations.', ), array( 'name' => 'user', 'short' => 'u', 'param' => 'username', 'default' => $default_user, 'help' => "Connect with __username__ instead of the configured ". "default ('{$default_user}').", ), array( 'name' => 'password', 'short' => 'p', 'param' => 'password', - 'default' => $default_password, 'help' => 'Use __password__ instead of the configured default.', ), array( 'name' => 'namespace', 'param' => 'name', 'default' => $default_namespace, 'help' => "Use namespace __namespace__ instead of the configured ". "default ('{$default_namespace}'). This is an advanced ". "feature used by unit tests; you should not normally ". "use this flag.", ), array( 'name' => 'dryrun', 'help' => 'Do not actually change anything, just show what would be '. 'changed.', ), )); } catch (PhutilArgumentUsageException $ex) { $args->printUsageException($ex); exit(77); } +if ($args->getArg('password') === null) { + // This is already a PhutilOpaqueEnvelope. + $password = $conf->getPassword(); +} else { + // Put this in a PhutilOpaqueEnvelope. + $password = new PhutilOpaqueEnvelope($args->getArg('password')); +} + $api = new PhabricatorStorageManagementAPI(); $api->setUser($args->getArg('user')); $api->setHost($default_host); -$api->setPassword($args->getArg('password')); +$api->setPassword($password); $api->setNamespace($args->getArg('namespace')); try { queryfx( $api->getConn('meta_data', $select_database = false), 'SELECT 1'); } catch (AphrontQueryException $ex) { echo phutil_console_format( "**%s**: %s\n", 'Unable To Connect', $ex->getMessage()); exit(1); } $workflows = array( new PhabricatorStorageManagementDatabasesWorkflow(), new PhabricatorStorageManagementDestroyWorkflow(), new PhabricatorStorageManagementDumpWorkflow(), new PhabricatorStorageManagementStatusWorkflow(), new PhabricatorStorageManagementUpgradeWorkflow(), ); $patches = PhabricatorSQLPatchList::buildAllPatches(); foreach ($workflows as $workflow) { $workflow->setAPI($api); $workflow->setPatches($patches); } $workflows[] = new PhutilHelpArgumentWorkflow(); $args->parseWorkflows($workflows); diff --git a/src/infrastructure/storage/configuration/DefaultDatabaseConfigurationProvider.php b/src/infrastructure/storage/configuration/DefaultDatabaseConfigurationProvider.php index 55b8989b26..9439c92765 100644 --- a/src/infrastructure/storage/configuration/DefaultDatabaseConfigurationProvider.php +++ b/src/infrastructure/storage/configuration/DefaultDatabaseConfigurationProvider.php @@ -1,59 +1,59 @@ dao = $dao; $this->mode = $mode; $this->namespace = $namespace; } public function getUser() { return PhabricatorEnv::getEnvConfig('mysql.user'); } public function getPassword() { - return PhabricatorEnv::getEnvConfig('mysql.pass'); + return new PhutilOpaqueEnvelope(PhabricatorEnv::getEnvConfig('mysql.pass')); } public function getHost() { return PhabricatorEnv::getEnvConfig('mysql.host'); } public function getDatabase() { if (!$this->getDao()) { return null; } return $this->namespace.'_'.$this->getDao()->getApplicationName(); } final protected function getDao() { return $this->dao; } } diff --git a/src/infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php b/src/infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php index 016b686afd..2a61c08d6e 100644 --- a/src/infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php +++ b/src/infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php @@ -1,100 +1,104 @@ requireConnection()); } public function getInsertID() { return mysql_insert_id($this->requireConnection()); } public function getAffectedRows() { return mysql_affected_rows($this->requireConnection()); } protected function closeConnection() { mysql_close($this->requireConnection()); } protected function connect() { if (!function_exists('mysql_connect')) { // We have to '@' the actual call since it can spew all sorts of silly // noise, but it will also silence fatals caused by not having MySQL // installed, which has bitten me on three separate occasions. Make sure // such failures are explicit and loud. throw new Exception( "About to call mysql_connect(), but the PHP MySQL extension is not ". "available!"); } $user = $this->getConfiguration('user'); $host = $this->getConfiguration('host'); $database = $this->getConfiguration('database'); + $pass = $this->getConfiguration('pass'); + if ($pass instanceof PhutilOpaqueEnvelope) { + $pass = $pass->openEnvelope(); + } $conn = @mysql_connect( $host, $user, $pass, $new_link = true, $flags = 0); if (!$conn) { $errno = mysql_errno(); $error = mysql_error(); throw new AphrontQueryConnectionException( "Attempt to connect to {$user}@{$host} failed with error ". "#{$errno}: {$error}.", $errno); } if ($database !== null) { $ret = @mysql_select_db($database, $conn); if (!$ret) { $this->throwQueryException($conn); } } mysql_set_charset('utf8', $conn); return $conn; } protected function rawQuery($raw_query) { return @mysql_query($raw_query, $this->requireConnection()); } protected function fetchAssoc($result) { return mysql_fetch_assoc($result); } protected function getErrorCode($connection) { return mysql_errno($connection); } protected function getErrorDescription($connection) { return mysql_error($connection); } } diff --git a/src/infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php b/src/infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php index 6892a2f5ab..0e3fac234a 100644 --- a/src/infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php +++ b/src/infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php @@ -1,90 +1,94 @@ requireConnection()->escape_string($string); } public function getInsertID() { return $this->requireConnection()->insert_id; } public function getAffectedRows() { return $this->requireConnection()->affected_rows; } protected function closeConnection() { $this->requireConnection()->close(); } protected function connect() { if (!class_exists('mysqli', false)) { throw new Exception( "About to call new mysqli(), but the PHP MySQLi extension is not ". "available!"); } $user = $this->getConfiguration('user'); $host = $this->getConfiguration('host'); $database = $this->getConfiguration('database'); + $pass = $this->getConfiguration('pass'); + if ($pass instanceof PhutilOpaqueEnvelope) { + $pass = $pass->openEnvelope(); + } $conn = @new mysqli( $host, $user, $pass, $database); $errno = $conn->connect_errno; if ($errno) { $error = $conn->connect_error; throw new AphrontQueryConnectionException( "Attempt to connect to {$user}@{$host} failed with error ". "#{$errno}: {$error}.", $errno); } $conn->set_charset('utf8'); return $conn; } protected function rawQuery($raw_query) { return @$this->requireConnection()->query($raw_query); } protected function fetchAssoc($result) { return $result->fetch_assoc(); } protected function getErrorCode($connection) { return $connection->errno; } protected function getErrorDescription($connection) { return $connection->error; } }