HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /home/panomity.de/vr.panomity.com/index.php
<?php
/**
 * Copyright (c) VR System Studio Paweł Jakubowski - All rights reserved
 * Copying or/and redistributing of this software without the express permission
 * granted by VR System Studio Paweł Jakubowski is strictly prohibited.
 */

$subdirPart = str_replace('/admin', '', dirname($_SERVER['PHP_SELF']));

// default settings
$templatesName = 'rubee';
$type = 'blank';
$panoId = 0;
$panoName = false;
$lang = 'en';
$view_h = 0;
$view_v = 0;
$view_f = 90;
$poiName = 'false';
$viewType = 'nv';
$fromlink = 'false';

$view_tx = 0;
$view_ty = 0;
$view_tz = 0;


$titles = [
    'project' => '',
    'pano' => '',
    'poi' => '',
];
$descriptions = [
    'project' => '',
    'pano' => '',
    'poi' => '',
];
$geoTag = false;

$initvars = "{templates_name:'%TEMPLATE%',%STICKER%mydata:'%MYDATA%'}";

$db = new SQLite3(__DIR__ . '/admin/data/vrm.db');

// SSL redirect
if((!isset($_SERVER["HTTPS"]) || strtolower($_SERVER["HTTPS"]) !== "on") && getSetting('force_ssl') == 1 && !isset($_GET['no_ssl'])) {
    header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
    exit;
}

// set template name
if (getSetting('template')) {
    $templatesName = getSetting('template');
}
$initvars = str_replace('%TEMPLATE%', $templatesName, $initvars);

if (getSetting('default_language')) {
    $lang = getSetting('default_language');
}

$projectLangSettings = json_decode(getSetting('project_lang_settings'), true);
if (isset($projectLangSettings[$lang]['name'])) {
    $titles['project'] = $projectLangSettings[$lang]['name'];
    $descriptions['project'] = strip_tags($projectLangSettings[$lang]['description']);
}

$req = $subdirPart !== '/' ? str_replace($subdirPart, '', $_SERVER['REQUEST_URI']) : $_SERVER['REQUEST_URI'];
$req = strtok($req, '?');

if (isset(explode('/', $req)[1]) && in_array(explode('/', $req)[1], ['poi', 'postcard', 'link', 'sticker', 'jitsi'])) {
    $linkDetails = json_decode(getLink(explode('/', $req)[2]), true);

    if (isset($linkDetails['mydata'])) {

        $initvars = str_replace('%MYDATA%', $linkDetails['mydata'], $initvars);
        $linkParams = explode('|', $linkDetails['mydata']);
        $panoId = str_replace('scene_p', '', $linkParams[1]);
        $lang = $linkParams[2];

        if (isset($projectLangSettings[$lang]['name'])) {
            $titles['project'] = $projectLangSettings[$lang]['name'];
            $descriptions['project'] = strip_tags($projectLangSettings[$lang]['description']);
        }

        if ($linkParams[0] === 'poi') {
            $poiDetails = getPoiDetails($linkParams[7], $linkParams[2]);
            $titles['poi'] = $poiDetails['poiName'];
            $descriptions['poi'] = strip_tags($poiDetails['poiDescription']);
        }

        $type = explode('/', $req)[1];
    }

    if (isset($linkDetails['type']) && $linkDetails['type'] === 'sticker') {
        $initvars = str_replace('%STICKER%', "sticker:'" . $linkDetails['typeVal'] . "',", $initvars);
    }
    elseif (isset($linkDetails['type']) && $linkDetails['type'] === 'room_id') {
        $initvars = str_replace('%STICKER%', "room_id:'" . $linkDetails['typeVal'] . "',", $initvars);
    } else {
        $initvars = str_replace('%STICKER%', '', $initvars);
    }
} else {

    $initvars = str_replace('%STICKER%', '', $initvars);

    $re = '/scene_(\d+)_([a-z]{2}).html\/?(poi.*)?$/';
    preg_match_all($re, $req, $matches, PREG_SET_ORDER, 0);

    if (isset($matches[0][1])) {
        $type = 'link';
        $panoId = $matches[0][1];
        $panoDetails = getSinglePano($panoId);
        $startView = explode(',', $panoDetails['start_view'] ?? '');

        if (count(array_filter($startView))) {
          $view_h = trim($startView[0]);
          $view_v = trim($startView[1]);
          $view_f = trim($startView[2]);

          if(isset($startView[3])) {

            $view_tx = trim($startView[3]);
            $view_ty = trim($startView[4]);
            $view_tz = trim($startView[5]);

          }
        }
    }

    // get first panoId if it was not revealed from the matching (for main url visits)
    $readFile = file_exists('tourdata-backup.xml') ? 'tourdata-backup.xml' : 'tourdata.xml';
    if (!$panoId && file_exists($readFile)) {
        $xmlFile = simplexml_load_file($readFile);
        if ($xmlFile->xpath('structure/cat[contains(@hide,"false")]//pano[contains(@active,"true")]')) {
            $firstPanoName = (string)$xmlFile->xpath('structure/cat[contains(@hide,"false")]//pano[contains(@active,"true")]')[0]->attributes()['name'];
            $panoId = str_replace('scene_p', '', $firstPanoName);
        }
    }

    if (isset($matches[0][2])) {
        $lang = $matches[0][2];
    }

    if (isset($matches[0][3])) {
        $poiId = str_replace('poi_', '', $matches[0][3]);
        $poiName = getPoiName($poiId);
        $poiName = $poiName ? $poiName : 'false';
        $type = 'poi';
        if ($poiName !== 'false') {
            $poiDetails = getPoiDetails($poiName, $lang);
            $titles['poi'] = $poiDetails['poiName'];
            $descriptions['poi'] = strip_tags($poiDetails['poiDescription']);
        }
    }

    $mydata = $type . "|" . ($panoId ? 'scene_p' . $panoId : 0) . "|" . $lang . "|" . $view_h . "|" . $view_v . "|" . $view_f . "|" . $viewType . "|" . $poiName . "|" .$view_tx . "|" .$view_ty. "|" . $view_tz;
    $initvars = str_replace('%MYDATA%', $mydata, $initvars);

}

