Provide http access to git repositories
/p/$project/source/repo for git repos now exposes both "dumb" and "smart" http protocol access.
This commit is contained in:
parent
aa2868eb17
commit
34c9d04a35
@ -924,4 +924,82 @@ class IDF_Scm_Git extends IDF_Scm
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function repository($request, $match)
|
||||||
|
{
|
||||||
|
// authenticate: authenticate connection through "extra" password
|
||||||
|
if (isset($_SERVER['HTTP_AUTHORIZATION']) && $_SERVER['HTTP_AUTHORIZATION'] != '')
|
||||||
|
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':' , base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
|
||||||
|
|
||||||
|
if (isset($_SERVER['PHP_AUTH_USER'])) {
|
||||||
|
$sql = new Pluf_SQL('login=%s', array($_SERVER['PHP_AUTH_USER']));
|
||||||
|
$users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen()));
|
||||||
|
if ((count($users) == 1) && ($users[0]->active)) {
|
||||||
|
$user = $users[0];
|
||||||
|
$realkey = substr(sha1($user->password.Pluf::f('secret_key')), 0, 8);
|
||||||
|
if ($_SERVER['PHP_AUTH_PW'] == $realkey) {
|
||||||
|
$request->user = $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IDF_Precondition::accessSource($request) !== true) {
|
||||||
|
$response = new Pluf_HTTP_Response("");
|
||||||
|
$response->status_code = 401;
|
||||||
|
$response->headers['WWW-Authenticate']='Basic realm="git for '.$this->project.'"';
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = $match[2];
|
||||||
|
|
||||||
|
// update files before delivering them
|
||||||
|
if (($path == 'objects/info/pack') || ($path == 'info/refs')) {
|
||||||
|
$cmd = sprintf(Pluf::f('idf_exec_cmd_prefix', '').
|
||||||
|
'GIT_DIR=%s '.Pluf::f('git_path', 'git').' update-server-info -f',
|
||||||
|
escapeshellarg($this->repo));
|
||||||
|
self::shell_exec('IDF_Scm_Git::repository', $cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// smart HTTP discovery
|
||||||
|
if (($path == 'info/refs') &&
|
||||||
|
(array_key_exists('service', $request->GET))){
|
||||||
|
$service = $request->GET["service"];
|
||||||
|
switch ($service) {
|
||||||
|
case 'git-upload-pack':
|
||||||
|
case 'git-receive-pack':
|
||||||
|
$content = sprintf('%04x',strlen($service)+15).
|
||||||
|
'# service='.$service."\n0000";
|
||||||
|
$content .= self::shell_exec('IDF_Scm_Git::repository',
|
||||||
|
$service.' --stateless-rpc --advertise-refs '.
|
||||||
|
$this->repo);
|
||||||
|
$response = new Pluf_HTTP_Response($content,
|
||||||
|
'application/x-'.$service.'-advertisement');
|
||||||
|
return $response;
|
||||||
|
default:
|
||||||
|
throw new Exception('unknown service: '.$service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch($path) {
|
||||||
|
// smart HTTP RPC
|
||||||
|
case 'git-upload-pack':
|
||||||
|
case 'git-receive-pack':
|
||||||
|
$response = new Pluf_HTTP_Response_CommandPassThru($path.
|
||||||
|
' --stateless-rpc '.$this->repo,
|
||||||
|
'application/x-'.$path.'-result');
|
||||||
|
$response->addStdin('php://input');
|
||||||
|
return $response;
|
||||||
|
|
||||||
|
// regular file
|
||||||
|
default:
|
||||||
|
// make sure we're inside the repo hierarchy (ie. no break-out)
|
||||||
|
if (is_file($this->repo.'/'.$path) &&
|
||||||
|
strpos(realpath($this->repo.'/'.$path), $this->repo.'/') == 0) {
|
||||||
|
return new Pluf_HTTP_Response_File($this->repo.'/'.$path,
|
||||||
|
'application/octet-stream');
|
||||||
|
} else {
|
||||||
|
return new Pluf_HTTP_Response_NotFound($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user