LastModified и Office

Столкнулся с прoблемой компонента LastModified и Office. При включённом плагине перестаёт корректно работать авторизация. После ввода данных и нажатии на кнопку Вход не происходит смены чанков с не авторизованного на авторизованный и также с выходом. Ты вроде вышел, а отображается твоя учётка. При обновлении кэша браузера через CTRL + F5 всё нормально отображается. Может кто-нибудь подсказать как можно плагин допилить, чтобы сниппет Office не кэшировался?

<?php
/**
 * MODx Revolution plugin which handle request If-Modified-Since
 *
 * @package lastmodified
 * @var modX $modx MODX instance
 * @var integer $dtm Value of last update time of document
 * @var integer $ltm Value of HTTP_IF_MODIFIED_SINCE from request
 * @var string $rule Cache-control directive (public, private)
 * @var integer $maxage Cache max age in seconds
 * @var integer $expire Cache expire in seconds
 */
if ($modx->event->name == 'OnWebPagePrerender') {
    $dtm = ($modx->resource->get('editedon')) ? strtotime($modx->resource->get('editedon')) : strtotime($modx->resource->get('createdon'));
    if (empty($dtm)) {
        return '';
    }

    $rule = trim($modx->getOption('lastmodified.response'));

    if (!in_array($rule, ['private', 'public'])) { // 'no-cache'
        $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: wrong response directive value. Check configuration.');
        return '';
    }

    $maxage = ((int)$modx->getOption('lastmodified.maxage') > 0) ? (int)$modx->getOption('lastmodified.maxage') : 3600;
    $expire = ((int)$modx->getOption('lastmodified.expires') > 0) ? (int)$modx->getOption('lastmodified.expires') : 3600;

    if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
        $ltm = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
        if ($dtm <= $ltm) {
            $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
            header($protocol . ' 304 Not Modified');
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $dtm) . ' GMT');
            header('Cache-control: ' . $rule . ', max-age=' . $maxage);
            header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expire));
            exit();
        }
    }
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $dtm) . ' GMT');
    header('Cache-control: ' . $rule . ', max-age=' . $maxage);
    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expire));
    return '';
}

/**
 * Update parent editedon field
 *
 * @var modX $modx MODX instance
 * @var modResource $parent Parent resource object
 */
if ($modx->event->name == 'OnDocFormSave') {

    if ($modx->getOption('lastmodified.update_start')) {

        $mainId = $modx->getOption('site_start');

        if ($mainId > 0 && $mainId !== $id) {

            $main = $modx->getObject('modResource', $mainId);

            if (!$main instanceof modResource) {
                $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: get wrong modResource instance for main page with id ' . $mainId . ' for document ' . $id. '.');
                return '';
            }

            $main->set('editedon', time());
            $main->save();

            unset($main);
        }

        unset($mainId);
    }

    if ($modx->getOption('lastmodified.update_parent')) {
        $level = ((int)$modx->getOption('lastmodified.update_level') > 0) ? (int)$modx->getOption('lastmodified.update_level') : 1;

        $parentIds = $modx->getParentIds($id, $level, ['context' => 'web']);

        foreach ($parentIds as $parentId) {
            if ($parentId === 0) {
                continue;
            }

            $parent = $modx->getObject('modResource', $parentId);

            if (!$parent instanceof modResource) {
                $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: get wrong modResource instance for parent with id ' . $parentId . ' for document ' . $id. '.');
                return '';
            }

            $parent->set('editedon', time());
            $parent->save();

            unset($parent);
        }

        return '';
    }
}
SEQUEL.ONE
02 октября 2018, 13:54
modx.pro
804
0

Комментарии: 48

