2022-11-23 12:50:12 +01:00
< ? php declare ( strict_types = 1 );
2022-01-15 19:40:44 +01:00
/**
* Hybula Looking Glass
*
* Provides UI and input for the looking glass backend .
*
* @ copyright 2022 Hybula B . V .
* @ license Mozilla Public License 2.0
* @ version 0.1
* @ since File available since release 0.1
* @ link https :// github . com / hybula / lookingglass
*/
2022-11-23 12:50:12 +01:00
require __DIR__ . '/bootstrap.php' ;
2022-01-15 19:40:44 +01:00
use Hybula\LookingGlass ;
2022-11-23 12:50:50 +01:00
$errorMessage = null ;
2022-01-15 19:40:44 +01:00
if ( ! empty ( $_POST )) {
2022-11-23 12:50:50 +01:00
if ( ! isset ( $_POST [ 'csrfToken' ]) || ! isset ( $_SESSION [ LookingGlass :: SESSION_CSRF ]) || ( $_POST [ 'csrfToken' ] !== $_SESSION [ LookingGlass :: SESSION_CSRF ])) {
exitErrorMessage ( 'Missing or incorrect CSRF token.' );
}
if ( ! isset ( $_POST [ 'submitForm' ]) || ! isset ( $_POST [ 'backendMethod' ]) || ! isset ( $_POST [ 'targetHost' ])) {
exitErrorMessage ( 'Unsupported POST received.' );
}
2022-01-15 19:40:44 +01:00
2022-11-23 12:50:50 +01:00
if ( ! in_array ( $_POST [ 'backendMethod' ], LG_METHODS )) {
exitErrorMessage ( 'Unsupported backend method.' );
}
2022-11-23 11:50:57 +01:00
2022-11-23 12:50:50 +01:00
$_SESSION [ LookingGlass :: SESSION_TARGET_METHOD ] = $_POST [ 'backendMethod' ];
$_SESSION [ LookingGlass :: SESSION_TARGET_HOST ] = $_POST [ 'targetHost' ];
if ( ! isset ( $_POST [ 'checkTerms' ]) && LG_TERMS ) {
exitErrorMessage ( 'You must agree with the Terms of Service.' );
}
$targetHost = $_POST [ 'targetHost' ];
if ( in_array ( $_POST [ 'backendMethod' ], [ 'ping' , 'mtr' , 'traceroute' ])) {
if ( ! LookingGlass :: isValidIpv4 ( $_POST [ 'targetHost' ]) &&
! $targetHost = LookingGlass :: isValidHost ( $_POST [ 'targetHost' ], LookingGlass :: IPV4 )
) {
exitErrorMessage ( 'No valid IPv4 provided.' );
}
}
2022-11-23 11:50:57 +01:00
2022-11-23 12:50:50 +01:00
if ( in_array ( $_POST [ 'backendMethod' ], [ 'ping6' , 'mtr6' , 'traceroute6' ])) {
2022-12-27 00:24:31 +01:00
if ( ! LookingGlass :: isValidIpv6 ( $_POST [ 'targetHost' ]) &&
2022-11-23 12:50:50 +01:00
! $targetHost = LookingGlass :: isValidHost ( $_POST [ 'targetHost' ], LookingGlass :: IPV6 )
) {
exitErrorMessage ( 'No valid IPv6 provided.' );
2022-01-15 19:40:44 +01:00
}
2022-11-23 12:50:50 +01:00
}
$_SESSION [ LookingGlass :: SESSION_TARGET_HOST ] = $targetHost ;
$_SESSION [ LookingGlass :: SESSION_TOS_CHECKED ] = true ;
$_SESSION [ LookingGlass :: SESSION_CALL_BACKEND ] = true ;
exitNormal ();
}
$templateData [ 'session_target' ] = $_SESSION [ LookingGlass :: SESSION_TARGET_HOST ] ? ? '' ;
$templateData [ 'session_method' ] = $_SESSION [ LookingGlass :: SESSION_TARGET_METHOD ] ? ? '' ;
$templateData [ 'session_call_backend' ] = $_SESSION [ LookingGlass :: SESSION_CALL_BACKEND ] ? ? false ;
$templateData [ 'session_tos_checked' ] = isset ( $_SESSION [ LookingGlass :: SESSION_TOS_CHECKED ]) ? ' checked' : '' ;
if ( isset ( $_SESSION [ LookingGlass :: SESSION_ERROR_MESSAGE ])) {
$templateData [ 'error_message' ] = $_SESSION [ LookingGlass :: SESSION_ERROR_MESSAGE ];
unset ( $_SESSION [ LookingGlass :: SESSION_ERROR_MESSAGE ]);
2022-01-15 19:40:44 +01:00
}
if ( LG_BLOCK_CUSTOM ) {
2023-12-02 22:00:43 +01:00
if ( defined ( 'LG_CUSTOM_PHP' ) && file_exists ( LG_CUSTOM_PHP )) {
include LG_CUSTOM_PHP ;
}
2022-11-23 12:50:12 +01:00
2023-12-02 22:00:43 +01:00
if ( defined ( 'LG_CUSTOM_HTML' ) && file_exists ( LG_CUSTOM_HTML )) {
ob_start ();
include LG_CUSTOM_HTML ;
$templateData [ 'custom_html' ] = ob_get_clean ();
}
2023-11-01 11:00:16 -05:00
2023-12-02 22:00:43 +01:00
if ( defined ( 'LG_CUSTOM_HEADER_PHP' ) && file_exists ( LG_CUSTOM_HEADER_PHP )) {
2023-11-01 11:00:16 -05:00
ob_start ();
include LG_CUSTOM_HEADER_PHP ;
$templateData [ 'custom_header' ] = ob_get_clean ();
}
2023-12-02 22:00:43 +01:00
if ( defined ( 'LG_CUSTOM_FOOTER_PHP' ) && file_exists ( LG_CUSTOM_FOOTER_PHP )) {
2023-11-01 11:00:16 -05:00
ob_start ();
include LG_CUSTOM_FOOTER_PHP ;
$templateData [ 'custom_footer' ] = ob_get_clean ();
}
2022-01-15 19:40:44 +01:00
}
2022-11-23 12:50:12 +01:00
2023-11-01 19:14:38 +01:00
if ( LG_CHECK_LATENCY ) {
2023-03-25 15:35:05 +01:00
$templateData [ 'latency' ] = LookingGlass :: getLatency ();
}
2022-11-23 12:50:12 +01:00
$templateData [ 'csrfToken' ] = $_SESSION [ LookingGlass :: SESSION_CSRF ] = bin2hex ( random_bytes ( 12 ));
2022-01-15 19:40:44 +01:00
?>
<! doctype html >
2023-11-21 15:12:45 +01:00
< html lang = " en " data - bs - theme = " <?php if (LG_THEME != 'auto') echo LG_THEME; ?> " >
2022-01-15 19:40:44 +01:00
< head >
< meta charset = " utf-8 " >
< meta content = " width=device-width, initial-scale=1 " name = " viewport " >
< meta content = " " name = " description " >
< meta content = " Hybula " name = " author " >
2022-11-23 12:50:12 +01:00
< title >< ? php echo $templateData [ 'title' ] ?> </title>
2023-11-12 12:22:13 +01:00
< link href = " https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css " rel = " stylesheet " integrity = " sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN " crossorigin = " anonymous " >
2022-11-23 12:50:12 +01:00
< ? php if ( $templateData [ 'custom_css' ]) { echo '<link href="' . $templateData [ 'custom_css' ] . '" rel="stylesheet">' ; } ?>
2022-11-23 22:05:42 +01:00
< ? php if ( $templateData [ 'custom_head' ]) { echo $templateData [ 'custom_head' ]; } ?>
2022-01-15 19:40:44 +01:00
</ head >
< body >
2023-11-01 11:00:16 -05:00
< ? php echo isset ( $templateData [ 'custom_header' ]) ? $templateData [ 'custom_header' ] : '' ?>
2023-11-01 19:15:44 +01:00
< div class = " col-lg-8 mx-auto p-3 py-md-5 " >
2022-01-15 19:40:44 +01:00
< header class = " d-flex align-items-center pb-3 mb-5 border-bottom " >
< div class = " col-8 " >
2023-11-21 15:12:45 +01:00
< a class = " d-flex align-items-center text-primary text-decoration-none color-mode-choice color-mode-light-visible " href = " <?php echo $templateData['logo_url'] ?> " target = " _blank " >
2022-11-23 12:50:12 +01:00
< ? php echo $templateData [ 'logo_data' ] ?>
2022-01-15 19:40:44 +01:00
</ a >
2023-11-21 15:12:45 +01:00
< a class = " d-flex align-items-center text-primary text-decoration-none color-mode-choice color-mode-dark-visible " href = " <?php echo $templateData['logo_url'] ?> " target = " _blank " >
< ? php echo $templateData [ 'logo_data_dark' ] ?>
</ a >
2022-01-15 19:40:44 +01:00
</ div >
< div class = " col-4 float-end " >
< select class = " form-select " onchange = " window.location = this.options[this.selectedIndex].value " >
2022-11-23 12:50:12 +01:00
< option selected >< ? php echo $templateData [ 'current_location' ] ?> </option>
< ? php foreach ( $templateData [ 'locations' ] as $location => $link ) : ?>
< option value = " <?php echo $link ?> " >< ? php echo $location ?> </option>
< ? php endforeach ?>
2022-01-15 19:40:44 +01:00
</ select >
</ div >
</ header >
< main >
2022-11-23 12:50:12 +01:00
< ? php if ( LG_BLOCK_NETWORK ) : ?>
2022-01-15 19:40:44 +01:00
< div class = " row mb-5 " >
< div class = " card shadow-lg " >
< div class = " card-body p-3 " >
< h1 class = " fs-4 card-title mb-4 " > Network </ h1 >
< div class = " row mb-3 " >
< div class = " col-md-7 " >
< label class = " mb-2 text-muted " > Location </ label >
< div class = " input-group mb-3 " >
2022-11-23 12:50:12 +01:00
< input type = " text " class = " form-control " value = " <?php echo $templateData['current_location'] ?> " onfocus = " this.select() " readonly = " " >
< a class = " btn btn-outline-secondary " href = " https://www.openstreetmap.org/search?query=<?php echo urlencode( $templateData['maps_query'] ); ?> " target = " _blank " > Map </ a >
< ? php if ( ! empty ( $templateData [ 'locations' ])) : ?>
2022-01-15 19:40:44 +01:00
< button class = " btn btn-outline-secondary dropdown-toggle " type = " button " data - bs - toggle = " dropdown " aria - expanded = " false " > Locations </ button >
< ul class = " dropdown-menu dropdown-menu-end " >
2022-11-23 12:50:12 +01:00
< ? php foreach ( $templateData [ 'locations' ] as $location => $link ) : ?>
< li >< a class = " dropdown-item " href = " <?php echo $link ?> " >< ? php echo $location ?> </a></li>
< ? php endforeach ?>
2022-01-15 19:40:44 +01:00
</ ul >
2022-11-23 12:50:12 +01:00
< ? php endif ?>
2022-01-15 19:40:44 +01:00
</ div >
</ div >
< div class = " col-md-5 " >
< label class = " mb-2 text-muted " > Facility </ label >
< div class = " input-group " >
2022-11-23 12:50:12 +01:00
< input type = " text " class = " form-control " value = " <?php echo $templateData['facility'] ?> " onfocus = " this.select() " readonly = " " >
< a href = " <?php echo $templateData['facility_url'] ?> " class = " btn btn-outline-secondary " target = " _blank " > PeeringDB </ a >
2022-01-15 19:40:44 +01:00
</ div >
</ div >
</ div >
< div class = " row mb-3 " >
< div class = " col-md-3 " >
< label class = " mb-2 text-muted " > Test IPv4 </ label >
< div class = " input-group " >
2022-11-23 12:50:12 +01:00
< input type = " text " class = " form-control " value = " <?php echo $templateData['ipv4'] ?> " onfocus = " this.select() " readonly = " " >
< button class = " btn btn-outline-secondary " onclick = " copyToClipboard('<?php echo $templateData['ipv4'] ?>', this) " > Copy </ button >
2022-01-15 19:40:44 +01:00
</ div >
</ div >
< div class = " col-md-5 " >
< label class = " mb-2 text-muted " > Test IPv6 </ label >
< div class = " input-group " >
2022-11-23 12:50:12 +01:00
< input type = " text " class = " form-control " value = " <?php echo $templateData['ipv6'] ?> " onfocus = " this.select() " readonly = " " >
< button class = " btn btn-outline-secondary " onclick = " copyToClipboard('<?php echo $templateData['ipv6'] ?>', this) " > Copy </ button >
2022-01-15 19:40:44 +01:00
</ div >
</ div >
< div class = " col-md-4 " >
< label class = " mb-2 text-muted " > Your IP </ label >
< div class = " input-group " >
2022-11-23 12:50:12 +01:00
< input type = " text " class = " form-control " value = " <?php echo $templateData['user_ip'] ?> " onfocus = " this.select() " readonly = " " >
2023-11-01 19:14:38 +01:00
< ? php if ( LG_CHECK_LATENCY ) : ?> <label class="input-group-text" title="Latency between this looking glass and your connection." style="cursor: help;"><small><?php echo $templateData['latency'] ?> MS</small></label><?php endif ?>
2022-01-15 19:40:44 +01:00
</ div >
</ div >
</ div >
</ div >
</ div >
</ div >
2022-11-23 12:50:12 +01:00
< ? php endif ?>
2022-01-15 19:40:44 +01:00
2023-12-02 21:24:14 +01:00
< ? php if ( LG_BLOCK_LOOKINGGLASS ) : ?>
2022-01-15 19:40:44 +01:00
< div class = " row pb-5 " >
< div class = " card shadow-lg " >
< div class = " card-body p-3 " >
< h1 class = " fs-4 card-title mb-4 " > Looking Glass </ h1 >
2023-09-02 14:57:53 +00:00
< form method = " POST " autocomplete = " off " >
2022-11-23 12:50:12 +01:00
< input type = " hidden " name = " csrfToken " value = " <?php echo $templateData['csrfToken'] ?> " >
2022-01-15 19:40:44 +01:00
< div class = " row " >
< div class = " col-md-7 mb-3 " >
< div class = " input-group " >
< span class = " input-group-text " id = " basic-addon1 " > Target </ span >
2022-11-23 12:50:12 +01:00
< input type = " text " class = " form-control " placeholder = " IP address or host... " name = " targetHost " value = " <?php echo $templateData['session_target'] ?> " required = " " >
2022-01-15 19:40:44 +01:00
</ div >
</ div >
< div class = " col-md-5 mb-3 " >
< div class = " input-group " >
< label class = " input-group-text " > Method </ label >
< select class = " form-select " name = " backendMethod " id = " backendMethod " >
2022-11-23 12:50:12 +01:00
< ? php foreach ( $templateData [ 'methods' ] as $method ) : ?>
< option value = " <?php echo $method ?> " < ? php if ( $templateData [ 'session_method' ] === $method ) : ?> selected<?php endif ?>><?php echo $method ?></option>
< ? php endforeach ?>
2022-01-15 19:40:44 +01:00
</ select >
</ div >
</ div >
</ div >
< div class = " d-flex align-items-center " >
2022-11-23 12:50:12 +01:00
< ? php if ( $templateData [ 'tos' ]) : ?>
2022-01-15 19:40:44 +01:00
< div class = " form-check " >
2022-11-23 12:50:12 +01:00
< input type = " checkbox " id = " checkTerms " name = " checkTerms " class = " form-check-input " < ? php echo $templateData [ 'session_tos_checked' ] ?> >
< label for = " checkTerms " class = " form-check-label " > I agree with the < a href = " <?php echo $templateData['tos'] ?> " target = " _blank " > Terms of Use </ a ></ label >
2022-01-15 19:40:44 +01:00
</ div >
2022-11-23 12:50:12 +01:00
< ? php endif ?>
2022-01-15 19:40:44 +01:00
< button type = " submit " class = " btn btn-primary ms-auto " id = " executeButton " name = " submitForm " >
Execute
</ button >
</ div >
2022-11-23 12:50:12 +01:00
< ? php if ( $templateData [ 'error_message' ]) : ?>
2022-11-23 13:07:49 +01:00
< div class = " alert alert-danger mt-3 " role = " alert " >< ? php echo $templateData [ 'error_message' ] ?> </div>
< ? php endif ?>
2022-01-15 19:40:44 +01:00
2023-11-21 15:12:45 +01:00
< div class = " card card-body bg-dark text-light mt-4 " style = " display: none; " id = " outputCard " >
2023-03-01 10:36:51 +01:00
< pre id = " outputContent " style = " white-space: pre;word-wrap: normal;margin-bottom: 0;padding-bottom: 1rem; " ></ pre >
2022-01-15 19:40:44 +01:00
</ div >
</ form >
</ div >
</ div >
</ div >
2022-11-23 12:50:12 +01:00
< ? php endif ?>
2022-01-15 19:40:44 +01:00
2022-11-23 12:50:12 +01:00
< ? php if ( LG_BLOCK_SPEEDTEST ) : ?>
2022-01-15 19:40:44 +01:00
< div class = " row pb-5 " >
< div class = " card shadow-lg " >
< div class = " card-body p-3 " >
< h1 class = " fs-4 card-title mb-4 " > Speedtest </ h1 >
2022-11-23 12:50:12 +01:00
< ? php if ( $templateData [ 'speedtest_iperf' ]) : ?>
2022-01-15 19:40:44 +01:00
< div class = " row mb-3 " >
< div class = " col-md-6 " >
2022-11-23 12:50:12 +01:00
< label class = " mb-2 text-muted " >< ? php echo $templateData [ 'speedtest_incoming_label' ] ?> </label>
< p >< code >< ? php echo $templateData [ 'speedtest_incoming_cmd' ]; ?> </code></p>
< button class = " btn btn-sm btn-outline-secondary " onclick = " copyToClipboard('<?php echo $templateData['speedtest_incoming_cmd'] ?>', this) " > Copy </ button >
2022-01-15 19:40:44 +01:00
</ div >
< div class = " col-md-6 " >
2022-11-23 12:50:12 +01:00
< label class = " mb-2 text-muted " >< ? php echo $templateData [ 'speedtest_outgoing_label' ] ?> </label>
< p >< code >< ? php echo $templateData [ 'speedtest_outgoing_cmd' ] ?> </code></p>
< button class = " btn btn-sm btn-outline-secondary " onclick = " copyToClipboard('<?php echo $templateData['speedtest_outgoing_cmd'] ?>', this) " > Copy </ button >
2022-01-15 19:40:44 +01:00
</ div >
</ div >
2022-11-23 12:50:12 +01:00
< ? php endif ?>
2022-01-15 19:40:44 +01:00
< div class = " row " >
< label class = " mb-2 text-muted " > Test Files </ label >
< div class = " btn-group input-group mb-3 " >
2022-11-23 12:50:12 +01:00
< ? php foreach ( $templateData [ 'speedtest_files' ] as $file => $link ) : ?>
< a href = " <?php echo $link ?> " class = " btn btn-outline-secondary " >< ? php echo $file ?> </a>
< ? php endforeach ?>
2022-01-15 19:40:44 +01:00
</ div >
</ div >
</ div >
</ div >
</ div >
2022-11-23 12:50:12 +01:00
< ? php endif ?>
2022-01-15 19:40:44 +01:00
2022-11-23 12:50:12 +01:00
< ? php echo $templateData [ 'custom_html' ] ?>
2022-01-15 19:40:44 +01:00
</ main >
< footer class = " pt-3 mt-5 my-5 text-muted border-top " >
Powered by < a href = " https://github.com/hybula/lookingglass " target = " _blank " > Hybula Looking Glass </ a >
2022-04-19 14:14:16 +02:00
< a href = " https://github.com/hybula/lookingglass " target = " _blank " class = " float-end " >< img src = " https://img.shields.io/github/stars/hybula/lookingglass?style=social " alt = " GitHub " ></ a >
2022-01-15 19:40:44 +01:00
</ footer >
</ div >
2023-11-21 15:12:45 +01:00
< script type = " text/javascript " >
function setThemeClass () {
const colorMode = document . querySelector ( " html " ) . getAttribute ( " data-bs-theme " );
const allDivs = document . querySelectorAll ( '.color-mode-choice' )
allDivs . forEach (( div ) => {
div . classList . add ( 'd-none' )
if ( div . matches ( '.color-mode-' + colorMode + '-visible' )){
div . classList . remove ( 'd-none' )
}
})
};
setThemeClass ();
</ script >
< ? php if ( LG_THEME == 'auto' ) : ?>
< script type = " text/javascript " >
function updateThemeHelper () {
const colorMode = window . matchMedia ( " (prefers-color-scheme: dark) " ) . matches ? " dark " : " light " ;
document . querySelector ( " html " ) . setAttribute ( " data-bs-theme " , colorMode );
setThemeClass ();
}
updateThemeHelper ();
window . matchMedia ( '(prefers-color-scheme: dark)' ) . addEventListener ( 'change' , updateThemeHelper );
</ script >
< ? php endif ?>
2023-11-01 11:00:16 -05:00
< ? php echo isset ( $templateData [ 'custom_footer' ]) ? $templateData [ 'custom_footer' ] : '' ?>
2022-11-23 13:00:07 +01:00
< ? php if ( $templateData [ 'session_call_backend' ]) : ?>
2022-01-15 19:40:44 +01:00
< script type = " text/javascript " >
2022-11-23 13:05:48 +01:00
( function () {
const outputContent = document . getElementById ( 'outputContent' )
const executeButton = document . getElementById ( 'executeButton' )
const outputCard = document . getElementById ( 'outputCard' )
2022-11-23 12:04:10 +01:00
2022-11-23 13:05:48 +01:00
executeButton . innerText = 'Executing...'
executeButton . disabled = true
2022-11-23 12:04:10 +01:00
2022-11-23 13:05:48 +01:00
outputCard . style . display = 'inherit'
2022-11-23 12:04:10 +01:00
2023-09-02 14:57:53 +00:00
fetch ( 'backend.php' )
2022-11-23 13:05:48 +01:00
. then ( async ( response ) => {
// response.body is a ReadableStream
const reader = response . body . getReader ()
const decoder = new TextDecoder ()
2022-11-23 12:04:10 +01:00
2022-11-23 13:05:48 +01:00
for await ( const chunk of readChunks ( reader )) {
const text = decoder . decode ( chunk )
2022-11-23 12:04:10 +01:00
< ? php if ( in_array ( $_SESSION [ LookingGlass :: SESSION_TARGET_METHOD ], [ LookingGlass :: METHOD_MTR , LookingGlass :: METHOD_MTR6 ])) : ?>
let splittedText = text . split ( '---' )
2022-11-23 13:05:48 +01:00
if ( ! splittedText [ 1 ]) {
continue
}
outputContent . innerHTML = splittedText [ 1 ] . trim ()
2022-11-23 12:04:10 +01:00
< ? php else : ?>
2022-11-23 13:05:48 +01:00
outputContent . innerHTML = outputContent . innerHTML + text . trim () . replace ( /< br \ /> +/ g , '<br />' )
2022-11-23 12:04:10 +01:00
< ? php endif ?>
2022-11-23 13:05:48 +01:00
}
})
. finally (() => {
executeButton . innerText = 'Execute'
executeButton . disabled = false
console . log ( 'Backend ready!' )
})
})()
// readChunks() reads from the provided reader and yields the results into an async iterable
function readChunks ( reader ) {
return {
async * [ Symbol . asyncIterator ]() {
let readResult = await reader . read ()
while ( ! readResult . done ) {
yield readResult . value
readResult = await reader . read ()
}
},
}
}
2022-01-15 19:40:44 +01:00
</ script >
2022-11-23 12:04:10 +01:00
< ? php endif ?>
2022-01-15 19:40:44 +01:00
< script type = " text/javascript " >
async function copyToClipboard ( text , button ) {
2022-11-23 13:05:48 +01:00
if ( ! navigator || ! navigator . clipboard || ! navigator . clipboard . writeText ) {
return Promise . reject ( 'The Clipboard API is not available.' )
2022-11-23 11:51:58 +01:00
}
2022-11-23 13:05:48 +01:00
button . innerHTML = 'Copied!'
await navigator . clipboard . writeText ( text )
await new Promise ( r => setTimeout ( r , 2000 ))
button . innerHTML = 'Copy'
2022-01-15 19:40:44 +01:00
}
</ script >
2023-11-12 12:22:13 +01:00
< script src = " https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js " integrity = " sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL " crossorigin = " anonymous " ></ script >
2022-01-15 19:40:44 +01:00
</ body >
</ html >