" ---------------------------------
$maliciousTitle = 'Vidéo test';
$videoData = [
'thumbnailPath' => '/static/thumbnails/test.jpg',
];
$video = [
'id' => '9c5de94d-8e1a-4b3c-9d2e-1234567890ab',
'title' => $maliciousTitle,
'description' => 'Une description',
'duration' => 120,
'channel' => 'Chaîne ',
'views' => 42,
'date' => '2024-01-15 10:00:00',
'tags' => ['test'],
];
$jsonLd = generateVideoObjectJsonLd($videoData, $video);
assertNotContains('', $jsonLd, 'generateVideoObjectJsonLd ne reproduit pas "" en clair');
// L'équivalent encodé de "" (séquences \u00XX via JSON_HEX_TAG)
// doit apparaître à la place de la balise en clair
$encodedClosingTag = trim(json_encode('', JSON_UNESCAPED_SLASHES | JSON_HEX_TAG), '"');
assertContains(
$encodedClosingTag,
$jsonLd,
'generateVideoObjectJsonLd encode "<" et ">" en séquences unicode (JSON_HEX_TAG)'
);
$decoded = json_decode($jsonLd, true);
assertTrue(is_array($decoded), 'Le JSON-LD VideoObject reste un JSON valide');
assertEquals(
$maliciousTitle,
$decoded['name'],
'Le titre malveillant est préservé à l\'identique après décodage JSON'
);
// Les autres générateurs JSON-LD bénéficient des mêmes drapeaux d'encodage
$websiteLd = generateWebSiteJsonLd();
assertNotContains('', $websiteLd, 'generateWebSiteJsonLd ne contient pas ""');
assertTrue(json_decode($websiteLd, true) !== null, 'generateWebSiteJsonLd produit un JSON valide');
$breadcrumbLd = generateBreadcrumbJsonLd([
['name' => 'Accueil', 'url' => 'https://test.local'],
['name' => 'Page ', 'url' => 'https://test.local/page'],
]);
assertNotContains('', $breadcrumbLd, 'generateBreadcrumbJsonLd neutralise "" dans un nom de fil d\'Ariane');
$collectionLd = generateVideoCollectionJsonLd('Collection ', 'Description', [$video], 'https://test.local/col');
assertNotContains('', $collectionLd, 'generateVideoCollectionJsonLd neutralise "" dans le nom de collection');
$podcastLd = generatePodcastJsonLd([
[
'title' => 'Épisode ',
'link' => 'https://podcast.example/ep1',
'pubDate' => '2024-01-01',
],
]);
assertNotContains('', $podcastLd, 'generatePodcastJsonLd neutralise "" dans un titre d\'épisode');
assertTrue(json_decode($podcastLd, true) !== null, 'generatePodcastJsonLd produit un JSON valide');
// --- isValidAppHostName -------------------------------------------------------
assertTrue(isValidAppHostName('example.com'), 'isValidAppHostName accepte un nom de domaine');
assertTrue(isValidAppHostName('test.local'), 'isValidAppHostName accepte un domaine local');
assertTrue(isValidAppHostName('localhost'), 'isValidAppHostName accepte localhost');
assertTrue(isValidAppHostName('127.0.0.1:8080'), 'isValidAppHostName accepte une IPv4 avec port');
assertTrue(isValidAppHostName('sub.example-site.com'), 'isValidAppHostName accepte sous-domaines et tirets');
assertFalse(isValidAppHostName(''), 'isValidAppHostName refuse une chaîne vide');
assertFalse(isValidAppHostName('evil.com">';
$_SERVER['HTTPS'] = 'on';
assertEquals(
'https://' . APP_HOST_NAME,
getBaseUrl(),
'getBaseUrl utilise APP_HOST_NAME et ignore un HTTP_HOST malveillant'
);
assertNotContains('evil.example', getBaseUrl(), 'getBaseUrl ne reflète pas l\'en-tête Host');
assertEquals(APP_HOST_NAME, getAppHostName(), 'getAppHostName retourne APP_HOST_NAME validé');
unset($_SERVER['HTTPS']);
assertEquals('http://' . APP_HOST_NAME, getBaseUrl(), 'getBaseUrl retombe en http sans HTTPS');
// --- getCurrentUrl : REQUEST_URI assaini --------------------------------------
$_SERVER['REQUEST_URI'] = '/video.php?id=abc">';
$currentUrl = getCurrentUrl();
assertNotContains('"', $currentUrl, 'getCurrentUrl supprime les guillemets de REQUEST_URI');
assertNotContains('<', $currentUrl, 'getCurrentUrl supprime les chevrons de REQUEST_URI');
assertNotContains(' ', $currentUrl, 'getCurrentUrl supprime les espaces de REQUEST_URI');
assertEquals(
0,
strpos($currentUrl, 'http://' . APP_HOST_NAME . '/video.php?id=abc'),
'getCurrentUrl préfixe par l\'hôte validé et conserve le chemin'
);
$_SERVER['REQUEST_URI'] = 'sans-slash-initial';
assertEquals(
'http://' . APP_HOST_NAME . '/sans-slash-initial',
getCurrentUrl(),
'getCurrentUrl ajoute le slash initial manquant'
);
// Nettoyage des superglobales modifiées pour ne pas impacter d'autres tests
unset($_SERVER['HTTPS']);
$_SERVER['HTTP_HOST'] = APP_HOST_NAME;
$_SERVER['REQUEST_URI'] = '/';