Files
xxx/tests/php/fixtures/router.php
T
2026-09-26 15:27:51 +02:00

72 lines
3.0 KiB
PHP

<?php
/*
* The router for the page tests, which run the site on PHP's built-in
* web server (see tests/php/Support/PageTestCase.php). For each request
* it sets up the test environment, loads the fake tables from the state
* directory in XXX_PAGE_STATE, and runs the page as Apache does, with
* "/article" for article.php. The tables are saved when the page ends.
*
* The built-in server has no TLS, so a request counts as HTTPS unless it
* has an X-Test-Plain header. The captcha passes when its response is
* "pass".
*/
require dirname(__DIR__) . '/environment.php';
use Xxx\Tests\Support\FakeDb;
use Xxx\Tests\Support\FakeRecaptcha;
use Xxx\Tests\Support\SiteData;
// The page file for this request, TRUE when the router answered (404), or
// FALSE for a static file, which the server sends itself
function xxx_page_route() {
$path = rawurldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
$file = realpath(XXX_ROOT . $path);
if ($file !== FALSE && is_dir($file))
$file = realpath($file . '/index.php');
else if ($file === FALSE)
$file = realpath(XXX_ROOT . rtrim($path, '/') . '.php');
if ($file === FALSE || !str_starts_with($file, XXX_ROOT . '/') || str_starts_with($file, XXX_ROOT . '/tests/')) {
http_response_code(404);
return TRUE;
}
if (!str_ends_with($file, '.php'))
return FALSE;
$state = getenv('XXX_PAGE_STATE');
$saved = unserialize(file_get_contents("$state/tables.ser"));
FakeDb::$logFile = "$state/queries.jsonl";
SiteData::install($saved['tables']);
SiteData::$passwordLength = $saved['passwordLength'];
register_shutdown_function(function () use ($state) {
file_put_contents("$state/tables.ser", serialize(array('tables' => SiteData::$tables,
'passwordLength' => SiteData::$passwordLength)), LOCK_EX);
});
FakeRecaptcha::install(function ($post) use ($file) {
$token = $post['event']['token'] ?? '';
if ($token === 'unreachable')
return FALSE;
if ($token === 'api-error')
return '{"error":{"code":403,"status":"PERMISSION_DENIED"}}';
$action = $file === XXX_ROOT . '/publish/login.php' ? 'login' : 'submit';
return json_encode(array('tokenProperties' => array(
'valid' => in_array($token, array('pass', 'wrong-host', 'wrong-action'), TRUE),
'hostname' => $token === 'wrong-host' ? 'evil.example' : 'site.test',
'action' => $token === 'wrong-action' ? 'other' : $action,
)));
});
if (!isset($_SERVER['HTTP_X_TEST_PLAIN']))
$_SERVER['HTTPS'] = 'on';
// Apache with UseCanonicalName Off also takes SERVER_NAME from the Host header
$_SERVER['SERVER_NAME'] = preg_replace('/:\d+$/', '', $_SERVER['HTTP_HOST'] ?? '');
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_TEST_ADDRESS'] ?? '192.0.2.1';
$_SERVER['SCRIPT_FILENAME'] = $file;
$_SERVER['SCRIPT_NAME'] = $_SERVER['PHP_SELF'] = substr($file, strlen(XXX_ROOT));
chdir(dirname($file));
return $file;
}
if (!is_string($xxx_page = xxx_page_route()))
return $xxx_page;
require $xxx_page;