$panoDetails = getSinglePano($panoId);
if ($panoDetails && $panoDetails['lat'] != '' && $panoDetails['lng'] != '') {
    $geoTag['lat'] = $panoDetails['lat'];
    $geoTag['lng'] = $panoDetails['lng'];
}

if ($panoId !== 0) {
    $panoDetailsWithPhrases = getPanoDetailsWithPhrases($panoId, $lang);
    $titles['pano'] = $panoDetailsWithPhrases['panoName'];
    $descriptions['pano'] = strip_tags($panoDetailsWithPhrases['panoDescription'] ?? '');
}


function getSetting($key) {
    global $db;
    $q = $db->prepare('SELECT value FROM settings WHERE key=:key');
    $q->bindValue(':key', $key, SQLITE3_TEXT);
    $result = $q->execute()->fetchArray();
    if (!isset($result['value'])) {
        return false;
    }
    return $result['value'];
}

function getPanoDetails($panoId, $lang) {
    global $db;
    global $panoName;
    $stmt = $db->prepare('SELECT * from pano_phrases pp JOIN languages l ON l.id = pp.languages_id JOIN panos p ON p.id = pp.panos_id WHERE panos_id = :panos_id AND short = :lang AND l.public = 1 AND p.visible=1');
    $stmt->bindValue(':panos_id', $panoId, SQLITE3_INTEGER);
    $stmt->bindValue(':lang', $lang, SQLITE3_TEXT);

    $panoDetails = '';

    $result = $stmt->execute();
    while ($row = $result->fetchArray()) {
        $panoName = $row['name'];
        $panoDetails .= '<h1>' . $row['name'] . '</h1>' . PHP_EOL;
        $panoDetails .= $row['description'] . PHP_EOL;
    }

    return $panoDetails;
}

function getSinglePano($panoId) {
    global $db;
    $q = $db->prepare('SELECT * FROM panos WHERE id=:id');
    $q->bindValue(':id', $panoId, SQLITE3_INTEGER);
    return $q->execute()->fetchArray();
}

function getAllPanos() {
    global $db;
    $stmt = $db->prepare('SELECT * FROM pano_phrases pp JOIN languages l ON l.id = pp.languages_id JOIN panos p ON p.id = pp.panos_id WHERE l.public = 1 AND p.visible=1');

    $result = $stmt->execute();
    $return = [];
    while ($row = $result->fetchArray()) {
        if (!isset($return[$row['panos_id']])) {
            $return[$row['panos_id']] = [];
        }
        $return[$row['panos_id']][$row['short']] = $row['name'];
    }
    return $return;
}

function getLink($link) {
    global $db;
    $stmt = $db->prepare('SELECT * FROM shortlinks WHERE link = :link');
    $stmt->bindValue(':link', $link, SQLITE3_TEXT);
    $result = $stmt->execute()->fetchArray();
    return $result['params'];
}

function getPoiName($poiId) {
    global $db;
    $stmt = $db->prepare('SELECT * FROM poi WHERE id = :id');
    $stmt->bindValue(':id', $poiId, SQLITE3_INTEGER);
    $result = $stmt->execute()->fetchArray();
    return $result['name'];
}

