| | http_response_code( 403 ); |
| | echo "Read-only repository."; |
| | - exit; |
| | } elseif( $this->subPath === 'HEAD' ) { |
| | $this->serve( 'HEAD', 'text/plain' ); |
| | } elseif( strpos( $this->subPath, 'objects/' ) === 0 ) { |
| | $this->serve( $this->subPath, 'application/x-git-object' ); |
| | } else { |
| | http_response_code( 404 ); |
| | echo "Not Found"; |
| | - exit; |
| | } |
| | + |
| | + exit; |
| | } |
| | |
| | private function redirectBrowser(): void { |
| | - $uiUrl = str_replace( '.git', '', $_SERVER['REQUEST_URI'] ); |
| | - header( "Location: $uiUrl" ); |
| | - exit; |
| | + $url = str_replace( '.git', '', $_SERVER['REQUEST_URI'] ); |
| | + |
| | + header( "Location: $url" ); |
| | } |
| | |
 |
| | "ofs-delta shallow no-progress include-tag"; |
| | |
| | - if( !empty( $refs ) ) { |
| | + if( empty( $refs ) ) { |
| | $this->packetWrite( |
| | - $refs[0]['sha'] . " " . $refs[0]['ref'] . "\0" . $caps . "\n" |
| | + "0000000000000000000000000000000000000000 capabilities^{}\0" . |
| | + $caps . "\n" |
| | ); |
| | - for( $i = 1; $i < count( $refs ); $i++ ) { |
| | - $this->packetWrite( $refs[$i]['sha'] . " " . $refs[$i]['ref'] . "\n" ); |
| | - } |
| | } else { |
| | $this->packetWrite( |
| | - "0000000000000000000000000000000000000000 capabilities^{}\0" . |
| | - $caps . "\n" |
| | + $refs[0]['sha'] . " " . $refs[0]['ref'] . "\0" . $caps . "\n" |
| | ); |
| | + |
| | + for( $i = 1; $i < count( $refs ); $i++ ) { |
| | + $this->packetWrite( |
| | + $refs[$i]['sha'] . " " . $refs[$i]['ref'] . "\n" |
| | + ); |
| | + } |
| | } |
| | |
| | $this->packetFlush(); |
| | } else { |
| | header( 'Content-Type: text/plain' ); |
| | + |
| | if( !$this->git->streamRaw( 'info/refs' ) ) { |
| | $this->git->eachRef( function( $ref, $sha ) { |
| | echo "$sha\t$ref\n"; |
| | } ); |
| | } |
| | } |
| | - exit; |
| | } |
| | |
| | private function handleUploadPack(): void { |
| | header( 'Content-Type: application/x-git-upload-pack-result' ); |
| | header( 'Cache-Control: no-cache' ); |
| | |
| | - $input = file_get_contents( 'php://input' ); |
| | - $wants = []; |
| | - $haves = []; |
| | + $input = file_get_contents( 'php://input' ); |
| | + $wants = []; |
| | + $haves = []; |
| | $offset = 0; |
| | |
| | while( $offset < strlen( $input ) ) { |
| | $line = $this->readPacketLine( $input, $offset ); |
| | - if( $line === null ) break; |
| | - if( $line === '' ) continue; |
| | |
| | - $line = trim( $line ); |
| | - if( strpos( $line, 'want ' ) === 0 ) { |
| | - $wants[] = explode( ' ', $line )[1]; |
| | - } elseif( strpos( $line, 'have ' ) === 0 ) { |
| | - $haves[] = explode( ' ', $line )[1]; |
| | - } elseif( $line === 'done' ) { |
| | + if( $line === null || $line === 'done' ) { |
| | break; |
| | + } |
| | + |
| | + if( $line === '' ) { |
| | + continue; |
| | + } |
| | + |
| | + $trim = trim( $line ); |
| | + |
| | + if( strpos( $trim, 'want ' ) === 0 ) { |
| | + $wants[] = explode( ' ', $trim )[1]; |
| | + } elseif( strpos( $trim, 'have ' ) === 0 ) { |
| | + $haves[] = explode( ' ', $trim )[1]; |
| | } |
| | } |
| | |
| | - if( !empty( $wants ) ) { |
| | + if( $wants ) { |
| | $this->packetWrite( "NAK\n" ); |
| | |
| | - try { |
| | - $objects = $this->git->collectObjects( $wants, $haves ); |
| | - $packData = $this->git->generatePackfile( $objects ); |
| | - $this->sendSidebandData( 1, $packData ); |
| | - $this->packetFlush(); |
| | - } catch( Exception $e ) { |
| | - http_response_code( 500 ); |
| | - } |
| | - } else { |
| | - $this->packetFlush(); |
| | + $objects = $this->git->collectObjects( $wants, $haves ); |
| | + $pack = $this->git->generatePackfile( $objects ); |
| | + |
| | + $this->sendSidebandData( 1, $pack ); |
| | } |
| | - exit; |
| | + |
| | + $this->packetFlush(); |
| | } |
| | |
| | private function sendSidebandData( int $band, string $data ): void { |
| | $chunkSize = 65000; |
| | - $offset = 0; |
| | $len = strlen( $data ); |
| | |
| | - while( $offset < $len ) { |
| | + for( $offset = 0; $offset < $len; $offset += $chunkSize ) { |
| | $chunk = substr( $data, $offset, $chunkSize ); |
| | + |
| | $this->packetWrite( chr( $band ) . $chunk ); |
| | - $offset += strlen( $chunk ); |
| | } |
| | } |
 |
| | $len = hexdec( $lenHex ); |
| | $offset += 4; |
| | + $valid = $len >= 4 && $offset + ( $len - 4 ) <= strlen( $input ); |
| | |
| | - if( $len === 0 ) { |
| | - $line = ''; |
| | - } elseif( $len >= 4 && $offset + ( $len - 4 ) <= strlen( $input ) ) { |
| | - $line = substr( $input, $offset, $len - 4 ); |
| | - $offset += ( $len - 4 ); |
| | - } |
| | + $line = ($len === 0) |
| | + ? '' |
| | + : ($valid ? substr( $input, $offset, $len - 4 ) : null); |
| | + |
| | + $offset += ($len >= 4) ? ($len - 4) : 0; |
| | } |
| | } |
 |
| | echo "Missing: $path"; |
| | } |
| | - |
| | - exit; |
| | } |
| | |
 |
| | } |
| | } |
| | - |
| | |