= 10 ? $line : mb_substr($line, $findColon + 1)); } function ghcb_changelog_action(string &$line): string { $original = trim($line); $line = ghcb_strip_prefix($line); $firstSix = mb_strtolower(mb_substr($original, 0, 6)); if($firstSix === 'revert' || $firstSix === 'restor') return 'revert'; if($firstSix === 'import') return 'import'; $firstThree = mb_strtolower(mb_substr($original, 0, 3)); if($firstThree === 'add' || $firstSix === 'create') return 'add'; if($firstThree === 'fix') return 'fix'; $firstFour = mb_strtolower(mb_substr($original, 0, 4)); $firstEight = mb_strtolower(mb_substr($original, 0, 8)); if($firstSix === 'delete' || $firstSix === 'remove' || $firstFour === 'nuke' || $firstEight === 'dropkick') return 'remove'; return 'update'; } header('Content-Type: text/plain; charset=utf-8'); if($_SERVER['REQUEST_METHOD'] !== 'POST') die('no'); $config = MSZ_CONFIG . '/github.ini'; if(!is_file($config)) die('config missing'); $config = parse_ini_file($config, true); if(empty($config['tokens']['token'])) die('config invalid'); $isGitea = isset($_SERVER['HTTP_X_GITEA_DELIVERY']) && isset($_SERVER['HTTP_X_GITEA_EVENT']); $rawData = file_get_contents('php://input'); if(!is_string($rawData)) die('no input data'); $sigParts = $isGitea ? ['sha256', $_SERVER['HTTP_X_GITEA_SIGNATURE']] : explode('=', $_SERVER['HTTP_X_HUB_SIGNATURE'] ?? '', 2); if(empty($sigParts[1])) die('invalid signature'); $repoAuthenticated = false; foreach($config['tokens']['token'] as $repoName => $repoToken) { if(hash_equals(hash_hmac($sigParts[0], $rawData, $repoToken), $sigParts[1])) { $repoAuthenticated = true; break; } } if(!isset($repoName) || !is_string($repoName)) die('no repo name'); if(!$repoAuthenticated) die('signature check failed'); $data = json_decode($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded' ? $_POST['payload'] : $rawData); if(empty($data)) die('body is corrupt'); if(empty($data->repository->full_name)) die('body is corrupt'); if($data->repository->full_name !== $repoName) die('invalid repository token'); if($_SERVER['HTTP_X_GITHUB_EVENT'] !== 'push') die('only push event is supported'); if(!property_exists($data, 'commits')) die('commits property missing'); if(!property_exists($data, 'ref')) die('ref property missing'); $commitCount = count($data->commits); if($commitCount < 1) die('no commits received'); $repoInfo = $config['repo:' . $repoName] ?? []; $repoMaster = 'refs/heads/master'; if(!empty($repoInfo['master'])) $repoMaster = $repoInfo['master']; if($data->ref !== $repoMaster) die('only the master branch is tracked'); $tags = $repoInfo['tags'] ?? []; $addresses = $config['addresses'] ?? []; foreach($data->commits as $commit) { $message = trim($commit->message); if(mb_strpos($message, $repoName) !== false || mb_substr($message, 0, 2) === '//' || mb_strpos(mb_strtolower($message), 'merge pull request') !== false) continue; $index = mb_strpos($message, "\n"); $line = $index === false ? $message : mb_substr($message, 0, $index); $body = trim($index === false ? '' : mb_substr($message, $index + 1)); $changeInfo = $msz->changelog->createChange( ghcb_changelog_action($line), $line, $body, $addresses[$commit->author->email] ?? null, max(1, strtotime($commit->timestamp)) ); if(!empty($tags)) foreach($tags as $tag) $msz->changelog->addTagToChange($changeInfo, $tag); }