function getPoiDetails($poiName, $lang) {
    global $db;
    $stmt = $db->prepare('SELECT p.id AS poiId, pp.name AS poiName, params FROM poi p JOIN poi_phrases pp ON pp.poi_id = p.id JOIN languages l ON l.id = pp.languages_id
                                WHERE p.name = :poi_name AND short = :lang');
    $stmt->bindValue(':poi_name', $poiName, SQLITE3_TEXT);
    $stmt->bindValue(':lang', $lang, SQLITE3_TEXT);

    $result = $stmt->execute()->fetchArray();
    $paramsDecoded = json_decode($result['params']);
    return [
        'poiName' => $result['poiName'],
        'poiDescription' => $paramsDecoded->description
    ];
}

function getPanoDetailsWithPhrases($panoId, $lang) {
    global $db;
    $stmt = $db->prepare('SELECT * from pano_phrases pp JOIN languages l ON l.id = pp.languages_id JOIN panos p ON p.id = pp.panos_id WHERE panos_id = :panos_id AND short = :lang AND l.public = 1 AND p.visible=1');
    $stmt->bindValue(':panos_id', $panoId, SQLITE3_INTEGER);
    $stmt->bindValue(':lang', $lang, SQLITE3_TEXT);

    $result = $stmt->execute()->fetchArray();
    return [
        'panoName' => $result['name'] ?? '',
        'panoDescription' => $result['description'] ?? ''
    ];
}

function getPoiFromPano($panoId, $lang) {
    global $db;
    $stmt = $db->prepare('SELECT p.id AS poiId, pp.name AS poiName FROM poi p JOIN poi_phrases pp ON pp.poi_id = p.id JOIN languages l ON l.id = pp.languages_id
                                WHERE panos_id = :panos_id AND short = :lang');
    $stmt->bindValue(':panos_id', $panoId, SQLITE3_INTEGER);
    $stmt->bindValue(':lang', $lang, SQLITE3_TEXT);

    $result = $stmt->execute();
    while ($row = $result->fetchArray()) {
        echo '<li><a href="scene_' . $panoId . '_' . $lang . '.html/poi_' . $row['poiId'] . '" tabindex="-1">' . $row['poiName'] . '</a></li>' . PHP_EOL;
    }
}

$allPanos = getAllPanos();

$settings = json_decode(getSetting('global_modules'));
$googleUA = isset($settings->m_analytics->google_id) ? $settings->m_analytics->google_id : '';
$matomoURL = $settings->m_analytics->matomo_url ?? '';
$matomoSiteId = $settings->m_analytics->matomo_siteid ?? '';
$statisticsEnabled = $settings->m_analytics->aktyw === 'true';
$accessKeysEnabled = getSetting('access_keys_enabled') === '1';
$accessKeysLogo = $settings->m_logo->aktyw === 'true';

if ($matomoURL) {
    $matomoURL = parse_url($matomoURL, PHP_URL_HOST) . (parse_url($matomoURL, PHP_URL_PATH) !== '/' ? parse_url($matomoURL, PHP_URL_PATH) : '') . (parse_url($matomoURL, PHP_URL_QUERY) ? '?' . parse_url($matomoURL, PHP_URL_QUERY) : '');
}

$facebookAppId = false;
if (isset($settings->m_facebook->aktyw) && $settings->m_facebook->aktyw) {
    $facebookAppId = isset($settings->m_facebook->app_id) ? $settings->m_facebook->app_id : false;
}

$panoDetails = getPanoDetails($panoId, $lang);

$isSsl = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== '';

$sessionSubdirPart = preg_replace('/\/admin$/', '', dirname($_SERVER['PHP_SELF']));
if ($sessionSubdirPart === '') {
    $sessionSubdirPart = '/';
}
$cookieName = preg_replace("/[^a-zA-Z0-9-]+/", '-', str_replace(['/', '.'], '-', $sessionSubdirPart));
$sessionSavePath = __DIR__ . '/admin/data/cache/sessions';
if (!is_dir($sessionSavePath)) {
    @mkdir($sessionSavePath, 0775, true);
}
if (is_dir($sessionSavePath) && is_writable($sessionSavePath)) {
    session_save_path($sessionSavePath);
}
session_name('cms4vr' . $cookieName);
session_start();

$title = '';
$description = '';
if ($titles['poi']) {
    $title = $titles['poi'];
} elseif ($titles['pano'] && $type === 'link') {
    $title = $titles['project'] !== '' ? $titles['project'] . ' | ' . $titles['pano'] : $titles['pano'];
} else {
    $title = $titles['project'];
}
if ($descriptions['poi']) {
    $description = $descriptions['poi'];
} elseif ($descriptions['pano']) {
    $description = $descriptions['pano'];
} else {
    $description = $descriptions['project'];
}

if ($_SERVER['REQUEST_URI'] === '' || $_SERVER['REQUEST_URI'] === '/') {
    $title = $titles['project'];
    $description = $descriptions['project'];
}

?>
<!DOCTYPE html>
<html>
<head>
    <title><?= $title ?></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, viewport-fit=cover" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    <meta http-equiv="x-ua-compatible" content="IE=edge" />
    <base href="<?= $subdirPart != '/' ? $subdirPart . '/' : '/' ?>" />
    <?php if ($description) { ?>
    <meta name="description" content="<?= $description ?>" />
    <?php } ?>
    <?php if ($statisticsEnabled && $googleUA) { ?>
    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=<?= $googleUA ?>"></script>
    <script>
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());

        gtag('config', '<?= $googleUA ?>');
    </script>
    <!-- End Google Analytics -->
    <?php } ?>
    <?php if ($statisticsEnabled && $matomoURL && $matomoSiteId) { ?>
        <script type="text/javascript">
            var _paq = window._paq = window._paq || [];
            _paq.push(['trackPageView']);
            _paq.push(['enableLinkTracking']);
            (function() {
                var u="//<?= $matomoURL ?>/";
                _paq.push(['setTrackerUrl', u+'matomo.php']);
                _paq.push(['setSiteId', '<?= $matomoSiteId ?>']);
                var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
                g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
            })();
        </script>
    <?php } ?>

    <script type="text/javascript" src="admin/assets/js/jquery-1.10.2.js"></script>
    <!--  Paper Dashboard core CSS    -->
    <!-- <link href="admin/assets/css/paper-dashboard.css" rel="stylesheet"/> -->
    <link href="admin/assets/css/themify-icons.css" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="preloader.css">


    <style>
        html { height:100%; margin:0; padding:0;}
        body { height:100%; overflow:hidden; margin:0; padding:0; font-family:Arial, Helvetica, sans-serif; font-size:16px; color:#FFFFFF; background-color:#000000; }
        #krpanoSWFObject pre { background: none;}
        @media only screen and (max-device-width:768px){

            body.modal-open {
                overflow: hidden;
                /*position: fixed;*/
            }
        }

        body.viewport-lg {
            position: absolute;
        }
        .remote {
            position: absolute;
            left: -99999px;
            top: -99999px;
            z-index: -9999!important;
            font-size: 1px;
        }
        #access_keys input {
            border: 0;
            margin: 0 20px 20px 20px;
            border-radius: 10px;
            background: #f1f1f1;
            padding: 10px;
            width: 340px;
            font-size: 1.25em;
        }
        #access_keys button {
            cursor: pointer;
            color: #fff;
            border: 0;
            background-color: #28a745;
            display: inline-block;
            font-weight: 400;
            text-align: center;
            white-space: nowrap;
            vertical-align: middle;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
            padding: .375rem .75rem;
            font-size: 1rem;
            line-height: 1.5;
            border-radius: 2rem;
            transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
        }
        #access_keys button:hover {
            background-color: #218838;
            border-color: #1e7e34;
            text-decoration: none;
        }
        #access_keys .moreInfo {
            margin-top: 0;
            text-align:left;
            padding: 0 20px;
            font-size: 0.8em;
        }
        #access_keys #invalidToken {
            color: red;
            font-weight: bold;
            display: none;
        }
        #access_keys footer, #access_keys .box-info {
            text-align: center;
        }
        #privacy {
            width: calc(100vw - 120px);
            height: 100%;
            margin: auto;
            color: #000000;
        }
        .privacyContainer {
            padding-top:60px;
            margin-bottom: 60px;

        }
        .privacyBody {
            background: #ffffff;
            float: none;
            margin: 0 auto;
            -moz-box-shadow: 0 0 4px 1px rgba(0, 0, 0, .05);
            -webkit-box-shadow: 0 0 4px 1px rgba(0, 0, 0, .05);
            -o-box-shadow: 0 0 4px 1px rgba(0, 0, 0, .05);
            -ms-box-shadow: 0 0 4px 1px rgba(0, 0, 0, .05);
            box-shadow: 0 0 4px 1px rgba(0, 0, 0, .05);
            border: 1px solid #ccc;
        }
        .privacyText {
            padding:20px;
            color: #000000;
            overflow: auto;
            max-height: calc(100vh - 246px);
        }
        .privacyText p {
            margin:0;
        }
        .privacyBody > footer {
            text-align: center;
            padding-top: 20px;
            border-top: 1px solid #ccc;
        }
        .privacyBody > footer > .btn {
            padding: 10px 20px;
            margin: 0 10px;
            cursor: pointer;
        }
    </style>
    <!-- for Facebook -->
    <meta property="og:updated_time" content="<?=time()?>" />
    <?php if ($facebookAppId) { ?>
    <meta property="fb:app_id" content="<?= $facebookAppId ?>"/>
    <?php } ?>
    <meta property="og:url" content="<?= ($isSsl ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ?>" />
    <meta property="og:type" content="website" />
    <meta property="og:title" content="<?= $title ?>" />
    <meta property="og:description" content="<?= $description ?>" />
    <meta property="og:site_name" content="<?= $title ?>"/>
    <?php

    $thumbName = file_exists(__DIR__ . '/panos/p' . $panoId . '.tiles/fb_thumb.jpg') ? 'fb_thumb.jpg' : 'thumb.jpg';

    if ($panoId) {
        $imageSize = getimagesize(__DIR__ . '/panos/p' . $panoId . '.tiles/' . $thumbName);
        $imageLink = ($isSsl ? "https" : "http") . '://' . $_SERVER['HTTP_HOST'] . ($subdirPart !== '/' ? $subdirPart : '');
        $imageLink .= '/panos/p' . $panoId . '.tiles/' . $thumbName . '?nc=' . uniqid();
        echo '<meta property="og:image" content="' . $imageLink . '" />';
        $isSsl = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== '';
        if ($isSsl) {
            echo '<meta property="og:image:secure_url" content="' . $imageLink . '" />';
        }
    ?>
    <meta property="og:image:width" content="<?= $imageSize[0] ?>" />
    <meta property="og:image:height" content="<?= $imageSize[1] ?>" />
    <meta property="og:image:alt" content="thumbnail" />
    <meta property="og:image:type" content="image/jpeg" />

    <!-- for Twitter -->
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content="<?= $title ?>" />
    <meta name="twitter:description" content="<?= $description ?>" />
    <meta name="twitter:image" content="<?= $imageLink ?>" />

    <?php if ($geoTag) { ?>
    <meta name="geo.position" content="<?= $geoTag['lat'] ?>;<?= $geoTag['lng'] ?>" />
    <meta name="ICBM" content="<?= $geoTag['lat'] ?>, <?= $geoTag['lng'] ?>" />
    <?php } ?>
    <?php } ?>
