- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
160 lines
5.1 KiB
PHP
160 lines
5.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Test script to verify CSRF token handling in multipart/form-data requests
|
|
* This simulates what happens when a form is submitted via JavaScript with FormData
|
|
*/
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Framework\Cache\Driver\InMemoryCache;
|
|
use App\Framework\Cache\SmartCache;
|
|
use App\Framework\Http\Parser\HttpRequestParser;
|
|
use App\Framework\Http\Parser\ParserCache;
|
|
|
|
// Create a mock multipart/form-data request similar to what JavaScript FormData sends
|
|
function createMultipartRequest(): array
|
|
{
|
|
$boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW';
|
|
$contentType = "multipart/form-data; boundary=$boundary";
|
|
|
|
// Simulate multipart body with CSRF tokens
|
|
$body = "--$boundary\r\n";
|
|
$body .= "Content-Disposition: form-data; name=\"_form_id\"\r\n\r\n";
|
|
$body .= "contact_form\r\n";
|
|
$body .= "--$boundary\r\n";
|
|
$body .= "Content-Disposition: form-data; name=\"_token\"\r\n\r\n";
|
|
$body .= "abc123token456\r\n";
|
|
$body .= "--$boundary\r\n";
|
|
$body .= "Content-Disposition: form-data; name=\"name\"\r\n\r\n";
|
|
$body .= "John Doe\r\n";
|
|
$body .= "--$boundary\r\n";
|
|
$body .= "Content-Disposition: form-data; name=\"email\"\r\n\r\n";
|
|
$body .= "john@example.com\r\n";
|
|
$body .= "--$boundary--\r\n";
|
|
|
|
return [
|
|
'server' => [
|
|
'REQUEST_METHOD' => 'POST',
|
|
'REQUEST_URI' => '/contact',
|
|
'CONTENT_TYPE' => $contentType,
|
|
'HTTP_HOST' => 'localhost',
|
|
],
|
|
'body' => $body,
|
|
'expected_post' => [
|
|
'_form_id' => 'contact_form',
|
|
'_token' => 'abc123token456',
|
|
'name' => 'John Doe',
|
|
'email' => 'john@example.com',
|
|
],
|
|
];
|
|
}
|
|
|
|
// Test 1: Normal multipart parsing (should work with custom parsers)
|
|
function testMultipartParsing()
|
|
{
|
|
echo "=== Test 1: Normal Multipart Parsing ===\n";
|
|
|
|
$data = createMultipartRequest();
|
|
$cache = new ParserCache(new SmartCache(new InMemoryCache()));
|
|
$parser = new HttpRequestParser($cache);
|
|
|
|
try {
|
|
$request = $parser->parseRequest(
|
|
method: $data['server']['REQUEST_METHOD'],
|
|
uri: $data['server']['REQUEST_URI'],
|
|
server: $data['server'],
|
|
rawBody: $data['body']
|
|
);
|
|
|
|
echo "✓ Request parsed successfully\n";
|
|
echo "Method: " . $request->method->value . "\n";
|
|
echo "Parsed body data: " . json_encode($request->parsedBody->data) . "\n";
|
|
|
|
// Check if CSRF tokens are present
|
|
$formId = $request->parsedBody->get('_form_id');
|
|
$token = $request->parsedBody->get('_token');
|
|
|
|
if ($formId && $token) {
|
|
echo "✓ CSRF tokens found: form_id='$formId', token='$token'\n";
|
|
} else {
|
|
echo "✗ CSRF tokens missing!\n";
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
echo "✗ Error: " . $e->getMessage() . "\n";
|
|
}
|
|
|
|
echo "\n";
|
|
}
|
|
|
|
// Test 2: Simulate empty php://input scenario (this tests our fallback)
|
|
function testEmptyInputFallback()
|
|
{
|
|
echo "=== Test 2: Empty php://input Fallback ===\n";
|
|
|
|
// Simulate the scenario where php://input is empty but $_POST has data
|
|
// This is what actually happens with multipart/form-data
|
|
global $_POST;
|
|
$originalPost = $_POST;
|
|
|
|
$_POST = [
|
|
'_form_id' => 'contact_form',
|
|
'_token' => 'fallback_token_123',
|
|
'name' => 'Jane Doe',
|
|
'email' => 'jane@example.com',
|
|
];
|
|
|
|
$cache = new ParserCache(new SmartCache(new InMemoryCache()));
|
|
$parser = new HttpRequestParser($cache);
|
|
|
|
try {
|
|
$request = $parser->parseRequest(
|
|
method: 'POST',
|
|
uri: '/contact',
|
|
server: [
|
|
'REQUEST_METHOD' => 'POST',
|
|
'REQUEST_URI' => '/contact',
|
|
'CONTENT_TYPE' => 'multipart/form-data; boundary=test',
|
|
'HTTP_HOST' => 'localhost',
|
|
],
|
|
rawBody: '' // Empty body simulates php://input being empty
|
|
);
|
|
|
|
echo "✓ Request parsed with empty body\n";
|
|
echo "Parsed body data: " . json_encode($request->parsedBody->data) . "\n";
|
|
|
|
// Check if fallback worked
|
|
$formId = $request->parsedBody->get('_form_id');
|
|
$token = $request->parsedBody->get('_token');
|
|
|
|
if ($formId === 'contact_form' && $token === 'fallback_token_123') {
|
|
echo "✓ Fallback to \$_POST worked correctly!\n";
|
|
} else {
|
|
echo "✗ Fallback failed: form_id='$formId', token='$token'\n";
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
echo "✗ Error: " . $e->getMessage() . "\n";
|
|
} finally {
|
|
$_POST = $originalPost; // Restore original $_POST
|
|
}
|
|
|
|
echo "\n";
|
|
}
|
|
|
|
// Run tests
|
|
echo "Testing CSRF Token Handling in Multipart Requests\n";
|
|
echo "================================================\n\n";
|
|
|
|
testMultipartParsing();
|
|
testEmptyInputFallback();
|
|
|
|
echo "Test completed!\n";
|
|
echo "\n";
|
|
echo "If both tests pass, the CSRF token issue should be resolved.\n";
|
|
echo "The key improvement is that HttpRequestParser now uses \$_POST as fallback\n";
|
|
echo "when php://input is empty for multipart/form-data requests.\n";
|