| | header( 'Cache-Control: no-cache' ); |
| | |
| | - $input = file_get_contents( 'php://input' ); |
| | - $wants = []; |
| | - $haves = []; |
| | - $offset = 0; |
| | - $isGzip = isset( $_SERVER['HTTP_CONTENT_ENCODING'] ) && |
| | - $_SERVER['HTTP_CONTENT_ENCODING'] === 'gzip'; |
| | - |
| | - if( $isGzip ) { |
| | - $decoded = gzdecode( $input ); |
| | + $wants = []; |
| | + $haves = []; |
| | + $handle = fopen( 'php://input', 'rb' ); |
| | |
| | - if( is_string( $decoded ) ) { |
| | - $input = $decoded; |
| | + if( $handle ) { |
| | + // If the input is gzipped, we wrap the stream |
| | + if( isset( $_SERVER['HTTP_CONTENT_ENCODING'] ) && |
| | + $_SERVER['HTTP_CONTENT_ENCODING'] === 'gzip' ) { |
| | + stream_filter_append( $handle, 'zlib.inflate', STREAM_FILTER_READ, [ |
| | + 'window' => 31 |
| | + ] ); |
| | } |
| | - } |
| | |
| | - while( $offset < strlen( $input ) ) { |
| | - $result = $this->readPacketLine( $input, $offset ); |
| | - $line = $result[0]; |
| | - $next = $result[1]; |
| | + while( !feof( $handle ) ) { |
| | + $lenHex = fread( $handle, 4 ); |
| | |
| | - if( $next === $offset || $line === 'done' ) { |
| | - break; |
| | - } |
| | + if( strlen( $lenHex ) < 4 ) { |
| | + break; |
| | + } |
| | |
| | - $offset = $next; |
| | + $len = hexdec( $lenHex ); |
| | |
| | - if( $line === '' ) { |
| | - continue; |
| | - } |
| | + if( $len === 0 ) { // Flush packet |
| | + break; |
| | + } |
| | |
| | - $trim = trim( $line ); |
| | + if( $len <= 4 ) { |
| | + continue; |
| | + } |
| | |
| | - if( strpos( $trim, 'want ' ) === 0 ) { |
| | - $wants[] = explode( ' ', $trim )[1]; |
| | - } elseif( strpos( $trim, 'have ' ) === 0 ) { |
| | - $haves[] = explode( ' ', $trim )[1]; |
| | + $line = fread( $handle, $len - 4 ); |
| | + $trim = trim( $line ); |
| | + |
| | + if( strpos( $trim, 'want ' ) === 0 ) { |
| | + $wants[] = explode( ' ', $trim )[1]; |
| | + } elseif( strpos( $trim, 'have ' ) === 0 ) { |
| | + $haves[] = explode( ' ', $trim )[1]; |
| | + } |
| | + |
| | + if( $trim === 'done' ) { |
| | + break; |
| | + } |
| | } |
| | + |
| | + fclose( $handle ); |
| | } |
| | |
| | if( !empty( $wants ) ) { |
| | $this->packetWrite( "NAK\n" ); |
| | |
| | $objects = $this->git->collectObjects( $wants, $haves ); |
| | - $packGen = $this->git->generatePackfile( $objects ); |
| | |
| | - foreach( $packGen as $chunk ) { |
| | + ob_start(); |
| | + foreach( $this->git->generatePackfile( $objects ) as $chunk ) { |
| | + $buffered = ob_get_clean(); |
| | + |
| | + if( $buffered !== '' ) { |
| | + $this->sendSidebandData( 1, $buffered ); |
| | + } |
| | + |
| | if( $chunk !== '' ) { |
| | $this->sendSidebandData( 1, $chunk ); |
| | } |
| | + ob_start(); |
| | } |
| | + ob_end_clean(); |
| | } |
| | |