</head>

<?php
$cookie = 1;
if (getSetting('m_privacy') === 'true') {
    $cookie = isset($_COOKIE['cms4vr-privacy-fe']) ? (int)$_COOKIE['cms4vr-privacy-fe'] : 0;
    if (isset($_GET['cookie-accepted'])) {
        $cookie = 1;
    }
}
?>

<body<?= $cookie === 0 || $accessKeysEnabled ? ' style="background: #f4f6fa"' : ''?>>

<?php

function isBot() {
    return isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/bot|curl|crawl|facebook|fetch|mediapartners|slurp|spider/i',
            $_SERVER['HTTP_USER_AGENT']);
}

if ($cookie === 0 && trim(strip_tags(getSetting('privacy_fe_' . $lang))) && !isBot()) { ?>
<div id="privacy">
    <div class="privacyContainer">
        <div class="privacyBody">
            <div class="box-info full privacyText">
                <?= getSetting('privacy_fe_' . $lang) ?>
            </div>
            <footer>
                <button id="cookieAccept" class="btn"><i class="ti-check"></i></button>
                <button id="cookieReject" class="btn"><i class="ti-close"></i></button>
            </footer>
            <br />
        </div>
    </div>
</div>
<?php } elseif ($accessKeysEnabled && (!isset($_SESSION['access_key_valid']) || $_SESSION['access_key_valid'] === false || $_SESSION['access_key_valid_until'] < time())) { ?>
    <div id="access_keys" style="width: 400px; height: 100%;margin: auto; color:black">
        <div class="row-fluid" style="padding-top:60px">
            <div class="col-md-5" style="background: #ffffff; float: none; margin: 0 auto;-moz-border-radius:20px;-webkit-border-radius:20px;-ms-border-radius:20px;-o-border-radius:20px;border-radius:20px;-moz-box-shadow: 0 0 4px 1px rgba(0, 0, 0, .05);-webkit-box-shadow: 0 0 4px 1px rgba(0, 0, 0, .05);-o-box-shadow: 0 0 4px 1px rgba(0, 0, 0, .05);-ms-box-shadow: 0 0 4px 1px rgba(0, 0, 0, .05);box-shadow: 0 0 4px 1px rgba(0, 0, 0, .05);border: 1px solid #ccc">
                <div class="page-heading animated fadeInDownBig">
                    <?php if ($accessKeysLogo) { ?>
                        <img src="media/logo_thumb.png?nc=<?= uniqid(); ?>" style="display: block;margin: 20px auto" />
                    <?php } ?>
                </div>
                <div class="box-info full">
                    <p>USE YOUR E-TICKET</p>
                    <div>
                        <input type="text" id="access_key" placeholder="token code" />
                    </div>
                    <?php if (getSetting('access_keys_url') !== '') { ?>
                    <p class="moreInfo"><a href="<?= getSetting('access_keys_url') ?>" target="_blank">More info here</a></p>
                    <?php } ?>
                    <div id="invalidToken">
                        <p>Invalid or expired e-ticket</p>
                    </div>
                </div>
                <footer>
                    <button id="accessKeyCheck" class="btn btn-success">ENTER</button>
                </footer>
                <br />
            </div>
        </div>
    </div>
<?php } else { ?>
<script src="tour.js?nc=<?= getSetting('version') ?>"></script>
<div id="pano" style="width:100%;height:100%;" data-nosnippet>
    <script>
        var krpano = null;
        var cms4vrNavLastScene = null;
        var cms4vrNavSceneWatcher = null;

        function cms4vrBool(value) {
            return value === true || value === 'true' || value === 1 || value === '1';
        }

        function cms4vrHideHelpOverlay() {
            if (!krpano || typeof krpano.set !== 'function') {
                return;
            }
            try { krpano.set('layer[help_100_bg].visible', false); } catch (e) {}
            try { krpano.set('layer[help_infobox].visible', false); } catch (e) {}
            try { krpano.set('layer[help_popup_bg].visible', false); } catch (e) {}
        }

        function cms4vrTryOpenLeftNav(sceneName, triesLeft) {
            if (!krpano || typeof krpano.get !== 'function' || triesLeft <= 0) {
                return;
            }

            var currentScene = '';
            try { currentScene = String(krpano.get('xml.scene') || ''); } catch (e) {}
            if (sceneName && currentScene && sceneName !== currentScene) {
                return;
            }

            cms4vrHideHelpOverlay();

            var iconVisible = false;
            var iconAction = '';
            try { iconVisible = cms4vrBool(krpano.get('layer[rightbox_navi_ico_style].visible')); } catch (e) {}
            try { iconAction = String(krpano.get('layer[rightbox_navi_ico_style].onclick') || ''); } catch (e) {}

            if (iconVisible && iconAction) {
                try { krpano.call(iconAction); } catch (e) {}
            }

            setTimeout(function () {
                if (!krpano || typeof krpano.get !== 'function') {
                    return;
                }

                var stillClosed = false;
                try {
                    stillClosed = cms4vrBool(krpano.get('layer[rightbox_navi_ico_style].visible'));
                } catch (e) {
                    stillClosed = true;
                }

                if (!stillClosed) {
                    cms4vrNavLastScene = sceneName || currentScene || cms4vrNavLastScene;
                    return;
                }

                cms4vrTryOpenLeftNav(sceneName, triesLeft - 1);
            }, 350);
        }

        function cms4vrEnsureLeftNav() {
            if (!krpano || typeof krpano.get !== 'function') {
                return;
            }

            var sceneName = '';
            try { sceneName = String(krpano.get('xml.scene') || ''); } catch (e) {}

            if (!sceneName || sceneName === cms4vrNavLastScene) {
                return;
            }

            cms4vrTryOpenLeftNav(sceneName, 20);
        }

        if (navigator.msPointerEnabled)
        {
          navigator.__defineGetter__("msPointerEnabled", function(){return false;});
          navigator.__defineGetter__("pointerEnabled", function(){return true;});
        }
        // navigator.pointerEnabled = navigator.maxTouchPoints > 0;               // Edge 17 touch support workaround
        document.documentElement.ontouchstart = navigator.maxTouchPoints > 0;  // Chrome 70 touch support workaround
        <?php if ($panoId !== 0) { ?>
        embedpano({xml:"tour.xml?nc=<?= uniqid() ?>", target:"pano", html5:(navigator.userAgent.toLowerCase().indexOf("googlebot") >= 0 ? "always" : "auto"), initvars:<?= $initvars ?>, mobilescale:1.0, passQueryParameters:true,onready:krpano_onready_callback});
        <?php } else { ?>
        embedpano({id : "krpanoSWFObject", xml:"plugins/under_construction.xml",target : "pano", passQueryParameters : false});
        <?php } ?>

        function krpano_onready_callback(krpano_interface) {
            krpano = krpano_interface;
            cms4vrEnsureLeftNav();
            if (!cms4vrNavSceneWatcher) {
                cms4vrNavSceneWatcher = setInterval(cms4vrEnsureLeftNav, 1000);
            }
        }
    </script>
</div>
    <div id="loadinginfo"></div>
<?php } ?>