Илья Александрович
10 февраля 2019, 02:17
0
Так же проблема наблюдается в связке с miniShop2, корзина перестаёт обновляться при переходе между страницами.
Удалось допилить LastModified?
    Кудашев Сергей
    12 марта 2019, 00:37
    0
    Илья Александрович к сожалению плотно не работал с miniShop2, не было такой необходимости. Сегодня посмотрю что можно с этой проблемой сделать.
    Кудашев Сергей
    12 марта 2019, 00:36
    +1
    Господа, как автор плагина, хочу обратить ваше внимание, что с проблемами лучше писать в личку или на github.

    SEQUEL.ONE посмотрите пожалуйста, выпустил вариант с предотвращение обработки для авторизованных пользователей. В теории, должно решить Вашу проблему.
      Кудашев Сергей
      12 марта 2019, 03:26
      0
      Если правильно понял причину проблемы, то необходимые правки внес. Добавил дополнительный параметр, который предупреждает обработку If-Modified-Since в случае, если в именах переменных сессии встречаются определенные названия. В нашем случае это minishop2, о сделан настройкой по умолчанию.

      Попробуйте обновить компонент и отписаться здесь по результатам, если не сложно :)
        Сергей
        12 марта 2019, 11:05
        0
        Спасибо за компонент, но он не работает с ssl
          Кудашев Сергей
          12 марта 2019, 11:31
          0
          Сергей, хотелось бы более развернутого комментария и каких нибудь подтверждений, что значит не работает?

          Если Вы под словом SSL подразумеваете защищенное https соединение, то компонент вообще не смотрим, есть ли защищенное соединение или нет, ему все равно. Он просто анализирует дату последнего изменения документа и если она совпадает с датой в запросе, отдает 304 заголовок и умирает, потому что отдавать контент смысла нет.

          Пример работы компонента с https соединением на скриншоте:
            Сергей
            12 марта 2019, 11:40
            0
            Спасибо за ответ. Верно понимаю, что компонент работает из коробки? Значит мне так не везет) Скрин. Я просто уже как то давно потратил много времени на попутку установить, но увы не вышло.
              Кудашев Сергей
              12 марта 2019, 11:46
              0
              Компонент работает из коробки. Никаких сложностей с установкой быть не должно.
              Каких-то дополнительных настроек компонент не требует, насколько я помню :)
                Сергей
                12 марта 2019, 11:51
                0
                Ну вы сами видите результат, может это конечно из-за кеша на сервера. Я прошлый раз я так и не нашел причины(
                  Кудашев Сергей
                  12 марта 2019, 11:52
                  0
                  А он именно на https не отдает или не http тоже не отдает?
                    Сергей
                    12 марта 2019, 11:54
                    0
                    Честно не пробовал, но читал что есть проблемы в https. (Это был конечно другой компонент)
                      Сергей
                      12 марта 2019, 11:56
                      0
                      Проверил еще один сайт, такая-же ситуация, не работает(
                        Кудашев Сергей
                        12 марта 2019, 11:57
                        0
                        Тогда попробуйте и можете сюда скинуть скрины для http и для https, и левую и правую части того, что выводит last-modified.com.
                          Сергей
                          12 марта 2019, 12:03
                          0
                          Отключил кэшировани, сжатие, перевел на http и результат такой же) скрин
                            Кудашев Сергей
                            12 марта 2019, 12:19
                            0
                            Можете в плагине заменить
                            if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
                                    $ltm = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
                            
                                    if ($dtm <= $ltm) {
                                        $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
                                        header($protocol . ' 304 Not Modified');
                                        header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $dtm) . ' GMT');
                                        header('Cache-control: ' . $rule . ', max-age=' . $maxage);
                                        header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expire));
                                        exit();
                                    }
                                }
                            на следующий код
                            if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
                                    $ltm = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
                                    ob_start();
                            var_dump($ltm);
                            var_dump($dtm);
                            $contents = ob_get_contents();
                            ob_end_clean();
                            error_log(print_r($contents."\n",1), 3, $modx->getOption(xPDO::OPT_CACHE_PATH).'logs/error.log');
                                    if ($dtm <= $ltm) {
                                        $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
                                        header($protocol . ' 304 Not Modified');
                                        header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $dtm) . ' GMT');
                                        header('Cache-control: ' . $rule . ', max-age=' . $maxage);
                                        header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expire));
                                        exit();
                                    }
                                }
                            и результат из логов сбросить сюда. В логах должно будет отразиться похожее на:
                            int(1552381472)
                            int(1552381432)
                            Сергей
                            12 марта 2019, 12:29
                            0
                            В логах нет такой информации. все на 100 раз проверил.
                            Сергей
                            12 марта 2019, 12:38
                            0
                            Может это как-то связанно с тем что у сайта по факту то стоит HTTP/2?
                            Кудашев Сергей
                            12 марта 2019, 12:48
                            0
                            Отлично тогда возвращаем все как было и меняем верхнюю часть:
                            if ($modx->event->name == 'OnWebPagePrerender') {
                                if ($modx->getOption('lastmodified.prevent_authorized') && ($modx->user->get('username') !== '(anonymous)')) {
                                    return '';
                                }
                            
                                if (!empty($modx->getOption('lastmodified.prevent_session'))) {
                                    $prevent = array_map(function ($s) {return strtolower(trim($s));}, explode(',', $modx->getOption('lastmodified.prevent_session')));
                                    if (empty($prevent)) {
                                        $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: incorrect prevent session list. Check configuration.');
                                        return '';
                                    }
                            
                                    $sessionkeys = array_map(function ($s) {return strtolower(trim($s));}, array_keys($_SESSION));
                            
                                    if (array_intersect($prevent, $sessionkeys)) {
                                        return '';
                                    }
                                }
                            
                                $dtm = $modx->resource->get('editedon') ? strtotime($modx->resource->get('editedon')) : strtotime($modx->resource->get('createdon'));
                                if (empty($dtm)) {
                                    return '';
                                }
                            
                                $rule = trim($modx->getOption('lastmodified.response'));
                            
                                if (!in_array($rule, ['private', 'public'])) { // 'no-cache'
                                    $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: wrong response directive value. Check configuration.');
                                    return '';
                                }
                            на:
                            if ($modx->event->name == 'OnWebPagePrerender') {
                                $modx->log(modX::LOG_LEVEL_ERROR, 'In plugin');
                                if ($modx->getOption('lastmodified.prevent_authorized') && ($modx->user->get('username') !== '(anonymous)')) {
                                    return '';
                                }
                                $modx->log(modX::LOG_LEVEL_ERROR, 'After authorized');
                                if (!empty($modx->getOption('lastmodified.prevent_session'))) {
                                    $prevent = array_map(function ($s) {return strtolower(trim($s));}, explode(',', $modx->getOption('lastmodified.prevent_session')));
                                    if (empty($prevent)) {
                                        $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: incorrect prevent session list. Check configuration.');
                                        return '';
                                    }
                            
                                    $sessionkeys = array_map(function ($s) {return strtolower(trim($s));}, array_keys($_SESSION));
                            
                                    if (array_intersect($prevent, $sessionkeys)) {
                                        return '';
                                    }
                                }
                                $modx->log(modX::LOG_LEVEL_ERROR, 'After prevent');
                                $dtm = $modx->resource->get('editedon') ? strtotime($modx->resource->get('editedon')) : strtotime($modx->resource->get('createdon'));
                                if (empty($dtm)) {
                                    return '';
                                }
                            ob_start();
                            var_dump($dtm);
                            $contents = ob_get_contents();
                            ob_end_clean();
                            error_log(print_r($contents."\n",1), 3, $modx->getOption(xPDO::OPT_CACHE_PATH).'logs/error.log');
                                $rule = trim($modx->getOption('lastmodified.response'));
                            
                                if (!in_array($rule, ['private', 'public'])) { // 'no-cache'
                                    $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: wrong response directive value. Check configuration.');
                                    return '';
                                }
                                $modx->log(modX::LOG_LEVEL_ERROR, 'After check');
                            И все что выведется в логах разместите пожалуйста здесь.
                            Сергей
                            12 марта 2019, 13:03
                            0
                            Сейчас да, есть такое дело и еще как ошибку определяет эту строчку
                            $modx->log(modX::LOG_LEVEL_ERROR, 'In plugin');

                            int(1552382843)
                            Кудашев Сергей
                            12 марта 2019, 13:13
                            0
                            Сергей, у меня не так много времени есть, и если мы так с Вами дальше пойдем, то это очень надолго затянется. Если есть возможность отправьте пожалуйста доступ к админке на почту мою: kudashevs@gmail.com, мне будет проще так разобраться чем тут переписываться. Можете пароли поменять перед и после, поверьте мне не особо интересно что у Вас там :)
                            Кудашев Сергей
                            12 марта 2019, 14:45
                            0
                            Сергей, не хотите доступ давать к рабочему проекту, не проблема. Сделайте чистый проект на этом хостинге и пришлите доступ. Я так понимаю дело в любом случае в хостинге и хотелось бы сначала исключить какую-то «особенную» работу плагина, а потом уже развлекаться с настройками. Вы так меньше времени потеряете :)
                            SEQUEL.ONE
                            12 марта 2019, 12:50
                            0
                            Проблема не с протоколом 100%. Видимо чего-то на сервере не хватает. Какая конфигурация сервера? Какой веб-сервер стоит? Apache или nginx?
                            Сергей
                            12 марта 2019, 13:06
                            0
                            Вот настройки скрин
                            Кудашев Сергей
                            12 марта 2019, 13:14
                            0
                            А Вы на 7.1 или 7.0 не пробовали переключать? Вообще под 7.2 не всегда все в MODX корректно работает, по моим наблюдениям.
                            SEQUEL.ONE
                            12 марта 2019, 13:19
                            0
                            Стабильная версия PHP под MODX 7.0

                            В WWW-домены у сайта сервер какой подключен? Apache, CGI или FastCGI?
                            Сергей
                            12 марта 2019, 13:20
                            0
                            CGI стоит
                            Сергей
                            12 марта 2019, 13:19
                            0
                            Попробовал, нет, даже очень старую версию ставил, но результат один(
                            SEQUEL.ONE
                            12 марта 2019, 13:22
                            0
                            Попробуйте для начала включить Apache для версии PHP 7.0, а потом подключите эту связку в WWW-доменах к сайту.
                            Сергей
                            12 марта 2019, 13:30
                            0
                            Поставил 7.0.32 как Apache, включил на сайт, перезагрузил ngix, результат такой-же. Пробовал как FastCGI, но modx ложится почему то под ним, работает только главная и тоже не работают заголовки(
                            SEQUEL.ONE
                            12 марта 2019, 13:48
                            0
                            Сервер под FastCGI ложиться, потому, что не настроены конфиги под MODX. Оставьте версию Apache и PHP 7.0

                            Я сейчас посмотрю как у меня настроено, я вроде бы какие-то дополнительные правки вносил. А сжатие выставляли в WWW-доменах?
                            Сергей
                            12 марта 2019, 13:51
                            0
                            Да, сжатие стоит, я его убирал полностью, не помогло.
                            Сергей
                            12 марта 2019, 14:46
                            0
                            А почему у вас X-Powered-By написана версия PHP а у меня Modx Revo)
                            Кудашев Сергей
                            12 марта 2019, 16:09
                            0
                            Потому что в целях безопасности рекомендуется отключать показ X-Powered-By в настройках MODX.
                            SEQUEL.ONE
                            12 марта 2019, 16:07
                            0
                            Сейчас у себя пробую данный плагин. Похоже дело в нём, если на плагин повесить событие OnHandleRequest и добавить следующий код, то в сервисе last-modified.com/ru/ всё отдаёт корректно.

                            <?php
                            $LastModified_unix = 1294844676; // время последнего изменения страницы
                            $LastModified = gmdate("D, d M Y H:i:s \G\M\T", $LastModified_unix);
                            $IfModifiedSince = false;
                            if (isset($_ENV['HTTP_IF_MODIFIED_SINCE']))
                                $IfModifiedSince = strtotime(substr($_ENV['HTTP_IF_MODIFIED_SINCE'], 5));  
                            if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
                                $IfModifiedSince = strtotime(substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 5));
                            if ($IfModifiedSince && $IfModifiedSince >= $LastModified_unix) {
                                header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
                                exit;
                            }
                            header('Last-Modified: '. $LastModified);
                            Пробую сейчас поковырять сам плагин.
                            Сергей
                            12 марта 2019, 16:13
                            0
                            Спасибо всем за помощь, я уверен на 200% что проблема в сервере, только не знаю куда копать, так-как ошибок то особо нет. Поставил модуль на WP, там такая-же ситуация, не работает LastModified. Попробовал Ваш код, ситуация не меняется(
                            SEQUEL.ONE
                            12 марта 2019, 16:15
                            +1
                            Важный момент, у вас должен быть выключен SSI в WWW-доменах.
                            Сергей
                            12 марта 2019, 16:19
                            0
                            Вы про это скрин? Там же 301 стоит.
                            Сергей
                            12 марта 2019, 18:17
                            0
                            Все верно! SSI отключил и все заработало как часы! Спасибо вам огромное за помощь!
        Кудашев Сергей
        12 марта 2019, 18:36
        0
        SEQUEL.ONE Вы обновились, проблема решилась? Или так и остался косяк с кешированием?
          SEQUEL.ONE
          12 марта 2019, 18:40
          0
          Похоже зря я на ваш плагин грешил) Пользуюсь cloudflare.com и там настройку выключил Always Online™

          После этого заработало. Но пытаюсь с идентичными настройками на другом домене воспроизвести, так ничего пока не вышло. Сижу ковыряюсь)))
            Кудашев Сергей
            12 марта 2019, 18:54
            +1
            Ну если что вдруг не заработает или еще какое-то странное поведение, пишите :)

            В плагине сейчас принудительно отключается любая обработка 304 заголовков для авторизованных пользователей (кстати, спасибо за эту идею :) ), плюс можно принудительно запретить обработку если в сессиии встречается какая-то переменная. Для пакета Office она так и будет называться, просто в настройках обновленной версии в prevent_session прописываете office и все, перестанет обрабатываться.
              SEQUEL.ONE
              13 марта 2019, 00:48
              0
              Целый день потратил на то, чтобы запустить плагин на сайте со всеми идентичными настройками как у другого сайта где он работает, плагин даже ошибок никаких в лог не пишет :(

              Ума не приложу как его завести((( Похоже придётся поочерёдно все плагины по-выключать.
                SEQUEL.ONE
                13 марта 2019, 01:01
                0
                Вопрос снимается, всё дело было в системной настройке lastmodified.prevent_session. Удалил от туда minishop2 и всё заработало)
                Кудашев Сергей
                13 марта 2019, 01:04
                0
                Ну вообще проще всего отлаживать заменяя начало кода плагина:
                if ($modx->event->name == 'OnWebPagePrerender') {
                    if ($modx->getOption('lastmodified.prevent_authorized') && ($modx->user->get('username') !== '(anonymous)')) {
                        return '';
                    }
                
                    if (!empty($modx->getOption('lastmodified.prevent_session'))) {
                        $prevent = array_map(function ($s) {return strtolower(trim($s));}, explode(',', $modx->getOption('lastmodified.prevent_session')));
                        if (empty($prevent)) {
                            $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: incorrect prevent session list. Check configuration.');
                            return '';
                        }
                
                        $sessionkeys = array_map(function ($s) {return strtolower(trim($s));}, array_keys($_SESSION));
                
                        if (array_intersect($prevent, $sessionkeys)) {
                            return '';
                        }
                    }
                
                    $dtm = $modx->resource->get('editedon') ? strtotime($modx->resource->get('editedon')) : strtotime($modx->resource->get('createdon'));
                    if (empty($dtm)) {
                        return '';
                    }
                
                    $rule = trim($modx->getOption('lastmodified.response'));
                
                    if (!in_array($rule, ['private', 'public'])) { // 'no-cache'
                        $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: wrong response directive value. Check configuration.');
                        return '';
                    }
                на:
                if ($modx->event->name == 'OnWebPagePrerender') {
                    $modx->log(modX::LOG_LEVEL_ERROR, 'In plugin');
                    if ($modx->getOption('lastmodified.prevent_authorized') && ($modx->user->get('username') !== '(anonymous)')) {
                        return '';
                    }
                    $modx->log(modX::LOG_LEVEL_ERROR, 'After authorized');
                    if (!empty($modx->getOption('lastmodified.prevent_session'))) {
                        $prevent = array_map(function ($s) {return strtolower(trim($s));}, explode(',', $modx->getOption('lastmodified.prevent_session')));
                        if (empty($prevent)) {
                            $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: incorrect prevent session list. Check configuration.');
                            return '';
                        }
                
                        $sessionkeys = array_map(function ($s) {return strtolower(trim($s));}, array_keys($_SESSION));
                
                        if (array_intersect($prevent, $sessionkeys)) {
                            return '';
                        }
                    }
                    $modx->log(modX::LOG_LEVEL_ERROR, 'After prevent');
                    $dtm = $modx->resource->get('editedon') ? strtotime($modx->resource->get('editedon')) : strtotime($modx->resource->get('createdon'));
                    if (empty($dtm)) {
                        return '';
                    }
                ob_start();
                var_dump($dtm);
                $contents = ob_get_contents();
                ob_end_clean();
                error_log(print_r($contents,1), 3, $modx->getOption(xPDO::OPT_CACHE_PATH).'logs/error.log');
                    $rule = trim($modx->getOption('lastmodified.response'));
                
                    if (!in_array($rule, ['private', 'public'])) { // 'no-cache'
                        $modx->log(xPDO::LOG_LEVEL_ERROR, 'LastModified: wrong response directive value. Check configuration.');
                        return '';
                    }
                    $modx->log(modX::LOG_LEVEL_ERROR, 'After check');
                То есть он после каждого условия пишет в лог на уровне ошибки, прошел он по условию или нет. После чего еще и логирует дату документа. Очень удобно бывает посмотреть :)

                P.S. Мне кажется, вы просто под зарегистрированным юзером тестируете, а теперь он по умолчанию не отрабатывает для зарегистрированных. Так же он не будет отрабатывать, если minishop2 стоит. В настройках выключите prevent_authorized и prevent_session поле очистите и посмотрите, будет ли работать.
                  SEQUEL.ONE
                  13 марта 2019, 01:12
                  0
                  Вот за это спасибо, вроде научился недавно компоненты делать, сложные интерфейсы рисовать, а с плагинами беда. Единственное что намулевал так это маршрутизацию. Сейчас делаю репозиторий свой для MODX. Интерфейс готов, потихоньку с rest api разбираюсь. Удалось из базы вывести и сгенерить XML sequel.one/extras/repository/
                  sequel.one/extras/verify/
            Сергей
            12 марта 2019, 18:49
            0
            Оставил плагин в оригинале. Еще как замечание это 7.0 и Apache. А что касается CGI, то не работает с ним.
              Сергей
              12 марта 2019, 18:52
              0
              Хотя поставил еще на один, работает под 7.2.1 и CGI. Странное все это) Главное что SSI отключено. Ну и ssl тоже нет этого домена.
            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
            48