Index: scripts/repository/commit_hook.php =================================================================== --- scripts/repository/commit_hook.php +++ scripts/repository/commit_hook.php @@ -30,9 +30,10 @@ // Figure out which user is writing the commit. if ($repository->isGit() || $repository->isHg()) { - $username = getenv('PHABRICATOR_USER'); + $username = getenv(DiffusionCommitHookEngine::ENV_USER); if (!strlen($username)) { - throw new Exception(pht('usage: PHABRICATOR_USER should be defined!')); + throw new Exception( + pht('usage: %s should be defined!', DiffusionCommitHookEngine::ENV_USER)); } // TODO: If this is a Mercurial repository, the hook we're responding to @@ -41,8 +42,8 @@ } else if ($repository->isSVN()) { // NOTE: In Subversion, the entire environment gets wiped so we can't read - // PHABRICATOR_USER. Instead, we've set "--tunnel-user" to specify the - // correct user; read this user out of the commit log. + // DiffusionCommitHookEngine::ENV_USER. Instead, we've set "--tunnel-user" to + // specify the correct user; read this user out of the commit log. if ($argc < 4) { throw new Exception(pht('usage: commit-hook ')); @@ -86,6 +87,16 @@ $engine->setStdin($stdin); +$remote_address = getenv(DiffusionCommitHookEngine::ENV_REMOTE_ADDRESS); +if (strlen($remote_address)) { + $engine->setRemoteAddress($remote_address); +} + +$remote_protocol = getenv(DiffusionCommitHookEngine::ENV_REMOTE_PROTOCOL); +if (strlen($remote_protocol)) { + $engine->setRemoteProtocol($remote_protocol); +} + try { $err = $engine->execute(); } catch (DiffusionCommitHookRejectException $ex) { Index: src/applications/diffusion/controller/DiffusionPushLogListController.php =================================================================== --- src/applications/diffusion/controller/DiffusionPushLogListController.php +++ src/applications/diffusion/controller/DiffusionPushLogListController.php @@ -41,6 +41,10 @@ ), $callsign), $this->getHandle($log->getPusherPHID())->renderLink(), + $log->getRemoteAddress() + ? long2ip($log->getRemoteAddress()) + : null, + $log->getRemoteProtocol(), $log->getRefType(), $log->getRefName(), $log->getRefOldShort(), @@ -54,6 +58,8 @@ array( pht('Repository'), pht('Pusher'), + pht('From'), + pht('Via'), pht('Type'), pht('Name'), pht('Old'), @@ -65,6 +71,8 @@ '', '', '', + '', + '', 'wide', 'n', 'n', Index: src/applications/diffusion/controller/DiffusionServeController.php =================================================================== --- src/applications/diffusion/controller/DiffusionServeController.php +++ src/applications/diffusion/controller/DiffusionServeController.php @@ -318,12 +318,11 @@ 'PATH_INFO' => $request_path, 'REMOTE_USER' => $viewer->getUsername(), - 'PHABRICATOR_USER' => $viewer->getUsername(), // TODO: Set these correctly. // GIT_COMMITTER_NAME // GIT_COMMITTER_EMAIL - ); + ) + $this->getCommonEnvironment($viewer); $input = PhabricatorStartup::getRawInput(); @@ -416,9 +415,7 @@ throw new Exception("Unable to find `hg` in PATH!"); } - $env = array( - 'PHABRICATOR_USER' => $viewer->getUsername(), - ); + $env = $this->getCommonEnvironment($viewer); $input = PhabricatorStartup::getRawInput(); $cmd = $request->getStr('cmd'); @@ -557,5 +554,15 @@ return $has_pack && $is_hangup; } + private function getCommonEnvironment(PhabricatorUser $viewer) { + $remote_addr = $this->getRequest()->getRemoteAddr(); + + return array( + DiffusionCommitHookEngine::ENV_USER => $viewer->getUsername(), + DiffusionCommitHookEngine::ENV_REMOTE_ADDRESS => $remote_addr, + DiffusionCommitHookEngine::ENV_REMOTE_PROTOCOL => 'http', + ); + } + } Index: src/applications/diffusion/engine/DiffusionCommitHookEngine.php =================================================================== --- src/applications/diffusion/engine/DiffusionCommitHookEngine.php +++ src/applications/diffusion/engine/DiffusionCommitHookEngine.php @@ -7,12 +7,35 @@ */ final class DiffusionCommitHookEngine extends Phobject { + const ENV_USER = 'PHABRICATOR_USER'; + const ENV_REMOTE_ADDRESS = 'PHABRICATOR_REMOTE_ADDRESS'; + const ENV_REMOTE_PROTOCOL = 'PHABRICATOR_REMOTE_PROTOCOL'; + private $viewer; private $repository; private $stdin; private $subversionTransaction; private $subversionRepository; + private $remoteAddress; + private $remoteProtocol; + + public function setRemoteProtocol($remote_protocol) { + $this->remoteProtocol = $remote_protocol; + return $this; + } + + public function getRemoteProtocol() { + return $this->remoteProtocol; + } + public function setRemoteAddress($remote_address) { + $this->remoteAddress = $remote_address; + return $this; + } + + public function getRemoteAddress() { + return $this->remoteAddress; + } public function setSubversionTransactionInfo($transaction, $repository) { $this->subversionTransaction = $transaction; @@ -86,13 +109,21 @@ $transaction_key = PhabricatorHash::digestForIndex( Filesystem::readRandomBytes(64)); + // If whatever we have here isn't a valid IPv4 address, just store `null`. + // Older versions of PHP return `-1` on failure instead of `false`. + $remote_address = $this->getRemoteAddress(); + $remote_address = max(0, ip2long($remote_address)); + $remote_address = nonempty($remote_address, null); + + $remote_protocol = $this->getRemoteProtocol(); + $logs = array(); foreach ($updates as $update) { $log = PhabricatorRepositoryPushLog::initializeNewLog($this->getViewer()) ->setRepositoryPHID($this->getRepository()->getPHID()) ->setEpoch(time()) - ->setRemoteAddress(null) // TODO: Populate this where possible. - ->setRemoteProtocol(null) // TODO: Populate this where possible. + ->setRemoteAddress($remote_address) + ->setRemoteProtocol($remote_protocol) ->setTransactionKey($transaction_key) ->setRefType($update['type']) ->setRefNameHash(PhabricatorHash::digestForIndex($update['ref'])) Index: src/applications/diffusion/ssh/DiffusionSSHWorkflow.php =================================================================== --- src/applications/diffusion/ssh/DiffusionSSHWorkflow.php +++ src/applications/diffusion/ssh/DiffusionSSHWorkflow.php @@ -18,9 +18,19 @@ } public function getEnvironment() { - return array( - 'PHABRICATOR_USER' => $this->getUser()->getUsername(), + $env = array( + DiffusionCommitHookEngine::ENV_USER => $this->getUser()->getUsername(), + DiffusionCommitHookEngine::ENV_REMOTE_PROTOCOL => 'ssh', ); + + $ssh_client = getenv('SSH_CLIENT'); + if ($ssh_client) { + // This has the format " ". Grab the IP. + $remote_address = head(explode(' ', $ssh_client)); + $env[DiffusionCommitHookEngine::ENV_REMOTE_ADDRESS] = $remote_address; + } + + return $env; } abstract protected function executeRepositoryOperations();