72 lines
3.0 KiB
PHP
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;
|