'한국어', 'en' => 'English']); } require_once $projectRoot.'/public/install/includes/functions.php'; require_once $projectRoot.'/public/install/includes/binary-path-policy.php'; require_once $projectRoot.'/public/install/includes/request-handler.php'; } protected function tearDown(): void { $_POST = []; parent::tearDown(); } /** * Step 3 POST 를 실행하고 에러 배열을 돌려줍니다. * * @param array $post POST 본문 (DB 검증은 일부러 실패시킨다) * @return array 에러 배열 */ private function runStep3(array $post): array { $_POST = $post + [ 'db_write_host' => '', 'db_write_database' => '', 'db_write_username' => '', 'admin_email' => 'not-an-email', 'admin_language' => 'ko', 'admin_password' => '', 'admin_password_confirm' => '', ]; $formData = []; $errors = []; handleStep3Post('ko', $formData, $errors); return $errors; } /** * 개행이 섞인 .env 대상 필드는 저장 시점에 거부된다. * * @param string $field 필드명 * @param string $payload 주입 시도 값 */ #[Test] #[DataProvider('lineBreakFieldProvider')] public function it_rejects_line_breaks_in_env_bound_fields(string $field, string $payload): void { $errors = $this->runStep3([$field => $payload]); $this->assertArrayHasKey( $field, $errors, "{$field} 에 개행이 섞였는데 저장 시점에 통과했다 — .env 에 임의 변수 줄이 주입된다" ); } /** * 개행 주입 벡터 (필드 × CR/LF). * * @return array */ public static function lineBreakFieldProvider(): array { return [ 'app_name + LF' => ['app_name', "그누보드7\nAPP_DEBUG=true"], 'app_name + CR' => ['app_name', "그누보드7\rAPP_DEBUG=true"], 'app_url + LF' => ['app_url', "https://example.com\nAPP_DEBUG=true"], 'app_url + CRLF' => ['app_url', "https://example.com\r\nAPP_DEBUG=true"], 'github_url + LF' => ['core_update_github_url', "https://github.com/gnuboard/g7\nAPP_DEBUG=true"], 'app_name + NUL' => ['app_name', "그누보드7\0APP_DEBUG=true"], ]; } /** * 스킴 없는 URL 은 거부된다. */ #[Test] public function it_rejects_url_fields_without_an_http_scheme(): void { $errors = $this->runStep3(['app_url' => 'javascript:alert(1)']); $this->assertArrayHasKey('app_url', $errors); } /** * 정상 값은 이 게이트에 걸리지 않는다 (회귀 방지). */ #[Test] public function it_accepts_normal_values(): void { $errors = $this->runStep3([ 'app_name' => '그누보드7', 'app_url' => 'https://example.com', 'core_update_github_url' => 'https://github.com/gnuboard/g7', ]); $this->assertArrayNotHasKey('app_name', $errors); $this->assertArrayNotHasKey('app_url', $errors); $this->assertArrayNotHasKey('core_update_github_url', $errors); } /** * 값이 비어 있으면 URL 형태 검사는 건너뛴다 (선택 입력 보존). */ #[Test] public function it_skips_url_shape_check_for_empty_values(): void { $errors = $this->runStep3([ 'app_url' => '', 'core_update_github_url' => '', ]); $this->assertArrayNotHasKey('app_url', $errors); $this->assertArrayNotHasKey('core_update_github_url', $errors); } }