(string)($opt['agent'] ?? 'LittleBeast')]; $method = $_SERVER['REQUEST_METHOD'] ?? 'GET'; if ($action === 'info/refs' && $method === 'GET') { $service = (string)($_GET['service'] ?? ''); if ($service !== 'git-upload-pack' && ($service !== 'git-receive-pack' || !$push)) return self::error(403, 'このサービスは使えません'); self::headers("application/x-{$service}-advertisement"); $out ??= fopen('php://output', 'wb'); if ($service === 'git-upload-pack') (new UploadPack($repo, $agent))->advertise($out, $version !== 2, $version); else (new ReceivePack($repo, $agent + ($opt['receive'] ?? [])))->advertise($out, true); return 200; } if (($action === 'git-upload-pack' || $action === 'git-receive-pack') && $method === 'POST') { if ($action === 'git-receive-pack' && !$push) return self::error(403, 'プッシュは出来ません'); if (($_SERVER['CONTENT_TYPE'] ?? '') !== "application/x-{$action}-request") return self::error(415, '不正なContent-Type'); $in ??= fopen('php://input', 'rb'); $enc = strtolower((string)($_SERVER['HTTP_CONTENT_ENCODING'] ?? '')); if ($enc === 'gzip' || $enc === 'x-gzip') stream_filter_append($in, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 31]); @set_time_limit(0); self::headers("application/x-{$action}-result"); $out ??= fopen('php://output', 'wb'); while (ob_get_level() > 0) ob_end_flush(); if ($action === 'git-upload-pack') (new UploadPack($repo, $agent))->serve($in, $out, true, $version); else (new ReceivePack($repo, $agent + ($opt['receive'] ?? [])))->serve($in, $out, true); return 200; } return self::error(404, '有りません'); } private static function headers(string $type): void { if (headers_sent()) return; header('Content-Type: '.$type); header('Cache-Control: no-cache, max-age=0, must-revalidate'); header('Pragma: no-cache'); header('Expires: Fri, 01 Jan 1980 00:00:00 GMT'); } private static function error(int $code, string $msg): int { if (!headers_sent()) { http_response_code($code); header('Content-Type: text/plain; charset=UTF-8'); } echo $msg, "\n"; return $code; } }