<article class="remote">
    <?= $panoDetails ?>
</article>
<aside class="remote">
    <ul>
        <?php getPoiFromPano($panoId, $lang); ?>
    </ul>
</aside>
<nav class="remote">
    <ul>
        <?php
        foreach ($allPanos as $panoId => $languages) {
            foreach ($languages as $lang => $langPhrase) {
                echo '<li><a href="scene_' . $panoId . '_' . $lang . '.html" tabindex="-1">' . $langPhrase . '</a></li>' . PHP_EOL;
            }
        }
        ?>
    </ul>
</nav>

<div id="vrModal" class="modal fade bs-example-modal-lg remote" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" style="z-index:2000000">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-body">
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal"><i class="mdi mdi-window-close"></i></button>
            </div>
        </div>
    </div>
</div>

<script type="text/javascript">
    function jsTranslate(string) {
        const translations = {
            'en': {
                'USE YOUR E-TICKET': 'USE YOUR E-TICKET',
                'e-ticket code': 'e-ticket code',
                'More info here': 'More info here',
                'ENTER': 'ENTER',
                'token code': 'enter the e-ticket code',
                'Invalid or expired e-ticket': 'Invalid or expired e-ticket',
            },
            'es': {
                'USE YOUR E-TICKET': 'UTILICE SU E-TICKET',
                'e-ticket code': 'Código de e-ticket',
                'More info here': 'Más información aquí',
                'ENTER': 'ENTRAR',
                'token code': 'introduce el código del e-billete',
                'Invalid or expired e-ticket': 'Billete electrónico no válido o caducado',
            },
            'fr': {
                'USE YOUR E-TICKET': 'UTILISEZ VOTRE E-BILLET',
                'e-ticket code': 'Code du e-billet',
                'More info here': 'Plus d\'informations ici',
                'ENTER': 'ENTRER',
                'token code': 'entrez le code du billet électronique',
                'Invalid or expired e-ticket': 'Billet électronique invalide ou expiré',
            },
            'de': {
                'USE YOUR E-TICKET': 'BENUTZEN SIE IHR E-TICKET',
                'e-ticket code': 'E-Ticket-Code',
                'More info here': 'Mehr Infos hier',
                'ENTER': 'EINGEBEN',
                'token code': 'Geben Sie den E-Ticket-Code ein',
                'Invalid or expired e-ticket': 'Ungültiges oder abgelaufenes E-Ticket',
            },
            'it': {
                'USE YOUR E-TICKET': 'UTILIZZA IL TUO BIGLIETTO ELETTRONICO',
                'e-ticket code': 'Codice del biglietto elettronico',
                'More info here': 'Ulteriori informazioni qui',
                'ENTER': 'ENTRA',
                'token code': 'inserisci il codice del biglietto elettronico',
                'Invalid or expired e-ticket': 'Biglietto elettronico non valido o scaduto',
            },
            'pt': {
                'USE YOUR E-TICKET': 'USE SEU E-TICKET',
                'e-ticket code': 'Código do e-ticket',
                'More info here': 'Mais informações aqui',
                'ENTER': 'ENTRAR',
                'token code': 'digite o código do bilhete eletrônico',
                'Invalid or expired e-ticket': 'Bilhete eletrônico inválido ou expirado',
            },
            'nl': {
                'USE YOUR E-TICKET': 'GEBRUIK UW E-TICKET',
                'e-ticket code': 'E-ticketcode',
                'More info here': 'Meer info hier',
                'ENTER': 'INVOEREN',
                'token code': 'voer de e-ticketcode in',
                'Invalid or expired e-ticket': 'Ongeldig of verlopen e-ticket',
            },
            'ru': {
                'USE YOUR E-TICKET': 'ИСПОЛЬЗУЙТЕ ВАШ ЭЛЕКТРОННЫЙ БИЛЕТ',
                'e-ticket code': 'Код электронного билета',
                'More info here': 'Дополнительная информация здесь',
                'ENTER': 'ВВОД',
                'token code': 'введите код электронного билета',
                'Invalid or expired e-ticket': 'Недействительный или просроченный электронный билет',
            },
            'zh': {
                'USE YOUR E-TICKET': '使用您的电子票',
                'e-ticket code': '电子票代码',
                'More info here': '更多信息在这里',
                'ENTER': '进入',
                'token code': '输入电子客票代码',
                'Invalid or expired e-ticket': '电子客票无效或过期',
            },
            'ja': {
                'USE YOUR E-TICKET': 'あなたのEチケットを使用してください',
                'e-ticket code': 'Eチケットコード',
                'More info here': 'こちらで詳細情報をご覧いただけます',
                'ENTER': '入力',
                'token code': 'eチケットコードを入力してください',
                'Invalid or expired e-ticket': '無効または期限切れの電子チケット',
            },
            'ko': {
                'USE YOUR E-TICKET': 'E-티켓을 사용하세요',
                'e-ticket code': 'E-티켓 코드',
                'More info here': '여기에서 더 많은 정보',
                'ENTER': '입력',
                'token code': 'E-티켓 코드를 입력하세요',
                'Invalid or expired e-ticket': '유효하지 않거나 만료된 E-티켓',
            },
            'ar': {
                'USE YOUR E-TICKET': 'استخدم تذكرتك الإلكتروني',
                'e-ticket code': 'رمز تذكرة الإلكترونية',
                'More info here': 'المزيد من المعلومات هنا',
                'ENTER': 'أدخل',
                'token code': 'أدخل رمز التذكرة الإلكترونية',
                'Invalid or expired e-ticket': 'ذكرة إلكترونية غير صالحة أو منتهية الصلاحية',
            },
            'hi': {
                'USE YOUR E-TICKET': 'अपना ई-टिकट प्रयोग करें',
                'e-ticket code': 'ई-टिकट कोड',
                'More info here': 'यहाँ और अधिक जानकारी',
                'ENTER': 'प्रवेश करें',
                'token code': 'ई-टिकट कोड दर्ज करें',
                'Invalid or expired e-ticket': 'अमान्य या समाप्त ई-टिकट',
            },
            'pl': {
                'USE YOUR E-TICKET': 'UŻYJ SWOJEGO E-BILETU',
                'e-ticket code': 'Kod e-biletu',
                'More info here': 'Więcej informacji tutaj',
                'ENTER': 'WEJDŹ',
                'token code': 'wprowadź kod e-biletu',
                'Invalid or expired e-ticket': 'Nieważny lub wygasły e-bilet',
            },
            'tr': {
                'USE YOUR E-TICKET': 'E-BİLETİNİZİ KULLANIN',
                'e-ticket code': 'E-bilet kodu',
                'More info here': 'Daha fazla bilgi burada',
                'ENTER': 'GİRİŞ',
                'token code': 'e-bilet kodunu girin',
                'Invalid or expired e-ticket': 'Geçersiz veya süresi dolmuş e-bilet',
            },
            'vi': {
                'USE YOUR E-TICKET': 'SỬ DỤNG VÉ ĐIỆN TỬ CỦA BẠN',
                'e-ticket code': 'Mã vé điện tử',
                'More info here': 'Thêm thông tin tại đây',
                'ENTER': 'NHẬP',
                'token code': 'nhập mã vé điện tử',
                'Invalid or expired e-ticket': 'Vé điện tử không hợp lệ hoặc hết hạn',
            },
        };

        const language = navigator.language.substring(0, 2);
        const translation = translations[language];
        if (translation && translation[string]) {
            return translation[string];
        }
        return string;
    }

    $(document).ready(function () {
        $('#access_keys').find('p, button, input').map(function () {
            if ($(this).prop("tagName") === 'INPUT') {
                $(this).attr('placeholder', jsTranslate($(this).attr('placeholder')));
            } else {
                $(this).text(jsTranslate($(this).text()))
            }
        });

        $('#vrModal').on('hide.bs.modal', function (e) {
            $('#vrModal').addClass('remote');
            var krpano = document.getElementById("krpanoSWFObject");
            krpano.set('html_popup_is_open', false);
        });
        $('#vrModal').on('show.bs.modal', function (e) {
            $('#vrModal').removeClass('remote');
        });
        $('#cookieAccept').click(function(e){
            e.preventDefault();
            var CookieDate = new Date;
            CookieDate.setFullYear(CookieDate.getFullYear() + 1);
            document.cookie = 'cms4vr-privacy-fe=1; expires=' + CookieDate.toGMTString() + ';';
            // document.cookie = 'cms4vr-privacy-fe=1; expires=' + CookieDate.toGMTString() + '; SameSite=None; Secure';
            var url = new URL(window.location.href);
            url.searchParams.set('cookie-accepted','1');
            window.location.href = url.href;
        });
        $('#cookieReject').click(function(e){
            e.preventDefault();
            document.cookie = 'cms4vr-privacy-fe=0';
            window.location.reload();
        });
        $('#accessKeyCheck').click(function(e){
            e.preventDefault();
            $('#invalidToken').hide();
            $.ajax({
                type: "POST",
                url: 'admin/?c=settings&action=checkAccessKeyAjax',
                dataType: "json",
                data: {
                    access_key: $('#access_key').val(),
                },
                success: function (response) {
                    if (response.success) {
                        window.location.reload();
                    } else {
                        $('#invalidToken').show(200);
                    }
                },
            });
        });
    });
</script>
</body>
</html>