Changeset View
Changeset View
Standalone View
Standalone View
src/applications/diffusion/controller/DiffusionServeController.php
| Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | final class DiffusionServeController extends DiffusionController { | ||||
| private static function getCallsign(AphrontRequest $request) { | private static function getCallsign(AphrontRequest $request) { | ||||
| $uri = $request->getRequestURI(); | $uri = $request->getRequestURI(); | ||||
| $regex = '@^/diffusion/(?P<callsign>[A-Z]+)(/|$)@'; | $regex = '@^/diffusion/(?P<callsign>[A-Z]+)(/|$)@'; | ||||
| $matches = null; | $matches = null; | ||||
| if (!preg_match($regex, (string)$uri, $matches)) { | if (!preg_match($regex, (string)$uri, $matches)) { | ||||
| return null; | return null; | ||||
| } | } | ||||
| return $matches['callsign']; | return $matches['callsign']; | ||||
| } | } | ||||
| public function processRequest() { | public function processRequest() { | ||||
| $request = $this->getRequest(); | $request = $this->getRequest(); | ||||
| $callsign = self::getCallsign($request); | $callsign = self::getCallsign($request); | ||||
| // If authentication credentials have been provided, try to find a user | // If authentication credentials have been provided, try to find a user | ||||
| ▲ Show 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | private function isReadOnlyRequest( | ||||
| $request = $this->getRequest(); | $request = $this->getRequest(); | ||||
| $method = $_SERVER['REQUEST_METHOD']; | $method = $_SERVER['REQUEST_METHOD']; | ||||
| // TODO: This implementation is safe by default, but very incomplete. | // TODO: This implementation is safe by default, but very incomplete. | ||||
| switch ($repository->getVersionControlSystem()) { | switch ($repository->getVersionControlSystem()) { | ||||
| case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: | case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: | ||||
| $service = $request->getStr('service'); | $service = $request->getStr('service'); | ||||
| $path = $this->getRequestDirectoryPath(); | $path = $this->getRequestDirectoryPath($repository); | ||||
| // NOTE: Service names are the reverse of what you might expect, as they | // NOTE: Service names are the reverse of what you might expect, as they | ||||
| // are from the point of view of the server. The main read service is | // are from the point of view of the server. The main read service is | ||||
| // "git-upload-pack", and the main write service is "git-receive-pack". | // "git-upload-pack", and the main write service is "git-receive-pack". | ||||
| if ($method == 'GET' && | if ($method == 'GET' && | ||||
| $path == '/info/refs' && | $path == '/info/refs' && | ||||
| $service == 'git-upload-pack') { | $service == 'git-upload-pack') { | ||||
| return true; | return true; | ||||
| Show All 21 Lines | final class DiffusionServeController extends DiffusionController { | ||||
| /** | /** | ||||
| * @phutil-external-symbol class PhabricatorStartup | * @phutil-external-symbol class PhabricatorStartup | ||||
| */ | */ | ||||
| private function serveGitRequest( | private function serveGitRequest( | ||||
| PhabricatorRepository $repository, | PhabricatorRepository $repository, | ||||
| PhabricatorUser $viewer) { | PhabricatorUser $viewer) { | ||||
| $request = $this->getRequest(); | $request = $this->getRequest(); | ||||
| $request_path = $this->getRequestDirectoryPath(); | $request_path = $this->getRequestDirectoryPath($repository); | ||||
| $repository_root = $repository->getLocalPath(); | $repository_root = $repository->getLocalPath(); | ||||
| // Rebuild the query string to strip `__magic__` parameters and prevent | // Rebuild the query string to strip `__magic__` parameters and prevent | ||||
| // issues where we might interpret inputs like "service=read&service=write" | // issues where we might interpret inputs like "service=read&service=write" | ||||
| // differently than the server does and pass it an unsafe command. | // differently than the server does and pass it an unsafe command. | ||||
| // NOTE: This does not use getPassthroughRequestParameters() because | // NOTE: This does not use getPassthroughRequestParameters() because | ||||
| // that code is HTTP-method agnostic and will encode POST data. | // that code is HTTP-method agnostic and will encode POST data. | ||||
| ▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | if ($err) { | ||||
| return new PhabricatorVCSResponse( | return new PhabricatorVCSResponse( | ||||
| 500, | 500, | ||||
| pht('Error %d: %s', $err, $stderr)); | pht('Error %d: %s', $err, $stderr)); | ||||
| } | } | ||||
| return id(new DiffusionGitResponse())->setGitData($stdout); | return id(new DiffusionGitResponse())->setGitData($stdout); | ||||
| } | } | ||||
| private function getRequestDirectoryPath() { | private function getRequestDirectoryPath(PhabricatorRepository $repository) { | ||||
| $request = $this->getRequest(); | $request = $this->getRequest(); | ||||
| $request_path = $request->getRequestURI()->getPath(); | $request_path = $request->getRequestURI()->getPath(); | ||||
| return preg_replace('@^/diffusion/[A-Z]+@', '', $request_path); | $base_path = preg_replace('@^/diffusion/[A-Z]+@', '', $request_path); | ||||
| // For Git repositories, strip an optional directory component if it | |||||
| // isn't the name of a known Git resource. This allows users to clone | |||||
| // repositories as "/diffusion/X/anything.git", for example. | |||||
| if ($repository->isGit()) { | |||||
| $known = array( | |||||
| 'info', | |||||
| 'git-upload-pack', | |||||
| 'git-receive-pack', | |||||
| ); | |||||
| foreach ($known as $key => $path) { | |||||
| $known[$key] = preg_quote($path, '@'); | |||||
| } | |||||
| $known = implode('|', $known); | |||||
| if (preg_match('@^/([^/]+)/('.$known.')(/|$)@', $base_path)) { | |||||
| $base_path = preg_replace('@^/([^/]+)@', '', $base_path); | |||||
| } | |||||
| } | |||||
| return $base_path; | |||||
| } | } | ||||
| private function authenticateHTTPRepositoryUser( | private function authenticateHTTPRepositoryUser( | ||||
| $username, | $username, | ||||
| PhutilOpaqueEnvelope $password) { | PhutilOpaqueEnvelope $password) { | ||||
| if (!PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth')) { | if (!PhabricatorEnv::getEnvConfig('diffusion.allow-http-auth')) { | ||||
| // No HTTP auth permitted. | // No HTTP auth permitted. | ||||
| ▲ Show 20 Lines • Show All 203 Lines • Show Last 20 Lines | |||||