Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/treetrek.git

Allows cloning using .git name

AuthorDave Jarvis <email>
Date2026-02-16 00:44:51 GMT-0800
Commitc9fcfc8ab7240ddbbbfd1c9f7901f55f9595d25a
Parent0a6d5f0
RepositoryList.php
}
- $repos[$basename] = [
- 'name' => $basename,
- 'safe_name' => $basename,
+ $name = $basename;
+
+ if( str_ends_with( $name, '.git' ) ) {
+ $name = substr( $name, 0, -4 );
+ }
+
+ $repos[$name] = [
+ 'name' => $name,
+ 'safe_name' => $name,
'path' => $dir
];
Router.php
private $repos = [];
private $git;
- private $basePath;
public function __construct( string $reposPath ) {
public function route(): Page {
$uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
-
$scriptName = dirname( $_SERVER['SCRIPT_NAME'] );
$repoName = array_shift( $parts );
-
- $nextPart = $parts[0] ?? '';
- $uiActions = [
- 'tree', 'blob', 'raw', 'commits', 'commit', 'tags', 'compare'
- ];
- if( str_ends_with( $repoName, '.git' ) &&
- !in_array( $nextPart, $uiActions ) && !empty( $parts ) ) {
+ if( str_ends_with( $repoName, '.git' ) ) {
$realName = substr( $repoName, 0, -4 );
- $isRealRepo =
- isset( $this->repos[$realName] ) ||
- isset( $this->repos[$repoName] );
- if( $isRealRepo ) {
- $subPath = implode( '/', $parts );
- $repoPath = $this->repos[$repoName]['path'] ??
- $this->repos[$realName]['path'];
+ $repoPath = null;
+ if( isset( $this->repos[$realName] ) ) {
+ $repoPath = $this->repos[$realName]['path'];
+ } elseif( isset( $this->repos[$repoName] ) ) {
+ $repoPath = $this->repos[$repoName]['path'];
+ }
+ if( $repoPath ) {
$this->git->setRepository( $repoPath );
-
+ $subPath = implode( '/', $parts );
return new ClonePage( $this->git, $subPath );
}
pages/ClonePage.php
public function render() {
- if( $this->subPath === 'git-receive-pack' ) {
- http_response_code( 403 );
- echo "Read-only repository.";
- exit;
- }
-
- if( $this->subPath === 'info/refs' ) {
+ if( str_ends_with( $this->subPath, 'info/refs' ) ) {
$this->renderInfoRefs();
return;
}
- if( $this->subPath === 'git-upload-pack' ) {
+ if( str_ends_with( $this->subPath, 'git-upload-pack' ) ) {
$this->handleUploadPack();
return;
+ }
+
+ if( $this->subPath === 'git-receive-pack' ) {
+ http_response_code( 403 );
+ echo "Read-only repository.";
+ exit;
}
}
- $this->serve( $this->subPath, 'text/plain' );
+ http_response_code( 404 );
+ echo "Not Found";
+ exit;
}
private function renderInfoRefs(): void {
$service = $_GET['service'] ?? '';
-
- if( $service === 'git-receive-pack' ) {
- http_response_code( 403 );
- echo "Read-only repository.";
- exit;
- }
if( $service === 'git-upload-pack' ) {
$this->packetWrite( $refs[$i]['sha'] . " " . $refs[$i]['ref'] . "\n" );
}
+ } else {
+ $this->packetWrite( "0000000000000000000000000000000000000000 capabilities^{}\0$caps\n" );
}
$this->packetFlush();
exit;
}
header( 'Content-Type: text/plain' );
-
if( $this->git->streamRaw( 'info/refs' ) ) {
exit;
}
$this->git->eachRef( function( $ref, $sha ) {
echo "$sha\t$ref\n";
} );
-
exit;
}
if( empty( $wants ) ) {
- $this->packetWrite( "ERR no wants provided\n" );
$this->packetFlush();
exit;
$chunkSize = 65000;
$offset = 0;
+ $len = strlen( $data );
- while( $offset < strlen( $data ) ) {
+ if ( $len === 0 ) return;
+
+ while( $offset < $len ) {
$chunk = substr( $data, $offset, $chunkSize );
$packet = chr( $band ) . $chunk;
$lenHex = substr( $input, $offset, 4 );
+
+ if( !ctype_xdigit( $lenHex ) ) return null;
+
$len = hexdec( $lenHex );
$offset += 4;
- $data = substr( $input, $offset, $len - 4 );
- $offset += $len - 4;
+ $dataLen = $len - 4;
+
+ if( $offset + $dataLen > strlen( $input ) ) {
+ return null;
+ }
+
+ $data = substr( $input, $offset, $dataLen );
+ $offset += $dataLen;
return $data;
Delta46 lines added, 41 lines removed, 5-line increase